diff --git a/aoc21 b/aoc21 index 9b7903d..ed4d172 100755 --- a/aoc21 +++ b/aoc21 @@ -6,6 +6,7 @@ use AdventOfCode21\Day1; use AdventOfCode21\Day2; use AdventOfCode21\Day3; use AdventOfCode21\Day4; +use AdventOfCode21\Day6; use AdventOfCode21\Puzzle; use Symfony\Component\Console\Application; @@ -16,5 +17,6 @@ $application->add(new Day1()); $application->add(new Day2()); $application->add(new Day3()); $application->add(new Day4()); +$application->add(new Day6()); $application->run(); diff --git a/data/day6/data.txt b/data/day6/data.txt new file mode 100644 index 0000000..ba3c3cc --- /dev/null +++ b/data/day6/data.txt @@ -0,0 +1 @@ +5,4,3,5,1,1,2,1,2,1,3,2,3,4,5,1,2,4,3,2,5,1,4,2,1,1,2,5,4,4,4,1,5,4,5,2,1,2,5,5,4,1,3,1,4,2,4,2,5,1,3,5,3,2,3,1,1,4,5,2,4,3,1,5,5,1,3,1,3,2,2,4,1,3,4,3,3,4,1,3,4,3,4,5,2,1,1,1,4,5,5,1,1,3,2,4,1,2,2,2,4,1,2,5,5,1,4,5,2,4,2,1,5,4,1,3,4,1,2,3,1,5,1,3,4,5,4,1,4,3,3,3,5,5,1,1,5,1,5,5,1,5,2,1,5,1,2,3,5,5,1,3,3,1,5,3,4,3,4,3,2,5,2,1,2,5,1,1,1,1,5,1,1,4,3,3,5,1,1,1,4,4,1,3,3,5,5,4,3,2,1,2,2,3,4,1,5,4,3,1,1,5,1,4,2,3,2,2,3,4,1,3,4,1,4,3,4,3,1,3,3,1,1,4,1,1,1,4,5,3,1,1,2,5,2,5,1,5,3,3,1,3,5,5,1,5,4,3,1,5,1,1,5,5,1,1,2,5,5,5,1,1,3,2,2,3,4,5,5,2,5,4,2,1,5,1,4,4,5,4,4,1,2,1,1,2,3,5,5,1,3,1,4,2,3,3,1,4,1,1 diff --git a/data/day6/example.txt b/data/day6/example.txt new file mode 100644 index 0000000..55129f1 --- /dev/null +++ b/data/day6/example.txt @@ -0,0 +1 @@ +3,4,3,1,2 diff --git a/data/day6/puzzle.md b/data/day6/puzzle.md new file mode 100644 index 0000000..03f2fa5 --- /dev/null +++ b/data/day6/puzzle.md @@ -0,0 +1,68 @@ +# Day 6: Lanternfish + +[https://adventofcode.com/2021/day/6](https://adventofcode.com/2021/day/6) + +## Description + +### Part One + +The sea floor is getting steeper. Maybe the sleigh keys got carried this way? + +A massive school of glowing [lanternfish](https://en.wikipedia.org/wiki/Lanternfish) swims past. They must spawn quickly to reach such large numbers - maybe _exponentially_ quickly? You should model their growth rate to be sure. + +Although you know nothing about this specific species of lanternfish, you make some guesses about their attributes. Surely, each lanternfish creates a new lanternfish once every _7_ days. + +However, this process isn't necessarily synchronized between every lanternfish - one lanternfish might have 2 days left until it creates another lanternfish, while another might have 4. So, you can model each fish as a single number that represents _the number of days until it creates a new lanternfish_. + +Furthermore, you reason, a _new_ lanternfish would surely need slightly longer before it's capable of producing more lanternfish: two more days for its first cycle. + +So, suppose you have a lanternfish with an internal timer value of `3`: + +* After one day, its internal timer would become `2`. +* After another day, its internal timer would become `1`. +* After another day, its internal timer would become `0`. +* After another day, its internal timer would reset to `6`, and it would create a _new_ lanternfish with an internal timer of `8`. +* After another day, the first lanternfish would have an internal timer of `5`, and the second lanternfish would have an internal timer of `7`. + +A lanternfish that creates a new fish resets its timer to `6`, _not `7`_ (because `0` is included as a valid timer value). The new lanternfish starts with an internal timer of `8` and does not start counting down until the next day. + +Realizing what you're trying to do, the submarine automatically produces a list of the ages of several hundred nearby lanternfish (your puzzle input). For example, suppose you were given the following list: + + 3,4,3,1,2 + +This list means that the first fish has an internal timer of `3`, the second fish has an internal timer of `4`, and so on until the fifth fish, which has an internal timer of `2`. Simulating these fish over several days would proceed as follows: + + Initial state: 3,4,3,1,2 + After 1 day: 2,3,2,0,1 + After 2 days: 1,2,1,6,0,8 + After 3 days: 0,1,0,5,6,7,8 + After 4 days: 6,0,6,4,5,6,7,8,8 + After 5 days: 5,6,5,3,4,5,6,7,7,8 + After 6 days: 4,5,4,2,3,4,5,6,6,7 + After 7 days: 3,4,3,1,2,3,4,5,5,6 + After 8 days: 2,3,2,0,1,2,3,4,4,5 + After 9 days: 1,2,1,6,0,1,2,3,3,4,8 + After 10 days: 0,1,0,5,6,0,1,2,2,3,7,8 + After 11 days: 6,0,6,4,5,6,0,1,1,2,6,7,8,8,8 + After 12 days: 5,6,5,3,4,5,6,0,0,1,5,6,7,7,7,8,8 + After 13 days: 4,5,4,2,3,4,5,6,6,0,4,5,6,6,6,7,7,8,8 + After 14 days: 3,4,3,1,2,3,4,5,5,6,3,4,5,5,5,6,6,7,7,8 + After 15 days: 2,3,2,0,1,2,3,4,4,5,2,3,4,4,4,5,5,6,6,7 + After 16 days: 1,2,1,6,0,1,2,3,3,4,1,2,3,3,3,4,4,5,5,6,8 + After 17 days: 0,1,0,5,6,0,1,2,2,3,0,1,2,2,2,3,3,4,4,5,7,8 + After 18 days: 6,0,6,4,5,6,0,1,1,2,6,0,1,1,1,2,2,3,3,4,6,7,8,8,8,8 + + +Each day, a `0` becomes a `6` and adds a new `8` to the end of the list, while each other number decreases by 1 if it was present at the start of the day. + +In this example, after 18 days, there are a total of `26` fish. After 80 days, there would be a total of _`5934`_. + +Find a way to simulate lanternfish. _How many lanternfish would there be after 80 days?_ + +### Part Two + +Suppose the lanternfish live forever and have unlimited food and space. Would they take over the entire ocean? + +After 256 days in the example above, there would be a total of _`26984457539`_ lanternfish! + +_How many lanternfish would there be after 256 days?_ diff --git a/src/Day6.php b/src/Day6.php new file mode 100644 index 0000000..990a061 --- /dev/null +++ b/src/Day6.php @@ -0,0 +1,90 @@ + 0, + 7 => 0, + 6 => 0, + 5 => 0, + 4 => 0, + 3 => 0, + 2 => 0, + 1 => 0, + 0 => 0, + ]; + + /** + * {@inheritdoc} + */ + protected function part1(array $data): int + { + return $this->processPuzzle(80, $data[0]); + } + + /** + * {@inheritdoc} + */ + protected function part2(array $data): int + { + return $this->processPuzzle(256, $data[0]); + } + + /** + * @param int[] $state + * @psalm-param array{int: int} $state + * + * @return array + */ + protected function processDay(array $state): array + { + $newState = $state; + + /** + * @var int $key + * @var int $stateValue + */ + foreach ($state as $key => $stateValue) { + $newKey = $key - 1; + + if ($newKey < 0) { + $newState[8] = $stateValue; + $newKey = 6; + } + + $newState[$key] -= $stateValue; + $newState[$newKey] += $stateValue; + } + + return $newState; + } + + protected function processPuzzle(int $numberOfDays, string $data): int + { + $state = $this->startState; + + array_map(static function (string $stateValue) use (&$state) { + ++$state[(int) $stateValue]; + }, explode(',', $data)); + + for ($day = 0; $day < $numberOfDays; ++$day) { + $state = $this->processDay($state); + } + + return (int) array_sum($state); + } +} diff --git a/tests/Day6Test.php b/tests/Day6Test.php new file mode 100644 index 0000000..5ee96fa --- /dev/null +++ b/tests/Day6Test.php @@ -0,0 +1,24 @@ +