#![allow(dead_code)] #![allow(unused_variables)] #![allow(unused_mut)] use std::env; use std::fs::File; use std::io::Read; #[derive(Debug)] struct Stone { x: Vec, v: Vec, } fn ints(s: &str) -> Vec { s.to_string() .split(|c: char| !c.is_numeric() && c != '-') .filter_map(|x| x.parse().ok()) .collect() } fn crosses_xy(s1: &Stone, s2: &Stone, coord_min: f64, coord_max: f64) -> bool { // y = y0 + yv * (x - x0) / xv let n1: f64 = s1.x[1] - s1.x[0] * s1.v[1] / s1.v[0]; let k1: f64 = s1.v[1] / s1.v[0]; let n2: f64 = s2.x[1] - s2.x[0] * s2.v[1] / s2.v[0]; let k2: f64 = s2.v[1] / s2.v[0]; if k1 == k2 { return false; } let x = (n2 - n1) / (k1 - k2); let y = x * k1 + n1; let t1 = (x - s1.x[0]) / s1.v[0]; let t2 = (x - s2.x[0]) / s2.v[0]; if (coord_min <= x) && (x <= coord_max) && (coord_min <= y) && (y <= coord_max) && (t1 >= 0.) && (t2 >= 0.) { return true; } false } fn main() { let args: Vec = env::args().collect(); let (filename, testinput) = if args.len() == 1 { ("in/".to_owned() + args[0].split('/').last().unwrap() + ".pzl", false) } else { (args[1].clone(), true) }; let mut f = File::open(filename).expect("cannot open file"); let mut content = String::new(); f.read_to_string(&mut content).expect("cannot read file"); let lines = content.trim_end().split("\n"); let mut ss: Vec = Vec::new(); for line in lines { let (x, v) = line.split_once("@").unwrap(); ss.push(Stone { x: ints(x), v: ints(v), }); } let (coord_min, coord_max) = if testinput { (7.0, 27.0) } else { (200000000000000.0, 400000000000000.) }; let mut cross: Vec = Vec::new(); for i in 0..ss.len() { for j in i..ss.len() { cross.push(crosses_xy(&ss[i], &ss[j], coord_min, coord_max)); } } let res1 = cross.iter().filter(|x| **x).fold(0, |x, _| x + 1); let mut res2 = 0; println!("res1: {}", res1); println!("res2: {}", res2); }