Solutions for 2022, as well as 2015-2018 and 2019 up to day 11
This commit is contained in:
commit
1895197c49
722 changed files with 375457 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
.aocf
|
||||
day00
|
||||
**/target
|
||||
**/Cargo.lock
|
||||
**/dbg.log
|
||||
**/2
|
||||
**/.vimdid
|
8
2015/day01-not_quite_lisp/Cargo.toml
Normal file
8
2015/day01-not_quite_lisp/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day01-not_quite_lisp"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
46
2015/day01-not_quite_lisp/challenge.txt
Normal file
46
2015/day01-not_quite_lisp/challenge.txt
Normal file
|
@ -0,0 +1,46 @@
|
|||
\--- Day 1: Not Quite Lisp ---
|
||||
----------
|
||||
|
||||
Santa was hoping for a white Christmas, but his weather machine's "snow" function is powered by stars, and he's fresh out! To save Christmas, he needs you to collect *fifty stars* by December 25th.
|
||||
|
||||
Collect stars by helping Santa solve puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants *one star*. Good luck!
|
||||
|
||||
Here's an easy puzzle to warm you up.
|
||||
|
||||
Santa is trying to deliver presents in a large apartment building, but he can't find the right floor - the directions he got are a little confusing. He starts on the ground floor (floor `0`) and then follows the instructions one character at a time.
|
||||
|
||||
An opening parenthesis, `(`, means he should go up one floor, and a closing parenthesis, `)`, means he should go down one floor.
|
||||
|
||||
The apartment building is very tall, and the basement is very deep; he will never find the top or bottom floors.
|
||||
|
||||
For example:
|
||||
|
||||
* `(())` and `()()` both result in floor `0`.
|
||||
* `(((` and `(()(()(` both result in floor `3`.
|
||||
* `))(((((` also results in floor `3`.
|
||||
* `())` and `))(` both result in floor `-1` (the first basement level).
|
||||
* `)))` and `)())())` both result in floor `-3`.
|
||||
|
||||
To *what floor* do the instructions take Santa?
|
||||
|
||||
Your puzzle answer was `232`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Now, given the same instructions, find the *position* of the first character that causes him to enter the basement (floor `-1`). The first character in the instructions has position `1`, the second character has position `2`, and so on.
|
||||
|
||||
For example:
|
||||
|
||||
* `)` causes him to enter the basement at character position `1`.
|
||||
* `()())` causes him to enter the basement at character position `5`.
|
||||
|
||||
What is the *position* of the character that causes Santa to first enter the basement?
|
||||
|
||||
Your puzzle answer was `1783`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](1/input).
|
48
2015/day01-not_quite_lisp/src/lib.rs
Normal file
48
2015/day01-not_quite_lisp/src/lib.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
fn char_to_floor(c: char) -> isize {
|
||||
match c {
|
||||
'(' => 1,
|
||||
')' => -1,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn final_floor(input: &str) -> isize {
|
||||
input.chars().map(char_to_floor).sum()
|
||||
}
|
||||
|
||||
pub fn first_basement_pos(input: &str) -> usize {
|
||||
let mut floors = input.chars().scan(0, |curr_floor, c| { *curr_floor += char_to_floor(c);Some(*curr_floor) } );
|
||||
floors.position(|i| i==-1).expect("Never reached Floor -1") + 1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
let expected = [0, 0, 3, 3, 3, -1, -1, -3, -3];
|
||||
for (line_number, line) in sample_input.lines().enumerate() {
|
||||
assert_eq!(final_floor(line), expected[line_number]);
|
||||
}
|
||||
let samples_2 = [")", "()())"];
|
||||
let expected_2 = [1, 5];
|
||||
for (sample_number, sample) in samples_2.iter().enumerate() {
|
||||
assert_eq!(first_basement_pos(sample), expected_2[sample_number]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(final_floor(&challenge_input), 232);
|
||||
assert_eq!(first_basement_pos(&challenge_input), 1783);
|
||||
}
|
||||
}
|
1
2015/day01-not_quite_lisp/tests/challenge_input
Normal file
1
2015/day01-not_quite_lisp/tests/challenge_input
Normal file
File diff suppressed because one or more lines are too long
9
2015/day01-not_quite_lisp/tests/sample_input
Normal file
9
2015/day01-not_quite_lisp/tests/sample_input
Normal file
|
@ -0,0 +1,9 @@
|
|||
(())
|
||||
()()
|
||||
(((
|
||||
(()(()(
|
||||
))(((((
|
||||
())
|
||||
))(
|
||||
)))
|
||||
)())())
|
8
2015/day02-I_was_told_there_would_be_no_math/Cargo.toml
Normal file
8
2015/day02-I_was_told_there_would_be_no_math/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day02-I_was_told_there_would_be_no_math"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
37
2015/day02-I_was_told_there_would_be_no_math/challenge.txt
Normal file
37
2015/day02-I_was_told_there_would_be_no_math/challenge.txt
Normal file
|
@ -0,0 +1,37 @@
|
|||
\--- Day 2: I Was Told There Would Be No Math ---
|
||||
----------
|
||||
|
||||
The elves are running low on wrapping paper, and so they need to submit an order for more. They have a list of the dimensions (length `l`, width `w`, and height `h`) of each present, and only want to order exactly as much as they need.
|
||||
|
||||
Fortunately, every present is a box (a perfect [right rectangular prism](https://en.wikipedia.org/wiki/Cuboid#Rectangular_cuboid)), which makes calculating the required wrapping paper for each gift a little easier: find the surface area of the box, which is `2*l*w + 2*w*h + 2*h*l`. The elves also need a little extra paper for each present: the area of the smallest side.
|
||||
|
||||
For example:
|
||||
|
||||
* A present with dimensions `2x3x4` requires `2*6 + 2*12 + 2*8 = 52` square feet of wrapping paper plus `6` square feet of slack, for a total of `58` square feet.
|
||||
* A present with dimensions `1x1x10` requires `2*1 + 2*10 + 2*10 = 42` square feet of wrapping paper plus `1` square foot of slack, for a total of `43` square feet.
|
||||
|
||||
All numbers in the elves' list are in feet. How many total *square feet of wrapping paper* should they order?
|
||||
|
||||
Your puzzle answer was `1598415`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
The elves are also running low on ribbon. Ribbon is all the same width, so they only have to worry about the length they need to order, which they would again like to be exact.
|
||||
|
||||
The ribbon required to wrap a present is the shortest distance around its sides, or the smallest perimeter of any one face. Each present also requires a bow made out of ribbon as well; the feet of ribbon required for the perfect bow is equal to the cubic feet of volume of the present. Don't ask how they tie the bow, though; they'll never tell.
|
||||
|
||||
For example:
|
||||
|
||||
* A present with dimensions `2x3x4` requires `2+2+3+3 = 10` feet of ribbon to wrap the present plus `2*3*4 = 24` feet of ribbon for the bow, for a total of `34` feet.
|
||||
* A present with dimensions `1x1x10` requires `1+1+1+1 = 4` feet of ribbon to wrap the present plus `1*1*10 = 10` feet of ribbon for the bow, for a total of `14` feet.
|
||||
|
||||
How many total *feet of ribbon* should they order?
|
||||
|
||||
Your puzzle answer was `3812909`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](2/input).
|
55
2015/day02-I_was_told_there_would_be_no_math/src/lib.rs
Normal file
55
2015/day02-I_was_told_there_would_be_no_math/src/lib.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
fn min_2(a: usize, b: usize, c: usize) -> (usize, usize) {
|
||||
match a.cmp(&b) {
|
||||
std::cmp::Ordering::Less => (a, b.min(c)),
|
||||
std::cmp::Ordering::Equal => (a, b.min(c)),
|
||||
std::cmp::Ordering::Greater => (b, a.min(c)),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_dimensions(line: &str) -> (usize, usize, usize) {
|
||||
let sides: Vec<&str> = line.split('x').collect();
|
||||
assert_eq!(sides.len(), 3);
|
||||
(sides[0].parse::<usize>().unwrap(), sides[1].parse::<usize>().unwrap(), sides[2].parse::<usize>().unwrap())
|
||||
}
|
||||
|
||||
fn get_wrapping_paper((l, w, h): (usize, usize, usize)) -> usize {
|
||||
let (short, mid) = min_2(l, w, h);
|
||||
|
||||
2*l*w + 2*w*h + 2*h*l + short*mid
|
||||
}
|
||||
|
||||
fn get_ribbon((l, w, h): (usize, usize, usize)) -> usize {
|
||||
let (short, mid) = min_2(l, w, h);
|
||||
|
||||
2*(short+mid) + l*w*h
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize ) {
|
||||
let dimensions: Vec<_> = input.lines().map(get_dimensions).collect();
|
||||
let first = dimensions.iter().cloned().map(get_wrapping_paper).sum();
|
||||
let second = dimensions.iter().cloned().map(get_ribbon).sum();
|
||||
(first, second)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (101, 48));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (1598415, 3812909));
|
||||
}
|
||||
}
|
1000
2015/day02-I_was_told_there_would_be_no_math/tests/challenge_input
Normal file
1000
2015/day02-I_was_told_there_would_be_no_math/tests/challenge_input
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,2 @@
|
|||
2x3x4
|
||||
1x1x10
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day03-perfectly_spherical_houses_in_a_vacuum"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
|
@ -0,0 +1,39 @@
|
|||
\--- Day 3: Perfectly Spherical Houses in a Vacuum ---
|
||||
----------
|
||||
|
||||
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.
|
||||
|
||||
Your puzzle answer was `2592`.
|
||||
|
||||
\--- 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.
|
||||
|
||||
Your puzzle answer was `2360`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](3/input).
|
55
2015/day03-perfectly_spherical_houses_in_a_vacuum/src/lib.rs
Normal file
55
2015/day03-perfectly_spherical_houses_in_a_vacuum/src/lib.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use std::{fs::read_to_string, collections::HashSet};
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
fn movement((x, y): (isize, isize), direction: char) -> (isize, isize) {
|
||||
match direction {
|
||||
'^' => (x, y-1),
|
||||
'v' => (x, y+1),
|
||||
'<' => (x-1, y),
|
||||
'>' => (x+1, y),
|
||||
_ => (x, y),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let mut first: HashSet<(isize, isize)> = input.chars().scan((0, 0), |curr, c| {
|
||||
*curr = movement(*curr, c);
|
||||
Some(*curr)
|
||||
}).collect();
|
||||
first.insert((0, 0));
|
||||
|
||||
let mut second: HashSet<(isize, isize)> = input.chars().enumerate().scan(((0,0), (0,0)), |(santa, robo), (idx, c)| {
|
||||
match idx % 2 {
|
||||
0 => { *santa = movement(*santa, c); Some(*santa) },
|
||||
1 => { *robo = movement(*robo, c); Some(*robo) },
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}).collect();
|
||||
second.insert((0, 0));
|
||||
|
||||
(first.len(), second.len())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
let sample_input: Vec<&str> = sample_input.lines().collect();
|
||||
let expected = [(2,2), (4,3), (2,11)];
|
||||
for (index, input) in sample_input.iter().enumerate() {
|
||||
assert_eq!(run(input), expected[index]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (2592, 2360));
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,3 @@
|
|||
>
|
||||
^>v<
|
||||
^v^v^v^v^v
|
9
2015/day04-ideal_stocking_suffer/Cargo.toml
Normal file
9
2015/day04-ideal_stocking_suffer/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "day04-ideal_stocking_suffer"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
md-5 = "0.10.5"
|
26
2015/day04-ideal_stocking_suffer/challenge.txt
Normal file
26
2015/day04-ideal_stocking_suffer/challenge.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
\--- Day 4: The Ideal Stocking Stuffer ---
|
||||
----------
|
||||
|
||||
Santa needs help [mining](https://en.wikipedia.org/wiki/Bitcoin#Mining) some AdventCoins (very similar to [bitcoins](https://en.wikipedia.org/wiki/Bitcoin)) to use as gifts for all the economically forward-thinking little girls and boys.
|
||||
|
||||
To do this, he needs to find [MD5](https://en.wikipedia.org/wiki/MD5) hashes which, in [hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal), start with at least *five zeroes*. The input to the MD5 hash is some secret key (your puzzle input, given below) followed by a number in decimal. To mine AdventCoins, you must find Santa the lowest positive number (no leading zeroes: `1`, `2`, `3`, ...) that produces such a hash.
|
||||
|
||||
For example:
|
||||
|
||||
* If your secret key is `abcdef`, the answer is `609043`, because the MD5 hash of `abcdef609043` starts with five zeroes (`000001dbbfa...`), and it is the lowest such number to do so.
|
||||
* If your secret key is `pqrstuv`, the lowest number it combines with to make an MD5 hash starting with five zeroes is `1048970`; that is, the MD5 hash of `pqrstuv1048970` looks like `000006136ef...`.
|
||||
|
||||
Your puzzle answer was `254575`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Now find one that starts with *six zeroes*.
|
||||
|
||||
Your puzzle answer was `1038736`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
Your puzzle input was `bgvyzdsv`.
|
51
2015/day04-ideal_stocking_suffer/src/lib.rs
Normal file
51
2015/day04-ideal_stocking_suffer/src/lib.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
use md5::{Md5, Digest};
|
||||
|
||||
fn hash_has_leading_zeroes(input: &str, counter: usize, zeroes: usize) -> bool {
|
||||
let mut hasher = Md5::new();
|
||||
hasher.update(input.to_owned() + &(counter.to_string())[..]);
|
||||
let hash = hasher.finalize();
|
||||
for i in 0..zeroes/2 {
|
||||
if hash[i] != 0 {
|
||||
return false;
|
||||
}
|
||||
if zeroes % 2 == 1 && hash[zeroes/2] >= 16 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let first = (0..).find(|i| hash_has_leading_zeroes(input, *i, 5)).unwrap();
|
||||
|
||||
let second = (first..).find(|i| hash_has_leading_zeroes(input, *i, 6)).unwrap();
|
||||
|
||||
(first, second)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
let expected = [(609043, 6742839), (1048970, 5714438)];
|
||||
for (idx, input) in sample_input.lines().enumerate() {
|
||||
assert_eq!(run(input), expected[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
for input in challenge_input.lines() {
|
||||
assert_eq!(run(input), (254575, 1038736));
|
||||
}
|
||||
}
|
||||
}
|
1
2015/day04-ideal_stocking_suffer/tests/challenge_input
Normal file
1
2015/day04-ideal_stocking_suffer/tests/challenge_input
Normal file
|
@ -0,0 +1 @@
|
|||
bgvyzdsv
|
2
2015/day04-ideal_stocking_suffer/tests/sample_input
Normal file
2
2015/day04-ideal_stocking_suffer/tests/sample_input
Normal file
|
@ -0,0 +1,2 @@
|
|||
abcdef
|
||||
pqrstuv
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day05-doesnt_he_have_intern-elves_for_this"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
|
@ -0,0 +1,49 @@
|
|||
\--- Day 5: Doesn't He Have Intern-Elves For This? ---
|
||||
----------
|
||||
|
||||
Santa needs help figuring out which strings in his text file are naughty or nice.
|
||||
|
||||
A *nice string* is one with all of the following properties:
|
||||
|
||||
* It contains at least three vowels (`aeiou` only), like `aei`, `xazegov`, or `aeiouaeiouaeiou`.
|
||||
* It contains at least one letter that appears twice in a row, like `xx`, `abcdde` (`dd`), or `aabbccdd` (`aa`, `bb`, `cc`, or `dd`).
|
||||
* It does *not* contain the strings `ab`, `cd`, `pq`, or `xy`, even if they are part of one of the other requirements.
|
||||
|
||||
For example:
|
||||
|
||||
* `ugknbfddgicrmopn` is nice because it has at least three vowels (`u...i...o...`), a double letter (`...dd...`), and none of the disallowed substrings.
|
||||
* `aaa` is nice because it has at least three vowels and a double letter, even though the letters used by different rules overlap.
|
||||
* `jchzalrnumimnmhp` is naughty because it has no double letter.
|
||||
* `haegwjzuvuyypxyu` is naughty because it contains the string `xy`.
|
||||
* `dvszwmarrgswjxmb` is naughty because it contains only one vowel.
|
||||
|
||||
How many strings are nice?
|
||||
|
||||
Your puzzle answer was `255`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Realizing the error of his ways, Santa has switched to a better model of determining whether a string is naughty or nice. None of the old rules apply, as they are all clearly ridiculous.
|
||||
|
||||
Now, a nice string is one with all of the following properties:
|
||||
|
||||
* It contains a pair of any two letters that appears at least twice in the string without overlapping, like `xyxy` (`xy`) or `aabcdefgaa` (`aa`), but not like `aaa` (`aa`, but it overlaps).
|
||||
* It contains at least one letter which repeats with exactly one letter between them, like `xyx`, `abcdefeghi` (`efe`), or even `aaa`.
|
||||
|
||||
For example:
|
||||
|
||||
* `qjhvhtzxzqqjkmpb` is nice because is has a pair that appears twice (`qj`) and a letter that repeats with exactly one letter between them (`zxz`).
|
||||
* `xxyxx` is nice because it has a pair that appears twice and a letter that repeats with one between, even though the letters used by each rule overlap.
|
||||
* `uurcxstgmygtbstg` is naughty because it has a pair (`tg`) but no repeat with a single letter between them.
|
||||
* `ieodomkazucvgmuy` is naughty because it has a repeating letter with one between (`odo`), but no pair that appears twice.
|
||||
|
||||
How many strings are nice under these new rules?
|
||||
|
||||
Your puzzle answer was `55`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](5/input).
|
65
2015/day05-doesnt_he_have_intern-elves_for_this/src/lib.rs
Normal file
65
2015/day05-doesnt_he_have_intern-elves_for_this/src/lib.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
fn is_vowel(c: char) -> bool {
|
||||
['a', 'e', 'i', 'o', 'u'].contains(&c)
|
||||
}
|
||||
|
||||
fn is_nice_v2(line: &str) -> bool {
|
||||
let mut pair = false;
|
||||
for j in 0..line.len()-3 {
|
||||
let this_pair = &line[j..=j+1];
|
||||
if line[j+2..].contains(this_pair) {
|
||||
pair = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let mut repeat = false;
|
||||
for i in 0..line.len()-2 {
|
||||
if line.chars().nth(i) == line.chars().nth(i+2) {
|
||||
repeat = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pair && repeat
|
||||
}
|
||||
|
||||
fn is_nice_v1(line: &str) -> bool {
|
||||
let mut repeat = false;
|
||||
for i in 0..line.len()-1 {
|
||||
if line.chars().nth(i) == line.chars().nth(i+1) {
|
||||
repeat = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
line.chars().filter(|c| is_vowel(*c)).count() > 2 &&
|
||||
repeat &&
|
||||
!line.contains("ab") && !line.contains("cd") && !line.contains("pq") && !line.contains("xy")
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let first = input.lines().filter(|l| is_nice_v1(l)).count();
|
||||
let second = input.lines().filter(|l| is_nice_v2(l)).count();
|
||||
(first, second)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (2, 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (255, 55));
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,9 @@
|
|||
ugknbfddgicrmopn
|
||||
aaa
|
||||
jchzalrnumimnmhp
|
||||
haegwjzuvuyypxyu
|
||||
dvszwmarrgswjxmb
|
||||
qjhvhtzxzqqjkmpb
|
||||
xxyxx
|
||||
uurcxstgmygtbstg
|
||||
ieodomkazucvgmuy
|
8
2015/day06-probably_a_fire_hazard/Cargo.toml
Normal file
8
2015/day06-probably_a_fire_hazard/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day06-probably_a_fire_hazard"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
48
2015/day06-probably_a_fire_hazard/challenge.txt
Normal file
48
2015/day06-probably_a_fire_hazard/challenge.txt
Normal file
|
@ -0,0 +1,48 @@
|
|||
\--- Day 6: Probably a Fire Hazard ---
|
||||
----------
|
||||
|
||||
Because your neighbors keep defeating you in the holiday house decorating contest year after year, you've decided to deploy one million lights in a 1000x1000 grid.
|
||||
|
||||
Furthermore, because you've been especially nice this year, Santa has mailed you instructions on how to display the ideal lighting configuration.
|
||||
|
||||
Lights in your grid are numbered from 0 to 999 in each direction; the lights at each corner are at `0,0`, `0,999`, `999,999`, and `999,0`. The instructions include whether to `turn on`, `turn off`, or `toggle` various inclusive ranges given as coordinate pairs. Each coordinate pair represents opposite corners of a rectangle, inclusive; a coordinate pair like `0,0 through 2,2` therefore refers to 9 lights in a 3x3 square. The lights all start turned off.
|
||||
|
||||
To defeat your neighbors this year, all you have to do is set up your lights by doing the instructions Santa sent you in order.
|
||||
|
||||
For example:
|
||||
|
||||
* `turn on 0,0 through 999,999` would turn on (or leave on) every light.
|
||||
* `toggle 0,0 through 999,0` would toggle the first line of 1000 lights, turning off the ones that were on, and turning on the ones that were off.
|
||||
* `turn off 499,499 through 500,500` would turn off (or leave off) the middle four lights.
|
||||
|
||||
After following the instructions, *how many lights are lit*?
|
||||
|
||||
Your puzzle answer was `543903`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
You just finish implementing your winning light pattern when you realize you mistranslated Santa's message from Ancient Nordic Elvish.
|
||||
|
||||
The light grid you bought actually has individual brightness controls; each light can have a brightness of zero or more. The lights all start at zero.
|
||||
|
||||
The phrase `turn on` actually means that you should increase the brightness of those lights by `1`.
|
||||
|
||||
The phrase `turn off` actually means that you should decrease the brightness of those lights by `1`, to a minimum of zero.
|
||||
|
||||
The phrase `toggle` actually means that you should increase the brightness of those lights by `2`.
|
||||
|
||||
What is the *total brightness* of all lights combined after following Santa's instructions?
|
||||
|
||||
For example:
|
||||
|
||||
* `turn on 0,0 through 0,0` would increase the total brightness by `1`.
|
||||
* `toggle 0,0 through 999,999` would increase the total brightness by `2000000`.
|
||||
|
||||
Your puzzle answer was `14687245`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](6/input).
|
BIN
2015/day06-probably_a_fire_hazard/day06_probably_a_fi.core
Normal file
BIN
2015/day06-probably_a_fire_hazard/day06_probably_a_fi.core
Normal file
Binary file not shown.
78
2015/day06-probably_a_fire_hazard/src/lib.rs
Normal file
78
2015/day06-probably_a_fire_hazard/src/lib.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use std::fs::read_to_string;
|
||||
|
||||
enum Command { On, Off, Toggle }
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
fn perform(instruction: &str, target: &mut [Vec<u32>], op_mode: u8) {
|
||||
let components: Vec<&str> = instruction.split(' ').collect();
|
||||
let (command, tl, br) = match components.len() {
|
||||
4 => (Command::Toggle, components[1], components[3]),
|
||||
5 if components[1] == "on" => (Command::On, components[2], components[4]),
|
||||
5 if components[1] == "off" => (Command::Off, components[2], components[4]),
|
||||
_ => panic!("Unable to parse {instruction}"),
|
||||
};
|
||||
|
||||
let (x_min, y_min) = tl.split_once(',').unwrap();
|
||||
let (x_max, y_max) = br.split_once(',').unwrap();
|
||||
let x_min = x_min.parse::<usize>().unwrap();
|
||||
let x_max = x_max.parse::<usize>().unwrap();
|
||||
let y_min = y_min.parse::<usize>().unwrap();
|
||||
let y_max = y_max.parse::<usize>().unwrap();
|
||||
|
||||
target.iter_mut()
|
||||
.take(x_max+1)
|
||||
.skip(x_min)
|
||||
.for_each(|row| { row.iter_mut()
|
||||
.take(y_max+1)
|
||||
.skip(y_min)
|
||||
.for_each(|cell| {
|
||||
let old_val = *cell;
|
||||
if op_mode == 1 {
|
||||
*cell = match command {
|
||||
Command::On => 1,
|
||||
Command::Off => 0,
|
||||
Command::Toggle => 1-old_val,
|
||||
};
|
||||
} else {
|
||||
*cell = match command {
|
||||
Command::On => old_val + 1,
|
||||
Command::Off => old_val.saturating_sub(1),
|
||||
Command::Toggle => old_val + 2,
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (u32, u32) {
|
||||
let mut lights_1 = vec![vec![0_u32; 1000]; 1000];
|
||||
let mut lights_2 = vec![vec![0_u32; 1000]; 1000];
|
||||
for instruction in input.lines() {
|
||||
perform(instruction, &mut lights_1, 1);
|
||||
perform(instruction, &mut lights_2, 2);
|
||||
}
|
||||
|
||||
let first = lights_1.iter().flatten().sum();
|
||||
let second = lights_2.iter().flatten().sum();
|
||||
(first, second)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (998996, 1_001_996));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (543903, 14687245));
|
||||
}
|
||||
}
|
300
2015/day06-probably_a_fire_hazard/tests/challenge_input
Normal file
300
2015/day06-probably_a_fire_hazard/tests/challenge_input
Normal file
|
@ -0,0 +1,300 @@
|
|||
toggle 461,550 through 564,900
|
||||
turn off 370,39 through 425,839
|
||||
turn off 464,858 through 833,915
|
||||
turn off 812,389 through 865,874
|
||||
turn on 599,989 through 806,993
|
||||
turn on 376,415 through 768,548
|
||||
turn on 606,361 through 892,600
|
||||
turn off 448,208 through 645,684
|
||||
toggle 50,472 through 452,788
|
||||
toggle 205,417 through 703,826
|
||||
toggle 533,331 through 906,873
|
||||
toggle 857,493 through 989,970
|
||||
turn off 631,950 through 894,975
|
||||
turn off 387,19 through 720,700
|
||||
turn off 511,843 through 581,945
|
||||
toggle 514,557 through 662,883
|
||||
turn off 269,809 through 876,847
|
||||
turn off 149,517 through 716,777
|
||||
turn off 994,939 through 998,988
|
||||
toggle 467,662 through 555,957
|
||||
turn on 952,417 through 954,845
|
||||
turn on 565,226 through 944,880
|
||||
turn on 214,319 through 805,722
|
||||
toggle 532,276 through 636,847
|
||||
toggle 619,80 through 689,507
|
||||
turn on 390,706 through 884,722
|
||||
toggle 17,634 through 537,766
|
||||
toggle 706,440 through 834,441
|
||||
toggle 318,207 through 499,530
|
||||
toggle 698,185 through 830,343
|
||||
toggle 566,679 through 744,716
|
||||
toggle 347,482 through 959,482
|
||||
toggle 39,799 through 981,872
|
||||
turn on 583,543 through 846,710
|
||||
turn off 367,664 through 595,872
|
||||
turn on 805,439 through 964,995
|
||||
toggle 209,584 through 513,802
|
||||
turn off 106,497 through 266,770
|
||||
turn on 975,2 through 984,623
|
||||
turn off 316,684 through 369,876
|
||||
turn off 30,309 through 259,554
|
||||
turn off 399,680 through 861,942
|
||||
toggle 227,740 through 850,829
|
||||
turn on 386,603 through 552,879
|
||||
turn off 703,795 through 791,963
|
||||
turn off 573,803 through 996,878
|
||||
turn off 993,939 through 997,951
|
||||
turn on 809,221 through 869,723
|
||||
turn off 38,720 through 682,751
|
||||
turn off 318,732 through 720,976
|
||||
toggle 88,459 through 392,654
|
||||
turn off 865,654 through 911,956
|
||||
toggle 264,284 through 857,956
|
||||
turn off 281,776 through 610,797
|
||||
toggle 492,660 through 647,910
|
||||
turn off 879,703 through 925,981
|
||||
turn off 772,414 through 974,518
|
||||
turn on 694,41 through 755,96
|
||||
turn on 452,406 through 885,881
|
||||
turn off 107,905 through 497,910
|
||||
turn off 647,222 through 910,532
|
||||
turn on 679,40 through 845,358
|
||||
turn off 144,205 through 556,362
|
||||
turn on 871,804 through 962,878
|
||||
turn on 545,676 through 545,929
|
||||
turn off 316,716 through 413,941
|
||||
toggle 488,826 through 755,971
|
||||
toggle 957,832 through 976,992
|
||||
toggle 857,770 through 905,964
|
||||
toggle 319,198 through 787,673
|
||||
turn on 832,813 through 863,844
|
||||
turn on 818,296 through 818,681
|
||||
turn on 71,699 through 91,960
|
||||
turn off 838,578 through 967,928
|
||||
toggle 440,856 through 507,942
|
||||
toggle 121,970 through 151,974
|
||||
toggle 391,192 through 659,751
|
||||
turn on 78,210 through 681,419
|
||||
turn on 324,591 through 593,939
|
||||
toggle 159,366 through 249,760
|
||||
turn off 617,167 through 954,601
|
||||
toggle 484,607 through 733,657
|
||||
turn on 587,96 through 888,819
|
||||
turn off 680,984 through 941,991
|
||||
turn on 800,512 through 968,691
|
||||
turn off 123,588 through 853,603
|
||||
turn on 1,862 through 507,912
|
||||
turn on 699,839 through 973,878
|
||||
turn off 848,89 through 887,893
|
||||
toggle 344,353 through 462,403
|
||||
turn on 780,731 through 841,760
|
||||
toggle 693,973 through 847,984
|
||||
toggle 989,936 through 996,958
|
||||
toggle 168,475 through 206,963
|
||||
turn on 742,683 through 769,845
|
||||
toggle 768,116 through 987,396
|
||||
turn on 190,364 through 617,526
|
||||
turn off 470,266 through 530,839
|
||||
toggle 122,497 through 969,645
|
||||
turn off 492,432 through 827,790
|
||||
turn on 505,636 through 957,820
|
||||
turn on 295,476 through 698,958
|
||||
toggle 63,298 through 202,396
|
||||
turn on 157,315 through 412,939
|
||||
turn off 69,789 through 134,837
|
||||
turn off 678,335 through 896,541
|
||||
toggle 140,516 through 842,668
|
||||
turn off 697,585 through 712,668
|
||||
toggle 507,832 through 578,949
|
||||
turn on 678,279 through 886,621
|
||||
toggle 449,744 through 826,910
|
||||
turn off 835,354 through 921,741
|
||||
toggle 924,878 through 985,952
|
||||
turn on 666,503 through 922,905
|
||||
turn on 947,453 through 961,587
|
||||
toggle 525,190 through 795,654
|
||||
turn off 62,320 through 896,362
|
||||
turn on 21,458 through 972,536
|
||||
turn on 446,429 through 821,970
|
||||
toggle 376,423 through 805,455
|
||||
toggle 494,896 through 715,937
|
||||
turn on 583,270 through 667,482
|
||||
turn off 183,468 through 280,548
|
||||
toggle 623,289 through 750,524
|
||||
turn on 836,706 through 967,768
|
||||
turn on 419,569 through 912,908
|
||||
turn on 428,260 through 660,433
|
||||
turn off 683,627 through 916,816
|
||||
turn on 447,973 through 866,980
|
||||
turn on 688,607 through 938,990
|
||||
turn on 245,187 through 597,405
|
||||
turn off 558,843 through 841,942
|
||||
turn off 325,666 through 713,834
|
||||
toggle 672,606 through 814,935
|
||||
turn off 161,812 through 490,954
|
||||
turn on 950,362 through 985,898
|
||||
turn on 143,22 through 205,821
|
||||
turn on 89,762 through 607,790
|
||||
toggle 234,245 through 827,303
|
||||
turn on 65,599 through 764,997
|
||||
turn on 232,466 through 965,695
|
||||
turn on 739,122 through 975,590
|
||||
turn off 206,112 through 940,558
|
||||
toggle 690,365 through 988,552
|
||||
turn on 907,438 through 977,691
|
||||
turn off 838,809 through 944,869
|
||||
turn on 222,12 through 541,832
|
||||
toggle 337,66 through 669,812
|
||||
turn on 732,821 through 897,912
|
||||
toggle 182,862 through 638,996
|
||||
turn on 955,808 through 983,847
|
||||
toggle 346,227 through 841,696
|
||||
turn on 983,270 through 989,756
|
||||
turn off 874,849 through 876,905
|
||||
turn off 7,760 through 678,795
|
||||
toggle 973,977 through 995,983
|
||||
turn off 911,961 through 914,976
|
||||
turn on 913,557 through 952,722
|
||||
turn off 607,933 through 939,999
|
||||
turn on 226,604 through 517,622
|
||||
turn off 3,564 through 344,842
|
||||
toggle 340,578 through 428,610
|
||||
turn on 248,916 through 687,925
|
||||
toggle 650,185 through 955,965
|
||||
toggle 831,359 through 933,536
|
||||
turn off 544,614 through 896,953
|
||||
toggle 648,939 through 975,997
|
||||
turn on 464,269 through 710,521
|
||||
turn off 643,149 through 791,320
|
||||
turn off 875,549 through 972,643
|
||||
turn off 953,969 through 971,972
|
||||
turn off 236,474 through 772,591
|
||||
toggle 313,212 through 489,723
|
||||
toggle 896,829 through 897,837
|
||||
toggle 544,449 through 995,905
|
||||
turn off 278,645 through 977,876
|
||||
turn off 887,947 through 946,977
|
||||
turn on 342,861 through 725,935
|
||||
turn on 636,316 through 692,513
|
||||
toggle 857,470 through 950,528
|
||||
turn off 736,196 through 826,889
|
||||
turn on 17,878 through 850,987
|
||||
turn on 142,968 through 169,987
|
||||
turn on 46,470 through 912,853
|
||||
turn on 182,252 through 279,941
|
||||
toggle 261,143 through 969,657
|
||||
turn off 69,600 through 518,710
|
||||
turn on 372,379 through 779,386
|
||||
toggle 867,391 through 911,601
|
||||
turn off 174,287 through 900,536
|
||||
toggle 951,842 through 993,963
|
||||
turn off 626,733 through 985,827
|
||||
toggle 622,70 through 666,291
|
||||
turn off 980,671 through 985,835
|
||||
turn off 477,63 through 910,72
|
||||
turn off 779,39 through 940,142
|
||||
turn on 986,570 through 997,638
|
||||
toggle 842,805 through 943,985
|
||||
turn off 890,886 through 976,927
|
||||
turn off 893,172 through 897,619
|
||||
turn off 198,780 through 835,826
|
||||
toggle 202,209 through 219,291
|
||||
turn off 193,52 through 833,283
|
||||
toggle 414,427 through 987,972
|
||||
turn on 375,231 through 668,236
|
||||
turn off 646,598 through 869,663
|
||||
toggle 271,462 through 414,650
|
||||
turn off 679,121 through 845,467
|
||||
toggle 76,847 through 504,904
|
||||
turn off 15,617 through 509,810
|
||||
toggle 248,105 through 312,451
|
||||
turn off 126,546 through 922,879
|
||||
turn on 531,831 through 903,872
|
||||
toggle 602,431 through 892,792
|
||||
turn off 795,223 through 892,623
|
||||
toggle 167,721 through 533,929
|
||||
toggle 813,251 through 998,484
|
||||
toggle 64,640 through 752,942
|
||||
turn on 155,955 through 892,985
|
||||
turn on 251,329 through 996,497
|
||||
turn off 341,716 through 462,994
|
||||
toggle 760,127 through 829,189
|
||||
turn on 86,413 through 408,518
|
||||
toggle 340,102 through 918,558
|
||||
turn off 441,642 through 751,889
|
||||
turn on 785,292 through 845,325
|
||||
turn off 123,389 through 725,828
|
||||
turn on 905,73 through 983,270
|
||||
turn off 807,86 through 879,276
|
||||
toggle 500,866 through 864,916
|
||||
turn on 809,366 through 828,534
|
||||
toggle 219,356 through 720,617
|
||||
turn off 320,964 through 769,990
|
||||
turn off 903,167 through 936,631
|
||||
toggle 300,137 through 333,693
|
||||
toggle 5,675 through 755,848
|
||||
turn off 852,235 through 946,783
|
||||
toggle 355,556 through 941,664
|
||||
turn on 810,830 through 867,891
|
||||
turn off 509,869 through 667,903
|
||||
toggle 769,400 through 873,892
|
||||
turn on 553,614 through 810,729
|
||||
turn on 179,873 through 589,962
|
||||
turn off 466,866 through 768,926
|
||||
toggle 143,943 through 465,984
|
||||
toggle 182,380 through 569,552
|
||||
turn off 735,808 through 917,910
|
||||
turn on 731,802 through 910,847
|
||||
turn off 522,74 through 731,485
|
||||
turn on 444,127 through 566,996
|
||||
turn off 232,962 through 893,979
|
||||
turn off 231,492 through 790,976
|
||||
turn on 874,567 through 943,684
|
||||
toggle 911,840 through 990,932
|
||||
toggle 547,895 through 667,935
|
||||
turn off 93,294 through 648,636
|
||||
turn off 190,902 through 532,970
|
||||
turn off 451,530 through 704,613
|
||||
toggle 936,774 through 937,775
|
||||
turn off 116,843 through 533,934
|
||||
turn on 950,906 through 986,993
|
||||
turn on 910,51 through 945,989
|
||||
turn on 986,498 through 994,945
|
||||
turn off 125,324 through 433,704
|
||||
turn off 60,313 through 75,728
|
||||
turn on 899,494 through 940,947
|
||||
toggle 832,316 through 971,817
|
||||
toggle 994,983 through 998,984
|
||||
toggle 23,353 through 917,845
|
||||
toggle 174,799 through 658,859
|
||||
turn off 490,878 through 534,887
|
||||
turn off 623,963 through 917,975
|
||||
toggle 721,333 through 816,975
|
||||
toggle 589,687 through 890,921
|
||||
turn on 936,388 through 948,560
|
||||
turn off 485,17 through 655,610
|
||||
turn on 435,158 through 689,495
|
||||
turn on 192,934 through 734,936
|
||||
turn off 299,723 through 622,847
|
||||
toggle 484,160 through 812,942
|
||||
turn off 245,754 through 818,851
|
||||
turn on 298,419 through 824,634
|
||||
toggle 868,687 through 969,760
|
||||
toggle 131,250 through 685,426
|
||||
turn off 201,954 through 997,983
|
||||
turn on 353,910 through 832,961
|
||||
turn off 518,781 through 645,875
|
||||
turn off 866,97 through 924,784
|
||||
toggle 836,599 through 857,767
|
||||
turn on 80,957 through 776,968
|
||||
toggle 277,130 through 513,244
|
||||
turn off 62,266 through 854,434
|
||||
turn on 792,764 through 872,842
|
||||
turn off 160,949 through 273,989
|
||||
turn off 664,203 through 694,754
|
||||
toggle 491,615 through 998,836
|
||||
turn off 210,146 through 221,482
|
||||
turn off 209,780 through 572,894
|
||||
turn on 766,112 through 792,868
|
||||
turn on 222,12 through 856,241
|
3
2015/day06-probably_a_fire_hazard/tests/sample_input
Normal file
3
2015/day06-probably_a_fire_hazard/tests/sample_input
Normal file
|
@ -0,0 +1,3 @@
|
|||
turn on 0,0 through 999,999
|
||||
toggle 0,0 through 999,0
|
||||
turn off 499,499 through 500,500
|
8
2015/day07-some_assembly_required/Cargo.toml
Normal file
8
2015/day07-some_assembly_required/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day07-some_assembly_required"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
62
2015/day07-some_assembly_required/challenge.txt
Normal file
62
2015/day07-some_assembly_required/challenge.txt
Normal file
|
@ -0,0 +1,62 @@
|
|||
\--- Day 7: Some Assembly Required ---
|
||||
----------
|
||||
|
||||
This year, Santa brought little Bobby Tables a set of wires and [bitwise logic gates](https://en.wikipedia.org/wiki/Bitwise_operation)! Unfortunately, little Bobby is a little under the recommended age range, and he needs help assembling the circuit.
|
||||
|
||||
Each wire has an identifier (some lowercase letters) and can carry a [16-bit](https://en.wikipedia.org/wiki/16-bit) signal (a number from `0` to `65535`). A signal is provided to each wire by a gate, another wire, or some specific value. Each wire can only get a signal from one source, but can provide its signal to multiple destinations. A gate provides no signal until all of its inputs have a signal.
|
||||
|
||||
The included instructions booklet describes how to connect the parts together: `x AND y -> z` means to connect wires `x` and `y` to an AND gate, and then connect its output to wire `z`.
|
||||
|
||||
For example:
|
||||
|
||||
* `123 -> x` means that the signal `123` is provided to wire `x`.
|
||||
* `x AND y -> z` means that the [bitwise AND](https://en.wikipedia.org/wiki/Bitwise_operation#AND) of wire `x` and wire `y` is provided to wire `z`.
|
||||
* `p LSHIFT 2 -> q` means that the value from wire `p` is [left-shifted](https://en.wikipedia.org/wiki/Logical_shift) by `2` and then provided to wire `q`.
|
||||
* `NOT e -> f` means that the [bitwise complement](https://en.wikipedia.org/wiki/Bitwise_operation#NOT) of the value from wire `e` is provided to wire `f`.
|
||||
|
||||
Other possible gates include `OR` ([bitwise OR](https://en.wikipedia.org/wiki/Bitwise_operation#OR)) and `RSHIFT` ([right-shift](https://en.wikipedia.org/wiki/Logical_shift)). If, for some reason, you'd like to *emulate* the circuit instead, almost all programming languages (for example, [C](https://en.wikipedia.org/wiki/Bitwise_operations_in_C), [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators), or [Python](https://wiki.python.org/moin/BitwiseOperators)) provide operators for these gates.
|
||||
|
||||
For example, here is a simple circuit:
|
||||
|
||||
```
|
||||
123 -> x
|
||||
456 -> y
|
||||
x AND y -> d
|
||||
x OR y -> e
|
||||
x LSHIFT 2 -> f
|
||||
y RSHIFT 2 -> g
|
||||
NOT x -> h
|
||||
NOT y -> i
|
||||
|
||||
```
|
||||
|
||||
After it is run, these are the signals on the wires:
|
||||
|
||||
```
|
||||
d: 72
|
||||
e: 507
|
||||
f: 492
|
||||
g: 114
|
||||
h: 65412
|
||||
i: 65079
|
||||
x: 123
|
||||
y: 456
|
||||
|
||||
```
|
||||
|
||||
In little Bobby's kit's instructions booklet (provided as your puzzle input), what signal is ultimately provided to *wire `a`*?
|
||||
|
||||
Your puzzle answer was `46065`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Now, take the signal you got on wire `a`, override wire `b` to that signal, and reset the other wires (including wire `a`). What new signal is ultimately provided to wire `a`?
|
||||
|
||||
Your puzzle answer was `14134`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](7/input).
|
87
2015/day07-some_assembly_required/src/lib.rs
Normal file
87
2015/day07-some_assembly_required/src/lib.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Instruction {
|
||||
And(String, String),
|
||||
Or(String, String),
|
||||
Not(String),
|
||||
Lshift(String, u8),
|
||||
Rshift(String, u8),
|
||||
Equal(String),
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
fn parse(line: &str) -> (String, Instruction) {
|
||||
let components: Vec<&str> = line.split(' ').collect();
|
||||
match components[1] {
|
||||
"->" => (components[2].to_string(), Instruction::Equal(components[0].to_string())),
|
||||
"AND" => (components[4].to_string(), Instruction::And(components[0].to_string(), components[2].to_string())),
|
||||
"OR" => (components[4].to_string(), Instruction::Or(components[0].to_string(), components[2].to_string())),
|
||||
"LSHIFT" => (components[4].to_string(), Instruction::Lshift(components[0].to_string(), components[2].parse().unwrap())),
|
||||
"RSHIFT" => (components[4].to_string(), Instruction::Rshift(components[0].to_string(), components[2].parse().unwrap())),
|
||||
_ => (components[3].to_string(), Instruction::Not(components[1].to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_for(wire: String, circuit: &mut HashMap<String, Instruction>) -> u16 {
|
||||
if let Ok(num) = wire.parse::<u16>() {
|
||||
return num;
|
||||
}
|
||||
let instruction = Instruction::clone(circuit.get(&wire).unwrap_or_else(|| panic!("Wire not found: {wire}")));
|
||||
let result = match instruction {
|
||||
Instruction::Equal(val) => eval_for(val, circuit),
|
||||
Instruction::Not(val) => !(eval_for(val, circuit)),
|
||||
Instruction::And(l, r) => (eval_for(l, circuit)) & (eval_for(r, circuit)),
|
||||
Instruction::Or(l, r) => (eval_for(l, circuit)) | (eval_for(r, circuit)),
|
||||
Instruction::Lshift(val, bits) => eval_for(val, circuit) << bits,
|
||||
Instruction::Rshift(val, bits) => eval_for(val, circuit) >> bits,
|
||||
};
|
||||
circuit.insert(wire, Instruction::Equal(result.to_string()));
|
||||
result
|
||||
}
|
||||
|
||||
pub fn assemble(input: &str) -> HashMap<String, Instruction> {
|
||||
input.lines()
|
||||
.map(Instruction::parse)
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
let mut circuit = assemble(&sample_input);
|
||||
let expected = [
|
||||
("d", 72),
|
||||
("e", 507),
|
||||
("f", 492),
|
||||
("g", 114),
|
||||
("h", 65412),
|
||||
("i", 65079),
|
||||
("x", 123),
|
||||
("y", 456),
|
||||
];
|
||||
for (wire, output) in expected {
|
||||
assert_eq!(eval_for(wire.to_string(), &mut circuit), output);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
let mut circuit = assemble(&challenge_input);
|
||||
let first_a = eval_for(String::from("a"), &mut circuit.clone());
|
||||
assert_eq!(first_a, 46065);
|
||||
circuit.insert(String::from("b"), Instruction::Equal(first_a.to_string()));
|
||||
assert_eq!(eval_for(String::from("a"), &mut circuit), 14134);
|
||||
}
|
||||
}
|
339
2015/day07-some_assembly_required/tests/challenge_input
Normal file
339
2015/day07-some_assembly_required/tests/challenge_input
Normal file
|
@ -0,0 +1,339 @@
|
|||
bn RSHIFT 2 -> bo
|
||||
lf RSHIFT 1 -> ly
|
||||
fo RSHIFT 3 -> fq
|
||||
cj OR cp -> cq
|
||||
fo OR fz -> ga
|
||||
t OR s -> u
|
||||
lx -> a
|
||||
NOT ax -> ay
|
||||
he RSHIFT 2 -> hf
|
||||
lf OR lq -> lr
|
||||
lr AND lt -> lu
|
||||
dy OR ej -> ek
|
||||
1 AND cx -> cy
|
||||
hb LSHIFT 1 -> hv
|
||||
1 AND bh -> bi
|
||||
ih AND ij -> ik
|
||||
c LSHIFT 1 -> t
|
||||
ea AND eb -> ed
|
||||
km OR kn -> ko
|
||||
NOT bw -> bx
|
||||
ci OR ct -> cu
|
||||
NOT p -> q
|
||||
lw OR lv -> lx
|
||||
NOT lo -> lp
|
||||
fp OR fv -> fw
|
||||
o AND q -> r
|
||||
dh AND dj -> dk
|
||||
ap LSHIFT 1 -> bj
|
||||
bk LSHIFT 1 -> ce
|
||||
NOT ii -> ij
|
||||
gh OR gi -> gj
|
||||
kk RSHIFT 1 -> ld
|
||||
lc LSHIFT 1 -> lw
|
||||
lb OR la -> lc
|
||||
1 AND am -> an
|
||||
gn AND gp -> gq
|
||||
lf RSHIFT 3 -> lh
|
||||
e OR f -> g
|
||||
lg AND lm -> lo
|
||||
ci RSHIFT 1 -> db
|
||||
cf LSHIFT 1 -> cz
|
||||
bn RSHIFT 1 -> cg
|
||||
et AND fe -> fg
|
||||
is OR it -> iu
|
||||
kw AND ky -> kz
|
||||
ck AND cl -> cn
|
||||
bj OR bi -> bk
|
||||
gj RSHIFT 1 -> hc
|
||||
iu AND jf -> jh
|
||||
NOT bs -> bt
|
||||
kk OR kv -> kw
|
||||
ks AND ku -> kv
|
||||
hz OR ik -> il
|
||||
b RSHIFT 1 -> v
|
||||
iu RSHIFT 1 -> jn
|
||||
fo RSHIFT 5 -> fr
|
||||
be AND bg -> bh
|
||||
ga AND gc -> gd
|
||||
hf OR hl -> hm
|
||||
ld OR le -> lf
|
||||
as RSHIFT 5 -> av
|
||||
fm OR fn -> fo
|
||||
hm AND ho -> hp
|
||||
lg OR lm -> ln
|
||||
NOT kx -> ky
|
||||
kk RSHIFT 3 -> km
|
||||
ek AND em -> en
|
||||
NOT ft -> fu
|
||||
NOT jh -> ji
|
||||
jn OR jo -> jp
|
||||
gj AND gu -> gw
|
||||
d AND j -> l
|
||||
et RSHIFT 1 -> fm
|
||||
jq OR jw -> jx
|
||||
ep OR eo -> eq
|
||||
lv LSHIFT 15 -> lz
|
||||
NOT ey -> ez
|
||||
jp RSHIFT 2 -> jq
|
||||
eg AND ei -> ej
|
||||
NOT dm -> dn
|
||||
jp AND ka -> kc
|
||||
as AND bd -> bf
|
||||
fk OR fj -> fl
|
||||
dw OR dx -> dy
|
||||
lj AND ll -> lm
|
||||
ec AND ee -> ef
|
||||
fq AND fr -> ft
|
||||
NOT kp -> kq
|
||||
ki OR kj -> kk
|
||||
cz OR cy -> da
|
||||
as RSHIFT 3 -> au
|
||||
an LSHIFT 15 -> ar
|
||||
fj LSHIFT 15 -> fn
|
||||
1 AND fi -> fj
|
||||
he RSHIFT 1 -> hx
|
||||
lf RSHIFT 2 -> lg
|
||||
kf LSHIFT 15 -> kj
|
||||
dz AND ef -> eh
|
||||
ib OR ic -> id
|
||||
lf RSHIFT 5 -> li
|
||||
bp OR bq -> br
|
||||
NOT gs -> gt
|
||||
fo RSHIFT 1 -> gh
|
||||
bz AND cb -> cc
|
||||
ea OR eb -> ec
|
||||
lf AND lq -> ls
|
||||
NOT l -> m
|
||||
hz RSHIFT 3 -> ib
|
||||
NOT di -> dj
|
||||
NOT lk -> ll
|
||||
jp RSHIFT 3 -> jr
|
||||
jp RSHIFT 5 -> js
|
||||
NOT bf -> bg
|
||||
s LSHIFT 15 -> w
|
||||
eq LSHIFT 1 -> fk
|
||||
jl OR jk -> jm
|
||||
hz AND ik -> im
|
||||
dz OR ef -> eg
|
||||
1 AND gy -> gz
|
||||
la LSHIFT 15 -> le
|
||||
br AND bt -> bu
|
||||
NOT cn -> co
|
||||
v OR w -> x
|
||||
d OR j -> k
|
||||
1 AND gd -> ge
|
||||
ia OR ig -> ih
|
||||
NOT go -> gp
|
||||
NOT ed -> ee
|
||||
jq AND jw -> jy
|
||||
et OR fe -> ff
|
||||
aw AND ay -> az
|
||||
ff AND fh -> fi
|
||||
ir LSHIFT 1 -> jl
|
||||
gg LSHIFT 1 -> ha
|
||||
x RSHIFT 2 -> y
|
||||
db OR dc -> dd
|
||||
bl OR bm -> bn
|
||||
ib AND ic -> ie
|
||||
x RSHIFT 3 -> z
|
||||
lh AND li -> lk
|
||||
ce OR cd -> cf
|
||||
NOT bb -> bc
|
||||
hi AND hk -> hl
|
||||
NOT gb -> gc
|
||||
1 AND r -> s
|
||||
fw AND fy -> fz
|
||||
fb AND fd -> fe
|
||||
1 AND en -> eo
|
||||
z OR aa -> ab
|
||||
bi LSHIFT 15 -> bm
|
||||
hg OR hh -> hi
|
||||
kh LSHIFT 1 -> lb
|
||||
cg OR ch -> ci
|
||||
1 AND kz -> la
|
||||
gf OR ge -> gg
|
||||
gj RSHIFT 2 -> gk
|
||||
dd RSHIFT 2 -> de
|
||||
NOT ls -> lt
|
||||
lh OR li -> lj
|
||||
jr OR js -> jt
|
||||
au AND av -> ax
|
||||
0 -> c
|
||||
he AND hp -> hr
|
||||
id AND if -> ig
|
||||
et RSHIFT 5 -> ew
|
||||
bp AND bq -> bs
|
||||
e AND f -> h
|
||||
ly OR lz -> ma
|
||||
1 AND lu -> lv
|
||||
NOT jd -> je
|
||||
ha OR gz -> hb
|
||||
dy RSHIFT 1 -> er
|
||||
iu RSHIFT 2 -> iv
|
||||
NOT hr -> hs
|
||||
as RSHIFT 1 -> bl
|
||||
kk RSHIFT 2 -> kl
|
||||
b AND n -> p
|
||||
ln AND lp -> lq
|
||||
cj AND cp -> cr
|
||||
dl AND dn -> do
|
||||
ci RSHIFT 2 -> cj
|
||||
as OR bd -> be
|
||||
ge LSHIFT 15 -> gi
|
||||
hz RSHIFT 5 -> ic
|
||||
dv LSHIFT 1 -> ep
|
||||
kl OR kr -> ks
|
||||
gj OR gu -> gv
|
||||
he RSHIFT 5 -> hh
|
||||
NOT fg -> fh
|
||||
hg AND hh -> hj
|
||||
b OR n -> o
|
||||
jk LSHIFT 15 -> jo
|
||||
gz LSHIFT 15 -> hd
|
||||
cy LSHIFT 15 -> dc
|
||||
kk RSHIFT 5 -> kn
|
||||
ci RSHIFT 3 -> ck
|
||||
at OR az -> ba
|
||||
iu RSHIFT 3 -> iw
|
||||
ko AND kq -> kr
|
||||
NOT eh -> ei
|
||||
aq OR ar -> as
|
||||
iy AND ja -> jb
|
||||
dd RSHIFT 3 -> df
|
||||
bn RSHIFT 3 -> bp
|
||||
1 AND cc -> cd
|
||||
at AND az -> bb
|
||||
x OR ai -> aj
|
||||
kk AND kv -> kx
|
||||
ao OR an -> ap
|
||||
dy RSHIFT 3 -> ea
|
||||
x RSHIFT 1 -> aq
|
||||
eu AND fa -> fc
|
||||
kl AND kr -> kt
|
||||
ia AND ig -> ii
|
||||
df AND dg -> di
|
||||
NOT fx -> fy
|
||||
k AND m -> n
|
||||
bn RSHIFT 5 -> bq
|
||||
km AND kn -> kp
|
||||
dt LSHIFT 15 -> dx
|
||||
hz RSHIFT 2 -> ia
|
||||
aj AND al -> am
|
||||
cd LSHIFT 15 -> ch
|
||||
hc OR hd -> he
|
||||
he RSHIFT 3 -> hg
|
||||
bn OR by -> bz
|
||||
NOT kt -> ku
|
||||
z AND aa -> ac
|
||||
NOT ak -> al
|
||||
cu AND cw -> cx
|
||||
NOT ie -> if
|
||||
dy RSHIFT 2 -> dz
|
||||
ip LSHIFT 15 -> it
|
||||
de OR dk -> dl
|
||||
au OR av -> aw
|
||||
jg AND ji -> jj
|
||||
ci AND ct -> cv
|
||||
dy RSHIFT 5 -> eb
|
||||
hx OR hy -> hz
|
||||
eu OR fa -> fb
|
||||
gj RSHIFT 3 -> gl
|
||||
fo AND fz -> gb
|
||||
1 AND jj -> jk
|
||||
jp OR ka -> kb
|
||||
de AND dk -> dm
|
||||
ex AND ez -> fa
|
||||
df OR dg -> dh
|
||||
iv OR jb -> jc
|
||||
x RSHIFT 5 -> aa
|
||||
NOT hj -> hk
|
||||
NOT im -> in
|
||||
fl LSHIFT 1 -> gf
|
||||
hu LSHIFT 15 -> hy
|
||||
iq OR ip -> ir
|
||||
iu RSHIFT 5 -> ix
|
||||
NOT fc -> fd
|
||||
NOT el -> em
|
||||
ck OR cl -> cm
|
||||
et RSHIFT 3 -> ev
|
||||
hw LSHIFT 1 -> iq
|
||||
ci RSHIFT 5 -> cl
|
||||
iv AND jb -> jd
|
||||
dd RSHIFT 5 -> dg
|
||||
as RSHIFT 2 -> at
|
||||
NOT jy -> jz
|
||||
af AND ah -> ai
|
||||
1 AND ds -> dt
|
||||
jx AND jz -> ka
|
||||
da LSHIFT 1 -> du
|
||||
fs AND fu -> fv
|
||||
jp RSHIFT 1 -> ki
|
||||
iw AND ix -> iz
|
||||
iw OR ix -> iy
|
||||
eo LSHIFT 15 -> es
|
||||
ev AND ew -> ey
|
||||
ba AND bc -> bd
|
||||
fp AND fv -> fx
|
||||
jc AND je -> jf
|
||||
et RSHIFT 2 -> eu
|
||||
kg OR kf -> kh
|
||||
iu OR jf -> jg
|
||||
er OR es -> et
|
||||
fo RSHIFT 2 -> fp
|
||||
NOT ca -> cb
|
||||
bv AND bx -> by
|
||||
u LSHIFT 1 -> ao
|
||||
cm AND co -> cp
|
||||
y OR ae -> af
|
||||
bn AND by -> ca
|
||||
1 AND ke -> kf
|
||||
jt AND jv -> jw
|
||||
fq OR fr -> fs
|
||||
dy AND ej -> el
|
||||
NOT kc -> kd
|
||||
ev OR ew -> ex
|
||||
dd OR do -> dp
|
||||
NOT cv -> cw
|
||||
gr AND gt -> gu
|
||||
dd RSHIFT 1 -> dw
|
||||
NOT gw -> gx
|
||||
NOT iz -> ja
|
||||
1 AND io -> ip
|
||||
NOT ag -> ah
|
||||
b RSHIFT 5 -> f
|
||||
NOT cr -> cs
|
||||
kb AND kd -> ke
|
||||
jr AND js -> ju
|
||||
cq AND cs -> ct
|
||||
il AND in -> io
|
||||
NOT ju -> jv
|
||||
du OR dt -> dv
|
||||
dd AND do -> dq
|
||||
b RSHIFT 2 -> d
|
||||
jm LSHIFT 1 -> kg
|
||||
NOT dq -> dr
|
||||
bo OR bu -> bv
|
||||
gk OR gq -> gr
|
||||
he OR hp -> hq
|
||||
NOT h -> i
|
||||
hf AND hl -> hn
|
||||
gv AND gx -> gy
|
||||
x AND ai -> ak
|
||||
bo AND bu -> bw
|
||||
hq AND hs -> ht
|
||||
hz RSHIFT 1 -> is
|
||||
gj RSHIFT 5 -> gm
|
||||
g AND i -> j
|
||||
gk AND gq -> gs
|
||||
dp AND dr -> ds
|
||||
b RSHIFT 3 -> e
|
||||
gl AND gm -> go
|
||||
gl OR gm -> gn
|
||||
y AND ae -> ag
|
||||
hv OR hu -> hw
|
||||
1674 -> b
|
||||
ab AND ad -> ae
|
||||
NOT ac -> ad
|
||||
1 AND ht -> hu
|
||||
NOT hn -> ho
|
8
2015/day07-some_assembly_required/tests/sample_input
Normal file
8
2015/day07-some_assembly_required/tests/sample_input
Normal file
|
@ -0,0 +1,8 @@
|
|||
123 -> x
|
||||
456 -> y
|
||||
x AND y -> d
|
||||
x OR y -> e
|
||||
x LSHIFT 2 -> f
|
||||
y RSHIFT 2 -> g
|
||||
NOT x -> h
|
||||
NOT y -> i
|
8
2015/day08-matchsticks/Cargo.toml
Normal file
8
2015/day08-matchsticks/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day08-matchsticks"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
45
2015/day08-matchsticks/challenge.txt
Normal file
45
2015/day08-matchsticks/challenge.txt
Normal file
|
@ -0,0 +1,45 @@
|
|||
\--- Day 8: Matchsticks ---
|
||||
----------
|
||||
|
||||
Space on the sleigh is limited this year, and so Santa will be bringing his list as a digital copy. He needs to know how much space it will take up when stored.
|
||||
|
||||
It is common in many programming languages to provide a way to escape special characters in strings. For example, [C](https://en.wikipedia.org/wiki/Escape_sequences_in_C), [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), [Perl](http://perldoc.perl.org/perlop.html#Quote-and-Quote-like-Operators), [Python](https://docs.python.org/2.0/ref/strings.html), and even [PHP](http://php.net/manual/en/language.types.string.php#language.types.string.syntax.double) handle special characters in very similar ways.
|
||||
|
||||
However, it is important to realize the difference between the number of characters *in the code representation of the string literal* and the number of characters *in the in-memory string itself*.
|
||||
|
||||
For example:
|
||||
|
||||
* `""` is `2` characters of code (the two double quotes), but the string contains zero characters.
|
||||
* `"abc"` is `5` characters of code, but `3` characters in the string data.
|
||||
* `"aaa\"aaa"` is `10` characters of code, but the string itself contains six "a" characters and a single, escaped quote character, for a total of `7` characters in the string data.
|
||||
* `"\x27"` is `6` characters of code, but the string itself contains just one - an apostrophe (`'`), escaped using hexadecimal notation.
|
||||
|
||||
Santa's list is a file that contains many double-quoted string literals, one on each line. The only escape sequences used are `\\` (which represents a single backslash), `\"` (which represents a lone double-quote character), and `\x` plus two hexadecimal characters (which represents a single character with that ASCII code).
|
||||
|
||||
Disregarding the whitespace in the file, what is *the number of characters of code for string literals* minus *the number of characters in memory for the values of the strings* in total for the entire file?
|
||||
|
||||
For example, given the four strings above, the total number of characters of string code (`2 + 5 + 10 + 6 = 23`) minus the total number of characters in memory for string values (`0 + 3 + 7 + 1 = 11`) is `23 - 11 = 12`.
|
||||
|
||||
Your puzzle answer was `1333`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Now, let's go the other way. In addition to finding the number of characters of code, you should now *encode each code representation as a new string* and find the number of characters of the new encoded representation, including the surrounding double quotes.
|
||||
|
||||
For example:
|
||||
|
||||
* `""` encodes to `"\"\""`, an increase from `2` characters to `6`.
|
||||
* `"abc"` encodes to `"\"abc\""`, an increase from `5` characters to `9`.
|
||||
* `"aaa\"aaa"` encodes to `"\"aaa\\\"aaa\""`, an increase from `10` characters to `16`.
|
||||
* `"\x27"` encodes to `"\"\\x27\""`, an increase from `6` characters to `11`.
|
||||
|
||||
Your task is to find *the total number of characters to represent the newly encoded strings* minus *the number of characters of code in each original string literal*. For example, for the strings above, the total encoded length (`6 + 9 + 16 + 11 = 42`) minus the characters in the original code representation (`23`, just like in the first part of this puzzle) is `42 - 23 = 19`.
|
||||
|
||||
Your puzzle answer was `2046`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](8/input).
|
62
2015/day08-matchsticks/src/lib.rs
Normal file
62
2015/day08-matchsticks/src/lib.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let first = input.lines().map(get_decoding_overhead).sum();
|
||||
let second = input.lines().map(get_encoding_overhead).sum();
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn get_decoding_overhead(line: &str) -> usize {
|
||||
let mut rendered_len = 0;
|
||||
let mut literal = true;
|
||||
for c in line.chars() {
|
||||
match c {
|
||||
'"' => {
|
||||
if !literal {
|
||||
rendered_len += 1;
|
||||
literal = true;
|
||||
}
|
||||
},
|
||||
'\\' => {
|
||||
if !literal {
|
||||
rendered_len += 1;
|
||||
}
|
||||
literal = !literal;
|
||||
},
|
||||
'x' => {
|
||||
if literal {
|
||||
rendered_len += 1;
|
||||
} else {
|
||||
rendered_len -= 1;
|
||||
literal = true;
|
||||
}
|
||||
},
|
||||
_ => rendered_len += 1
|
||||
};
|
||||
}
|
||||
line.chars().count() - rendered_len as usize
|
||||
}
|
||||
|
||||
fn get_encoding_overhead(line: &str) -> usize {
|
||||
2 + line.matches('"').count() + line.matches('\\').count()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (12, 19));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (1333, 2046));
|
||||
}
|
||||
}
|
300
2015/day08-matchsticks/tests/challenge_input
Normal file
300
2015/day08-matchsticks/tests/challenge_input
Normal file
|
@ -0,0 +1,300 @@
|
|||
"sjdivfriyaaqa\xd2v\"k\"mpcu\"yyu\"en"
|
||||
"vcqc"
|
||||
"zbcwgmbpijcxu\"yins\"sfxn"
|
||||
"yumngprx"
|
||||
"bbdj"
|
||||
"czbggabkzo\"wsnw\"voklp\"s"
|
||||
"acwt"
|
||||
"aqttwnsohbzian\"evtllfxwkog\"cunzw"
|
||||
"ugvsgfv"
|
||||
"xlnillibxg"
|
||||
"kexh\"pmi"
|
||||
"syvugow"
|
||||
"m\"ktqnw"
|
||||
"yrbajyndte\\rm"
|
||||
"f\"kak\x70sn\xc4kjri"
|
||||
"yxthr"
|
||||
"alvumfsjni\"kohg"
|
||||
"trajs\x5brom\xf1yoijaumkem\"\"tahlzs"
|
||||
"\"oedr\"pwdbnnrc"
|
||||
"qsmzhnx\""
|
||||
"\"msoytqimx\\tbklqz"
|
||||
"mjdfcgwdshrehgs"
|
||||
"\"rivyxahf\""
|
||||
"ciagc\x04bp"
|
||||
"xkfc"
|
||||
"xrgcripdu\x4c\xc4gszjhrvumvz\"mngbirb"
|
||||
"gvmae\"yiiujoqvr\"mkxmgbbut\"u"
|
||||
"ih"
|
||||
"ncrqlejehs"
|
||||
"mkno\x43pcfdukmemycp"
|
||||
"uanzoqxkpsksbvdnkji\"feamp"
|
||||
"axoufpnbx\\ao\x61pfj\"b"
|
||||
"dz\\ztawzdjy"
|
||||
"ihne\"enumvswypgf"
|
||||
"\"dgazthrphbshdo\\vuqoiy\""
|
||||
"dlnmptzt\\zahwpylc\\b\"gmslrqysk"
|
||||
"mhxznyzcp"
|
||||
"rebr\"amvxw\x5fmbnfpkkeghlntavj"
|
||||
"lades\x47ncgdof\"\"jmbbk"
|
||||
"dwxuis\xa5wdkx\\z\"admgnoddpgkt\\zs"
|
||||
"g\\k\x27qsl\x34hwfglcdxqbeclt\xca\\"
|
||||
"lhyjky\\m\"pvnm\\xmynpxnlhndmahjl"
|
||||
"c\"uxabbgorrpprw\"xas\\vefkxioqpt"
|
||||
"rfrvjxpevcmma\x71gtfipo"
|
||||
"fgh\"kcwoqwfnjgdlzfclprg\"q"
|
||||
"onxnwykrba"
|
||||
"hkkg\x60f\"tjzsanpvarzgkfipl"
|
||||
"\"aintes\"ofq\"juiaqlqxmvpe\\a"
|
||||
"wiyczzs\"ciwk"
|
||||
"mfqeu"
|
||||
"v\xe1z\x7ftzalmvdmncfivrax\\rjwq"
|
||||
"k\"vtg"
|
||||
"exhrtdugeml\xf0"
|
||||
"behnchkpld"
|
||||
"mhgxy\"mfcrg\xc5gnp\"\"osqhj"
|
||||
"rlvjy"
|
||||
"awe"
|
||||
"ctwy"
|
||||
"vt"
|
||||
"\x54t"
|
||||
"zugfmmfomz"
|
||||
"cv\"cvcvfaada\x04fsuqjinbfh\xa9cq\xd2c\"d"
|
||||
"oj"
|
||||
"xazanf\"wbmcrn"
|
||||
"\\\\zkisyjpbzandqikqjqvee"
|
||||
"dpsnbzdwnxk\\v"
|
||||
"sj\"tuupr\\oyoh"
|
||||
"myvkgnw\x81q\xaaokt\\emgejbsyvxcl\\\xee"
|
||||
"ejeuqvunjcirdkkpt\"nlns"
|
||||
"twmlvwxyvfyqqzu"
|
||||
"\"xwtzdp\x98qkcis\"dm\\\"ep\"xyykq"
|
||||
"vvcq\\expok"
|
||||
"wgukjfanjgpdjb"
|
||||
"\"mjcjajnxy\\dcpc"
|
||||
"wdvgnecw\\ab\x44klceduzgsvu"
|
||||
"dqtqkukr\"iacngufbqkdpxlwjjt"
|
||||
"\"xj\"\x66qofsqzkoah"
|
||||
"nptiwwsqdep"
|
||||
"gsnlxql\x30mjl"
|
||||
"yeezwokjwrhelny\""
|
||||
"bjauamn\\izpmzqqasid"
|
||||
"tvjdbkn\"tiziw\x82r"
|
||||
"w"
|
||||
"xwoakbbnjnypnaa\xa9wft\"slrmoqkl"
|
||||
"vwxtnlvaaasyruykgygrvpiopzygf\"vq"
|
||||
"qdancvnvmhlmpj\\isdxs"
|
||||
"xzc\\elw"
|
||||
"b\"wxeqvy\"qf\"g\xcaoklsucwicyw\"dovr"
|
||||
"yomlvvjdbngz\"rly\"afr"
|
||||
"bfb\"x\"aweuwbwmoa\x13\"t\"zhr"
|
||||
"\"dmfoxb\"qvpjzzhykt\xd2\"\"ryhxi"
|
||||
"psqef\"yu\\qiflie\"\x79w"
|
||||
"arzewkej\"lqmh\\sayyusxxo\\"
|
||||
"vuvvp"
|
||||
"hc\"lg\x6bcpupsewzklai\"l"
|
||||
"cjdfygc\"auorqybnuqghsh\x10"
|
||||
"j"
|
||||
"wqjexk\"eyq\\lbroqhk\\dqzsqk"
|
||||
"dws\"ru\"dvxfiwapif\"oqwzmle"
|
||||
"agcykg\\jt\\vzklqjvknoe"
|
||||
"kksd\"jmslja\\z\"y\\b\xaagpyojct"
|
||||
"nnpipxufvbfpoz\"jno"
|
||||
"dtw"
|
||||
"xlolvtahvgqkx\\dgnhj\\spsclpcxv\\"
|
||||
"mxea\\mbjpi"
|
||||
"lgbotkk\"zmxh\\\\qji\"jszulnjsxkqf"
|
||||
"lwckmhwhx\"gmftlb\x91am"
|
||||
"xxdxqyxth"
|
||||
"\"lmqhwkjxmvayxy"
|
||||
"tf"
|
||||
"qy"
|
||||
"wdqmwxdztax\"m\"\x09\x11xdxmfwxmtqgwvf"
|
||||
"\xcbnazlf\"ghziknszmsrahaf"
|
||||
"e\x6aupmzhxlvwympgjjpdvo\"kylfa"
|
||||
"\x81vhtlillb\xactgoatva"
|
||||
"dvnlgr"
|
||||
"f"
|
||||
"xg\xfacwizsadgeclm"
|
||||
"vnnrzbtw\"\\prod\\djbyppngwayy\""
|
||||
"lrt\xf4jahwvfz"
|
||||
"aqpnjtom\"ymkak\\dadfybqrso\\fwv"
|
||||
"gz\"aac\"mrbk\"ktommrojraqh"
|
||||
"wycamwoecsftepfnlcdkm"
|
||||
"nrhddblbuzlqsl\x9cben"
|
||||
"vckxhyqkmqmdseazcykrbysm"
|
||||
"sil\xbbtevmt\"gvrvybui\"faw\"j"
|
||||
"cjex\\tp\x45pzf"
|
||||
"asjobvtxszfodgf\"ibftg"
|
||||
"gkyjyjdrxdcllnh\"sjcibenrdnxv"
|
||||
"oswsdpjyxpbwnqbcpl\"yrdvs\\zq"
|
||||
"\"\"tyowzc\\fycbp\"jbwrbvgui"
|
||||
"cbpcabqkdgzmpgcwjtrchxp"
|
||||
"iyrzfh\x45gw\"fdlfpiaap\x31xqq"
|
||||
"evgksznidz"
|
||||
"b\\w\\"
|
||||
"loufizbiy\x57aim\"bgk"
|
||||
"qjfyk"
|
||||
"g\"anmloghvgr\x07zwqougqhdz"
|
||||
"usbbmwcxd\\bdgg"
|
||||
"htitqcpczml"
|
||||
"eke\\cqvpexqqk\"to\"tqmljrpn\xe6lji\""
|
||||
"g\xd2ifdsej"
|
||||
"h\"sk\"haajajpagtcqnzrfqn\xe6btzo"
|
||||
"wfkuffdxlvm\\cvlyzlbyunclhmpp"
|
||||
"myaavh\"spue"
|
||||
"hqvez\x68d\"eo\"eaioh"
|
||||
"s\"qd\"oyxxcglcdnuhk"
|
||||
"ilqvar"
|
||||
"srh"
|
||||
"puuifxrfmpc\"bvalwi\x2blu\\"
|
||||
"yywlbutufzysbncw\\nqsfbhpz\"mngjq"
|
||||
"zbl\\jfcuop"
|
||||
"hjdouiragzvxsqkreup\\"
|
||||
"qi"
|
||||
"ckx\\funlj\xa7ahi"
|
||||
"k"
|
||||
"ufrcnh\"ajteit"
|
||||
"cqv\"bgjozjj\x60x\xa8yhvmdvutchjotyuz"
|
||||
"hkuiet\"oku\x8cfhumfpasl"
|
||||
"\"\\sbe\x4d"
|
||||
"vhknazqt"
|
||||
"eyyizvzcahgflvmoowvs\\jhvygci"
|
||||
"kki\x3ewcefkgtjap\"xtpxh\"lzepoqj"
|
||||
"wvtk"
|
||||
"\"ynet"
|
||||
"zh\\obk\"otagx\x59txfzf"
|
||||
"ocowhxlx\xe6zqg\x63wx\\tclkhq\\vmaze"
|
||||
"w\"cf"
|
||||
"qpniprnrzrnvykghqnalr"
|
||||
"jctcqra\"\x05dhlydpqamorqjsijt\\xjdgt"
|
||||
"sig"
|
||||
"qhlbidbflwxe\"xljbwls\x20vht"
|
||||
"irmrebfla\xefsg\"j"
|
||||
"nep"
|
||||
"hjuvsqlizeqobepf"
|
||||
"guzbcdp\"obyh"
|
||||
"\"mjagins\xf9tqykaxy\""
|
||||
"knvsdnmtr\"zervsb"
|
||||
"hzuy"
|
||||
"zza\"k\"buapb\\elm\xfeya"
|
||||
"lrqar\"dfqwkaaqifig\"uixjsz"
|
||||
"\"azuo\x40rmnlhhluwsbbdb\x32pk\\yu\"pbcf"
|
||||
"dplkdyty"
|
||||
"rfoyciebwlwphcycmguc"
|
||||
"ivnmmiemhgytmlprq\\eh"
|
||||
"lhkyzaaothfdhmbpsqd\\yyw"
|
||||
"tnlzifupcjcaj"
|
||||
"\\qiyirsdrfpmu\\\x15xusifaag"
|
||||
"\\lcomf\\s"
|
||||
"uramjivcirjhqcqcg"
|
||||
"kkbaklbxfxikffnuhtu\xc6t\"d"
|
||||
"n\xefai"
|
||||
"\"toy\"bnbpevuzoc\"muywq\"gz\"grbm"
|
||||
"\"muu\\wt"
|
||||
"\\srby\"ee"
|
||||
"erf\"gvw\"swfppf"
|
||||
"pbqcgtn\"iuianhcdazfvmidn\\nslhxdf"
|
||||
"uxbp"
|
||||
"up\\mgrcyaegiwmjufn"
|
||||
"nulscgcewj\\dvoyvhetdegzhs\""
|
||||
"masv\"k\\rzrb"
|
||||
"qtx\x79d\"xdxmbxrvhj"
|
||||
"fid\\otpkgjlh\"qgsvexrckqtn\xf4"
|
||||
"tagzu"
|
||||
"bvl\\\"noseec"
|
||||
"\\xgicuuh"
|
||||
"w\"a\"npemf"
|
||||
"sxp"
|
||||
"nsmpktic\x8awxftscdcvijjobnq\"gjd"
|
||||
"uks\"\"jxvyvfezz\"aynxoev\"cuoav"
|
||||
"m"
|
||||
"lkvokj"
|
||||
"vkfam\"yllr\"q\x92o\x4ebecnvhshhqe\\"
|
||||
"efdxcjkjverw"
|
||||
"lmqzadwhfdgmep\x02tzfcbgrbfekhat"
|
||||
"cpbk\x9azqegbpluczssouop\x36ztpuoxsw"
|
||||
"cqwoczxdd\"erdjka"
|
||||
"cwvqnjgbw\\fxdlby"
|
||||
"mvtm"
|
||||
"lt\"bbqzpumplkg"
|
||||
"ntd\xeeuwweucnuuslqfzfq"
|
||||
"y\xabl\"dbebxjrlbmuoo\\\x1au"
|
||||
"qjoqx\\a"
|
||||
"pu\"ekdnfpmly\xbago\""
|
||||
"fjhhdy"
|
||||
"arl"
|
||||
"xcywisim\"bwuwf\"\"raepeawwjub"
|
||||
"pbe"
|
||||
"dbnqfpzyaumxtqnd\xc5dcqrkwyop"
|
||||
"ojv\x40vtkwgkqepm\x8bzft\\vedrry"
|
||||
"wggqkfbwqumsgajqwphjec\"mstxpwz"
|
||||
"zjkbem"
|
||||
"icpfqxbelxazlls"
|
||||
"pvpqs\\abcmtyielugfgcv\"tjxapxqxnx"
|
||||
"oqddwlvmtv\"\x39lyybylfb\"jmngnpjrdw"
|
||||
"gisgbve"
|
||||
"\"aglg"
|
||||
"y\"\"ss\xafvhxlrjv"
|
||||
"qbgqjsra"
|
||||
"ihshbjgqpdcljpmdwdprwloy"
|
||||
"djja\\wcdn\"svkrgpqn\"uz\"hc\x43hj"
|
||||
"cbjm"
|
||||
"pnn"
|
||||
"pqvh\"noh"
|
||||
"\"\\fdktlp"
|
||||
"ncea"
|
||||
"pqgzphiyy"
|
||||
"\xbedovhxuipaohlcvkwtxwmpz\"ckaif\"r"
|
||||
"arjuzbjowqciunfwgxtph\"vlhy\"n"
|
||||
"c"
|
||||
"nrpdxunulgudqzlhtae"
|
||||
"iefheu\"uru\""
|
||||
"aqijysxuijud\"np\\opbichhudil\xbesum"
|
||||
"pfpevmtstl\"lde\"bzr\"vspdxs"
|
||||
"vparfbdjwvzsocpnzhp"
|
||||
"g\x4ffxaarafrsjthq\\\xc1rw"
|
||||
"ng\\rqx\\gwpzucbh\xafl"
|
||||
"rw\"nf\\dna"
|
||||
"jkkeahxurxla\\g\xb3czrlsyimmwcwthr"
|
||||
"twaailoypu\"oas\"kpuuyedlaw\\\xb0vzt"
|
||||
"hznex\\gdiqvtugi"
|
||||
"imdibsunjeswhk"
|
||||
"ta\\icileuzpxro\"cfmv\"mzp"
|
||||
"coykr\x57luiysucfaflmilhlehmvzeiepo"
|
||||
"u\x3dfh\xd4yt"
|
||||
"piw\x1bz\"eowy\"vfk\"wqiekw"
|
||||
"gan\"y"
|
||||
"p\"bevidoazcznr\"hddxuuq\""
|
||||
"bwzucczznutbxe"
|
||||
"z\"viqgyqjisior\\iecosmjbknol"
|
||||
"dmlpcglcfkfsctxydjvayhymv\x3c\\gp"
|
||||
"bfvkqrintbbvgfv"
|
||||
"xlzntrgdck\"cprc\xadczyarbznqmuhxyuh"
|
||||
"uqdxnuwioc\"kdytxq\\ig"
|
||||
"xrafmucpmfi"
|
||||
"vr\"hltmfrge"
|
||||
"eonf\"nt\\wtcnsocs"
|
||||
"j\xb7xoslyjeyjksplkqixncgkylkw"
|
||||
"njw\"pefgfbez\x9axshdmplxzquqe"
|
||||
"di\x58bvptfsafirpc"
|
||||
"l\x1fkco"
|
||||
"x"
|
||||
"mprndo\"n"
|
||||
"psegit"
|
||||
"svbdnkkuuqs\"sqxu\"oqcyz\"aizashk"
|
||||
"cwkljukxer\\\"\\nff\"esjwiyaoy"
|
||||
"ilxrkgbjjxpvhdtq\"cpiuoofdnkpp"
|
||||
"hlngi\"ulxep\\qohtmqnqjb\"rkgerho"
|
||||
"gxws\"bcgm\"p"
|
||||
"bv\"mds\\zhfusiepgrz\\b\x32fscdzz"
|
||||
"l\xfampwtme\x69qvxnx\"\"\xc4jruuymjxrpsv"
|
||||
"qqmxhrn"
|
||||
"xziq\\\x18ybyv\x9am\"neacoqjzytertisysza"
|
||||
"aqcbvlvcrzceeyx\\j\"\"x"
|
||||
"yjuhhb"
|
||||
"\x5em\"squulpy"
|
||||
"dpbntplgmwb"
|
||||
"utsgfkm\\vbftjknlktpthoeo"
|
||||
"ccxjgiocmuhf\"ycnh"
|
||||
"lltj\"kbbxi"
|
4
2015/day08-matchsticks/tests/sample_input
Normal file
4
2015/day08-matchsticks/tests/sample_input
Normal file
|
@ -0,0 +1,4 @@
|
|||
""
|
||||
"abc"
|
||||
"aaa\"aaa"
|
||||
"\x27"
|
8
2015/day09-all_in_a_single_night/Cargo.toml
Normal file
8
2015/day09-all_in_a_single_night/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day09-all_in_a_single_night"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
52
2015/day09-all_in_a_single_night/challenge.txt
Normal file
52
2015/day09-all_in_a_single_night/challenge.txt
Normal file
|
@ -0,0 +1,52 @@
|
|||
\--- Day 9: All in a Single Night ---
|
||||
----------
|
||||
|
||||
Every year, Santa manages to deliver all of his presents in a single night.
|
||||
|
||||
This year, however, he has some new locations to visit; his elves have provided him the distances between every pair of locations. He can start and end at any two (different) locations he wants, but he must visit each location exactly once. What is the *shortest distance* he can travel to achieve this?
|
||||
|
||||
For example, given the following distances:
|
||||
|
||||
```
|
||||
London to Dublin = 464
|
||||
London to Belfast = 518
|
||||
Dublin to Belfast = 141
|
||||
|
||||
```
|
||||
|
||||
The possible routes are therefore:
|
||||
|
||||
```
|
||||
Dublin -> London -> Belfast = 982
|
||||
London -> Dublin -> Belfast = 605
|
||||
London -> Belfast -> Dublin = 659
|
||||
Dublin -> Belfast -> London = 659
|
||||
Belfast -> Dublin -> London = 605
|
||||
Belfast -> London -> Dublin = 982
|
||||
|
||||
```
|
||||
|
||||
The shortest of these is `London -> Dublin -> Belfast = 605`, and so the answer is `605` in this example.
|
||||
|
||||
What is the distance of the shortest route?
|
||||
|
||||
Your puzzle answer was `117`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
The next year, just to show off, Santa decides to take the route with the *longest distance* instead.
|
||||
|
||||
He can still start and end at any two (different) locations he wants, and he still must visit each location exactly once.
|
||||
|
||||
For example, given the distances above, the longest route would be `982` via (for example) `Dublin -> London -> Belfast`.
|
||||
|
||||
What is the distance of the longest route?
|
||||
|
||||
Your puzzle answer was `909`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](9/input).
|
72
2015/day09-all_in_a_single_night/src/lib.rs
Normal file
72
2015/day09-all_in_a_single_night/src/lib.rs
Normal file
|
@ -0,0 +1,72 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let distances = get_distances(input);
|
||||
let first = try_all(&distances, &{|a, b| b.cmp(a)});
|
||||
let second = try_all(&distances, &{|a, b| a.cmp(b)});
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn get_distances(input: &str) -> HashMap<(u16, u16), usize> {
|
||||
let mut cities = HashMap::new();
|
||||
let mut map = HashMap::new();
|
||||
|
||||
input.lines().for_each(|line| {
|
||||
let components: Vec<&str> = line.split(' ').collect();
|
||||
assert_eq!(components.len(), 5);
|
||||
|
||||
let next = 2_u16.pow(cities.len() as u32);
|
||||
let from = *cities.entry(components[0]).or_insert(next);
|
||||
let next = 2_u16.pow(cities.len() as u32);
|
||||
let to = *cities.entry(components[2]).or_insert(next);
|
||||
let distance = components[4].parse().unwrap();
|
||||
|
||||
map.insert((from, to), distance);
|
||||
map.insert((to, from), distance);
|
||||
});
|
||||
|
||||
map
|
||||
}
|
||||
|
||||
fn try_all<F>(distances: &HashMap<(u16, u16), usize>, comparison: &F) -> usize
|
||||
where F: Fn(&usize, &usize) -> std::cmp::Ordering
|
||||
{
|
||||
let starting_points: HashSet<u16> = distances.keys().map(|(from, _)| *from).collect();
|
||||
|
||||
starting_points.iter()
|
||||
.map(|&from| try_all_from(from, distances, from, comparison))
|
||||
.max_by(comparison)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn try_all_from<F>(current: u16, distances: &HashMap<(u16, u16), usize>, visited: u16, comparison: &F) -> usize
|
||||
where F: Fn(&usize, &usize) -> std::cmp::Ordering
|
||||
{
|
||||
distances.keys()
|
||||
.filter(|(from, to)| *from == current && *to & visited == 0)
|
||||
.map(|(_, to)| distances.get(&(current, *to)).unwrap() + try_all_from(*to, distances, visited | to, comparison))
|
||||
.max_by(comparison)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (605, 982));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (117, 909));
|
||||
}
|
||||
}
|
28
2015/day09-all_in_a_single_night/tests/challenge_input
Normal file
28
2015/day09-all_in_a_single_night/tests/challenge_input
Normal file
|
@ -0,0 +1,28 @@
|
|||
Faerun to Tristram = 65
|
||||
Faerun to Tambi = 129
|
||||
Faerun to Norrath = 144
|
||||
Faerun to Snowdin = 71
|
||||
Faerun to Straylight = 137
|
||||
Faerun to AlphaCentauri = 3
|
||||
Faerun to Arbre = 149
|
||||
Tristram to Tambi = 63
|
||||
Tristram to Norrath = 4
|
||||
Tristram to Snowdin = 105
|
||||
Tristram to Straylight = 125
|
||||
Tristram to AlphaCentauri = 55
|
||||
Tristram to Arbre = 14
|
||||
Tambi to Norrath = 68
|
||||
Tambi to Snowdin = 52
|
||||
Tambi to Straylight = 65
|
||||
Tambi to AlphaCentauri = 22
|
||||
Tambi to Arbre = 143
|
||||
Norrath to Snowdin = 8
|
||||
Norrath to Straylight = 23
|
||||
Norrath to AlphaCentauri = 136
|
||||
Norrath to Arbre = 115
|
||||
Snowdin to Straylight = 101
|
||||
Snowdin to AlphaCentauri = 84
|
||||
Snowdin to Arbre = 96
|
||||
Straylight to AlphaCentauri = 107
|
||||
Straylight to Arbre = 14
|
||||
AlphaCentauri to Arbre = 46
|
3
2015/day09-all_in_a_single_night/tests/sample_input
Normal file
3
2015/day09-all_in_a_single_night/tests/sample_input
Normal file
|
@ -0,0 +1,3 @@
|
|||
London to Dublin = 464
|
||||
London to Belfast = 518
|
||||
Dublin to Belfast = 141
|
8
2015/day10-elves_look_elves_say/Cargo.toml
Normal file
8
2015/day10-elves_look_elves_say/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day10-elves_look_elves_say"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
50
2015/day10-elves_look_elves_say/src/lib.rs
Normal file
50
2015/day10-elves_look_elves_say/src/lib.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
pub fn run(input: &str, count: u8) -> String {
|
||||
let mut look = String::from(input);
|
||||
for _ in 0..count {
|
||||
look = look_and_say(&look);
|
||||
}
|
||||
|
||||
look
|
||||
}
|
||||
|
||||
fn look_and_say(number: &str) -> String {
|
||||
let mut say = String::new();
|
||||
let mut last_digit = ' ';
|
||||
let mut count = 0;
|
||||
|
||||
for digit in number.chars() {
|
||||
if digit == last_digit {
|
||||
count += 1;
|
||||
} else {
|
||||
say += &(count.to_string() + &last_digit.to_string());
|
||||
count = 1;
|
||||
last_digit = digit;
|
||||
}
|
||||
}
|
||||
say += &(count.to_string() + &last_digit.to_string());
|
||||
say[2..].to_string()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
/*use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}*/
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = "1";
|
||||
assert_eq!(run(sample_input, 5), "312211".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = "1113122113";
|
||||
let after_40 = run(challenge_input, 40);
|
||||
assert_eq!(after_40.len(), 360154);
|
||||
assert_eq!(run(&after_40, 10).len(), 5103798);
|
||||
}
|
||||
}
|
0
2015/day10-elves_look_elves_say/tests/challenge_input
Normal file
0
2015/day10-elves_look_elves_say/tests/challenge_input
Normal file
0
2015/day10-elves_look_elves_say/tests/sample_input
Normal file
0
2015/day10-elves_look_elves_say/tests/sample_input
Normal file
8
2015/day11-corporate_policy/Cargo.toml
Normal file
8
2015/day11-corporate_policy/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day11-corporate_policy"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
39
2015/day11-corporate_policy/challenge.txt
Normal file
39
2015/day11-corporate_policy/challenge.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
\--- Day 11: Corporate Policy ---
|
||||
----------
|
||||
|
||||
Santa's previous password expired, and he needs help choosing a new one.
|
||||
|
||||
To help him remember his new password after the old one expires, Santa has devised a method of coming up with a password based on the previous one. Corporate policy dictates that passwords must be exactly eight lowercase letters (for security reasons), so he finds his new password by *incrementing* his old password string repeatedly until it is valid.
|
||||
|
||||
Incrementing is just like counting with numbers: `xx`, `xy`, `xz`, `ya`, `yb`, and so on. Increase the rightmost letter one step; if it was `z`, it wraps around to `a`, and repeat with the next letter to the left until one doesn't wrap around.
|
||||
|
||||
Unfortunately for Santa, a new Security-Elf recently started, and he has imposed some additional password requirements:
|
||||
|
||||
* Passwords must include one increasing straight of at least three letters, like `abc`, `bcd`, `cde`, and so on, up to `xyz`. They cannot skip letters; `abd` doesn't count.
|
||||
* Passwords may not contain the letters `i`, `o`, or `l`, as these letters can be mistaken for other characters and are therefore confusing.
|
||||
* Passwords must contain at least two different, non-overlapping pairs of letters, like `aa`, `bb`, or `zz`.
|
||||
|
||||
For example:
|
||||
|
||||
* `hijklmmn` meets the first requirement (because it contains the straight `hij`) but fails the second requirement requirement (because it contains `i` and `l`).
|
||||
* `abbceffg` meets the third requirement (because it repeats `bb` and `ff`) but fails the first requirement.
|
||||
* `abbcegjk` fails the third requirement, because it only has one double letter (`bb`).
|
||||
* The next password after `abcdefgh` is `abcdffaa`.
|
||||
* The next password after `ghijklmn` is `ghjaabcc`, because you eventually skip all the passwords that start with `ghi...`, since `i` is not allowed.
|
||||
|
||||
Given Santa's current password (your puzzle input), what should his *next password* be?
|
||||
|
||||
Your puzzle answer was `cqjxxyzz`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Santa's password expired again. What's the next one?
|
||||
|
||||
Your puzzle answer was `cqkaabcc`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
Your puzzle input was `cqjxjnds`.
|
80
2015/day11-corporate_policy/src/lib.rs
Normal file
80
2015/day11-corporate_policy/src/lib.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
pub fn run(input: &str) -> String {
|
||||
let mut next_password = increment(input);
|
||||
while !meets_requirements(&next_password) {
|
||||
next_password = increment(&next_password);
|
||||
}
|
||||
next_password
|
||||
}
|
||||
|
||||
fn to_number(password: &str) -> usize {
|
||||
password.bytes().map(|b| (b - b'a') as usize).fold(0, |acc, b| 26*acc+b)
|
||||
}
|
||||
|
||||
fn to_password(number: usize) -> String {
|
||||
let mut password = String::new();
|
||||
let mut number = number;
|
||||
while number > 0 {
|
||||
password += &char::from(b'a' + (number % 26) as u8).to_string();
|
||||
number /= 26;
|
||||
}
|
||||
password += &("a".repeat(8-password.len()));
|
||||
password.chars().rev().collect()
|
||||
}
|
||||
|
||||
fn increment(password: &str) -> String {
|
||||
to_password(to_number(password) + 1)
|
||||
}
|
||||
|
||||
fn meets_requirements(password: &str) -> bool {
|
||||
let mut includes_straight = false;
|
||||
for idx in 0..password.bytes().len()-2 {
|
||||
if *password.as_bytes().get(idx+2).unwrap() == password.as_bytes().get(idx).unwrap() + 2 &&
|
||||
*password.as_bytes().get(idx+1).unwrap() == password.as_bytes().get(idx).unwrap() + 1 {
|
||||
includes_straight = true;
|
||||
}
|
||||
}
|
||||
|
||||
let includes_confusing = password.chars().any(|c| ['i', 'o', 'l'].contains(&c));
|
||||
|
||||
let mut pairs = 0;
|
||||
let mut iter = 0..password.chars().count()-1;
|
||||
while let Some(idx) = iter.next() {
|
||||
if password.chars().nth(idx+1) == password.chars().nth(idx) {
|
||||
pairs += 1;
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
|
||||
includes_straight && !includes_confusing && pairs > 1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn requirements_tests() {
|
||||
let samples = [ "hijklmmn", "abbceffg", "abbcegjk" ];
|
||||
for s in samples {
|
||||
assert_eq!(to_password(to_number(s)), s.to_string());
|
||||
assert!(!meets_requirements(s));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = ["abcdefgh", "ghjaaaaa" /*"ghijklmn"*/ ];
|
||||
let expected = ["abcdffaa", "ghjaabcc"];
|
||||
for (idx, s) in sample_input.iter().enumerate() {
|
||||
assert_eq!(run(s), expected[idx].to_string());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = "cqjxjnds";
|
||||
let next_password = run(challenge_input);
|
||||
assert_eq!(next_password, "cqjxxyzz".to_string());
|
||||
assert_eq!(run(&next_password), "cqkaabcc".to_string());
|
||||
}
|
||||
}
|
0
2015/day11-corporate_policy/tests/challenge_input
Normal file
0
2015/day11-corporate_policy/tests/challenge_input
Normal file
0
2015/day11-corporate_policy/tests/sample_input
Normal file
0
2015/day11-corporate_policy/tests/sample_input
Normal file
8
2015/day12-jsabacusframework_io/Cargo.toml
Normal file
8
2015/day12-jsabacusframework_io/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day12-jsabacusframework_io"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
1
2015/day12-jsabacusframework_io/challenge.json
Normal file
1
2015/day12-jsabacusframework_io/challenge.json
Normal file
File diff suppressed because one or more lines are too long
39
2015/day12-jsabacusframework_io/challenge.txt
Normal file
39
2015/day12-jsabacusframework_io/challenge.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
\--- Day 12: JSAbacusFramework.io ---
|
||||
----------
|
||||
|
||||
Santa's Accounting-Elves need help balancing the books after a recent order. Unfortunately, their accounting software uses a peculiar storage format. That's where you come in.
|
||||
|
||||
They have a [JSON](http://json.org/) document which contains a variety of things: arrays (`[1,2,3]`), objects (`{"a":1, "b":2}`), numbers, and strings. Your first job is to simply find all of the *numbers* throughout the document and add them together.
|
||||
|
||||
For example:
|
||||
|
||||
* `[1,2,3]` and `{"a":2,"b":4}` both have a sum of `6`.
|
||||
* `[[[3]]]` and `{"a":{"b":4},"c":-1}` both have a sum of `3`.
|
||||
* `{"a":[-1,1]}` and `[-1,{"a":1}]` both have a sum of `0`.
|
||||
* `[]` and `{}` both have a sum of `0`.
|
||||
|
||||
You will not encounter any strings containing numbers.
|
||||
|
||||
What is the *sum of all numbers* in the document?
|
||||
|
||||
Your puzzle answer was `119433`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Uh oh - the Accounting-Elves have realized that they double-counted everything *red*.
|
||||
|
||||
Ignore any object (and all of its children) which has any property with the value `"red"`. Do this only for objects (`{...}`), not arrays (`[...]`).
|
||||
|
||||
* `[1,2,3]` still has a sum of `6`.
|
||||
* `[1,{"c":"red","b":2},3]` now has a sum of `4`, because the middle object is ignored.
|
||||
* `{"d":"red","e":[1,2,3,4],"f":5}` now has a sum of `0`, because the entire structure is ignored.
|
||||
* `[1,"red",5]` has a sum of `6`, because `"red"` in an array has no effect.
|
||||
|
||||
Your puzzle answer was `68466`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](12/input).
|
85
2015/day12-jsabacusframework_io/src/lib.rs
Normal file
85
2015/day12-jsabacusframework_io/src/lib.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
pub fn run(input: &str) -> (i32, i32) {
|
||||
let first = input.lines().map(sumup_numbers).sum();
|
||||
let second = input.lines().map(|line| sumup_numbers(&filter_red(line))).sum();
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn sumup_numbers(line: &str) -> i32 {
|
||||
let mut sum = 0;
|
||||
|
||||
let mut sign = 1_i32;
|
||||
let mut this_number = 0_u32;
|
||||
for c in line.chars() {
|
||||
if c == '-' {
|
||||
sign *= -1;
|
||||
} else if let Some(d) = c.to_digit(10) {
|
||||
this_number *= 10;
|
||||
this_number += d;
|
||||
} else {
|
||||
sum += this_number as i32 * sign;
|
||||
this_number = 0;
|
||||
sign = 1
|
||||
}
|
||||
}
|
||||
// dbg!(sum)
|
||||
sum
|
||||
}
|
||||
|
||||
fn filter_red(line: &str) -> String {
|
||||
let left_square: Vec<_> = line.match_indices('[').map(|(idx, _)| idx).collect();
|
||||
let right_square: Vec<_> = line.match_indices(']').map(|(idx, _)| idx).collect();
|
||||
let left_curly: Vec<_> = line.match_indices('{').map(|(idx, _)| idx).collect();
|
||||
let right_curly: Vec<_> = line.match_indices('}').map(|(idx, _)| idx).collect();
|
||||
let reds: Vec<_> = line.match_indices("red").map(|(idx, _)| idx).collect();
|
||||
|
||||
let mut filtered = String::from(line);
|
||||
|
||||
for red in &reds {
|
||||
let left_count = left_curly.partition_point(|lc| lc < red);
|
||||
let right_count = right_curly.partition_point(|rc| rc < red);
|
||||
let curly_level = left_count - right_count;
|
||||
let start = *left_curly.iter().take(left_count).rev().find(|lc| left_curly.partition_point(|left| left <= lc) - right_curly.partition_point(|right| right <= lc) == curly_level).unwrap();
|
||||
|
||||
// skip reds that are in an array, unless they are part of an object inside the array
|
||||
let left_square_count = left_square.partition_point(|ls| ls < red);
|
||||
let square_level = left_square_count - right_square.partition_point(|rs| rs < red);
|
||||
if square_level > 0 {
|
||||
let opening_square = *left_square.iter().take(left_square_count).rev().find(|ls| left_square.partition_point(|left| left <= ls) - right_square.partition_point(|right| right <= ls) == square_level).unwrap();
|
||||
if opening_square > start {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let end = *right_curly.iter()
|
||||
.enumerate()
|
||||
.skip(right_count)
|
||||
.find(|(idx, end)| left_curly.partition_point(|lc| lc < end) - idx == curly_level)
|
||||
.unwrap_or_else(|| panic!("Unable to find a right brace after {red} in {line}"))
|
||||
.1 + 1;
|
||||
|
||||
filtered.replace_range(start..end, &"x".repeat(end-start));
|
||||
}
|
||||
|
||||
filtered
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (39, 22));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (119433, 68466));
|
||||
}
|
||||
}
|
1
2015/day12-jsabacusframework_io/tests/challenge_input
Normal file
1
2015/day12-jsabacusframework_io/tests/challenge_input
Normal file
File diff suppressed because one or more lines are too long
10
2015/day12-jsabacusframework_io/tests/sample_input
Normal file
10
2015/day12-jsabacusframework_io/tests/sample_input
Normal file
|
@ -0,0 +1,10 @@
|
|||
[1,2,3]
|
||||
[1,{"c":"red","b":2},3]
|
||||
[[[3]]]
|
||||
{"a":{"b":4},"c":-1}
|
||||
{"a":[-1,1]}
|
||||
[-1,{"a":1}]
|
||||
[]
|
||||
{}
|
||||
{"d":"red","e":[1,2,3,4],"f":5}
|
||||
{[1,"red",5]}
|
8
2015/day13-knights_of_the_dinner_table/Cargo.toml
Normal file
8
2015/day13-knights_of_the_dinner_table/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day13-knights_of_the_dinner_table"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
60
2015/day13-knights_of_the_dinner_table/challenge.txt
Normal file
60
2015/day13-knights_of_the_dinner_table/challenge.txt
Normal file
|
@ -0,0 +1,60 @@
|
|||
\--- Day 13: Knights of the Dinner Table ---
|
||||
----------
|
||||
|
||||
In years past, the holiday feast with your family hasn't gone so well. Not everyone gets along! This year, you resolve, will be different. You're going to find the *optimal seating arrangement* and avoid all those awkward conversations.
|
||||
|
||||
You start by writing up a list of everyone invited and the amount their happiness would increase or decrease if they were to find themselves sitting next to each other person. You have a circular table that will be just big enough to fit everyone comfortably, and so each person will have exactly two neighbors.
|
||||
|
||||
For example, suppose you have only four attendees planned, and you calculate their potential happiness as follows:
|
||||
|
||||
```
|
||||
Alice would gain 54 happiness units by sitting next to Bob.
|
||||
Alice would lose 79 happiness units by sitting next to Carol.
|
||||
Alice would lose 2 happiness units by sitting next to David.
|
||||
Bob would gain 83 happiness units by sitting next to Alice.
|
||||
Bob would lose 7 happiness units by sitting next to Carol.
|
||||
Bob would lose 63 happiness units by sitting next to David.
|
||||
Carol would lose 62 happiness units by sitting next to Alice.
|
||||
Carol would gain 60 happiness units by sitting next to Bob.
|
||||
Carol would gain 55 happiness units by sitting next to David.
|
||||
David would gain 46 happiness units by sitting next to Alice.
|
||||
David would lose 7 happiness units by sitting next to Bob.
|
||||
David would gain 41 happiness units by sitting next to Carol.
|
||||
|
||||
```
|
||||
|
||||
Then, if you seat Alice next to David, Alice would lose `2` happiness units (because David talks so much), but David would gain `46` happiness units (because Alice is such a good listener), for a total change of `44`.
|
||||
|
||||
If you continue around the table, you could then seat Bob next to Alice (Bob gains `83`, Alice gains `54`). Finally, seat Carol, who sits next to Bob (Carol gains `60`, Bob loses `7`) and David (Carol gains `55`, David gains `41`). The arrangement looks like this:
|
||||
|
||||
```
|
||||
+41 +46
|
||||
+55 David -2
|
||||
Carol Alice
|
||||
+60 Bob +54
|
||||
-7 +83
|
||||
|
||||
```
|
||||
|
||||
After trying every other seating arrangement in this hypothetical scenario, you find that this one is the most optimal, with a total change in happiness of `330`.
|
||||
|
||||
What is the *total change in happiness* for the optimal seating arrangement of the actual guest list?
|
||||
|
||||
Your puzzle answer was `618`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
In all the commotion, you realize that you forgot to seat yourself. At this point, you're pretty apathetic toward the whole thing, and your happiness wouldn't really go up or down regardless of who you sit next to. You assume everyone else would be just as ambivalent about sitting next to you, too.
|
||||
|
||||
So, add yourself to the list, and give all happiness relationships that involve you a score of `0`.
|
||||
|
||||
What is the *total change in happiness* for the optimal seating arrangement that actually includes yourself?
|
||||
|
||||
Your puzzle answer was `601`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](13/input).
|
88
2015/day13-knights_of_the_dinner_table/src/lib.rs
Normal file
88
2015/day13-knights_of_the_dinner_table/src/lib.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
pub fn run(input: &str) -> (isize, isize) {
|
||||
let mut happiness_table = get_happiness_table(input);
|
||||
let first = get_max_happiness(&happiness_table);
|
||||
append_ambivalent(&mut happiness_table);
|
||||
let second = get_max_happiness(&happiness_table);
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn append_ambivalent(table: &mut HashMap<(u16, u16), isize>) {
|
||||
let new = table.keys().map(|k| k.0).max().unwrap() * 2;
|
||||
let mut this = 1;
|
||||
while this < new {
|
||||
table.insert((this, new), 0);
|
||||
table.insert((new, this), 0);
|
||||
this *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_max_happiness(table: &HashMap<(u16, u16), isize>) -> isize {
|
||||
// since the table is round, the first placement ist arbitrary. Place attendee 1 there, since
|
||||
// they are guaranteed to exist.
|
||||
let current = 1;
|
||||
try_all(table, current, current)
|
||||
}
|
||||
|
||||
fn try_all(table: &HashMap<(u16, u16), isize>, current: u16, seated: u16) -> isize {
|
||||
let to_place: Vec<_> = table.keys().filter(|(s, o)| *s == current && *o & seated == 0).map(|(_s, o)| *o).collect();
|
||||
if to_place.len() > 1 {
|
||||
to_place.iter()
|
||||
.map(|next| table.get(&(current, *next)).unwrap() +
|
||||
table.get(&(*next, current)).unwrap() +
|
||||
try_all(table, *next, seated | *next))
|
||||
.max()
|
||||
.unwrap()
|
||||
} else {
|
||||
let next = to_place[0];
|
||||
table.get(&(current, next)).unwrap() +
|
||||
table.get(&(next, current)).unwrap() +
|
||||
table.get(&(next, 1)).unwrap() +
|
||||
table.get(&(1, next)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_happiness_table(input: &str) -> HashMap<(u16, u16), isize> {
|
||||
let mut attendees = HashMap::new();
|
||||
let mut table = HashMap::new();
|
||||
for line in input.lines() {
|
||||
let components: Vec<_> = line.split(' ').collect();
|
||||
assert_eq!(components.len(), 11);
|
||||
|
||||
let next = 2_u16.pow(attendees.len() as u32);
|
||||
let subject = *attendees.entry(components[0]).or_insert(next);
|
||||
let next = 2_u16.pow(attendees.len() as u32);
|
||||
let object = *attendees.entry(&components[10][..components[10].len()-1]).or_insert(next);
|
||||
let sign = match components[2] {
|
||||
"gain" => 1,
|
||||
"lose" => -1,
|
||||
_ => panic!("unexpected token {} in line {}", components[2], input),
|
||||
};
|
||||
let amount: isize = components[3].parse().unwrap();
|
||||
table.insert((subject, object), sign*amount);
|
||||
}
|
||||
table
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (330, 286));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (618, 601));
|
||||
}
|
||||
}
|
56
2015/day13-knights_of_the_dinner_table/tests/challenge_input
Normal file
56
2015/day13-knights_of_the_dinner_table/tests/challenge_input
Normal file
|
@ -0,0 +1,56 @@
|
|||
Alice would lose 57 happiness units by sitting next to Bob.
|
||||
Alice would lose 62 happiness units by sitting next to Carol.
|
||||
Alice would lose 75 happiness units by sitting next to David.
|
||||
Alice would gain 71 happiness units by sitting next to Eric.
|
||||
Alice would lose 22 happiness units by sitting next to Frank.
|
||||
Alice would lose 23 happiness units by sitting next to George.
|
||||
Alice would lose 76 happiness units by sitting next to Mallory.
|
||||
Bob would lose 14 happiness units by sitting next to Alice.
|
||||
Bob would gain 48 happiness units by sitting next to Carol.
|
||||
Bob would gain 89 happiness units by sitting next to David.
|
||||
Bob would gain 86 happiness units by sitting next to Eric.
|
||||
Bob would lose 2 happiness units by sitting next to Frank.
|
||||
Bob would gain 27 happiness units by sitting next to George.
|
||||
Bob would gain 19 happiness units by sitting next to Mallory.
|
||||
Carol would gain 37 happiness units by sitting next to Alice.
|
||||
Carol would gain 45 happiness units by sitting next to Bob.
|
||||
Carol would gain 24 happiness units by sitting next to David.
|
||||
Carol would gain 5 happiness units by sitting next to Eric.
|
||||
Carol would lose 68 happiness units by sitting next to Frank.
|
||||
Carol would lose 25 happiness units by sitting next to George.
|
||||
Carol would gain 30 happiness units by sitting next to Mallory.
|
||||
David would lose 51 happiness units by sitting next to Alice.
|
||||
David would gain 34 happiness units by sitting next to Bob.
|
||||
David would gain 99 happiness units by sitting next to Carol.
|
||||
David would gain 91 happiness units by sitting next to Eric.
|
||||
David would lose 38 happiness units by sitting next to Frank.
|
||||
David would gain 60 happiness units by sitting next to George.
|
||||
David would lose 63 happiness units by sitting next to Mallory.
|
||||
Eric would gain 23 happiness units by sitting next to Alice.
|
||||
Eric would lose 69 happiness units by sitting next to Bob.
|
||||
Eric would lose 33 happiness units by sitting next to Carol.
|
||||
Eric would lose 47 happiness units by sitting next to David.
|
||||
Eric would gain 75 happiness units by sitting next to Frank.
|
||||
Eric would gain 82 happiness units by sitting next to George.
|
||||
Eric would gain 13 happiness units by sitting next to Mallory.
|
||||
Frank would gain 77 happiness units by sitting next to Alice.
|
||||
Frank would gain 27 happiness units by sitting next to Bob.
|
||||
Frank would lose 87 happiness units by sitting next to Carol.
|
||||
Frank would gain 74 happiness units by sitting next to David.
|
||||
Frank would lose 41 happiness units by sitting next to Eric.
|
||||
Frank would lose 99 happiness units by sitting next to George.
|
||||
Frank would gain 26 happiness units by sitting next to Mallory.
|
||||
George would lose 63 happiness units by sitting next to Alice.
|
||||
George would lose 51 happiness units by sitting next to Bob.
|
||||
George would lose 60 happiness units by sitting next to Carol.
|
||||
George would gain 30 happiness units by sitting next to David.
|
||||
George would lose 100 happiness units by sitting next to Eric.
|
||||
George would lose 63 happiness units by sitting next to Frank.
|
||||
George would gain 57 happiness units by sitting next to Mallory.
|
||||
Mallory would lose 71 happiness units by sitting next to Alice.
|
||||
Mallory would lose 28 happiness units by sitting next to Bob.
|
||||
Mallory would lose 10 happiness units by sitting next to Carol.
|
||||
Mallory would gain 44 happiness units by sitting next to David.
|
||||
Mallory would gain 22 happiness units by sitting next to Eric.
|
||||
Mallory would gain 79 happiness units by sitting next to Frank.
|
||||
Mallory would lose 16 happiness units by sitting next to George.
|
12
2015/day13-knights_of_the_dinner_table/tests/sample_input
Normal file
12
2015/day13-knights_of_the_dinner_table/tests/sample_input
Normal file
|
@ -0,0 +1,12 @@
|
|||
Alice would gain 54 happiness units by sitting next to Bob.
|
||||
Alice would lose 79 happiness units by sitting next to Carol.
|
||||
Alice would lose 2 happiness units by sitting next to David.
|
||||
Bob would gain 83 happiness units by sitting next to Alice.
|
||||
Bob would lose 7 happiness units by sitting next to Carol.
|
||||
Bob would lose 63 happiness units by sitting next to David.
|
||||
Carol would lose 62 happiness units by sitting next to Alice.
|
||||
Carol would gain 60 happiness units by sitting next to Bob.
|
||||
Carol would gain 55 happiness units by sitting next to David.
|
||||
David would gain 46 happiness units by sitting next to Alice.
|
||||
David would lose 7 happiness units by sitting next to Bob.
|
||||
David would gain 41 happiness units by sitting next to Carol.
|
8
2015/day14-reindeer_olympics/Cargo.toml
Normal file
8
2015/day14-reindeer_olympics/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day14-reindeer_olympics"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
40
2015/day14-reindeer_olympics/challenge.txt
Normal file
40
2015/day14-reindeer_olympics/challenge.txt
Normal file
|
@ -0,0 +1,40 @@
|
|||
\--- Day 14: Reindeer Olympics ---
|
||||
----------
|
||||
|
||||
This year is the Reindeer Olympics! Reindeer can fly at high speeds, but must rest occasionally to recover their energy. Santa would like to know which of his reindeer is fastest, and so he has them race.
|
||||
|
||||
Reindeer can only either be *flying* (always at their top speed) or *resting* (not moving at all), and always spend whole seconds in either state.
|
||||
|
||||
For example, suppose you have the following Reindeer:
|
||||
|
||||
* Comet can fly *14 km/s for 10 seconds*, but then must rest for *127 seconds*.
|
||||
* Dancer can fly *16 km/s for 11 seconds*, but then must rest for *162 seconds*.
|
||||
|
||||
After one second, Comet has gone 14 km, while Dancer has gone 16 km. After ten seconds, Comet has gone 140 km, while Dancer has gone 160 km. On the eleventh second, Comet begins resting (staying at 140 km), and Dancer continues on for a total distance of 176 km. On the 12th second, both reindeer are resting. They continue to rest until the 138th second, when Comet flies for another ten seconds. On the 174th second, Dancer flies for another 11 seconds.
|
||||
|
||||
In this example, after the 1000th second, both reindeer are resting, and Comet is in the lead at *`1120`* km (poor Dancer has only gotten `1056` km by that point). So, in this situation, Comet would win (if the race ended at 1000 seconds).
|
||||
|
||||
Given the descriptions of each reindeer (in your puzzle input), after exactly `2503` seconds, *what distance has the winning reindeer traveled*?
|
||||
|
||||
Your puzzle answer was `2660`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Seeing how reindeer move in bursts, Santa decides he's not pleased with the old scoring system.
|
||||
|
||||
Instead, at the end of each second, he awards one point to the reindeer currently in the lead. (If there are multiple reindeer tied for the lead, they each get one point.) He keeps the traditional 2503 second time limit, of course, as doing otherwise would be entirely ridiculous.
|
||||
|
||||
Given the example reindeer from above, after the first second, Dancer is in the lead and gets one point. He stays in the lead until several seconds into Comet's second burst: after the 140th second, Comet pulls into the lead and gets his first point. Of course, since Dancer had been in the lead for the 139 seconds before that, he has accumulated 139 points by the 140th second.
|
||||
|
||||
After the 1000th second, Dancer has accumulated *`689`* points, while poor Comet, our old champion, only has `312`. So, with the new scoring system, Dancer would win (if the race ended at 1000 seconds).
|
||||
|
||||
Again given the descriptions of each reindeer (in your puzzle input), after exactly `2503` seconds, *how many points does the winning reindeer have*?
|
||||
|
||||
Your puzzle answer was `1256`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](14/input).
|
49
2015/day14-reindeer_olympics/src/lib.rs
Normal file
49
2015/day14-reindeer_olympics/src/lib.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
pub fn run(input: &str, finish_time: usize) -> (usize, usize) {
|
||||
let reindeers: Vec<_> = input.lines().map(get_speeds).collect();
|
||||
let first = reindeers.iter().map(|r| distance_at(*r, finish_time)).max().unwrap();
|
||||
let mut points = vec![0; reindeers.len()];
|
||||
for t in 1..=finish_time {
|
||||
let max = reindeers.iter().map(|r| distance_at(*r, t)).max().unwrap();
|
||||
reindeers.iter().enumerate().filter(|&(_idx, r)| distance_at(*r, t) == max).for_each(|(idx, _r)| points[idx] += 1);
|
||||
}
|
||||
let second = *points.iter().max().unwrap();
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn distance_at((speed, travel_time, rest_time): (usize, usize, usize), finish_time: usize) -> usize {
|
||||
let full_sorties = finish_time / (travel_time + rest_time);
|
||||
let last_partial = finish_time % (travel_time + rest_time);
|
||||
full_sorties * travel_time * speed + last_partial.min(travel_time) * speed
|
||||
}
|
||||
|
||||
fn get_speeds(line: &str) -> (usize, usize, usize) {
|
||||
let components: Vec<_> = line.split(' ').collect();
|
||||
assert_eq!(components.len(), 15);
|
||||
(
|
||||
components[3].parse().unwrap(),
|
||||
components[6].parse().unwrap(),
|
||||
components[13].parse().unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input, 1000), (1120, 689));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input, 2503), (2660, 1256));
|
||||
}
|
||||
}
|
9
2015/day14-reindeer_olympics/tests/challenge_input
Normal file
9
2015/day14-reindeer_olympics/tests/challenge_input
Normal file
|
@ -0,0 +1,9 @@
|
|||
Vixen can fly 19 km/s for 7 seconds, but then must rest for 124 seconds.
|
||||
Rudolph can fly 3 km/s for 15 seconds, but then must rest for 28 seconds.
|
||||
Donner can fly 19 km/s for 9 seconds, but then must rest for 164 seconds.
|
||||
Blitzen can fly 19 km/s for 9 seconds, but then must rest for 158 seconds.
|
||||
Comet can fly 13 km/s for 7 seconds, but then must rest for 82 seconds.
|
||||
Cupid can fly 25 km/s for 6 seconds, but then must rest for 145 seconds.
|
||||
Dasher can fly 14 km/s for 3 seconds, but then must rest for 38 seconds.
|
||||
Dancer can fly 3 km/s for 16 seconds, but then must rest for 37 seconds.
|
||||
Prancer can fly 25 km/s for 6 seconds, but then must rest for 143 seconds.
|
2
2015/day14-reindeer_olympics/tests/sample_input
Normal file
2
2015/day14-reindeer_olympics/tests/sample_input
Normal file
|
@ -0,0 +1,2 @@
|
|||
Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds.
|
||||
Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds.
|
8
2015/day15-science_for_hungry_people/Cargo.toml
Normal file
8
2015/day15-science_for_hungry_people/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day15-science_for_hungry_people"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
52
2015/day15-science_for_hungry_people/challenge.txt
Normal file
52
2015/day15-science_for_hungry_people/challenge.txt
Normal file
|
@ -0,0 +1,52 @@
|
|||
\--- Day 15: Science for Hungry People ---
|
||||
----------
|
||||
|
||||
Today, you set out on the task of perfecting your milk-dunking cookie recipe. All you have to do is find the right balance of ingredients.
|
||||
|
||||
Your recipe leaves room for exactly `100` teaspoons of ingredients. You make a list of the *remaining ingredients you could use to finish the recipe* (your puzzle input) and their *properties per teaspoon*:
|
||||
|
||||
* `capacity` (how well it helps the cookie absorb milk)
|
||||
* `durability` (how well it keeps the cookie intact when full of milk)
|
||||
* `flavor` (how tasty it makes the cookie)
|
||||
* `texture` (how it improves the feel of the cookie)
|
||||
* `calories` (how many calories it adds to the cookie)
|
||||
|
||||
You can only measure ingredients in whole-teaspoon amounts accurately, and you have to be accurate so you can reproduce your results in the future. The *total score* of a cookie can be found by adding up each of the properties (negative totals become `0`) and then multiplying together everything except calories.
|
||||
|
||||
For instance, suppose you have these two ingredients:
|
||||
|
||||
```
|
||||
Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8
|
||||
Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3
|
||||
|
||||
```
|
||||
|
||||
Then, choosing to use `44` teaspoons of butterscotch and `56` teaspoons of cinnamon (because the amounts of each ingredient must add up to `100`) would result in a cookie with the following properties:
|
||||
|
||||
* A `capacity` of `44*-1 + 56*2 = 68`
|
||||
* A `durability` of `44*-2 + 56*3 = 80`
|
||||
* A `flavor` of `44*6 + 56*-2 = 152`
|
||||
* A `texture` of `44*3 + 56*-1 = 76`
|
||||
|
||||
Multiplying these together (`68 * 80 * 152 * 76`, ignoring `calories` for now) results in a total score of `62842880`, which happens to be the best score possible given these ingredients. If any properties had produced a negative total, it would have instead become zero, causing the whole score to multiply to zero.
|
||||
|
||||
Given the ingredients in your kitchen and their properties, what is the *total score* of the highest-scoring cookie you can make?
|
||||
|
||||
Your puzzle answer was `222870`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Your cookie recipe becomes wildly popular! Someone asks if you can make another recipe that has exactly `500` calories per cookie (so they can use it as a meal replacement). Keep the rest of your award-winning process the same (100 teaspoons, same ingredients, same scoring system).
|
||||
|
||||
For example, given the ingredients above, if you had instead selected `40` teaspoons of butterscotch and `60` teaspoons of cinnamon (which still adds to `100`), the total calorie count would be `40*8 + 60*3 = 500`. The total score would go down, though: only `57600000`, the best you can do in such trying circumstances.
|
||||
|
||||
Given the ingredients in your kitchen and their properties, what is the *total score* of the highest-scoring cookie you can make with a calorie total of `500`?
|
||||
|
||||
Your puzzle answer was `117936`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](15/input).
|
95
2015/day15-science_for_hungry_people/src/lib.rs
Normal file
95
2015/day15-science_for_hungry_people/src/lib.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
struct Ingredient {
|
||||
capacity: isize,
|
||||
durability: isize,
|
||||
flavour: isize,
|
||||
texture: isize,
|
||||
calories: usize,
|
||||
}
|
||||
|
||||
impl Ingredient {
|
||||
fn parse(line: &str) -> Self {
|
||||
let components: Vec<_> = line.split(' ').collect();
|
||||
assert_eq!(components.len(), 11);
|
||||
Self {
|
||||
capacity: strip_last_char(components[2]).parse().unwrap(),
|
||||
durability: strip_last_char(components[4]).parse().unwrap(),
|
||||
flavour: strip_last_char(components[6]).parse().unwrap(),
|
||||
texture: strip_last_char(components[8]).parse().unwrap(),
|
||||
calories: components[10].parse().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn strip_last_char(string: &str) -> &str {
|
||||
&string[..string.len()-1]
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let ingredients: Vec<_> = input.lines().map(Ingredient::parse).collect();
|
||||
|
||||
let first = try_combinations(&ingredients, None);
|
||||
let second = try_combinations(&ingredients, Some(500));
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn try_combinations(ingredients: &Vec<Ingredient>, cal_requirement: Option<usize>) -> usize {
|
||||
let ingredient_count = ingredients.len();
|
||||
let amounts = vec![0; ingredient_count];
|
||||
|
||||
stars_and_bars(100, ingredient_count, &amounts, ingredients, cal_requirement)
|
||||
|
||||
}
|
||||
|
||||
fn stars_and_bars(stars: u8, bars: usize, amounts: &[u8], ingredients: &[Ingredient], cal_requirement: Option<usize>) -> usize {
|
||||
match bars {
|
||||
0 => get_score(amounts, ingredients, cal_requirement),
|
||||
1 => {
|
||||
let mut new_amounts = amounts.to_vec();
|
||||
new_amounts[0] = stars;
|
||||
stars_and_bars(0, 0, &new_amounts, ingredients, cal_requirement)
|
||||
},
|
||||
_ => {
|
||||
(0..=stars).map(|i| {
|
||||
let mut new_amounts = amounts.to_vec();
|
||||
new_amounts[bars-1] = i;
|
||||
stars_and_bars(stars-i, bars-1, &new_amounts, ingredients, cal_requirement)
|
||||
}).max().unwrap_or(0)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn get_score(amounts: &[u8], ingredients: &[Ingredient], cal_requirement: Option<usize>) -> usize {
|
||||
let calories = amounts.iter().enumerate().map(|(idx, &a)| a as usize * ingredients.get(idx).unwrap().calories).sum::<usize>();
|
||||
if cal_requirement.is_some() && Some(calories) != cal_requirement {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let capacity = amounts.iter().enumerate().map(|(idx, &a)| a as isize * ingredients.get(idx).unwrap().capacity).sum::<isize>().max(0);
|
||||
let durability = amounts.iter().enumerate().map(|(idx, &a)| a as isize * ingredients.get(idx).unwrap().durability).sum::<isize>().max(0);
|
||||
let flavour = amounts.iter().enumerate().map(|(idx, &a)| a as isize * ingredients.get(idx).unwrap().flavour).sum::<isize>().max(0);
|
||||
let texture = amounts.iter().enumerate().map(|(idx, &a)| a as isize * ingredients.get(idx).unwrap().texture).sum::<isize>().max(0);
|
||||
|
||||
(capacity * durability * texture * flavour) as usize
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (62842880, 57600000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (222870, 117936));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
Sugar: capacity 3, durability 0, flavor 0, texture -3, calories 2
|
||||
Sprinkles: capacity -3, durability 3, flavor 0, texture 0, calories 9
|
||||
Candy: capacity -1, durability 0, flavor 4, texture 0, calories 1
|
||||
Chocolate: capacity 0, durability 0, flavor -2, texture 2, calories 8
|
2
2015/day15-science_for_hungry_people/tests/sample_input
Normal file
2
2015/day15-science_for_hungry_people/tests/sample_input
Normal file
|
@ -0,0 +1,2 @@
|
|||
Butterscotch: capacity -1, durability -2, flavor 6, texture 3, calories 8
|
||||
Cinnamon: capacity 2, durability 3, flavor -2, texture -1, calories 3
|
8
2015/day16-aunt_sue/Cargo.toml
Normal file
8
2015/day16-aunt_sue/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day16-aunt_sue"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
57
2015/day16-aunt_sue/challenge.txt
Normal file
57
2015/day16-aunt_sue/challenge.txt
Normal file
|
@ -0,0 +1,57 @@
|
|||
\--- Day 16: Aunt Sue ---
|
||||
----------
|
||||
|
||||
Your Aunt Sue has given you a wonderful gift, and you'd like to send her a thank you card. However, there's a small problem: she signed it "From, Aunt Sue".
|
||||
|
||||
You have 500 Aunts named "Sue".
|
||||
|
||||
So, to avoid sending the card to the wrong person, you need to figure out which Aunt Sue (which you conveniently number 1 to 500, for sanity) gave you the gift. You open the present and, as luck would have it, good ol' Aunt Sue got you a My First Crime Scene Analysis Machine! Just what you wanted. Or needed, as the case may be.
|
||||
|
||||
The My First Crime Scene Analysis Machine (MFCSAM for short) can detect a few specific compounds in a given sample, as well as how many distinct kinds of those compounds there are. According to the instructions, these are what the MFCSAM can detect:
|
||||
|
||||
* `children`, by human DNA age analysis.
|
||||
* `cats`. It doesn't differentiate individual breeds.
|
||||
* Several seemingly random breeds of dog: `[samoyeds](https://en.wikipedia.org/wiki/Samoyed_%28dog%29)`, `[pomeranians](https://en.wikipedia.org/wiki/Pomeranian_%28dog%29)`, `[akitas](https://en.wikipedia.org/wiki/Akita_%28dog%29)`, and `[vizslas](https://en.wikipedia.org/wiki/Vizsla)`.
|
||||
* `goldfish`. No other kinds of fish.
|
||||
* `trees`, all in one group.
|
||||
* `cars`, presumably by exhaust or gasoline or something.
|
||||
* `perfumes`, which is handy, since many of your Aunts Sue wear a few kinds.
|
||||
|
||||
In fact, many of your Aunts Sue have many of these. You put the wrapping from the gift into the MFCSAM. It beeps inquisitively at you a few times and then prints out a message on [ticker tape](https://en.wikipedia.org/wiki/Ticker_tape):
|
||||
|
||||
```
|
||||
children: 3
|
||||
cats: 7
|
||||
samoyeds: 2
|
||||
pomeranians: 3
|
||||
akitas: 0
|
||||
vizslas: 0
|
||||
goldfish: 5
|
||||
trees: 3
|
||||
cars: 2
|
||||
perfumes: 1
|
||||
|
||||
```
|
||||
|
||||
You make a list of the things you can remember about each Aunt Sue. Things missing from your list aren't zero - you simply don't remember the value.
|
||||
|
||||
What is the *number* of the Sue that got you the gift?
|
||||
|
||||
Your puzzle answer was `103`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
As you're about to send the thank you note, something in the MFCSAM's instructions catches your eye. Apparently, it has an outdated [retroencabulator](https://www.youtube.com/watch?v=RXJKdh1KZ0w), and so the output from the machine isn't exact values - some of them indicate ranges.
|
||||
|
||||
In particular, the `cats` and `trees` readings indicates that there are *greater than* that many (due to the unpredictable nuclear decay of cat dander and tree pollen), while the `pomeranians` and `goldfish` readings indicate that there are *fewer than* that many (due to the modial interaction of magnetoreluctance).
|
||||
|
||||
What is the *number* of the real Aunt Sue?
|
||||
|
||||
Your puzzle answer was `405`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](16/input).
|
121
2015/day16-aunt_sue/src/lib.rs
Normal file
121
2015/day16-aunt_sue/src/lib.rs
Normal file
|
@ -0,0 +1,121 @@
|
|||
#[derive(Debug)]
|
||||
struct Aunt {
|
||||
children: Option<u8>,
|
||||
cats: Option<u8>,
|
||||
samoyeds: Option<u8>,
|
||||
pomeranians: Option<u8>,
|
||||
akitas: Option<u8>,
|
||||
vizslas: Option<u8>,
|
||||
goldfish: Option<u8>,
|
||||
trees: Option<u8>,
|
||||
cars: Option<u8>,
|
||||
perfumes: Option<u8>,
|
||||
}
|
||||
|
||||
impl Aunt{
|
||||
fn new(line: &str) -> Self {
|
||||
let components: Vec<_> = line.split(' ').collect();
|
||||
assert_eq!(components.len(), 8);
|
||||
let (mut children, mut cats, mut samoyeds, mut pomeranians, mut akitas,
|
||||
mut vizslas, mut goldfish, mut trees, mut cars, mut perfumes) = (None, None, None, None, None, None, None, None, None, None);
|
||||
for i in 0..2 {
|
||||
match components[2*i+2] {
|
||||
"children:" => children = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"cats:" => cats = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"samoyeds:" => samoyeds = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"pomeranians:" => pomeranians = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"akitas:" => akitas = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"vizslas:" => vizslas = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"goldfish:" => goldfish = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"trees:" => trees = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"cars:" => cars = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
"perfumes:" => perfumes = Some(strip_last_char(components[2*i+3]).parse().unwrap()),
|
||||
_ => panic!("Unknown component: {}", components[2*i+2]),
|
||||
}
|
||||
}
|
||||
match components[6] {
|
||||
"children:" => children = Some(components[7].parse().unwrap()),
|
||||
"cats:" => cats = Some(components[7].parse().unwrap()),
|
||||
"samoyeds:" => samoyeds = Some(components[7].parse().unwrap()),
|
||||
"pomeranians:" => pomeranians = Some(components[7].parse().unwrap()),
|
||||
"akitas:" => akitas = Some(components[7].parse().unwrap()),
|
||||
"vizslas:" => vizslas = Some(components[7].parse().unwrap()),
|
||||
"goldfish:" => goldfish = Some(components[7].parse().unwrap()),
|
||||
"trees:" => trees = Some(components[7].parse().unwrap()),
|
||||
"cars:" => cars = Some(components[7].parse().unwrap()),
|
||||
"perfumes:" => perfumes = Some(components[7].parse().unwrap()),
|
||||
_ => panic!("Unknown component: {}", components[6]),
|
||||
}
|
||||
|
||||
Self {
|
||||
children,
|
||||
cats,
|
||||
samoyeds,
|
||||
pomeranians,
|
||||
akitas,
|
||||
vizslas,
|
||||
goldfish,
|
||||
trees,
|
||||
cars,
|
||||
perfumes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let detected = Aunt {
|
||||
children: Some(3),
|
||||
cats: Some(7),
|
||||
samoyeds: Some(2),
|
||||
pomeranians: Some(3),
|
||||
akitas: Some(0),
|
||||
vizslas: Some(0),
|
||||
goldfish: Some(5),
|
||||
trees: Some(3),
|
||||
cars: Some(2),
|
||||
perfumes: Some(1)
|
||||
};
|
||||
let first = input.lines().map(Aunt::new).position(|a|
|
||||
(a.children.is_none() || a.children == detected.children) &&
|
||||
(a.cats.is_none() || a.cats == detected.cats) &&
|
||||
(a.samoyeds.is_none() || a.samoyeds == detected.samoyeds) &&
|
||||
(a.pomeranians.is_none() || a.pomeranians == detected.pomeranians) &&
|
||||
(a.akitas.is_none() || a.akitas == detected.akitas) &&
|
||||
(a.vizslas.is_none() || a.vizslas == detected.vizslas) &&
|
||||
(a.goldfish.is_none() || a.goldfish == detected.goldfish) &&
|
||||
(a.trees.is_none() || a.trees == detected.trees) &&
|
||||
(a.cars.is_none() || a.cars == detected.cars) &&
|
||||
(a.perfumes.is_none() || a.perfumes == detected.perfumes) ).unwrap() + 1;
|
||||
let second = input.lines().map(Aunt::new).position(|a|
|
||||
(a.children.is_none() || a.children == detected.children) &&
|
||||
(a.cats.is_none() || a.cats > detected.cats) &&
|
||||
(a.samoyeds.is_none() || a.samoyeds == detected.samoyeds) &&
|
||||
(a.pomeranians.is_none() || a.pomeranians < detected.pomeranians) &&
|
||||
(a.akitas.is_none() || a.akitas == detected.akitas) &&
|
||||
(a.vizslas.is_none() || a.vizslas == detected.vizslas) &&
|
||||
(a.goldfish.is_none() || a.goldfish < detected.goldfish) &&
|
||||
(a.trees.is_none() || a.trees > detected.trees) &&
|
||||
(a.cars.is_none() || a.cars == detected.cars) &&
|
||||
(a.perfumes.is_none() || a.perfumes == detected.perfumes) ).unwrap() + 1;
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn strip_last_char(string: &str) -> &str {
|
||||
&string[..string.len()-1]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (103, 405));
|
||||
}
|
||||
}
|
500
2015/day16-aunt_sue/tests/challenge_input
Normal file
500
2015/day16-aunt_sue/tests/challenge_input
Normal file
|
@ -0,0 +1,500 @@
|
|||
Sue 1: goldfish: 6, trees: 9, akitas: 0
|
||||
Sue 2: goldfish: 7, trees: 1, akitas: 0
|
||||
Sue 3: cars: 10, akitas: 6, perfumes: 7
|
||||
Sue 4: perfumes: 2, vizslas: 0, cars: 6
|
||||
Sue 5: goldfish: 1, trees: 3, perfumes: 10
|
||||
Sue 6: children: 9, vizslas: 7, cars: 9
|
||||
Sue 7: cars: 6, vizslas: 5, cats: 3
|
||||
Sue 8: akitas: 10, vizslas: 9, children: 3
|
||||
Sue 9: vizslas: 8, cats: 2, trees: 1
|
||||
Sue 10: perfumes: 10, trees: 6, cars: 4
|
||||
Sue 11: cars: 9, children: 1, cats: 1
|
||||
Sue 12: pomeranians: 4, akitas: 6, goldfish: 8
|
||||
Sue 13: cats: 10, children: 5, trees: 9
|
||||
Sue 14: perfumes: 8, vizslas: 3, samoyeds: 1
|
||||
Sue 15: vizslas: 2, perfumes: 8, trees: 3
|
||||
Sue 16: pomeranians: 10, trees: 9, samoyeds: 4
|
||||
Sue 17: akitas: 7, vizslas: 0, goldfish: 6
|
||||
Sue 18: trees: 5, vizslas: 9, cars: 0
|
||||
Sue 19: akitas: 3, goldfish: 9, trees: 10
|
||||
Sue 20: perfumes: 7, samoyeds: 3, vizslas: 10
|
||||
Sue 21: perfumes: 7, pomeranians: 10, akitas: 8
|
||||
Sue 22: vizslas: 6, trees: 8, akitas: 10
|
||||
Sue 23: goldfish: 0, trees: 4, children: 9
|
||||
Sue 24: goldfish: 7, pomeranians: 9, akitas: 4
|
||||
Sue 25: cars: 7, trees: 4, pomeranians: 4
|
||||
Sue 26: trees: 9, akitas: 9, pomeranians: 7
|
||||
Sue 27: samoyeds: 0, perfumes: 9, goldfish: 10
|
||||
Sue 28: cars: 5, trees: 7, vizslas: 1
|
||||
Sue 29: perfumes: 9, trees: 1, children: 6
|
||||
Sue 30: goldfish: 10, trees: 0, cars: 4
|
||||
Sue 31: akitas: 2, perfumes: 5, goldfish: 5
|
||||
Sue 32: goldfish: 0, akitas: 5, trees: 0
|
||||
Sue 33: vizslas: 2, akitas: 2, samoyeds: 3
|
||||
Sue 34: goldfish: 8, perfumes: 5, cars: 3
|
||||
Sue 35: akitas: 1, cats: 4, trees: 9
|
||||
Sue 36: cars: 4, vizslas: 4, goldfish: 7
|
||||
Sue 37: akitas: 5, perfumes: 7, trees: 3
|
||||
Sue 38: goldfish: 10, trees: 2, vizslas: 9
|
||||
Sue 39: goldfish: 4, pomeranians: 5, vizslas: 5
|
||||
Sue 40: perfumes: 5, samoyeds: 4, akitas: 6
|
||||
Sue 41: goldfish: 9, cars: 4, perfumes: 5
|
||||
Sue 42: trees: 6, pomeranians: 9, goldfish: 8
|
||||
Sue 43: perfumes: 7, pomeranians: 1, akitas: 2
|
||||
Sue 44: vizslas: 9, cars: 5, cats: 0
|
||||
Sue 45: akitas: 1, goldfish: 6, trees: 0
|
||||
Sue 46: akitas: 5, vizslas: 8, trees: 2
|
||||
Sue 47: trees: 9, akitas: 2, vizslas: 9
|
||||
Sue 48: goldfish: 10, trees: 5, akitas: 2
|
||||
Sue 49: cars: 7, vizslas: 2, perfumes: 6
|
||||
Sue 50: akitas: 5, goldfish: 6, perfumes: 0
|
||||
Sue 51: cars: 9, cats: 7, trees: 5
|
||||
Sue 52: akitas: 7, goldfish: 10, cars: 0
|
||||
Sue 53: cars: 10, cats: 4, perfumes: 2
|
||||
Sue 54: goldfish: 2, pomeranians: 5, perfumes: 10
|
||||
Sue 55: vizslas: 5, akitas: 4, cars: 8
|
||||
Sue 56: goldfish: 9, vizslas: 4, akitas: 5
|
||||
Sue 57: perfumes: 8, samoyeds: 7, cars: 9
|
||||
Sue 58: cars: 5, akitas: 7, perfumes: 8
|
||||
Sue 59: samoyeds: 8, cars: 10, vizslas: 10
|
||||
Sue 60: akitas: 6, samoyeds: 0, goldfish: 3
|
||||
Sue 61: trees: 8, pomeranians: 0, akitas: 2
|
||||
Sue 62: trees: 1, perfumes: 3, vizslas: 4
|
||||
Sue 63: vizslas: 6, samoyeds: 9, goldfish: 8
|
||||
Sue 64: goldfish: 7, trees: 6, vizslas: 3
|
||||
Sue 65: cars: 1, vizslas: 0, akitas: 6
|
||||
Sue 66: cats: 6, pomeranians: 4, cars: 9
|
||||
Sue 67: trees: 10, pomeranians: 7, samoyeds: 3
|
||||
Sue 68: pomeranians: 5, goldfish: 9, akitas: 1
|
||||
Sue 69: akitas: 1, vizslas: 0, trees: 9
|
||||
Sue 70: cats: 4, goldfish: 4, vizslas: 10
|
||||
Sue 71: vizslas: 7, perfumes: 7, trees: 8
|
||||
Sue 72: children: 2, vizslas: 9, cats: 3
|
||||
Sue 73: cars: 8, pomeranians: 0, perfumes: 6
|
||||
Sue 74: akitas: 1, pomeranians: 8, vizslas: 10
|
||||
Sue 75: vizslas: 5, perfumes: 5, cars: 7
|
||||
Sue 76: cars: 3, vizslas: 3, goldfish: 0
|
||||
Sue 77: akitas: 9, samoyeds: 1, pomeranians: 3
|
||||
Sue 78: trees: 0, vizslas: 0, akitas: 6
|
||||
Sue 79: pomeranians: 9, cars: 1, perfumes: 0
|
||||
Sue 80: perfumes: 10, trees: 1, cats: 0
|
||||
Sue 81: goldfish: 5, akitas: 9, trees: 0
|
||||
Sue 82: vizslas: 1, akitas: 6, children: 4
|
||||
Sue 83: samoyeds: 7, perfumes: 8, pomeranians: 4
|
||||
Sue 84: perfumes: 3, children: 3, cats: 7
|
||||
Sue 85: goldfish: 9, trees: 3, cars: 9
|
||||
Sue 86: cars: 0, perfumes: 9, vizslas: 0
|
||||
Sue 87: children: 3, trees: 4, akitas: 3
|
||||
Sue 88: trees: 1, samoyeds: 1, goldfish: 0
|
||||
Sue 89: akitas: 8, cars: 3, vizslas: 9
|
||||
Sue 90: pomeranians: 9, trees: 9, goldfish: 8
|
||||
Sue 91: goldfish: 7, trees: 10, children: 0
|
||||
Sue 92: cats: 9, cars: 7, perfumes: 7
|
||||
Sue 93: vizslas: 2, goldfish: 7, cats: 9
|
||||
Sue 94: akitas: 5, cars: 8, vizslas: 4
|
||||
Sue 95: goldfish: 7, vizslas: 1, perfumes: 2
|
||||
Sue 96: goldfish: 5, trees: 6, perfumes: 10
|
||||
Sue 97: trees: 0, perfumes: 7, cars: 0
|
||||
Sue 98: cars: 2, perfumes: 6, trees: 8
|
||||
Sue 99: trees: 10, children: 7, cats: 9
|
||||
Sue 100: samoyeds: 5, goldfish: 6, vizslas: 6
|
||||
Sue 101: cars: 10, perfumes: 9, vizslas: 3
|
||||
Sue 102: pomeranians: 6, trees: 1, samoyeds: 4
|
||||
Sue 103: cars: 2, perfumes: 1, goldfish: 5
|
||||
Sue 104: goldfish: 2, cars: 8, pomeranians: 2
|
||||
Sue 105: goldfish: 6, vizslas: 0, trees: 10
|
||||
Sue 106: trees: 10, akitas: 10, pomeranians: 0
|
||||
Sue 107: vizslas: 2, pomeranians: 10, trees: 3
|
||||
Sue 108: children: 3, vizslas: 8, akitas: 7
|
||||
Sue 109: perfumes: 2, akitas: 2, samoyeds: 3
|
||||
Sue 110: goldfish: 7, trees: 1, perfumes: 1
|
||||
Sue 111: akitas: 2, cars: 9, perfumes: 2
|
||||
Sue 112: children: 10, cars: 0, akitas: 3
|
||||
Sue 113: akitas: 9, vizslas: 4, children: 3
|
||||
Sue 114: pomeranians: 3, trees: 2, goldfish: 5
|
||||
Sue 115: perfumes: 8, cars: 6, trees: 0
|
||||
Sue 116: samoyeds: 6, children: 3, pomeranians: 1
|
||||
Sue 117: goldfish: 1, trees: 2, akitas: 1
|
||||
Sue 118: goldfish: 10, akitas: 10, samoyeds: 0
|
||||
Sue 119: vizslas: 10, perfumes: 6, cars: 0
|
||||
Sue 120: cars: 2, perfumes: 9, goldfish: 5
|
||||
Sue 121: vizslas: 2, trees: 2, cars: 6
|
||||
Sue 122: vizslas: 3, trees: 0, akitas: 2
|
||||
Sue 123: akitas: 5, samoyeds: 7, goldfish: 1
|
||||
Sue 124: goldfish: 8, samoyeds: 7, trees: 8
|
||||
Sue 125: trees: 3, goldfish: 8, perfumes: 5
|
||||
Sue 126: cats: 3, vizslas: 9, goldfish: 0
|
||||
Sue 127: pomeranians: 9, goldfish: 3, perfumes: 6
|
||||
Sue 128: vizslas: 4, cars: 8, goldfish: 5
|
||||
Sue 129: vizslas: 8, children: 5, perfumes: 8
|
||||
Sue 130: cars: 7, children: 7, cats: 3
|
||||
Sue 131: perfumes: 1, akitas: 8, vizslas: 9
|
||||
Sue 132: perfumes: 7, samoyeds: 10, pomeranians: 6
|
||||
Sue 133: cars: 5, perfumes: 3, goldfish: 7
|
||||
Sue 134: perfumes: 9, akitas: 2, cats: 3
|
||||
Sue 135: perfumes: 1, trees: 9, vizslas: 9
|
||||
Sue 136: akitas: 7, cars: 3, perfumes: 7
|
||||
Sue 137: vizslas: 9, goldfish: 8, cars: 5
|
||||
Sue 138: trees: 0, samoyeds: 1, cars: 3
|
||||
Sue 139: cars: 0, perfumes: 6, trees: 0
|
||||
Sue 140: pomeranians: 4, cars: 1, perfumes: 7
|
||||
Sue 141: vizslas: 10, akitas: 8, cats: 3
|
||||
Sue 142: trees: 1, cats: 6, vizslas: 5
|
||||
Sue 143: pomeranians: 9, cars: 7, perfumes: 9
|
||||
Sue 144: cars: 0, perfumes: 2, pomeranians: 1
|
||||
Sue 145: trees: 1, goldfish: 9, perfumes: 8
|
||||
Sue 146: cars: 8, children: 5, vizslas: 2
|
||||
Sue 147: perfumes: 2, goldfish: 5, cars: 0
|
||||
Sue 148: akitas: 2, perfumes: 7, pomeranians: 6
|
||||
Sue 149: goldfish: 8, cars: 0, trees: 1
|
||||
Sue 150: akitas: 6, perfumes: 5, trees: 0
|
||||
Sue 151: vizslas: 6, samoyeds: 8, akitas: 10
|
||||
Sue 152: trees: 7, akitas: 7, perfumes: 6
|
||||
Sue 153: goldfish: 9, cats: 9, cars: 3
|
||||
Sue 154: vizslas: 10, trees: 0, cars: 9
|
||||
Sue 155: perfumes: 3, children: 2, goldfish: 1
|
||||
Sue 156: goldfish: 7, perfumes: 5, akitas: 6
|
||||
Sue 157: cats: 10, trees: 1, goldfish: 0
|
||||
Sue 158: cats: 7, children: 7, vizslas: 6
|
||||
Sue 159: perfumes: 9, akitas: 0, cars: 0
|
||||
Sue 160: akitas: 3, goldfish: 10, pomeranians: 2
|
||||
Sue 161: goldfish: 10, cars: 6, perfumes: 3
|
||||
Sue 162: trees: 0, cars: 9, goldfish: 1
|
||||
Sue 163: cars: 8, perfumes: 9, vizslas: 5
|
||||
Sue 164: goldfish: 1, trees: 10, children: 6
|
||||
Sue 165: goldfish: 0, vizslas: 6, cars: 0
|
||||
Sue 166: akitas: 5, vizslas: 1, cars: 5
|
||||
Sue 167: vizslas: 1, samoyeds: 1, children: 4
|
||||
Sue 168: samoyeds: 7, vizslas: 7, akitas: 3
|
||||
Sue 169: goldfish: 3, cats: 9, trees: 2
|
||||
Sue 170: cars: 5, perfumes: 9, vizslas: 5
|
||||
Sue 171: goldfish: 7, cars: 6, perfumes: 10
|
||||
Sue 172: cats: 6, akitas: 1, children: 6
|
||||
Sue 173: cats: 4, goldfish: 1, children: 3
|
||||
Sue 174: cars: 2, pomeranians: 2, vizslas: 7
|
||||
Sue 175: trees: 0, children: 4, goldfish: 7
|
||||
Sue 176: children: 8, cars: 5, cats: 9
|
||||
Sue 177: pomeranians: 4, vizslas: 7, trees: 3
|
||||
Sue 178: vizslas: 6, perfumes: 10, akitas: 6
|
||||
Sue 179: cars: 4, akitas: 4, trees: 4
|
||||
Sue 180: akitas: 8, goldfish: 6, trees: 9
|
||||
Sue 181: perfumes: 3, vizslas: 10, cars: 3
|
||||
Sue 182: vizslas: 3, samoyeds: 3, goldfish: 7
|
||||
Sue 183: goldfish: 10, perfumes: 2, cats: 1
|
||||
Sue 184: goldfish: 5, trees: 1, perfumes: 1
|
||||
Sue 185: vizslas: 10, trees: 9, perfumes: 2
|
||||
Sue 186: goldfish: 6, perfumes: 9, trees: 1
|
||||
Sue 187: cars: 0, trees: 9, goldfish: 6
|
||||
Sue 188: cars: 0, trees: 1, vizslas: 9
|
||||
Sue 189: akitas: 7, vizslas: 2, trees: 0
|
||||
Sue 190: pomeranians: 5, perfumes: 8, akitas: 10
|
||||
Sue 191: vizslas: 5, akitas: 3, cats: 0
|
||||
Sue 192: children: 1, trees: 1, cars: 2
|
||||
Sue 193: cars: 3, goldfish: 9, trees: 2
|
||||
Sue 194: samoyeds: 3, akitas: 4, perfumes: 8
|
||||
Sue 195: trees: 1, vizslas: 8, akitas: 10
|
||||
Sue 196: akitas: 6, cars: 5, pomeranians: 0
|
||||
Sue 197: akitas: 5, vizslas: 5, cats: 1
|
||||
Sue 198: trees: 4, cars: 6, goldfish: 6
|
||||
Sue 199: cats: 7, cars: 5, goldfish: 6
|
||||
Sue 200: vizslas: 4, cats: 0, akitas: 9
|
||||
Sue 201: pomeranians: 1, perfumes: 4, children: 2
|
||||
Sue 202: cats: 1, perfumes: 4, vizslas: 3
|
||||
Sue 203: vizslas: 1, akitas: 9, children: 5
|
||||
Sue 204: perfumes: 8, cars: 7, trees: 4
|
||||
Sue 205: perfumes: 7, pomeranians: 5, cats: 9
|
||||
Sue 206: vizslas: 8, trees: 2, akitas: 2
|
||||
Sue 207: akitas: 6, vizslas: 2, perfumes: 10
|
||||
Sue 208: vizslas: 1, children: 7, akitas: 4
|
||||
Sue 209: perfumes: 4, trees: 2, children: 1
|
||||
Sue 210: goldfish: 0, vizslas: 2, samoyeds: 10
|
||||
Sue 211: cars: 8, perfumes: 3, trees: 1
|
||||
Sue 212: cars: 8, samoyeds: 5, pomeranians: 8
|
||||
Sue 213: akitas: 2, goldfish: 8, pomeranians: 2
|
||||
Sue 214: akitas: 6, pomeranians: 2, cars: 0
|
||||
Sue 215: trees: 10, pomeranians: 4, vizslas: 0
|
||||
Sue 216: perfumes: 0, cars: 8, trees: 0
|
||||
Sue 217: samoyeds: 8, akitas: 7, children: 10
|
||||
Sue 218: perfumes: 1, vizslas: 6, children: 0
|
||||
Sue 219: children: 1, goldfish: 4, trees: 1
|
||||
Sue 220: akitas: 10, goldfish: 10, trees: 5
|
||||
Sue 221: cars: 7, pomeranians: 6, perfumes: 3
|
||||
Sue 222: vizslas: 6, children: 0, akitas: 5
|
||||
Sue 223: perfumes: 9, cars: 1, trees: 6
|
||||
Sue 224: pomeranians: 1, trees: 0, vizslas: 0
|
||||
Sue 225: goldfish: 8, akitas: 4, perfumes: 10
|
||||
Sue 226: pomeranians: 7, cats: 7, children: 4
|
||||
Sue 227: trees: 0, akitas: 2, perfumes: 1
|
||||
Sue 228: vizslas: 6, cars: 10, perfumes: 9
|
||||
Sue 229: cars: 0, perfumes: 6, trees: 4
|
||||
Sue 230: pomeranians: 7, perfumes: 5, trees: 2
|
||||
Sue 231: goldfish: 9, cars: 6, trees: 7
|
||||
Sue 232: akitas: 1, vizslas: 5, cars: 3
|
||||
Sue 233: akitas: 7, samoyeds: 2, vizslas: 5
|
||||
Sue 234: akitas: 6, cats: 8, pomeranians: 0
|
||||
Sue 235: pomeranians: 5, akitas: 5, vizslas: 3
|
||||
Sue 236: goldfish: 5, trees: 6, akitas: 5
|
||||
Sue 237: goldfish: 9, perfumes: 5, cats: 5
|
||||
Sue 238: cats: 8, goldfish: 4, perfumes: 0
|
||||
Sue 239: samoyeds: 8, children: 6, pomeranians: 6
|
||||
Sue 240: akitas: 4, samoyeds: 10, trees: 8
|
||||
Sue 241: trees: 2, goldfish: 8, cars: 1
|
||||
Sue 242: perfumes: 2, cars: 0, akitas: 10
|
||||
Sue 243: pomeranians: 1, cars: 7, trees: 2
|
||||
Sue 244: trees: 9, vizslas: 2, akitas: 10
|
||||
Sue 245: cars: 9, pomeranians: 4, trees: 0
|
||||
Sue 246: cars: 9, pomeranians: 7, perfumes: 1
|
||||
Sue 247: trees: 0, goldfish: 1, akitas: 8
|
||||
Sue 248: vizslas: 1, cats: 4, akitas: 4
|
||||
Sue 249: cats: 6, children: 4, goldfish: 9
|
||||
Sue 250: vizslas: 1, cars: 10, samoyeds: 5
|
||||
Sue 251: cars: 0, goldfish: 1, vizslas: 7
|
||||
Sue 252: cars: 7, akitas: 9, vizslas: 10
|
||||
Sue 253: akitas: 7, vizslas: 2, perfumes: 5
|
||||
Sue 254: vizslas: 10, akitas: 5, samoyeds: 0
|
||||
Sue 255: pomeranians: 8, goldfish: 0, cats: 6
|
||||
Sue 256: cars: 10, goldfish: 8, vizslas: 9
|
||||
Sue 257: goldfish: 3, perfumes: 9, cats: 3
|
||||
Sue 258: trees: 6, goldfish: 6, cars: 6
|
||||
Sue 259: trees: 0, goldfish: 2, perfumes: 8
|
||||
Sue 260: trees: 5, akitas: 0, cars: 0
|
||||
Sue 261: pomeranians: 9, goldfish: 7, perfumes: 8
|
||||
Sue 262: perfumes: 8, vizslas: 6, goldfish: 2
|
||||
Sue 263: vizslas: 6, trees: 5, goldfish: 9
|
||||
Sue 264: vizslas: 4, perfumes: 7, cars: 9
|
||||
Sue 265: goldfish: 10, trees: 3, perfumes: 1
|
||||
Sue 266: trees: 10, akitas: 8, goldfish: 8
|
||||
Sue 267: goldfish: 4, trees: 0, samoyeds: 9
|
||||
Sue 268: vizslas: 1, trees: 0, goldfish: 8
|
||||
Sue 269: cars: 2, perfumes: 10, goldfish: 5
|
||||
Sue 270: perfumes: 7, cars: 2, vizslas: 1
|
||||
Sue 271: cars: 6, perfumes: 10, goldfish: 6
|
||||
Sue 272: samoyeds: 4, goldfish: 2, vizslas: 9
|
||||
Sue 273: perfumes: 4, goldfish: 4, vizslas: 1
|
||||
Sue 274: children: 4, cars: 4, perfumes: 3
|
||||
Sue 275: children: 8, vizslas: 3, trees: 2
|
||||
Sue 276: vizslas: 5, children: 7, perfumes: 3
|
||||
Sue 277: perfumes: 3, cats: 4, vizslas: 5
|
||||
Sue 278: cars: 1, samoyeds: 10, akitas: 2
|
||||
Sue 279: trees: 9, perfumes: 9, cars: 10
|
||||
Sue 280: vizslas: 5, trees: 0, perfumes: 6
|
||||
Sue 281: vizslas: 3, akitas: 10, pomeranians: 7
|
||||
Sue 282: trees: 1, children: 2, akitas: 8
|
||||
Sue 283: akitas: 9, goldfish: 6, cats: 5
|
||||
Sue 284: cars: 9, children: 10, pomeranians: 2
|
||||
Sue 285: pomeranians: 0, perfumes: 4, cars: 7
|
||||
Sue 286: perfumes: 0, vizslas: 10, akitas: 10
|
||||
Sue 287: cats: 2, perfumes: 3, trees: 5
|
||||
Sue 288: akitas: 9, vizslas: 8, samoyeds: 9
|
||||
Sue 289: perfumes: 6, children: 2, cars: 7
|
||||
Sue 290: akitas: 0, children: 5, cars: 5
|
||||
Sue 291: cars: 4, perfumes: 0, trees: 1
|
||||
Sue 292: cats: 0, cars: 8, perfumes: 6
|
||||
Sue 293: akitas: 9, cats: 5, children: 5
|
||||
Sue 294: akitas: 4, cars: 9, goldfish: 3
|
||||
Sue 295: cars: 2, akitas: 3, perfumes: 7
|
||||
Sue 296: perfumes: 4, cars: 7, goldfish: 10
|
||||
Sue 297: trees: 5, akitas: 8, vizslas: 1
|
||||
Sue 298: perfumes: 0, goldfish: 6, trees: 9
|
||||
Sue 299: perfumes: 6, samoyeds: 8, cars: 1
|
||||
Sue 300: goldfish: 10, perfumes: 4, akitas: 2
|
||||
Sue 301: cars: 3, trees: 0, goldfish: 8
|
||||
Sue 302: perfumes: 7, samoyeds: 2, vizslas: 7
|
||||
Sue 303: children: 10, goldfish: 7, perfumes: 2
|
||||
Sue 304: samoyeds: 8, vizslas: 2, cars: 1
|
||||
Sue 305: trees: 1, cats: 0, goldfish: 10
|
||||
Sue 306: trees: 4, perfumes: 2, cars: 7
|
||||
Sue 307: cars: 6, vizslas: 2, children: 6
|
||||
Sue 308: vizslas: 2, cars: 0, akitas: 7
|
||||
Sue 309: cars: 3, vizslas: 8, perfumes: 6
|
||||
Sue 310: goldfish: 7, perfumes: 7, vizslas: 3
|
||||
Sue 311: pomeranians: 10, trees: 2, cars: 0
|
||||
Sue 312: samoyeds: 2, vizslas: 9, akitas: 1
|
||||
Sue 313: cars: 4, pomeranians: 7, goldfish: 7
|
||||
Sue 314: akitas: 2, pomeranians: 9, samoyeds: 10
|
||||
Sue 315: akitas: 3, vizslas: 2, trees: 0
|
||||
Sue 316: cars: 0, perfumes: 4, pomeranians: 6
|
||||
Sue 317: akitas: 10, goldfish: 3, pomeranians: 7
|
||||
Sue 318: cars: 9, trees: 0, pomeranians: 9
|
||||
Sue 319: akitas: 3, vizslas: 7, children: 10
|
||||
Sue 320: vizslas: 0, akitas: 8, pomeranians: 4
|
||||
Sue 321: cars: 10, akitas: 9, vizslas: 3
|
||||
Sue 322: perfumes: 0, akitas: 8, vizslas: 6
|
||||
Sue 323: vizslas: 10, perfumes: 5, cars: 3
|
||||
Sue 324: akitas: 0, goldfish: 6, vizslas: 7
|
||||
Sue 325: perfumes: 9, vizslas: 5, pomeranians: 2
|
||||
Sue 326: vizslas: 6, goldfish: 10, pomeranians: 8
|
||||
Sue 327: vizslas: 10, cars: 1, akitas: 7
|
||||
Sue 328: trees: 1, perfumes: 10, cars: 10
|
||||
Sue 329: pomeranians: 5, samoyeds: 3, cars: 10
|
||||
Sue 330: akitas: 6, cars: 1, pomeranians: 4
|
||||
Sue 331: cars: 5, children: 2, trees: 0
|
||||
Sue 332: vizslas: 6, pomeranians: 1, perfumes: 0
|
||||
Sue 333: akitas: 7, trees: 1, cats: 9
|
||||
Sue 334: vizslas: 6, goldfish: 9, akitas: 7
|
||||
Sue 335: akitas: 3, samoyeds: 3, cars: 3
|
||||
Sue 336: samoyeds: 10, perfumes: 9, trees: 6
|
||||
Sue 337: vizslas: 2, cars: 9, akitas: 0
|
||||
Sue 338: akitas: 6, perfumes: 9, vizslas: 3
|
||||
Sue 339: cars: 3, samoyeds: 8, trees: 2
|
||||
Sue 340: cats: 7, perfumes: 8, cars: 9
|
||||
Sue 341: goldfish: 9, perfumes: 5, cars: 10
|
||||
Sue 342: trees: 0, akitas: 3, perfumes: 5
|
||||
Sue 343: perfumes: 2, children: 0, cars: 6
|
||||
Sue 344: goldfish: 8, trees: 8, perfumes: 0
|
||||
Sue 345: perfumes: 6, cars: 6, goldfish: 5
|
||||
Sue 346: vizslas: 8, trees: 1, cars: 6
|
||||
Sue 347: cars: 0, cats: 3, perfumes: 7
|
||||
Sue 348: children: 7, perfumes: 10, cars: 7
|
||||
Sue 349: pomeranians: 8, akitas: 5, children: 2
|
||||
Sue 350: perfumes: 9, pomeranians: 4, goldfish: 3
|
||||
Sue 351: perfumes: 8, pomeranians: 7, trees: 4
|
||||
Sue 352: samoyeds: 1, goldfish: 9, akitas: 8
|
||||
Sue 353: akitas: 6, goldfish: 10, vizslas: 8
|
||||
Sue 354: akitas: 7, cars: 2, goldfish: 6
|
||||
Sue 355: cars: 3, goldfish: 6, akitas: 5
|
||||
Sue 356: akitas: 2, goldfish: 9, pomeranians: 1
|
||||
Sue 357: goldfish: 10, cars: 6, pomeranians: 9
|
||||
Sue 358: trees: 0, children: 2, goldfish: 6
|
||||
Sue 359: samoyeds: 3, cars: 2, akitas: 4
|
||||
Sue 360: trees: 1, goldfish: 8, cars: 5
|
||||
Sue 361: akitas: 5, vizslas: 7, perfumes: 1
|
||||
Sue 362: cats: 5, vizslas: 9, children: 4
|
||||
Sue 363: goldfish: 9, perfumes: 3, vizslas: 9
|
||||
Sue 364: children: 7, samoyeds: 2, pomeranians: 10
|
||||
Sue 365: perfumes: 9, akitas: 10, pomeranians: 4
|
||||
Sue 366: cars: 10, trees: 3, cats: 4
|
||||
Sue 367: vizslas: 6, akitas: 10, perfumes: 5
|
||||
Sue 368: akitas: 9, vizslas: 9, children: 4
|
||||
Sue 369: goldfish: 8, trees: 2, perfumes: 5
|
||||
Sue 370: trees: 0, children: 4, cars: 8
|
||||
Sue 371: cats: 6, perfumes: 0, vizslas: 2
|
||||
Sue 372: akitas: 7, cars: 5, perfumes: 3
|
||||
Sue 373: cars: 0, perfumes: 4, pomeranians: 10
|
||||
Sue 374: akitas: 5, perfumes: 5, vizslas: 2
|
||||
Sue 375: goldfish: 7, trees: 10, pomeranians: 7
|
||||
Sue 376: cars: 8, trees: 1, pomeranians: 8
|
||||
Sue 377: cars: 0, akitas: 9, vizslas: 1
|
||||
Sue 378: akitas: 5, perfumes: 3, vizslas: 7
|
||||
Sue 379: trees: 2, goldfish: 8, pomeranians: 8
|
||||
Sue 380: akitas: 5, cars: 9, perfumes: 9
|
||||
Sue 381: cars: 2, perfumes: 6, trees: 3
|
||||
Sue 382: perfumes: 6, vizslas: 2, goldfish: 9
|
||||
Sue 383: akitas: 8, vizslas: 7, cats: 1
|
||||
Sue 384: akitas: 9, trees: 10, vizslas: 7
|
||||
Sue 385: cars: 0, perfumes: 7, vizslas: 2
|
||||
Sue 386: vizslas: 10, akitas: 4, perfumes: 9
|
||||
Sue 387: perfumes: 6, pomeranians: 5, samoyeds: 8
|
||||
Sue 388: vizslas: 10, trees: 9, goldfish: 9
|
||||
Sue 389: goldfish: 8, akitas: 4, perfumes: 10
|
||||
Sue 390: goldfish: 6, trees: 8, akitas: 1
|
||||
Sue 391: vizslas: 4, akitas: 10, goldfish: 7
|
||||
Sue 392: akitas: 1, vizslas: 6, samoyeds: 5
|
||||
Sue 393: trees: 6, cars: 3, akitas: 5
|
||||
Sue 394: goldfish: 9, trees: 3, cars: 5
|
||||
Sue 395: akitas: 6, samoyeds: 4, goldfish: 4
|
||||
Sue 396: akitas: 2, trees: 1, cats: 5
|
||||
Sue 397: cars: 0, children: 9, trees: 10
|
||||
Sue 398: pomeranians: 3, samoyeds: 9, goldfish: 10
|
||||
Sue 399: cars: 7, akitas: 4, goldfish: 8
|
||||
Sue 400: cars: 4, akitas: 5, vizslas: 4
|
||||
Sue 401: pomeranians: 5, akitas: 8, vizslas: 5
|
||||
Sue 402: cats: 7, cars: 6, goldfish: 6
|
||||
Sue 403: samoyeds: 8, perfumes: 4, cars: 5
|
||||
Sue 404: akitas: 10, goldfish: 4, trees: 2
|
||||
Sue 405: trees: 8, perfumes: 1, cars: 2
|
||||
Sue 406: trees: 0, perfumes: 9, pomeranians: 10
|
||||
Sue 407: perfumes: 4, trees: 7, goldfish: 3
|
||||
Sue 408: akitas: 1, perfumes: 3, cars: 5
|
||||
Sue 409: trees: 6, samoyeds: 3, cars: 9
|
||||
Sue 410: vizslas: 3, goldfish: 5, akitas: 7
|
||||
Sue 411: goldfish: 10, trees: 1, vizslas: 9
|
||||
Sue 412: cars: 0, akitas: 6, trees: 6
|
||||
Sue 413: goldfish: 7, trees: 0, cars: 3
|
||||
Sue 414: pomeranians: 10, samoyeds: 3, cars: 10
|
||||
Sue 415: perfumes: 6, trees: 9, cars: 4
|
||||
Sue 416: trees: 2, cars: 4, goldfish: 8
|
||||
Sue 417: goldfish: 2, cars: 9, cats: 5
|
||||
Sue 418: vizslas: 1, cars: 9, akitas: 0
|
||||
Sue 419: perfumes: 6, cats: 3, children: 9
|
||||
Sue 420: cats: 5, goldfish: 7, akitas: 9
|
||||
Sue 421: trees: 1, samoyeds: 6, pomeranians: 1
|
||||
Sue 422: trees: 10, goldfish: 6, children: 7
|
||||
Sue 423: cars: 8, goldfish: 7, vizslas: 3
|
||||
Sue 424: samoyeds: 9, akitas: 7, trees: 5
|
||||
Sue 425: akitas: 5, children: 4, perfumes: 9
|
||||
Sue 426: goldfish: 1, children: 9, cats: 2
|
||||
Sue 427: vizslas: 9, akitas: 7, goldfish: 9
|
||||
Sue 428: pomeranians: 7, akitas: 5, vizslas: 1
|
||||
Sue 429: vizslas: 7, goldfish: 7, cars: 9
|
||||
Sue 430: trees: 7, perfumes: 0, pomeranians: 5
|
||||
Sue 431: children: 9, perfumes: 5, vizslas: 7
|
||||
Sue 432: trees: 6, samoyeds: 7, cats: 1
|
||||
Sue 433: goldfish: 5, trees: 5, children: 6
|
||||
Sue 434: goldfish: 9, akitas: 7, cars: 3
|
||||
Sue 435: samoyeds: 10, perfumes: 2, cars: 0
|
||||
Sue 436: akitas: 5, pomeranians: 4, perfumes: 7
|
||||
Sue 437: vizslas: 5, cats: 6, perfumes: 5
|
||||
Sue 438: trees: 2, goldfish: 6, vizslas: 7
|
||||
Sue 439: samoyeds: 8, pomeranians: 10, goldfish: 1
|
||||
Sue 440: akitas: 6, children: 9, perfumes: 4
|
||||
Sue 441: cars: 2, goldfish: 9, children: 0
|
||||
Sue 442: goldfish: 7, cars: 2, vizslas: 8
|
||||
Sue 443: goldfish: 6, samoyeds: 3, perfumes: 2
|
||||
Sue 444: trees: 2, goldfish: 7, cars: 8
|
||||
Sue 445: trees: 2, pomeranians: 0, children: 0
|
||||
Sue 446: perfumes: 4, akitas: 4, goldfish: 6
|
||||
Sue 447: vizslas: 7, akitas: 9, cars: 3
|
||||
Sue 448: goldfish: 6, trees: 9, cars: 0
|
||||
Sue 449: samoyeds: 7, perfumes: 4, vizslas: 10
|
||||
Sue 450: akitas: 7, cars: 10, goldfish: 7
|
||||
Sue 451: goldfish: 4, children: 7, pomeranians: 4
|
||||
Sue 452: cats: 4, vizslas: 6, trees: 7
|
||||
Sue 453: cars: 1, trees: 10, goldfish: 9
|
||||
Sue 454: trees: 2, goldfish: 3, vizslas: 10
|
||||
Sue 455: pomeranians: 9, vizslas: 3, akitas: 2
|
||||
Sue 456: vizslas: 10, akitas: 2, goldfish: 1
|
||||
Sue 457: trees: 5, cats: 5, children: 8
|
||||
Sue 458: cars: 6, goldfish: 3, akitas: 9
|
||||
Sue 459: goldfish: 7, akitas: 2, cats: 7
|
||||
Sue 460: akitas: 1, cars: 5, children: 8
|
||||
Sue 461: cars: 8, perfumes: 0, goldfish: 6
|
||||
Sue 462: pomeranians: 6, cats: 2, perfumes: 6
|
||||
Sue 463: vizslas: 7, perfumes: 3, goldfish: 3
|
||||
Sue 464: akitas: 10, goldfish: 10, trees: 1
|
||||
Sue 465: vizslas: 0, akitas: 2, trees: 2
|
||||
Sue 466: perfumes: 6, akitas: 8, cars: 2
|
||||
Sue 467: goldfish: 1, cars: 10, perfumes: 3
|
||||
Sue 468: goldfish: 4, trees: 2, cars: 9
|
||||
Sue 469: perfumes: 6, pomeranians: 0, vizslas: 10
|
||||
Sue 470: samoyeds: 8, children: 0, akitas: 7
|
||||
Sue 471: children: 3, goldfish: 9, cats: 9
|
||||
Sue 472: samoyeds: 0, goldfish: 0, trees: 0
|
||||
Sue 473: trees: 3, goldfish: 4, vizslas: 1
|
||||
Sue 474: perfumes: 10, cars: 3, trees: 7
|
||||
Sue 475: akitas: 5, vizslas: 4, goldfish: 5
|
||||
Sue 476: children: 2, akitas: 7, vizslas: 3
|
||||
Sue 477: vizslas: 6, pomeranians: 9, trees: 6
|
||||
Sue 478: vizslas: 7, pomeranians: 6, akitas: 7
|
||||
Sue 479: trees: 2, perfumes: 2, children: 2
|
||||
Sue 480: cars: 8, cats: 5, vizslas: 0
|
||||
Sue 481: trees: 5, goldfish: 0, akitas: 3
|
||||
Sue 482: cars: 8, perfumes: 6, goldfish: 10
|
||||
Sue 483: goldfish: 0, cars: 3, perfumes: 10
|
||||
Sue 484: pomeranians: 1, samoyeds: 1, perfumes: 3
|
||||
Sue 485: trees: 0, akitas: 2, vizslas: 4
|
||||
Sue 486: cars: 3, vizslas: 8, goldfish: 1
|
||||
Sue 487: pomeranians: 9, vizslas: 2, children: 10
|
||||
Sue 488: akitas: 6, vizslas: 10, perfumes: 9
|
||||
Sue 489: goldfish: 6, vizslas: 4, cars: 2
|
||||
Sue 490: vizslas: 10, cats: 8, samoyeds: 1
|
||||
Sue 491: cats: 9, cars: 1, perfumes: 10
|
||||
Sue 492: goldfish: 6, cars: 9, pomeranians: 9
|
||||
Sue 493: children: 10, goldfish: 10, vizslas: 0
|
||||
Sue 494: pomeranians: 5, cars: 0, vizslas: 0
|
||||
Sue 495: vizslas: 7, perfumes: 6, samoyeds: 3
|
||||
Sue 496: trees: 1, cats: 4, cars: 10
|
||||
Sue 497: cats: 1, perfumes: 0, cars: 7
|
||||
Sue 498: perfumes: 7, vizslas: 6, cats: 9
|
||||
Sue 499: vizslas: 8, perfumes: 1, akitas: 3
|
||||
Sue 500: perfumes: 4, cars: 9, trees: 4
|
8
2015/day17-no_such_thing_as_too_much/Cargo.toml
Normal file
8
2015/day17-no_such_thing_as_too_much/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day17-no_such_thing_as_too_much"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
32
2015/day17-no_such_thing_as_too_much/challenge.txt
Normal file
32
2015/day17-no_such_thing_as_too_much/challenge.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
\--- Day 17: No Such Thing as Too Much ---
|
||||
----------
|
||||
|
||||
The elves bought too much eggnog again - `150` liters this time. To fit it all into your refrigerator, you'll need to move it into smaller containers. You take an inventory of the capacities of the available containers.
|
||||
|
||||
For example, suppose you have containers of size `20`, `15`, `10`, `5`, and `5` liters. If you need to store `25` liters, there are four ways to do it:
|
||||
|
||||
* `15` and `10`
|
||||
* `20` and `5` (the first `5`)
|
||||
* `20` and `5` (the second `5`)
|
||||
* `15`, `5`, and `5`
|
||||
|
||||
Filling all containers entirely, how many different *combinations of containers* can exactly fit all `150` liters of eggnog?
|
||||
|
||||
Your puzzle answer was `654`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
While playing with all the containers in the kitchen, another load of eggnog arrives! The shipping and receiving department is requesting as many containers as you can spare.
|
||||
|
||||
Find the minimum number of containers that can exactly fit all `150` liters of eggnog. *How many different ways* can you fill that number of containers and still hold exactly `150` litres?
|
||||
|
||||
In the example above, the minimum number of containers was two. There were three ways to use that many containers, and so the answer there would be `3`.
|
||||
|
||||
Your puzzle answer was `57`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](17/input).
|
50
2015/day17-no_such_thing_as_too_much/src/lib.rs
Normal file
50
2015/day17-no_such_thing_as_too_much/src/lib.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
pub fn run(input: &str, amount: usize) -> (usize, usize) {
|
||||
let containers: Vec<_> = input.lines().map(|i| i.parse::<usize>().unwrap()).collect();
|
||||
let first = get_combinations_for_containers(&containers, amount, usize::MAX);
|
||||
let mut second = 0;
|
||||
let mut i = 1;
|
||||
while second == 0 {
|
||||
second = get_combinations_for_containers(&containers, amount, i);
|
||||
i += 1;
|
||||
}
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn get_combinations_for_containers(containers: &[usize], amount: usize, containers_remaining: usize) -> usize {
|
||||
if containers.is_empty() || containers_remaining == 0 {
|
||||
match amount {
|
||||
0 => 1,
|
||||
_ => 0,
|
||||
}
|
||||
} else {
|
||||
let first = containers[0];
|
||||
if first > amount {
|
||||
get_combinations_for_containers(&containers[1..], amount, containers_remaining)
|
||||
} else {
|
||||
get_combinations_for_containers(&containers[1..], amount, containers_remaining) +
|
||||
get_combinations_for_containers(&containers[1..], amount - first, containers_remaining-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input, 25), (4, 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input, 150), (654, 57));
|
||||
}
|
||||
}
|
20
2015/day17-no_such_thing_as_too_much/tests/challenge_input
Normal file
20
2015/day17-no_such_thing_as_too_much/tests/challenge_input
Normal file
|
@ -0,0 +1,20 @@
|
|||
50
|
||||
44
|
||||
11
|
||||
49
|
||||
42
|
||||
46
|
||||
18
|
||||
32
|
||||
26
|
||||
40
|
||||
21
|
||||
7
|
||||
18
|
||||
43
|
||||
10
|
||||
47
|
||||
36
|
||||
24
|
||||
22
|
||||
40
|
5
2015/day17-no_such_thing_as_too_much/tests/sample_input
Normal file
5
2015/day17-no_such_thing_as_too_much/tests/sample_input
Normal file
|
@ -0,0 +1,5 @@
|
|||
20
|
||||
15
|
||||
10
|
||||
5
|
||||
5
|
8
2015/day18-like_a_gif_for_your_yard/Cargo.toml
Normal file
8
2015/day18-like_a_gif_for_your_yard/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day18-like_a_gif_for_your_yard"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
148
2015/day18-like_a_gif_for_your_yard/challenge.txt
Normal file
148
2015/day18-like_a_gif_for_your_yard/challenge.txt
Normal file
|
@ -0,0 +1,148 @@
|
|||
\--- Day 18: Like a GIF For Your Yard ---
|
||||
----------
|
||||
|
||||
After the [million lights incident](6), the fire code has gotten stricter: now, at most ten thousand lights are allowed. You arrange them in a 100x100 grid.
|
||||
|
||||
Never one to let you down, Santa again mails you instructions on the ideal lighting configuration. With so few lights, he says, you'll have to resort to *animation*.
|
||||
|
||||
Start by setting your lights to the included initial configuration (your puzzle input). A `#` means "on", and a `.` means "off".
|
||||
|
||||
Then, animate your grid in steps, where each step decides the next configuration based on the current one. Each light's next state (either on or off) depends on its current state and the current states of the eight lights adjacent to it (including diagonals). Lights on the edge of the grid might have fewer than eight neighbors; the missing ones always count as "off".
|
||||
|
||||
For example, in a simplified 6x6 grid, the light marked `A` has the neighbors numbered `1` through `8`, and the light marked `B`, which is on an edge, only has the neighbors marked `1` through `5`:
|
||||
|
||||
```
|
||||
1B5...
|
||||
234...
|
||||
......
|
||||
..123.
|
||||
..8A4.
|
||||
..765.
|
||||
|
||||
```
|
||||
|
||||
The state a light should have next is based on its current state (on or off) plus the *number of neighbors that are on*:
|
||||
|
||||
* A light which is *on* stays on when `2` or `3` neighbors are on, and turns off otherwise.
|
||||
* A light which is *off* turns on if exactly `3` neighbors are on, and stays off otherwise.
|
||||
|
||||
All of the lights update simultaneously; they all consider the same current state before moving to the next.
|
||||
|
||||
Here's a few steps from an example configuration of another 6x6 grid:
|
||||
|
||||
```
|
||||
Initial state:
|
||||
.#.#.#
|
||||
...##.
|
||||
#....#
|
||||
..#...
|
||||
#.#..#
|
||||
####..
|
||||
|
||||
After 1 step:
|
||||
..##..
|
||||
..##.#
|
||||
...##.
|
||||
......
|
||||
#.....
|
||||
#.##..
|
||||
|
||||
After 2 steps:
|
||||
..###.
|
||||
......
|
||||
..###.
|
||||
......
|
||||
.#....
|
||||
.#....
|
||||
|
||||
After 3 steps:
|
||||
...#..
|
||||
......
|
||||
...#..
|
||||
..##..
|
||||
......
|
||||
......
|
||||
|
||||
After 4 steps:
|
||||
......
|
||||
......
|
||||
..##..
|
||||
..##..
|
||||
......
|
||||
......
|
||||
|
||||
```
|
||||
|
||||
After `4` steps, this example has four lights on.
|
||||
|
||||
In your grid of 100x100 lights, given your initial configuration, *how many lights are on after 100 steps*?
|
||||
|
||||
Your puzzle answer was `1061`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
You flip the instructions over; Santa goes on to point out that this is all just an implementation of [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway's_Game_of_Life). At least, it was, until you notice that something's wrong with the grid of lights you bought: four lights, one in each corner, are *stuck on* and can't be turned off. The example above will actually run like this:
|
||||
|
||||
```
|
||||
Initial state:
|
||||
##.#.#
|
||||
...##.
|
||||
#....#
|
||||
..#...
|
||||
#.#..#
|
||||
####.#
|
||||
|
||||
After 1 step:
|
||||
#.##.#
|
||||
####.#
|
||||
...##.
|
||||
......
|
||||
#...#.
|
||||
#.####
|
||||
|
||||
After 2 steps:
|
||||
#..#.#
|
||||
#....#
|
||||
.#.##.
|
||||
...##.
|
||||
.#..##
|
||||
##.###
|
||||
|
||||
After 3 steps:
|
||||
#...##
|
||||
####.#
|
||||
..##.#
|
||||
......
|
||||
##....
|
||||
####.#
|
||||
|
||||
After 4 steps:
|
||||
#.####
|
||||
#....#
|
||||
...#..
|
||||
.##...
|
||||
#.....
|
||||
#.#..#
|
||||
|
||||
After 5 steps:
|
||||
##.###
|
||||
.##..#
|
||||
.##...
|
||||
.##...
|
||||
#.#...
|
||||
##...#
|
||||
|
||||
```
|
||||
|
||||
After `5` steps, this example now has `17` lights on.
|
||||
|
||||
In your grid of 100x100 lights, given your initial configuration, but with the four corners always in the *on* state, *how many lights are on after 100 steps*?
|
||||
|
||||
Your puzzle answer was `1006`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](18/input).
|
108
2015/day18-like_a_gif_for_your_yard/src/lib.rs
Normal file
108
2015/day18-like_a_gif_for_your_yard/src/lib.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
#[derive(Clone)]
|
||||
struct Light {
|
||||
state: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Grid {
|
||||
lights: Vec<Vec<Light>>,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
fn from(input: &str) -> Self {
|
||||
Self {
|
||||
lights: input.lines()
|
||||
.map(|line| line.chars()
|
||||
.map(|c| Light { state: c == '#' })
|
||||
.collect())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_neighbours(&self, x: usize, y: usize) -> Vec<(usize, usize)> {
|
||||
let x_min = x.saturating_sub(1);
|
||||
let x_max = (x+1).min(self.lights[0].len()-1);
|
||||
let y_min = y.saturating_sub(1);
|
||||
let y_max = (y+1).min(self.lights.len()-1);
|
||||
|
||||
let mut out = Vec::new();
|
||||
for c in x_min..=x_max {
|
||||
for r in y_min..=y_max {
|
||||
if c != x || r != y {
|
||||
out.push((c, r));
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn step(&mut self, broken: bool) {
|
||||
let old_grid = self.clone();
|
||||
for (row_idx, row) in self.lights.iter_mut().enumerate() {
|
||||
for (col_idx, light) in row.iter_mut().enumerate() {
|
||||
let this_state = light.state;
|
||||
let neighbours_on = old_grid.get_neighbours(col_idx, row_idx).iter().filter(|n| old_grid.lights[n.1][n.0].state).count();
|
||||
|
||||
light.state = match (this_state, neighbours_on) {
|
||||
(true, n) if (2..=3).contains(&n) => true,
|
||||
(true, _) => false,
|
||||
(false, 3) => true,
|
||||
(false, _) => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
if broken {
|
||||
self.broken_on();
|
||||
}
|
||||
}
|
||||
|
||||
fn broken_on(&mut self) {
|
||||
for c in [0, self.lights[0].len()-1] {
|
||||
for r in [0, self.lights.len()-1] {
|
||||
self.lights[r][c].state = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn count_on(&self) -> usize {
|
||||
self.lights.iter().map(|r| r.iter().filter(|l| l.state).count()).sum()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str, steps: usize) -> (usize, usize) {
|
||||
let mut grid = Grid::from(input);
|
||||
let mut grid2 = grid.clone();
|
||||
grid2.broken_on();
|
||||
for _ in 0..steps {
|
||||
grid.step(false);
|
||||
grid2.step(true);
|
||||
}
|
||||
let first = grid.count_on();
|
||||
let second = grid2.count_on();
|
||||
(first, second)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
let expected = [ (15, 17), (11, 18), (8, 18), (4, 18), (4, 14), (4, 17) ];
|
||||
for (idx, lights) in expected.into_iter().enumerate() {
|
||||
assert_eq!(run(&sample_input, idx), lights);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input, 100), (1061, 1006));
|
||||
}
|
||||
}
|
100
2015/day18-like_a_gif_for_your_yard/tests/challenge_input
Normal file
100
2015/day18-like_a_gif_for_your_yard/tests/challenge_input
Normal file
|
@ -0,0 +1,100 @@
|
|||
#..####.##..#...#..#...#...###.#.#.#..#....#.##..#...##...#..#.....##..#####....#.##..##....##.#....
|
||||
.#..#..#..#.###...##..#.##.....#...#..##....#####.##............####.#..######..#.#.##.#...#..#...##
|
||||
#.....##.##.##.#..##.#..###...#.#.#..##..###.####.####.#.####.#...##.#..###.........#.###...#....###
|
||||
#.###..#######..##..#.....##.#.#.###.#.##..#.##..##.##.#.##...###.#...#.#####.#.##..#.#####..#.#####
|
||||
#.##.##.###.##..###.#.##.##...##.#.#..##..###.########.#.####..####...#####...#..#...##....##.##.##.
|
||||
..#.#.#.#..#.#.###....###...#...#.##..####.###.....#.####.###.###.#......#.#.###..#..#.#....#.#####.
|
||||
...#.###.#....#.###...#.#.#...#...#.#####....#....#...#####..#..#.#..######..#.##.#.##.#..###.#...##
|
||||
.###...#...#.#..#.#.####.#...#.....##...###.#....#..##.###....#.##....###..#.#####...###.#.##.####..
|
||||
#.#....##.#.....#####.#.##..#######.#.####..###.##.#####.##.#...###...#.#...###..#...#.#.###.###.###
|
||||
...##.##.....##..#.##...#.#...#...#.#####.#...#.#.#.#####.##.#...#.#..##.##..#...#....####..###.###.
|
||||
#..#....######...#...###.#....#####....#.#.#....#....#.#######.#####..#....#....#.##..#.##.###..#...
|
||||
#####.#.######.#.#####.#..##..##..####..#....#...#######....##..##.#..###..###.###..###...#...######
|
||||
#...##..##...###....##..##.##..#.#.#.#....##.#.......###..###..###...###..##.##.##.#.#.#..#.#..#..#.
|
||||
..###....##.###..#.#..########...###...##..#######....##..###..#####.##.#....###..##.##.##.#...##.#.
|
||||
###..#.#..#.#.##.##...##.....#..###.#..##.##.#....##.#.######..##..#.#.##.###...#..####...#.#..#.###
|
||||
.######....#..##..#.####.##..#.#..#.#..#....#..##.#..#.#...####..#....#.####.#.###.#...####.#...#.#.
|
||||
#.######.##..###.###..#..###.#...#..#...#...###.##....#.#......#...#.##.#.###..#.#####.#.#..###..#.#
|
||||
...#..#...####..###.########.....###.###.#..##.##....######..#..#.....#.##.##.#..##..#..##...#..#..#
|
||||
#..#..##..#.#.########.##.#.####..#.#####.#.###.##....###..##..#.#.###..#.##..##.##.####...######.##
|
||||
.######.###....#...##...#..#....##..#.#...###.######.##...#....##.##.#.#.##..#...###.###.#....#..##.
|
||||
####.#.##..##.##.###...#.###.##..##....###..####.##..#.#.##..###.#..##...####...#..####.#.#..##...#.
|
||||
.#.#..#.....##...#..#...#.#...#.#.##..#....#..#......#####.#######....#.#..#..###..##.#.########..##
|
||||
.##.#..#..##..#..####.#...####...#...#..##.#..###.#..######..#.#...###.##...#..#####..##.#..##.#.##.
|
||||
.###..##.##.##....###.###..#.#...##.#.#...#.#######.####..#..###.#######.#...#.#...#.##...#..####..#
|
||||
##.########..#..#....#.###..##.##.#.##.#..#......####..##.##.#..####..#####..#.....#####.###..#.#.#.
|
||||
.#..####..##.#.#..#####.##..#..#.#....#.#####.#####...######........##.##..##.#.#.###..#.#.#.#..##.#
|
||||
.##..##..#.######..###....#.#.###.#........#..###..#.########.....#.##...#.....#..#...##...#..#.###.
|
||||
##.##.#..####....####.#######.....#.#.#...#.######.#.....####.####...###..####.##.##....###..#..#...
|
||||
#.#..####...#......#...###...##....##.#######..#.###.#...###.##.##...####..#.####..#......##..#####.
|
||||
.#.#...##...#....#.####.##.....#....#.#.#######..###.#.....#.....####...##...#.#.##.####..##.###.#.#
|
||||
####.#.#.####...#...####.#.....#.#######.#.......####......###..###.#...######..#.##.#.##..#..##..##
|
||||
..##.###..#..####..####.......######.##..#.....##.##...##.##......#.###..###...#.##.#####.#.######.#
|
||||
.###..####.###..#..#.......#.##...##...##.######.....#..####.#......#.#...#...#...###...#.#.##..####
|
||||
.####....##.##.#.....##.###.####.#.......#.......#.#..#.#.#.....###.#.#####.#..#.#.#####.#####.###.#
|
||||
.##.#.###.#####..#..#....###.#.#.#..#..###..##..####..##.###....#..####.####.#..###.#..######.######
|
||||
####.#.....##..###....#.....#.##.#.##..##..########.#####..###.####....##.....######.#.#.##.......#.
|
||||
#.#.##.....#.....##.###.#..#.##.##....#..##....##.#.###.##.#..#..##.##.###.#..##.###...##..###.#####
|
||||
#.###.#.#.#.#.#.#.#...#..#.###..####.##...#..####.###....#..#..##.#....####..##.##....#.#.##.##....#
|
||||
...######....#..####...#.#..#.#.#..#.##.#.#.......#..#......##..#...#..#..##...##.#...#.#.#...##.##.
|
||||
.#####..#...####....#..###..##....#####..###.#.#...###..###.###..##...#......#...#...#.#.#...#.##..#
|
||||
......#####.#...#.#.#.##..#.###..##..#.#...###..###....##..#####..#######.#..#.###....###...##.#..#.
|
||||
..##.########.##..#....##.#...##.##.#.#..#.##..#.#.#.##....#.#.#.#.##....##....#....#####.##..#.##.#
|
||||
####...#....##.#.###......##.##.#..##...#..#####..#.#....##..#####...#.#.##...#.####.####..##.######
|
||||
.##.###.##.#...#.#....###.#######...##...##..#..##.###.#.####..#..###......#.#.##.#.#....#..##...#..
|
||||
.#.###.#.###.###.#.##.#..#......####.##...#..##.#..####.....#...#.###.##.##.#..#.##..#.###......#..#
|
||||
...##.####......#.#.#..###..#....###....#.##.#####..#..#..#...#.#.###...#.#.#.##....###.####..###.#.
|
||||
##..#.#.#.#....####...#.##.###..####....#..#####.######..#.##.##..#####.#.....#.#...##.#.##.##.#.#..
|
||||
#..##.#.#.#.###.#.#.###...#.#...##..#..#.#.#.##..###...#..##.#..#.#.#..#.....#.######.#.###..###.#..
|
||||
....#.#.##.###.##...#.##.#....#..##.#..##...#...#.##.####...##..####.#.........#..##..#...#...##.#..
|
||||
.##.......##...###.##.#.##.###.##.#..#..#..####...#...#....#####...###..##..#..#..##...#....#..#####
|
||||
..####..#...#...#..###....##.#.#####..#..#.....#......#...#.......##....####...##....##.##.#.#####.#
|
||||
##.#.#.#..##..##..#.####.##.##.###.#...###.#....#.....#.###...#######..###.####.###.####.##...##.#..
|
||||
..#.#...##.#....#..#..##.####.....#.#.#...#..#..###.#..###.#####.#.#####.#.#.#.#.###.##.###..#....##
|
||||
.###.#...#....###..#...####....####..#.##..#..##.###..#.#.#.#..#...###.#.#...#......#...#.##.##.#...
|
||||
..####.####.##.#.##....#...##....#..#....#..###..#...#..###.#####.....#####..##.#.#.#.#.#.##.####...
|
||||
...##.#.##.####..##.###..#.#.#.#.#.#.#..###...#.##..#.####.##...#.#.##......###..#...###....#.#.###.
|
||||
##...##..#.#.##..#.#.#....#.####.......#.#.#######.#..#....#.###.#...###.##....###.#.#..#.#.##.####.
|
||||
...##.......######.....##....#...#..#.##.###.#..#.##.###.#.###.#.#.#...#.#...##.##.##..#.##########.
|
||||
###..#....#.#.....#....###.#...##.......##.#.#..#.#...########......###..##.#..#..####.##..####...#.
|
||||
......##.###.#.###.....#..#...#.#......##....#....#........#..#...##.##.....#...##.##.........##....
|
||||
.##.##.#.#...#....######..##....##..##.#.#.##.#.##..##...#..###......##......#.#....#.#.#.......###.
|
||||
.......#.##..##.#...#.##..#..#####.#..#.######.........###.#####.####.#...##...........##...##..####
|
||||
#......#.#..#...#...##..#.#.###.##.##.#.#..#.###.##.#..###..#.###..#...###.##..###..#...#..###...#..
|
||||
####.##..#####..####.#...#..#..###..##.#.#...#...#...#.##.####.##.###....###...#.#.#..####.######.##
|
||||
.....#..####...#.#.#.####..####..##.###......#.....########.#...#.#..#..#...#.###..##.#####..###.###
|
||||
.#######.#.##..###.#...###.#####............##.###...#.##.#.##..##.#.#..#.######..######..#..#..####
|
||||
...##..#.####...#..#.#.##.#....#.####..#..###.###..#.#...#....##.##.#......##..##..#.#.#.###..#..#..
|
||||
........#...#.##.#.#..#....####....#.##...###..####...###.#.#..######..###..##.#####.###.###.#.#...#
|
||||
##......##.#..###.####.##.#.###.#.......#.##..####..#.###.##..##..##...##...#.###...#.#..#..#.#####.
|
||||
##..#.#.....##.####.#..##.#.##.#.#...#...#.#...####.#.#.##...##....##.###..###.####.#...#.###..#####
|
||||
.#####.####.####.####.#.##.##......###....###.####...###...#...#..#.##.#.#####.###..##.#..###...##..
|
||||
.#...#..##...##...#....#.#.#..##..#.##..#.###.#.###..###.#.#.###.#....#######.####.##..#..#...####..
|
||||
..##.##..#.##..#.#.###..#.##.########...####.#.###.##..#..###.###...##..##.#..#.######.##.#....###.#
|
||||
##.#####.###.##.#.##.##.##.###..##..##..#.#.#.#.####..#......#.#.#.#.#.#.##...#####.####...#.#...#.#
|
||||
.#..###..##.#####.#.##.#..##...##..##...#####.#.####..#...##.....######.#.#...##.#..#######.###.###.
|
||||
#.#..##.#.#####.#.#.....###.###.#..##.#####....#.###.##.##.#.#..##..#.#....#######.###.#.#.....#.###
|
||||
....###...#.###.####....###.....##....#####.##.###.###.##.##.##.#..###..######...####.#.#..####..#..
|
||||
###.....#..####..#.####..#..#...##.##..##.######.####.....#...##....#..#.##.#####..###.##.#.####...#
|
||||
.##.##.#...#..####...##.##.###...#...#..#.#.#####.....####...#.#.#..#.####...####.#...###.#......###
|
||||
###.##....#.#.#...#.###....####..##...##.##.##.#..#...####..#..#..##...#####.####.####...##.#..###.#
|
||||
..####.....##..###.#.#.###.########..#...#.##..#.#.#.......#.##.#..#...####.##.#..#.######..#.#...#.
|
||||
#.#.##.#.#.##.#....##......##......#######.#..#.##...##..#.#.###...#.#..#..###...#..###.....##.....#
|
||||
..#.##.#.##.#.##..##.....#.#..#.#..#...##..#..#.#....###.#####....####.####..#####.##.###...#..###.#
|
||||
#....#.###..#..########.###..#.#.#.##...##.#..##.###..#..#..#.#.##..###...###.#.##..#.##.#..#.#.####
|
||||
#.......#######......#...#...##.##...###.#....##.#..#....####.#.##.###...#.#####...##.###........##.
|
||||
.##.####.....###.##......####.###.########..#.####..#.##.#.####.....#...#.##....#######.##..#......#
|
||||
#.#.##.##....##..##.#.###..#.##.#..#..#.#..##.....###..###.##.##.####.##.#.#.##...####..#.#..##.#.#.
|
||||
...##.#.#.#...###.#.......#.#.....#.#...##....##.##.##.####...#.#..#..#..#.#.##.#..#.#.#....###..#.#
|
||||
....#.#.###.#####.##..###..##..#...#.##.#......##.####.#..####.#.##..####.#.#...##..#####..##.#.#...
|
||||
..###.#.##..#....#..#.#.....##.#####..##....#.#...#.##..##.#.#..#...##.##..##..##....#...#..#..#..##
|
||||
##.#.##.#...#.###.##.##.##.##..##.##...#..##.#..#######.#..#...#.#.##..#....##.#..####.###........#.
|
||||
.##.#..#.....#####..##.#.#.#.#..###.#######.###.###....##....#.#.#.###....###.#..#.#....#.#..###...#
|
||||
...###.#.#.###..#...#..###.######..##.#.#..#...####.#####.##..#..###...#..#..#..###..##.#.#...#.###.
|
||||
#......#.#..#..##.##.#.##.#.###.#.##.#.#..#....#.##..#..##..##.#.#.#....##.###.###.####.#.#####...##
|
||||
...#.##..#.######.......#.#.###.....#####....##.#.#.###........#.#.###.#.#########.##.##.#..##..#...
|
||||
##..###..###....####.##.##..##.###....####..##...####.####..####..###.####..##.#...###.#####.##.##.#
|
||||
###...##.#.#.#####..#..#####...##.#...#.#.###.#..##..###.##.#.#.....####.##.#..##.###.#...##.##...##
|
||||
...#.#.##.##..##....#..#.#####.##.###..#.#.#........####.###.##....##....####..#.#....#.#.#.###..#.#
|
||||
..#.#.#.#.###...#....##..######.##....#.#.##..###..#.#.###..#.##..#.#.###......#..#..#.####..#...##.
|
||||
.....####.#.....###.#.##.#..##.#..###.#####.#..##...###.#..###..#..##....###.#..##.#..#.##.#..#...##
|
6
2015/day18-like_a_gif_for_your_yard/tests/sample_input
Normal file
6
2015/day18-like_a_gif_for_your_yard/tests/sample_input
Normal file
|
@ -0,0 +1,6 @@
|
|||
.#.#.#
|
||||
...##.
|
||||
#....#
|
||||
..#...
|
||||
#.#..#
|
||||
####..
|
8
2015/day19-medicine_for_rudolph/Cargo.toml
Normal file
8
2015/day19-medicine_for_rudolph/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day19-medicine_for_rudolph"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
71
2015/day19-medicine_for_rudolph/challenge.txt
Normal file
71
2015/day19-medicine_for_rudolph/challenge.txt
Normal file
|
@ -0,0 +1,71 @@
|
|||
\--- Day 19: Medicine for Rudolph ---
|
||||
----------
|
||||
|
||||
Rudolph the Red-Nosed Reindeer is sick! His nose isn't shining very brightly, and he needs medicine.
|
||||
|
||||
Red-Nosed Reindeer biology isn't similar to regular reindeer biology; Rudolph is going to need custom-made medicine. Unfortunately, Red-Nosed Reindeer chemistry isn't similar to regular reindeer chemistry, either.
|
||||
|
||||
The North Pole is equipped with a Red-Nosed Reindeer nuclear fusion/fission plant, capable of constructing any Red-Nosed Reindeer molecule you need. It works by starting with some input molecule and then doing a series of *replacements*, one per step, until it has the right molecule.
|
||||
|
||||
However, the machine has to be calibrated before it can be used. Calibration involves determining the number of molecules that can be generated in one step from a given starting point.
|
||||
|
||||
For example, imagine a simpler machine that supports only the following replacements:
|
||||
|
||||
```
|
||||
H => HO
|
||||
H => OH
|
||||
O => HH
|
||||
|
||||
```
|
||||
|
||||
Given the replacements above and starting with `HOH`, the following molecules could be generated:
|
||||
|
||||
* `HOOH` (via `H => HO` on the first `H`).
|
||||
* `HOHO` (via `H => HO` on the second `H`).
|
||||
* `OHOH` (via `H => OH` on the first `H`).
|
||||
* `HOOH` (via `H => OH` on the second `H`).
|
||||
* `HHHH` (via `O => HH`).
|
||||
|
||||
So, in the example above, there are `4` *distinct* molecules (not five, because `HOOH` appears twice) after one replacement from `HOH`. Santa's favorite molecule, `HOHOHO`, can become `7` *distinct* molecules (over nine replacements: six from `H`, and three from `O`).
|
||||
|
||||
The machine replaces without regard for the surrounding characters. For example, given the string `H2O`, the transition `H => OO` would result in `OO2O`.
|
||||
|
||||
Your puzzle input describes all of the possible replacements and, at the bottom, the medicine molecule for which you need to calibrate the machine. *How many distinct molecules can be created* after all the different ways you can do one replacement on the medicine molecule?
|
||||
|
||||
Your puzzle answer was `535`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
Now that the machine is calibrated, you're ready to begin molecule fabrication.
|
||||
|
||||
Molecule fabrication always begins with just a single electron, `e`, and applying replacements one at a time, just like the ones during calibration.
|
||||
|
||||
For example, suppose you have the following replacements:
|
||||
|
||||
```
|
||||
e => H
|
||||
e => O
|
||||
H => HO
|
||||
H => OH
|
||||
O => HH
|
||||
|
||||
```
|
||||
|
||||
If you'd like to make `HOH`, you start with `e`, and then make the following replacements:
|
||||
|
||||
* `e => O` to get `O`
|
||||
* `O => HH` to get `HH`
|
||||
* `H => OH` (on the second `H`) to get `HOH`
|
||||
|
||||
So, you could make `HOH` after *`3` steps*. Santa's favorite molecule, `HOHOHO`, can be made in *`6` steps*.
|
||||
|
||||
How long will it take to make the medicine? Given the available *replacements* and the *medicine molecule* in your puzzle input, what is the *fewest number of steps* to go from `e` to the medicine molecule?
|
||||
|
||||
Your puzzle answer was `212`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
If you still want to see it, you can [get your puzzle input](19/input).
|
135
2015/day19-medicine_for_rudolph/src/lib.rs
Normal file
135
2015/day19-medicine_for_rudolph/src/lib.rs
Normal file
|
@ -0,0 +1,135 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let (replacements, initial) = parse_input(input);
|
||||
let first = get_replacements(&replacements, initial).len();
|
||||
let second = find_reduction(&replacements, initial.to_string()).expect("Unable to construct target molecule");
|
||||
// let second = a_star_search(initial, "e", &replacements, &str::len);
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> (Vec<(&str, &str)>, &str) {
|
||||
let (replacements_str, initial) = input.split_once("\n\n").expect("Unable to split input by blank line");
|
||||
|
||||
(
|
||||
replacements_str.lines()
|
||||
.map(|line| line.split_once(" => ").unwrap_or_else(|| panic!("unable to split {} by \" => \"", line)))
|
||||
.collect(),
|
||||
initial.trim()
|
||||
)
|
||||
}
|
||||
/*
|
||||
fn a_star_search(start: &str, goal: &str, replacements: &[(&str, &str)], h: &dyn Fn(&str)->usize) -> usize {
|
||||
// The set of discovered nodes. Initially only the start node is known.
|
||||
let mut open_set = HashSet::from([start.to_string()]);
|
||||
// A map from a node to its predecessor on its cheapest known path.
|
||||
let mut came_from = HashMap::new();
|
||||
// A map from a node to its lowest known costs.
|
||||
let mut g_score = HashMap::from([(start.to_string(), 0)]);
|
||||
// Estimated costs of each path (f = g+h)
|
||||
let mut f_score = HashMap::from([(start.to_string(), h(start))]);
|
||||
|
||||
loop {
|
||||
let current = open_set.iter()
|
||||
.min_by(|&a, &b| f_score.get(a).unwrap()
|
||||
.cmp(f_score.get(b).unwrap()))
|
||||
.unwrap().to_owned();
|
||||
if current == goal {
|
||||
return reconstruct_path(came_from, ¤t);
|
||||
}
|
||||
open_set.remove(¤t);
|
||||
for neighbour in get_reductions(replacements, current.to_string()) {
|
||||
let tentative_g_score = g_score.get(¤t).unwrap() + 1;
|
||||
let current_g_score = *g_score.get(&neighbour[..]).unwrap_or(&usize::MAX);
|
||||
if tentative_g_score < current_g_score {
|
||||
came_from.insert(neighbour.to_owned(), current.to_string());
|
||||
g_score.insert(neighbour.to_owned(), tentative_g_score);
|
||||
f_score.insert(neighbour.to_owned(), tentative_g_score + h(&neighbour));
|
||||
open_set.insert(neighbour);
|
||||
}
|
||||
}
|
||||
if open_set.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
panic!("Open Set is empty, but goal was never reached.")
|
||||
}
|
||||
|
||||
fn reconstruct_path(came_from: HashMap<String, String>, goal: &str) -> usize {
|
||||
let mut total_path_len = 0;
|
||||
let mut current = goal;
|
||||
while let Some(predecessor) = came_from.get(current) {
|
||||
total_path_len += 1;
|
||||
current = predecessor;
|
||||
}
|
||||
total_path_len
|
||||
}
|
||||
*/
|
||||
|
||||
// Always returns the first reduction it finds by trying to shorten the string as much as possible
|
||||
// as early as possible. This yields the correct results for me, but more hostile inputs probably
|
||||
// require a more thorough approach, such as the A* algorithm shown above.
|
||||
fn find_reduction(replacements: &[(&str, &str)], target: String) -> Option<usize> {
|
||||
if target == *"e" {
|
||||
Some(0)
|
||||
} else {
|
||||
let mut next_step: Vec<_> = get_reductions(replacements, target).into_iter().collect();
|
||||
|
||||
next_step.sort_by_key(|a| a.len());
|
||||
for next_attemt in next_step {
|
||||
let this_attempt = find_reduction(replacements, next_attemt);
|
||||
if let Some(score) = this_attempt {
|
||||
return Some(score + 1);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_reductions(replacements: &[(&str, &str)], target: String) -> HashSet<String> {
|
||||
let mut res = HashSet::new();
|
||||
for idx in 0..target.len() {
|
||||
for (from, to) in replacements {
|
||||
if target[idx..].find(*to) == Some(0) {
|
||||
res.insert(format!("{}{}{}", &target[..idx].to_string(), from, &target[idx+to.len()..].to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn get_replacements(replacements: &[(&str, &str)], initial: &str) -> HashSet<String> {
|
||||
let mut res = HashSet::new();
|
||||
for idx in 0..initial.len() {
|
||||
for (from, to) in replacements {
|
||||
if initial[idx..].find(*from) == Some(0) {
|
||||
res.insert(format!("{}{}{}", &initial[..idx].to_string(), to, &initial[idx+from.len()..].to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {}", name)[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (4, 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (535, 212));
|
||||
}
|
||||
}
|
45
2015/day19-medicine_for_rudolph/tests/challenge_input
Normal file
45
2015/day19-medicine_for_rudolph/tests/challenge_input
Normal file
|
@ -0,0 +1,45 @@
|
|||
Al => ThF
|
||||
Al => ThRnFAr
|
||||
B => BCa
|
||||
B => TiB
|
||||
B => TiRnFAr
|
||||
Ca => CaCa
|
||||
Ca => PB
|
||||
Ca => PRnFAr
|
||||
Ca => SiRnFYFAr
|
||||
Ca => SiRnMgAr
|
||||
Ca => SiTh
|
||||
F => CaF
|
||||
F => PMg
|
||||
F => SiAl
|
||||
H => CRnAlAr
|
||||
H => CRnFYFYFAr
|
||||
H => CRnFYMgAr
|
||||
H => CRnMgYFAr
|
||||
H => HCa
|
||||
H => NRnFYFAr
|
||||
H => NRnMgAr
|
||||
H => NTh
|
||||
H => OB
|
||||
H => ORnFAr
|
||||
Mg => BF
|
||||
Mg => TiMg
|
||||
N => CRnFAr
|
||||
N => HSi
|
||||
O => CRnFYFAr
|
||||
O => CRnMgAr
|
||||
O => HP
|
||||
O => NRnFAr
|
||||
O => OTi
|
||||
P => CaP
|
||||
P => PTi
|
||||
P => SiRnFAr
|
||||
Si => CaSi
|
||||
Th => ThCa
|
||||
Ti => BP
|
||||
Ti => TiTi
|
||||
e => HF
|
||||
e => NAl
|
||||
e => OMg
|
||||
|
||||
CRnCaCaCaSiRnBPTiMgArSiRnSiRnMgArSiRnCaFArTiTiBSiThFYCaFArCaCaSiThCaPBSiThSiThCaCaPTiRnPBSiThRnFArArCaCaSiThCaSiThSiRnMgArCaPTiBPRnFArSiThCaSiRnFArBCaSiRnCaPRnFArPMgYCaFArCaPTiTiTiBPBSiThCaPTiBPBSiRnFArBPBSiRnCaFArBPRnSiRnFArRnSiRnBFArCaFArCaCaCaSiThSiThCaCaPBPTiTiRnFArCaPTiBSiAlArPBCaCaCaCaCaSiRnMgArCaSiThFArThCaSiThCaSiRnCaFYCaSiRnFYFArFArCaSiRnFYFArCaSiRnBPMgArSiThPRnFArCaSiRnFArTiRnSiRnFYFArCaSiRnBFArCaSiRnTiMgArSiThCaSiThCaFArPRnFArSiRnFArTiTiTiTiBCaCaSiRnCaCaFYFArSiThCaPTiBPTiBCaSiThSiRnMgArCaF
|
7
2015/day19-medicine_for_rudolph/tests/sample_input
Normal file
7
2015/day19-medicine_for_rudolph/tests/sample_input
Normal file
|
@ -0,0 +1,7 @@
|
|||
e => H
|
||||
e => O
|
||||
H => HO
|
||||
H => OH
|
||||
O => HH
|
||||
|
||||
HOH
|
8
2015/day20-infinite_elves_and_infinite_houses/Cargo.toml
Normal file
8
2015/day20-infinite_elves_and_infinite_houses/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "day20-infinite_elves_and_infinite_houses"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
48
2015/day20-infinite_elves_and_infinite_houses/challenge.txt
Normal file
48
2015/day20-infinite_elves_and_infinite_houses/challenge.txt
Normal file
|
@ -0,0 +1,48 @@
|
|||
\--- Day 20: Infinite Elves and Infinite Houses ---
|
||||
----------
|
||||
|
||||
To keep the Elves busy, Santa has them deliver some presents by hand, door-to-door. He sends them down a street with infinite houses numbered sequentially: `1`, `2`, `3`, `4`, `5`, and so on.
|
||||
|
||||
Each Elf is assigned a number, too, and delivers presents to houses based on that number:
|
||||
|
||||
* The first Elf (number `1`) delivers presents to every house: `1`, `2`, `3`, `4`, `5`, ....
|
||||
* The second Elf (number `2`) delivers presents to every second house: `2`, `4`, `6`, `8`, `10`, ....
|
||||
* Elf number `3` delivers presents to every third house: `3`, `6`, `9`, `12`, `15`, ....
|
||||
|
||||
There are infinitely many Elves, numbered starting with `1`. Each Elf delivers presents equal to *ten times* his or her number at each house.
|
||||
|
||||
So, the first nine houses on the street end up like this:
|
||||
|
||||
```
|
||||
House 1 got 10 presents.
|
||||
House 2 got 30 presents.
|
||||
House 3 got 40 presents.
|
||||
House 4 got 70 presents.
|
||||
House 5 got 60 presents.
|
||||
House 6 got 120 presents.
|
||||
House 7 got 80 presents.
|
||||
House 8 got 150 presents.
|
||||
House 9 got 130 presents.
|
||||
|
||||
```
|
||||
|
||||
The first house gets `10` presents: it is visited only by Elf `1`, which delivers `1 * 10 = 10` presents. The fourth house gets `70` presents, because it is visited by Elves `1`, `2`, and `4`, for a total of `10 + 20 + 40 = 70` presents.
|
||||
|
||||
What is the *lowest house number* of the house to get at least as many presents as the number in your puzzle input?
|
||||
|
||||
Your puzzle answer was `665280`.
|
||||
|
||||
\--- Part Two ---
|
||||
----------
|
||||
|
||||
The Elves decide they don't want to visit an infinite number of houses. Instead, each Elf will stop after delivering presents to `50` houses. To make up for it, they decide to deliver presents equal to *eleven times* their number at each house.
|
||||
|
||||
With these changes, what is the new *lowest house number* of the house to get at least as many presents as the number in your puzzle input?
|
||||
|
||||
Your puzzle answer was `705600`.
|
||||
|
||||
Both parts of this puzzle are complete! They provide two gold stars: \*\*
|
||||
|
||||
At this point, all that is left is for you to [admire your Advent calendar](/2015).
|
||||
|
||||
Your puzzle input was `29000000`.
|
48
2015/day20-infinite_elves_and_infinite_houses/src/lib.rs
Normal file
48
2015/day20-infinite_elves_and_infinite_houses/src/lib.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
pub fn run(input: usize) -> (usize, usize) {
|
||||
let first = presents_count_for_house(input, 10, None);
|
||||
let second = presents_count_for_house(input, 11, Some(50));
|
||||
(first, second)
|
||||
}
|
||||
|
||||
fn presents_count_for_house(number: usize, multiplier: usize, max: Option<usize> ) -> usize {
|
||||
let max = max.unwrap_or(number/multiplier);
|
||||
let size = number/multiplier+1;
|
||||
let mut counts = vec![0; size];
|
||||
(1..=size).for_each(|n| {
|
||||
(n..=size.min(max*n)).step_by(n).for_each(|i| {
|
||||
counts[i-1] += multiplier*n;
|
||||
});
|
||||
});
|
||||
counts.iter().position(|i| *i >= number).unwrap_or(0) + 1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let exptected = [
|
||||
(9, (1, 1)),
|
||||
(10, (1, 1)),
|
||||
(11, (2, 1)),
|
||||
(30, (2, 2)),
|
||||
(40, (3, 3)),
|
||||
(70, (4, 4)),
|
||||
(60, (4, 4)),
|
||||
(120, (6, 6)),
|
||||
(80, (6, 6)),
|
||||
(150, (8, 8)),
|
||||
(130, (8, 6)),
|
||||
];
|
||||
for (input, output) in exptected {
|
||||
assert_eq!(run(input), output);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = 29_000_000;
|
||||
assert_eq!(run(challenge_input), (665280, 705600));
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue