use std::{
fs::File,
io::{BufRead, BufReader},
path::Path,
};
#[derive(Debug)]
struct M {
a: P,
b: P,
p: P,
}
impl M {
fn from_lines(lines: &[String]) -> Self {
let a_line = &lines[0];
let b_line = &lines[1];
let p_line = &lines[2];
Self {
a: P {
x: a_line[&a_line.find("X").unwrap() + 2..a_line.find(",").unwrap()]
.parse()
.unwrap(),
y: a_line[&a_line.find("Y").unwrap() + 2..a_line.len()]
.parse()
.unwrap(),
},
b: P {
x: b_line[&b_line.find("X").unwrap() + 2..b_line.find(",").unwrap()]
.parse()
.unwrap(),
y: b_line[&b_line.find("Y").unwrap() + 2..b_line.len()]
.parse()
.unwrap(),
},
p: P {
x: p_line[&p_line.find("X").unwrap() + 2..p_line.find(",").unwrap()]
.parse()
.unwrap(),
y: p_line[&p_line.find("Y").unwrap() + 2..p_line.len()]
.parse()
.unwrap(),
},
}
}
}
#[derive(Debug)]
struct P {
x: usize,
y: usize,
}
pub fn part_one(input: &Path) -> anyhow::Result<usize> {
let reader = BufReader::new(File::open(input)?);
let machines: Vec<M> = reader
.lines()
.filter_map(|l| {
let l = l.unwrap();
if !l.is_empty() {
Some(l)
} else {
None
}
})
.collect::<Vec<String>>()
.chunks(3)
.map(|l| -> M { M::from_lines(l) })
.collect();
let mut answer = 0;
for machine in machines {
let mut oks: Vec<usize> = vec![];
let (mut x, mut y) = (0, 0);
'a: for a in 1..101 {
x += machine.a.x;
y += machine.a.y;
let (mut x, mut y) = (x, y);
for b in 1..101 {
x += machine.b.x;
y += machine.b.y;
if x == machine.p.x && y == machine.p.y {
oks.push(a * 3 + b);
continue 'a;
}
}
}
if !oks.is_empty() {
oks.sort();
answer += oks.first().unwrap();
}
}
Ok(answer)
}