This commit is contained in:
cool-mist 2024-12-17 00:15:53 +05:30
parent 3395b25176
commit 3d46c28bea
3 changed files with 142 additions and 17 deletions

View File

@ -14,7 +14,7 @@ pub fn run() {
right.sort();
let res = left.iter().zip(right.iter()).map(diff).sum::<i32>();
println!("1. {}", res);
println!("1. {}", res); // 1646452
let left = HashSet::<i32>::from_iter(left.into_iter());
let mut acc = 0;
@ -24,7 +24,7 @@ pub fn run() {
}
}
println!("2. {}", acc);
println!("2. {}", acc); // 23609874
}
fn diff((a, b): (&i32, &i32)) -> i32 {

View File

@ -8,14 +8,14 @@ pub fn run() {
.filter_map(|mut line| is_safe(&mut line))
.count();
println!("1. {}", safe); // 510
let safe_corrected = input
.lines()
.map(ExpandedSplitWhitespaceNumbers::new)
.filter_map(|mut line| is_safe_corrected(&mut line))
.count();
println!("1. {}", safe);
println!("2. {}", safe_corrected);
println!("2. {}", safe_corrected); // 553
}
struct SplitWhitespaceNumbers<'a> {

View File

@ -2,16 +2,66 @@ use std::fmt::Display;
pub fn run() {
let input = include_str!("input");
let mut modifier_disabled = DoModifier::disabled();
let result = input
.lines()
.map(|line| parse_instr(line))
.map(|line| parse_instr(line, &mut modifier_disabled))
.map(|products| reduce_products(products))
.sum::<u64>();
println!("1. {}", result);
println!("1. {}", result); // 189600467
let mut modifier_default = DoModifier::default();
let result = input
.lines()
.map(|line| parse_instr(line, &mut modifier_default))
.map(|products| reduce_products(products))
.sum::<u64>();
println!("2. {}", result); // 107069718
}
fn parse_instr(line: &str) -> Vec<u64> {
struct DoModifier {
state: bool,
enabled: bool,
}
impl DoModifier {
fn disabled() -> Self {
DoModifier {
state: true,
enabled: false,
}
}
fn default() -> Self {
DoModifier {
state: true,
enabled: true,
}
}
fn should_mul(&self) -> bool {
if !self.enabled {
true
} else {
self.state
}
}
fn flip(&mut self, instr: Instr) {
if self.enabled {
self.state = match instr {
Instr::Do => true,
Instr::Dont => false,
_ => self.state,
}
}
}
}
fn parse_instr(line: &str, modifier: &mut DoModifier) -> Vec<u64> {
let mut instr = None;
let mut state = ParseState::None;
let mut first_num = Vec::new();
let mut second_num = Vec::new();
@ -19,18 +69,37 @@ fn parse_instr(line: &str) -> Vec<u64> {
for (_i, c) in line.chars().enumerate() {
let next = next_state(&state, c);
if let ParseState::ParamOne = next {
if let ParseState::D = next {
instr = Some(Instr::Do);
} else if let ParseState::T = next {
instr = Some(Instr::Dont);
} else if let ParseState::M = next {
instr = Some(Instr::Mul);
} else if let ParseState::ParamOne = next {
if modifier.should_mul() {
first_num.insert(0, c.to_digit(10).unwrap() as u64);
}
} else if let ParseState::Comma = next {
if modifier.should_mul() {
finalize_number(&mut first_num);
}
} else if let ParseState::ParamTwo = next {
second_num.insert(0, c.to_digit(10).unwrap() as u64);
} else if let ParseState::CloseParen = next {
match instr {
Some(Instr::Mul) => {
if modifier.should_mul() {
finalize_number(&mut second_num);
res.push(first_num[0] * second_num[0]);
}
first_num.clear();
second_num.clear();
}
Some(instr) => modifier.flip(instr),
None => {}
}
instr = None;
}
if let ParseState::CloseParen = next {
state = ParseState::None;
@ -65,8 +134,19 @@ fn reduce_products(products: Vec<u64>) -> u64 {
products.iter().sum()
}
enum Instr {
Do,
Dont,
Mul,
}
enum ParseState {
None,
D,
O,
N,
QUOTE,
T,
M,
U,
L,
@ -79,9 +159,48 @@ enum ParseState {
fn next_state(state: &ParseState, c: char) -> ParseState {
match state {
ParseState::None => {
ParseState::None | ParseState::CloseParen => {
if c == 'm' {
ParseState::M
} else if c == 'd' {
ParseState::D
} else {
ParseState::None
}
}
ParseState::D => {
if c == 'o' {
ParseState::O
} else {
ParseState::None
}
}
ParseState::O => {
if c == '(' {
ParseState::OpenParen
} else if c == 'n' {
ParseState::N
} else {
ParseState::None
}
}
ParseState::N => {
if c == '\'' {
ParseState::QUOTE
} else {
ParseState::None
}
}
ParseState::QUOTE => {
if c == 't' {
ParseState::T
} else {
ParseState::None
}
}
ParseState::T => {
if c == '(' {
ParseState::OpenParen
} else {
ParseState::None
}
@ -110,6 +229,8 @@ fn next_state(state: &ParseState, c: char) -> ParseState {
ParseState::OpenParen => {
if c.is_digit(10) {
ParseState::ParamOne
} else if c == ')' {
ParseState::CloseParen
} else {
ParseState::None
}
@ -139,7 +260,6 @@ fn next_state(state: &ParseState, c: char) -> ParseState {
ParseState::None
}
}
ParseState::CloseParen => ParseState::None,
}
}
@ -155,6 +275,11 @@ impl Display for ParseState {
ParseState::Comma => write!(f, ","),
ParseState::ParamTwo => write!(f, "ParamTwo"),
ParseState::CloseParen => write!(f, ")"),
ParseState::D => write!(f, "D"),
ParseState::O => write!(f, "O"),
ParseState::N => write!(f, "N"),
ParseState::QUOTE => write!(f, "'"),
ParseState::T => write!(f, "T"),
}
}
}