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 = time_toks.iter().skip(2).map(num_extract).collect(); let distances: Vec = 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") } }