parent
6a3286c7c6
commit
5997e898b1
@ -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…
Reference in new issue