use std::io; use std::io::BufRead; use std::cmp::max; use std::collections::HashSet; fn parse_pt(l: &str) -> ((i32, i32), (i32, i32)) { let i1 = l.find('<').unwrap(); let i2 = l[i1..].find(',').unwrap() + i1; let i3 = l[i2..].find('>').unwrap() + i2; let i4 = l[i3..].find('<').unwrap() + i3; let i5 = l[i4..].find(',').unwrap() + i4; let i6 = l[i5..].find('>').unwrap() + i5; let s1 = &l[i1+1..i2]; let s2 = &l[i2+1..i3]; let s3 = &l[i4+1..i5]; let s4 = &l[i5+1..i6]; ((s1.trim().parse().unwrap(), s2.trim().parse().unwrap()), (s3.trim().parse().unwrap(), s4.trim().parse().unwrap())) } fn dist((x, y): (i32, i32), (u, v): (i32, i32)) -> i32 { return ((u - x) as f32 * (u - x) as f32 + (v - y) as f32 * (v - y) as f32).sqrt() as i32; } pub fn main(reader: T) -> io::Result<(String, String)> { let dots: Vec<((i32, i32), (i32, i32))> = reader.lines().map(|l| l.unwrap()) .map(|l| parse_pt(&l)) .collect(); let mut pts: Vec<_> = dots.iter().map(|&(xy, _)| xy).collect(); let vels: Vec<_> = dots.iter().map(|&(_, v)| v).collect(); let maxvel = vels.iter().map(|&xy| dist(xy, (0, 0)) + 1).max().unwrap(); let mut maxscore = -1; let mut maxat; let mut iter = 0; loop { let mut has_dot: HashSet<(i32, i32)> = HashSet::new(); let mut avg = (0, 0); let mut score = 0; for &xy in &pts { if has_dot.contains(&xy) { score += 1; } else { has_dot.insert(xy); } avg.0 += xy.0; avg.1 += xy.1; } avg.0 /= dots.len() as i32; avg.1 /= dots.len() as i32; let maxdist = pts.iter().map(|&xy| dist(xy, avg)).max().unwrap(); if score > maxscore { maxscore = score; maxat = (iter, pts.clone(), has_dot.clone()); if maxscore > dots.len() as i32 / 2 { break; } } let multiplier = if maxdist > maxvel && maxdist > 100 { max(1, (maxdist - 100) / maxvel) } else { 1 }; // println!("iter={} multiplier={} maxdist={} maxvel={}", iter, multiplier, maxdist, maxvel); for i in 0..dots.len() { pts[i].0 += multiplier * vels[i].0; pts[i].1 += multiplier * vels[i].1; } iter += multiplier; } let mut part1 = String::new(); let part2 = maxat.0.to_string(); let pts = maxat.1; let has_dot = maxat.2; let minx = pts.iter().map(|&(x, _)| x).min().unwrap(); let miny = pts.iter().map(|&(_, y)| y).min().unwrap(); let maxx = pts.iter().map(|&(x, _)| x).max().unwrap(); let maxy = pts.iter().map(|&(_, y)| y).max().unwrap(); for y in miny..maxy+1 { if y != miny { part1 += "\n"; } for x in minx..maxx + 1 { if has_dot.contains(&(x, y)) { part1 += "#"; } else { part1 += "."; } } } Ok((part1, part2)) }