use std::collections::HashSet; #[allow(dead_code)] pub fn run() { let asteroids: HashSet<(i32, i32)> = std::fs::read_to_string("input/day10.txt") .unwrap() .lines() .enumerate() .map(|(y, line)| { line.chars() .enumerate() .filter(|(_, it)| *it == '#') .map(move |(x, _)| (x as i32, y as i32)) }) .flatten() .collect(); task1(&asteroids); } fn task1(asteroids: &HashSet<(i32, i32)>) { let max = asteroids .iter() .map(|asteroid| { //println!("inspecting {:?}", asteroid); // map to number of other asteroids it sees let mut others = asteroids.clone(); others.remove(&asteroid); // count those asteroids that are not blocked by another let count = others .iter() .filter(|target| { !others .iter() .any(|occluder| blocks_view(*asteroid, **target, *occluder)) }) //.inspect(|target| println!("sees {:?}", target)) .count(); println!("{:?}: {}", asteroid, count); count }) .max() .unwrap(); println!( "Task 1: maximum visible asteroids from another asteroid are {}", max ); //283 too high, 257 too low } fn blocks_view(pov: (i32, i32), target: (i32, i32), occluder: (i32, i32)) -> bool { let ux = occluder.0 - pov.0; let uy = occluder.1 - pov.1; let sx = (target.0 - pov.0) as f32 / ux as f32; let sy = (target.1 - pov.1) as f32 / uy as f32; //dbg!((ux, uy, sx, sy)); match (ux, uy) { (0, _) => sy.abs() > 1.0 && target.0 == pov.0, (_, 0) => sx.abs() > 1.0 && target.1 == pov.1, (_, _) => sx.abs() > 1.0 && sx == sy, } } mod test { #[test] fn block_test() { assert_eq!(true, super::blocks_view((3, 4), (1, 0), (2, 2))); assert_ne!(true, super::blocks_view((3, 4), (2, 2), (1, 0))); assert_ne!(true, super::blocks_view((3, 4), (1, 0), (1, 2))); assert_eq!(true, super::blocks_view((4, 4), (4, 0), (4, 3))); } }