day2 complete

master
Avril 4 years ago
parent 6a3286c7c6
commit 5997e898b1
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -1,5 +1,5 @@
DAYS= day1
DAYS= $(wildcard day*)
.PHONY: all
@ -9,5 +9,5 @@ day%/part2: day%
all: $(addsuffix /part2,$(DAYS))
clean:
for d in "$(shell find . -type d -name day\*)"; do cd $$d && $(MAKE) clean; done
for d in $(DAYS); do pushd $$d && $(MAKE) clean && popd; done

@ -0,0 +1,10 @@
[package]
name = "day2"
version = "0.1.0"
authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
smallmap = "1.2.0"

@ -0,0 +1,13 @@
.PHONY: all
all: target/release/day2
target/release/day2:
cargo build --release
ln -sf $@ part2
strip $@
clean:
rm -f target/release/day2
rm -f part2

@ -0,0 +1,39 @@
#![feature(str_split_once)]
use std::{
fs,
io::{
BufReader,
BufRead,
},
error,
};
const INPUT_FILE: &str = "input";
mod rule;
fn main() -> Result<(), Box<dyn error::Error>> {
let input = BufReader::new(fs::OpenOptions::new()
.read(true)
.open(INPUT_FILE)?);
let mut ok=0;
let mut ok2 =0;
for line in input.lines()
{
if let Some((rule, pass)) = line?.split_once(':')
{
let rule: rule::Policy = rule.parse()?;
let pass = pass.trim();
if rule.validate_str(pass) {
ok+=1;
}
if rule.into_v2().validate_str(pass) {
ok2+=1;
}
}
}
println!("{}", ok);
println!("{}", ok2);
Ok(())
}

@ -0,0 +1,128 @@
use std::{
ops::RangeInclusive,
str,
fmt,
error,
};
use smallmap::Map;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Policy
{
letter: char,
rep: RangeInclusive<usize>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PolicyV2
{
letter: char,
i: usize,
j: usize,
}
impl PolicyV2
{
#[inline] pub fn validate_str(&self, s: &str) -> bool
{
self.validate(s.chars().collect::<Vec<_>>())
}
pub fn validate(&self, vec: impl AsRef<[char]>) -> bool
{
let vec = vec.as_ref();
if self.i>=vec.len() || self.j>=vec.len() { return false; }
match (vec[self.i], vec[self.j]) {
(l, ll) if l == ll => false,
(x, _) | (_, x) if x == self.letter => true,
_ => false,
}
}
}
impl Policy
{
#[inline] pub fn into_v2(self) -> PolicyV2
{
PolicyV2
{
letter: self.letter,
i: (*self.rep.start())-1,
j: (*self.rep.end())-1,
}
}
#[inline(always)] pub fn validate_str(&self, s: impl AsRef<str>) -> bool
{
self.validate(s.as_ref().chars())
}
pub fn validate(&self, chars: impl IntoIterator<Item=char>) -> bool
{
let map: Map<char, usize> = {
let chars = chars.into_iter();
let mut mp = Map::new();
for ch in chars
{
let cnt = mp.entry(ch).or_insert(0);
*cnt += 1;
}
mp
};
if let Some(n) = map.get(&self.letter)
{
self.rep.contains(n)
} else {
false
}
}
}
impl fmt::Display for Policy
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}-{} {}", self.rep.start(), self.rep.end(), self.letter)
}
}
impl str::FromStr for Policy
{
type Err = FromStrError;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
let mut first = s.split('-');
let num1 = first.next().ok_or(FromStrError)?;
let (num2, letter) = {
let num2_rest = first.next().ok_or(FromStrError)?;
let mut rest = num2_rest.split(' ');
(rest.next().ok_or(FromStrError)?, rest.next().ok_or(FromStrError)?)
};
Ok(Self{
letter: letter.chars().next().ok_or(FromStrError)?,
rep: (num1.parse()?)..=(num2.parse()?),
})
}
}
#[derive(Debug)]
pub struct FromStrError;
impl From<std::num::ParseIntError> for FromStrError
{
#[inline] fn from(_: std::num::ParseIntError) -> Self
{
Self
}
}
impl error::Error for FromStrError{}
impl fmt::Display for FromStrError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "failed to parse policy rule")
}
}
Loading…
Cancel
Save