Solved 2024/18 P2

This commit is contained in:
FrederikBaerentsen 2024-12-19 18:04:23 +01:00
parent 2674f6e723
commit 2f5a9630d2
8 changed files with 353 additions and 49 deletions

126
2024/17/17.md Normal file
View File

@ -0,0 +1,126 @@
## \-\-- Day 17: Chronospatial Computer \-\--
The Historians push the button on their strange device, but this time,
you all just feel like you\'re [falling](/2018/day/6).
\"Situation critical\", the device announces in a familiar voice.
\"Bootstrapping process failed. Initializing debugger\....\"
The small handheld device suddenly unfolds into an entire computer! The
Historians look around nervously before one of them tosses it to you.
This seems to be a 3-bit computer: its program is a list of 3-bit
numbers (0 through 7), like `0,1,2,3`. The computer also has three
*registers* named `A`, `B`, and `C`, but these registers aren\'t limited
to 3 bits and can instead hold any integer.
The computer knows *eight instructions*, each identified by a 3-bit
number (called the instruction\'s *opcode*). Each instruction also reads
the 3-bit number after it as an input; this is called its *operand*.
A number called the *instruction pointer* identifies the position in the
program from which the next opcode will be read; it starts at `0`,
pointing at the first 3-bit number in the program. Except for jump
instructions, the instruction pointer increases by `2` after each
instruction is processed (to move past the instruction\'s opcode and its
operand). If the computer tries to read an opcode past the end of the
program, it instead *halts*.
So, the program `0,1,2,3` would run the instruction whose opcode is `0`
and pass it the operand `1`, then run the instruction having opcode `2`
and pass it the operand `3`, then halt.
There are two types of operands; each instruction specifies the type of
its operand. The value of a *literal operand* is the operand itself. For
example, the value of the literal operand `7` is the number `7`. The
value of a *combo operand* can be found as follows:
- Combo operands `0` through `3` represent literal values `0` through
`3`.
- Combo operand `4` represents the value of register `A`.
- Combo operand `5` represents the value of register `B`.
- Combo operand `6` represents the value of register `C`.
- Combo operand `7` is reserved and will not appear in valid programs.
The eight instructions are as follows:
The `adv` instruction (opcode `0`) performs *division*. The numerator is
the value in the `A` register. The denominator is found by raising 2 to
the power of the instruction\'s *combo* operand. (So, an operand of `2`
would divide `A` by `4` (`2^2`); an operand of `5` would divide `A` by
`2^B`.) The result of the division operation is *truncated* to an
integer and then written to the `A` register.
The `bxl` instruction (opcode `1`) calculates the [bitwise
XOR](https://en.wikipedia.org/wiki/Bitwise_operation#XOR)
of register `B` and the instruction\'s *literal* operand, then stores
the result in register `B`.
The `bst` instruction (opcode `2`) calculates the value of its *combo*
operand [modulo](https://en.wikipedia.org/wiki/Modulo)
8 (thereby keeping only its lowest 3 bits), then writes that value to
the `B` register.
The `jnz` instruction (opcode `3`) does *nothing* if the `A` register is
`0`. However, if the `A` register is *not zero*, it
*jumps*
by setting the instruction pointer to the value of its *literal*
operand; if this instruction jumps, the instruction pointer is *not*
increased by `2` after this instruction.
The `bxc` instruction (opcode `4`) calculates the *bitwise XOR* of
register `B` and register `C`, then stores the result in register `B`.
(For legacy reasons, this instruction reads an operand but *ignores*
it.)
The `out` instruction (opcode `5`) calculates the value of its *combo*
operand modulo 8, then *outputs* that value. (If a program outputs
multiple values, they are separated by commas.)
The `bdv` instruction (opcode `6`) works exactly like the `adv`
instruction except that the result is stored in the *`B` register*. (The
numerator is still read from the `A` register.)
The `cdv` instruction (opcode `7`) works exactly like the `adv`
instruction except that the result is stored in the *`C` register*. (The
numerator is still read from the `A` register.)
Here are some examples of instruction operation:
- If register `C` contains `9`, the program `2,6` would set register
`B` to `1`.
- If register `A` contains `10`, the program `5,0,5,1,5,4` would
output `0,1,2`.
- If register `A` contains `2024`, the program `0,1,5,4,3,0` would
output `4,2,5,6,7,7,7,7,3,1,0` and leave `0` in register `A`.
- If register `B` contains `29`, the program `1,7` would set register
`B` to `26`.
- If register `B` contains `2024` and register `C` contains `43690`,
the program `4,0` would set register `B` to `44354`.
The Historians\' strange device has finished initializing its debugger
and is displaying some *information about the program it is trying to
run* (your puzzle input). For example:
Register A: 729
Register B: 0
Register C: 0
Program: 0,1,5,4,3,0
Your first task is to *determine what the program is trying to output*.
To do this, initialize the registers to the given values, then run the
given program, collecting any output produced by `out` instructions.
(Always join the values produced by `out` instructions with commas.)
After the above program halts, its final output will be
`4,6,3,5,6,3,5,2,1,0`.
Using the information provided by the debugger, initialize the registers
to the given values, then run the program. Once it halts, *what do you
get if you use commas to join the values it output into a single
string?*
To begin, [get your puzzle input](17/input).
Answer:

31
2024/17/solution.py Normal file
View File

@ -0,0 +1,31 @@
#!/bin/python3
import sys,time,re
from pprint import pprint
sys.path.insert(0, '../../')
from fred import list2int,get_re,nprint,lprint,loadFile
start_time = time.time()
input_f = 'test'
#########################################
# #
# Part 1 #
# #
#########################################
def part1():
return
start_time = time.time()
print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms')
#########################################
# #
# Part 2 #
# #
#########################################
def part2():
return
start_time = time.time()
print('Part 2:',part2(), '\t\t', round((time.time() - start_time)*1000), 'ms')

View File

@ -96,8 +96,6 @@ the exit?*
Your puzzle answer was `294`. Your puzzle answer was `294`.
The first half of this puzzle is complete! It provides one gold star: \*
## \-\-- Part Two \-\-- {#part2} ## \-\-- Part Two \-\-- {#part2}
The Historians aren\'t as used to moving around in this pixelated The Historians aren\'t as used to moving around in this pixelated
@ -137,8 +135,14 @@ Simulate more of the bytes that are about to corrupt your memory space.
from being reachable from your starting position?* (Provide the answer from being reachable from your starting position?* (Provide the answer
as two integers separated by a comma with no other characters.) as two integers separated by a comma with no other characters.)
Answer: Your puzzle answer was `31,22`.
Although it hasn\'t changed, you can still [get your puzzle Both parts of this puzzle are complete! They provide two gold stars:
\*\*
At this point, you should [return to your Advent calendar](/2024) and
try another puzzle.
If you still want to see it, you can [get your puzzle
input](18/input). input](18/input).

View File

@ -12,33 +12,31 @@ input_f = 'input'
# Part 1 # # Part 1 #
# # # #
######################################### #########################################
def part1():
instructions = [] if input_f == 'test':
grid = [] w = 6
h = 6
size = 12
else:
w = 70 w = 70
h = 70 h = 70
end = (h,w) size = 1024
start = (0,0) end = (h,w)
with open(input_f) as file: start = (0,0)
instructions = []
grid = []
with open(input_f) as file:
for line in file: for line in file:
l = list2int(line.rstrip().split(',')) l = list2int(line.rstrip().split(','))
instructions.append((l[0],l[1])) instructions.append((l[1],l[0]))
#print(instructions) grid = [[ '.' for x in range(0,w+1)] for y in range(0,h+1)]
grid = [[ '.' for x in range(0,w+1)] for y in range(0,h+1)]
for i in range(1024):
x = instructions[i]
grid[x[0]][x[1]] = '#'
def is_goal(node):
#print(node)
def is_goal(node):
return True if node == end else False return True if node == end else False
def get_neighbors(node): def get_neighbors(node):
directions = ['up','down','left','right'] directions = ['up','down','left','right']
offsets = { offsets = {
'up': (-1, 0), 'up': (-1, 0),
@ -48,20 +46,24 @@ def part1():
} }
neighbors = [] neighbors = []
# Loop through all the directions
for d in directions: for d in directions:
tmp = addTuples(offsets[d],node) tmp = addTuples(offsets[d],node)
if get_value_in_direction(grid,node,d) != '#' and grid_valid(tmp[0],tmp[1],grid): if get_value_in_direction(grid,node,d) != '#' and grid_valid(tmp[0],tmp[1],grid):
neighbors.append((tmp[0],tmp[1])) neighbors.append((tmp[0],tmp[1]))
# Return the list of valid neighbors
return neighbors return neighbors
goal_nodes, path = bfs((0,0),is_goal,get_neighbors) def part1():
print(goal_nodes) for i in range(size):
return len(path[goal_nodes[0]])-1 x = instructions[i]
grid[x[0]][x[1]] = '#'
goal_nodes, path = bfs((0,0),is_goal,get_neighbors)
return len(path[goal_nodes[0]])-1, path
goal_nodes, path = part1()
start_time = time.time() start_time = time.time()
print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms') print('Part 1:',goal_nodes, '\t\t', round((time.time() - start_time)*1000), 'ms')
######################################### #########################################
@ -70,7 +72,13 @@ print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms')
# # # #
######################################### #########################################
def part2(): def part2():
return new_path = path
for i in range(size,len(instructions)):
x = instructions[i]
grid[x[0]][x[1]] = '#'
goal_nodes, new_path = bfs((0,0),is_goal,get_neighbors)
if not goal_nodes:
return x[1],x[0]
start_time = time.time() start_time = time.time()
print('Part 2:',part2(), '\t\t', round((time.time() - start_time)*1000), 'ms') print('Part 2:',part2(), '\t\t', round((time.time() - start_time)*1000), 'ms')

85
2024/19/19.md Normal file
View File

@ -0,0 +1,85 @@
## \-\-- Day 19: Linen Layout \-\--
Today, The Historians take you up to the [hot springs](/2023/day/12) on
Gear Island! Very
[suspiciously](https://www.youtube.com/watch?v=ekL881PJMjI),
absolutely nothing goes wrong as they begin their careful search of the
vast field of helixes.
Could this *finally* be your chance to visit the
[onsen](https://en.wikipedia.org/wiki/Onsen) next door?
Only one way to find out.
After a brief conversation with the reception staff at the onsen front
desk, you discover that you don\'t have the right kind of money to pay
the admission fee. However, before you can leave, the staff get your
attention. Apparently, they\'ve heard about how you helped at the hot
springs, and they\'re willing to make a deal: if you can simply help
them *arrange their towels*, they\'ll let you in for *free*!
Every towel at this onsen is marked with a *pattern of colored stripes*.
There are only a few patterns, but for any particular pattern, the staff
can get you as many towels with that pattern as you need. Each
stripe
can be *white* (`w`), *blue* (`u`), *black* (`b`), *red* (`r`), or
*green* (`g`). So, a towel with the pattern `ggr` would have a green
stripe, a green stripe, and then a red stripe, in that order. (You
can\'t reverse a pattern by flipping a towel upside-down, as that would
cause the onsen logo to face the wrong way.)
The Official Onsen Branding Expert has produced a list of *designs* -
each a long sequence of stripe colors - that they would like to be able
to display. You can use any towels you want, but all of the towels\'
stripes must exactly match the desired design. So, to display the design
`rgrgr`, you could use two `rg` towels and then an `r` towel, an `rgr`
towel and then a `gr` towel, or even a single massive `rgrgr` towel
(assuming such towel patterns were actually available).
To start, collect together all of the available towel patterns and the
list of desired designs (your puzzle input). For example:
r, wr, b, g, bwu, rb, gb, br
brwrr
bggr
gbbr
rrbgbr
ubwu
bwurrg
brgr
bbrgwb
The first line indicates the available towel patterns; in this example,
the onsen has unlimited towels with a single red stripe (`r`), unlimited
towels with a white stripe and then a red stripe (`wr`), and so on.
After the blank line, the remaining lines each describe a design the
onsen would like to be able to display. In this example, the first
design (`brwrr`) indicates that the onsen would like to be able to
display a black stripe, a red stripe, a white stripe, and then two red
stripes, in that order.
Not all designs will be possible with the available towels. In the above
example, the designs are possible or impossible as follows:
- `brwrr` can be made with a `br` towel, then a `wr` towel, and then
finally an `r` towel.
- `bggr` can be made with a `b` towel, two `g` towels, and then an `r`
towel.
- `gbbr` can be made with a `gb` towel and then a `br` towel.
- `rrbgbr` can be made with `r`, `rb`, `g`, and `br`.
- `ubwu` is *impossible*.
- `bwurrg` can be made with `bwu`, `r`, `r`, and `g`.
- `brgr` can be made with `br`, `g`, and `r`.
- `bbrgwb` is *impossible*.
In this example, `6` of the eight designs are possible with the
available towel patterns.
To get into the onsen as soon as possible, consult your list of towel
patterns and desired designs carefully. *How many designs are possible?*
To begin, [get your puzzle input](19/input).
Answer:

47
2024/19/solution.py Normal file
View File

@ -0,0 +1,47 @@
#!/bin/python3
import sys,time,re
from pprint import pprint
sys.path.insert(0, '../../')
from fred import list2int,get_re,nprint,bfs
start_time = time.time()
input_f = 'test'
def loadFile():
colors = []
towels = []
with open(input_f) as file:
for l,line in enumerate(file):
if l == 0:
colors = line.rstrip().split(',')
if l > 1:
towels.append(line.rstrip())
return colors,towels
#########################################
# #
# Part 1 #
# #
#########################################
def part1():
colors,towels = loadFile()
return
start_time = time.time()
print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms')
#########################################
# #
# Part 2 #
# #
#########################################
def part2():
return
start_time = time.time()
print('Part 2:',part2(), '\t\t', round((time.time() - start_time)*1000), 'ms')

Binary file not shown.

View File

@ -293,12 +293,15 @@ def nprint(grid, cur: set = None, sign: str = None, positions:list = None):
if len(sign) > 1: if len(sign) > 1:
print(prepend+sign[0] + grid[idx][jdx] + sign[1], end='') # Print with sign print(prepend+sign[0] + grid[idx][jdx] + sign[1], end='') # Print with sign
else: else:
print(prepend+colored(sign,'green',attrs=["underline"]), end=' ') # Print sign print(prepend+colored(sign,'blue',attrs=["underline","bold"]), end=' ') # Print sign
else: else:
print(prepend+colored(grid[idx][jdx],'green',attrs=["underline"]), end=' ') print(prepend+colored(grid[idx][jdx],'green',attrs=["underline"]), end=' ')
else: else:
if positions is not None: if positions is not None:
if (idx,jdx) in positions: if (idx,jdx) in positions:
if sign is not None:
print(prepend+colored(sign,'green'),end=' ')
else:
print(prepend+colored(grid[idx][jdx],'green'),end=' ') print(prepend+colored(grid[idx][jdx],'green'),end=' ')
else: else:
print(prepend+grid[idx][jdx], end=' ') print(prepend+grid[idx][jdx], end=' ')