You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.8 KiB
100 lines
2.8 KiB
mod input_tools;
|
|
mod lexer;
|
|
|
|
use lexer::*;
|
|
use input_tools::*;
|
|
|
|
fn quadradic_eq(a: f64, b: f64, c: f64) -> (f64, f64) {
|
|
let term1 = -b / (2.0*a);
|
|
let term2 = b*b - 4.0*a*c;
|
|
let term3 = f64::sqrt(term2) / (2.0*a);
|
|
|
|
let sol1 = term1 - term3;
|
|
let sol2 = term1 + term3;
|
|
|
|
let left = f64::min(sol1, sol2);
|
|
let right = f64::max(sol1, sol2);
|
|
|
|
println!("Quad {}, {}, {} : {} {} {} -> ({}, {})", a, b, c, term1, term2, term3, left, right);
|
|
|
|
(f64::min(sol1, sol2), f64::max(sol1, sol2))
|
|
}
|
|
|
|
fn puzzle1(verbose: bool) {
|
|
println!("Part 1");
|
|
|
|
let mut stdin = simple_stdin();
|
|
let times = stdin.next().unwrap();
|
|
let distances = stdin.next().unwrap();
|
|
|
|
let time_toks = tokenize_line(×);
|
|
let distance_toks = tokenize_line(&distances);
|
|
|
|
let num_extract = |x: &Token| match *x {
|
|
Token::Integer(i) => i as f64,
|
|
_ => panic!("Bad token")
|
|
};
|
|
|
|
let times: Vec<f64> = time_toks.iter().skip(2).map(num_extract).collect();
|
|
let distances: Vec<f64> = distance_toks.iter().skip(2).map(num_extract).collect();
|
|
|
|
let mut win_counts = vec![];
|
|
for idx in 0..times.len() {
|
|
let t = times[idx];
|
|
let d = distances[idx];
|
|
let (left, right) = quadradic_eq(-1.0, t, -d);
|
|
let discrete_left = f64::ceil(left + 0.01) as u32;
|
|
let discrete_right = f64::ceil(right) as u32;
|
|
win_counts.push(discrete_right - discrete_left);
|
|
}
|
|
|
|
|
|
if verbose {
|
|
println!("{:?}", times);
|
|
println!("{:?}", distances);
|
|
println!("{:?}", win_counts);
|
|
}
|
|
|
|
let products = win_counts.iter().fold(1, |acc, x| acc * x);
|
|
println!("Products: {}", products);
|
|
|
|
}
|
|
|
|
fn puzzle2(verbose: bool) {
|
|
println!("Part 2");
|
|
let mut stdin = simple_stdin();
|
|
let times = stdin.next().unwrap();
|
|
let distances = stdin.next().unwrap();
|
|
|
|
let race_time_str: String = times.chars().filter(|c| c.is_digit(10)).collect();
|
|
let distance_str: String = distances.chars().filter(|c| c.is_digit(10)).collect();
|
|
|
|
let race_time = u64::from_str_radix(&race_time_str, 10).unwrap() ;
|
|
let race_distance = u64::from_str_radix(&distance_str, 10).unwrap() as f64;
|
|
|
|
if verbose {
|
|
println!("Time: {}", race_time);
|
|
println!("Distance {}", race_distance);
|
|
}
|
|
|
|
let (left, right) = quadradic_eq(-1.0, race_time as f64, (-race_distance) as f64);
|
|
let discrete_left = f64::ceil(left + 0.01) as u32;
|
|
let discrete_right = f64::ceil(right) as u32;
|
|
|
|
let win_counts = discrete_right - discrete_left;
|
|
|
|
println!("Product: {}", win_counts);
|
|
}
|
|
|
|
fn main() {
|
|
let args = simple_args();
|
|
let verbose = args.get_flag("-v");
|
|
let part = args.get_value("-p", "1");
|
|
|
|
match part.as_str() {
|
|
"1" => puzzle1(verbose),
|
|
"2" => puzzle2(verbose),
|
|
_ => println!("Nothing to do")
|
|
}
|
|
}
|