1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
//! # [Day 3: Perfectly Spherical Houses in a Vacuum](https://adventofcode.com/2015/day/3)
//!
//! Santa is delivering presents to an infinite two-dimensional grid of houses.
//!
//! He begins by delivering a present to the house at his starting location, and
//! then an elf at the North Pole calls him via radio and tells him where to move
//! next. Moves are always exactly one house to the north (`^`), south (`v`),
//! east (`>`), or west (`<`). After each move, he delivers another present to the
//! house at his new location.
//!
//! However, the elf back at the north pole has had a little too much eggnog, and
//! so his directions are a little off, and Santa ends up visiting some houses more
//! than once. **How many houses receive at least one present?**
//!
//! For example:
//!
//! - `>` delivers presents to `2` houses: one at the starting location, and one
//! to the east.
//! - `^>v<` delivers presents to `4` houses in a square, including twice to the
//! house at his starting/ending location.
//! - `^v^v^v^v^v` delivers a bunch of presents to some very lucky children at
//! only `2` houses.
//!
//! # Part Two
//!
//! The next year, to speed up the process, Santa creates a robot version of himself,
//! Robo-Santa, to deliver presents with him.
//!
//! Santa and Robo-Santa start at the same location (delivering two presents to the same
//! starting house), then take turns moving based on instructions from the elf, who is eggnoggedly
//! reading from the same script as the previous year.
//!
//! **This year, how many houses receive at least one present?**
//!
//! For example:
//!
//! - `^v` delivers presents to `3` houses, because Santa goes north, and then Robo-Santa goes south.
//! - `^>v<` now delivers presents to `3` houses, and Santa and Robo-Santa end up back where
//! they started.
//! - `^v^v^v^v^v` now delivers presents to `11` houses, with Santa going one direction
//! and Robo-Santa going the other.
use itertools::Itertools;
use std::collections::HashMap;
/// Part 1: How many houses receive at least one present?
#[aoc(day3, part1)]
fn part1(input: &str) -> usize {
steps(input).len()
}
/// Part 2: This year, how many houses receive at least one present?
#[aoc(day3, part2)]
fn part2(input: &str) -> usize {
split_merge_steps(input)
}
type Point = (i32, i32);
fn steps(s: &str) -> HashMap<Point, u32> {
let mut history: HashMap<Point, u32> = HashMap::new();
let mut position: Point = (0, 0);
history.insert(position, 1);
for c in s.chars() {
position = match c {
'^' => (position.0, position.1 - 1),
'v' => (position.0, position.1 + 1),
'<' => (position.0 - 1, position.1),
'>' => (position.0 + 1, position.1),
_ => unreachable!(),
};
*history.entry(position).or_insert(0) += 1;
}
history
}
fn split_merge_steps(s: &str) -> usize {
let (even, odd): (String, String) = s.chars().enumerate().partition_map(|(idx, c)| {
if idx % 2 == 0 {
itertools::Either::Left(c)
} else {
itertools::Either::Right(c)
}
});
let mut even = steps(&even);
let odd = steps(&odd);
even.extend(odd.into_iter());
even.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn part1_example() {
/* `>` delivers presents to `2` houses: one at the starting location, and one
to the east. */
assert_eq!(steps(">").len(), 2);
/* `^>v<` delivers presents to `4` houses in a square, including twice to the
house at his starting/ending location. */
assert_eq!(steps("^>v<").len(), 4);
/* `^v^v^v^v^v` delivers a bunch of presents to some very lucky children at
only `2` houses. */
assert_eq!(steps("^v^v^v^v^v").len(), 2);
}
#[test]
fn part2_example() {
// `^v` delivers presents to `3` houses, because Santa goes north, and then Robo-Santa
// goes south.
assert_eq!(split_merge_steps(">"), 2);
// `^>v<` now delivers presents to `3` houses, and Santa and Robo-Santa end up back where
// they started.
assert_eq!(split_merge_steps("^>v<"), 3);
// `^v^v^v^v^v` now delivers presents to `11` houses, with Santa going one direction
// and Robo-Santa going the other.
assert_eq!(split_merge_steps("^v^v^v^v^v"), 11);
}
}