From 90075581f2ff378c32071f5c9b517abf0f412ccc Mon Sep 17 00:00:00 2001 From: Akumatic Date: Tue, 15 Dec 2020 14:04:34 +0100 Subject: [PATCH] 2020 Day 15 --- 2020/15/README.md | 57 ++++++++++++++++++++++++++++++++++++++++++++ 2020/15/code.py | 36 ++++++++++++++++++++++++++++ 2020/15/input.txt | 1 + 2020/15/solution.txt | 2 ++ 2020/15/test_code.py | 26 ++++++++++++++++++++ 2020/README.md | 2 +- 6 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 2020/15/README.md create mode 100644 2020/15/code.py create mode 100644 2020/15/input.txt create mode 100644 2020/15/solution.txt create mode 100644 2020/15/test_code.py diff --git a/2020/15/README.md b/2020/15/README.md new file mode 100644 index 0000000..15a3c08 --- /dev/null +++ b/2020/15/README.md @@ -0,0 +1,57 @@ +# 2020 Day 15: Rambunctious Recitation +#### [Direct Link](https://adventofcode.com/2020/day/15) + +## Part 1 + +You catch the airport shuttle and try to book a new flight to your vacation island. Due to the storm, all direct flights have been cancelled, but a route is available to get around the storm. You take it. + +While you wait for your flight, you decide to check in with the Elves back at the North Pole. They're playing a **memory game** and are ever so excited to explain the rules! + +In this game, the players take turns saying **numbers**. They begin by taking turns reading from a list of **starting numbers** (your puzzle input). Then, each turn consists of considering the **most recently spoken number**: + +- If that was the **first** time the number has been spoken, the current player says **`0`**. +- Otherwise, the number had been spoken before; the current player announces **how many turns apart** the number is from when it was previously spoken. + +So, after the starting numbers, each turn results in that player speaking aloud either **`0`** (if the last number is new) or an **age** (if the last number is a repeat). + +For example, suppose the starting numbers are `0,3,6`: + +- **Turn 1**: The `1`st number spoken is a starting number, **`0`**. +- **Turn 2**: The `2`nd number spoken is a starting number, **`3`**. +- **Turn 3**: The `3`rd number spoken is a starting number, **`6`**. +- **Turn 4**: Now, consider the last number spoken, `6`. Since that was the first time the number had been spoken, the `4`th number spoken is **`0`**. +- **Turn 5**: Next, again consider the last number spoken, `0`. Since it had been spoken before, the next number to speak is the difference between the turn number when it was last spoken (the previous turn, `4`) and the turn number of the time it was most recently spoken before then (turn `1`). Thus, the 5th number spoken is `4 - 1`, **`3`**. +- **Turn 6**: The last number spoken, `3` had also been spoken before, most recently on turns `5` and `2`. So, the `6`th number spoken is `5 - 2`, **`3`**. +- **Turn 7**: Since `3` was just spoken twice in a row, and the last two turns are `1` turn apart, the `7`th number spoken is **`1`**. +- **Turn 8**: Since `1` is new, the `8`th number spoken is **`0`**. +- **Turn 9**: `0` was last spoken on turns `8` and `4`, so the `9`th number spoken is the difference between them, **`4`**. +- **Turn 10**: `4` is new, so the `10`th number spoken is **`0`**. + +(The game ends when the Elves get sick of playing or dinner is ready, whichever comes first.) + +Their question for you is: what will be the **`2020`th** number spoken? In the example above, the `2020`th number spoken will be `436`. + +Here are a few more examples: + +- Given the starting numbers `1,3,2`, the `2020`th number spoken is `1`. +- Given the starting numbers `2,1,3`, the `2020`th number spoken is `10`. +- Given the starting numbers `1,2,3`, the `2020`th number spoken is `27`. +- Given the starting numbers `2,3,1`, the `2020`th number spoken is `78`. +- Given the starting numbers `3,2,1`, the `2020`th number spoken is `438`. +- Given the starting numbers `3,1,2`, the `2020`th number spoken is `1836`. + +Given your starting numbers, **what will be the 2020th number spoken?** + +## Part 2 + +Impressed, the Elves issue you a challenge: determine the 30000000th number spoken. For example, given the same starting numbers as above: + +- Given `0,3,6`, the `30000000th` number spoken is `175594`. +- Given `1,3,2`, the `30000000th` number spoken is `2578`. +- Given `2,1,3`, the `30000000th` number spoken is `3544142`. +- Given `1,2,3`, the `30000000th` number spoken is `261214`. +- Given `2,3,1`, the `30000000th` number spoken is `6895259`. +- Given `3,2,1`, the `30000000th` number spoken is `18`. +- Given `3,1,2`, the `30000000th` number spoken is `362`. + +Given your starting numbers, **what will be the 30000000th number spoken?** \ No newline at end of file diff --git a/2020/15/code.py b/2020/15/code.py new file mode 100644 index 0000000..62242e0 --- /dev/null +++ b/2020/15/code.py @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: MIT +# Copyright (c) 2020 Akumatic +# +#https://adventofcode.com/2020/day/15 + +def readFile() -> tuple: + with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f: + return [int(num) for num in f.readline().split(",")] + +def play(input: list, turns: int) -> int: + mem = {val: [idx + 1] for idx, val in enumerate(input)} + prev = input[-1] + for turn in range(len(input) + 1, turns + 1): + # set last spoken number + if prev not in mem or len(mem[prev]) == 1: + prev = 0 + else: + prev = mem[prev][-1] - mem[prev][-2] + # store the counter + if prev in mem: + mem[prev].append(turn) + else: + mem[prev] = [turn] + + return prev + +def part1(input: list) -> int: + return play(input, 2020) + +def part2(input: list) -> int: + return play(input, 30000000) + +if __name__ == "__main__": + input = readFile() + print(f"Part 1: {part1(input)}") + print(f"Part 2: {part2(input)}") \ No newline at end of file diff --git a/2020/15/input.txt b/2020/15/input.txt new file mode 100644 index 0000000..161a9a7 --- /dev/null +++ b/2020/15/input.txt @@ -0,0 +1 @@ +5,2,8,16,18,0,1 \ No newline at end of file diff --git a/2020/15/solution.txt b/2020/15/solution.txt new file mode 100644 index 0000000..a88b968 --- /dev/null +++ b/2020/15/solution.txt @@ -0,0 +1,2 @@ +Part 1: 517 +Part 2: 1047739 \ No newline at end of file diff --git a/2020/15/test_code.py b/2020/15/test_code.py new file mode 100644 index 0000000..b7c66db --- /dev/null +++ b/2020/15/test_code.py @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: MIT +# Copyright (c) 2020 Akumatic + +from code import part1, part2 + +def test(): + assert part1([0, 3, 6]) == 436 + assert part1([1, 3, 2]) == 1 + assert part1([2, 1, 3]) == 10 + assert part1([1, 2, 3]) == 27 + assert part1([2, 3, 1]) == 78 + assert part1([3, 2, 1]) == 438 + assert part1([3, 1, 2]) == 1836 + print(f"Passed part 1") + + assert part2([0,3,6]) == 175594 + assert part2([1,3,2]) == 2578 + assert part2([2,1,3]) == 3544142 + assert part2([1,2,3]) == 261214 + assert part2([2,3,1]) == 6895259 + assert part2([3,2,1]) == 18 + assert part2([3,1,2]) == 362 + print(f"Passed part 2") + +if __name__ == "__main__": + test() \ No newline at end of file diff --git a/2020/README.md b/2020/README.md index 037b2ae..619ea13 100644 --- a/2020/README.md +++ b/2020/README.md @@ -22,7 +22,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day | 09 | :white_check_mark: | :white_check_mark: || 10 | :white_check_mark: | :white_check_mark: | | 11 | :white_check_mark: | :white_check_mark: || 12 | :white_check_mark: | :white_check_mark: | | 13 | :white_check_mark: | :white_check_mark: || 14 | :white_check_mark: | :white_check_mark: | -| 15 | | || 16 | | | +| 15 | :white_check_mark: | :white_check_mark: || 16 | | | | 17 | | || 18 | | | | 19 | | || 20 | | | | 21 | | || 22 | | |