Advent of Code solutions in Rust

fix: avoid underflow in vector arithmetic in day 11, 2020

+14 -14
+14 -14
aoc_2020/src/day11.rs
··· 5 5 use itertools::Itertools; 6 6 7 7 pub(crate) struct Door { 8 - seats: HashSet<Vector<usize, 2>>, 8 + seats: HashSet<Vector<isize, 2>>, 9 9 } 10 10 11 11 impl<'input> Solution<'input> for Door { ··· 17 17 line.bytes() 18 18 .enumerate() 19 19 .filter(|&(_, b)| b == b'L') 20 - .map(move |(col, _)| Vector([row, col])) 20 + .map(move |(col, _)| Vector([row as isize, col as isize])) 21 21 }) 22 22 .collect(); 23 23 Door { seats } ··· 34 34 35 35 trait SeatPolicy { 36 36 const THRESHOLD: usize; 37 - fn neighbors(&self, seat: Vector<usize, 2>) -> impl Iterator<Item = Vector<usize, 2>>; 37 + fn neighbors(&self, seat: Vector<isize, 2>) -> impl Iterator<Item = Vector<isize, 2>>; 38 38 } 39 39 40 40 struct DirectNeighborSeatPolicy; ··· 42 42 impl SeatPolicy for DirectNeighborSeatPolicy { 43 43 const THRESHOLD: usize = 4; 44 44 45 - fn neighbors(&self, seat: Vector<usize, 2>) -> impl Iterator<Item = Vector<usize, 2>> { 45 + fn neighbors(&self, seat: Vector<isize, 2>) -> impl Iterator<Item = Vector<isize, 2>> { 46 46 seat.neighbors() 47 47 } 48 48 } 49 49 50 50 struct SightlineSeatPolicy<'s> { 51 - seats: &'s HashSet<Vector<usize, 2>>, 52 - bounds: [RangeInclusive<usize>; 2], 51 + seats: &'s HashSet<Vector<isize, 2>>, 52 + bounds: [RangeInclusive<isize>; 2], 53 53 } 54 54 55 55 impl<'s> SightlineSeatPolicy<'s> { 56 - fn new(seats: &'s HashSet<Vector<usize, 2>>) -> Self { 56 + fn new(seats: &'s HashSet<Vector<isize, 2>>) -> Self { 57 57 Self { 58 58 seats, 59 59 bounds: array::from_fn(|i| 0..=seats.iter().map(|s| s[i]).max().unwrap_or(0)), ··· 64 64 impl SeatPolicy for SightlineSeatPolicy<'_> { 65 65 const THRESHOLD: usize = 5; 66 66 67 - fn neighbors(&self, seat: Vector<usize, 2>) -> impl Iterator<Item = Vector<usize, 2>> { 67 + fn neighbors(&self, seat: Vector<isize, 2>) -> impl Iterator<Item = Vector<isize, 2>> { 68 68 seat.neighbors().filter_map(move |neighbor| { 69 69 let dir = neighbor - seat; 70 70 (1..) ··· 76 76 } 77 77 78 78 fn evolve<P: SeatPolicy>( 79 - occupied: &HashSet<Vector<usize, 2>>, 80 - seats: &HashSet<Vector<usize, 2>>, 79 + occupied: &HashSet<Vector<isize, 2>>, 80 + seats: &HashSet<Vector<isize, 2>>, 81 81 policy: &P, 82 - ) -> HashSet<Vector<usize, 2>> { 82 + ) -> HashSet<Vector<isize, 2>> { 83 83 let empty = seats.difference(occupied); 84 84 empty 85 85 .copied() ··· 95 95 } 96 96 97 97 fn fixed_point_occupancy( 98 - seats: &HashSet<Vector<usize, 2>>, 98 + seats: &HashSet<Vector<isize, 2>>, 99 99 policy: &impl SeatPolicy, 100 - ) -> HashSet<Vector<usize, 2>> { 100 + ) -> HashSet<Vector<isize, 2>> { 101 101 itertools::iterate(HashSet::new(), |prev| evolve(prev, seats, policy)) 102 102 .tuple_windows() 103 103 .find(|(lhs, rhs)| lhs == rhs) ··· 121 121 L.LLLLLL.L 122 122 L.LLLLL.LL"; 123 123 124 - const EXAMPLE_SEATS: [Vector<usize, 2>; 71] = [ 124 + const EXAMPLE_SEATS: [Vector<isize, 2>; 71] = [ 125 125 Vector([0, 0]), 126 126 Vector([0, 2]), 127 127 Vector([0, 3]),