This commit is contained in:
Stefan Harmuth 2025-01-12 09:47:12 +01:00
parent 1515086794
commit ecc905545b
3 changed files with 209 additions and 0 deletions

101
day21.py Normal file
View File

@ -0,0 +1,101 @@
from enum import Enum
from tools.aoc import AOCDay
from tools.types import String
from typing import Any
class OP(int, Enum):
SWAP = 0
ROTATE = 1
REVERSE = 2
MOVE = 3
def scramble(password: String, ops: list[tuple[OP, Any, ...]], reverse: bool = False) -> str:
if reverse:
ops = list(reversed(ops))
def get_rotate_num(c: str) -> int:
return 1 + password.index(c) + (password.index(c) >= 4)
for op in ops:
if op[0] == OP.SWAP:
x, y = op[1], op[2]
if not isinstance(x, int) or not isinstance(y, int):
x, y = password.index(x), password.index(y)
password = password.swap(x, y)
elif op[0] == OP.ROTATE:
rot = op[1]
if isinstance(rot, int):
if reverse:
rot *= -1
password = password.rotate(rot)
else:
if not reverse:
rot = get_rotate_num(rot)
password = password.rotate(rot)
else:
rot_count = 0
while rot_count != get_rotate_num(rot):
rot_count += 1
password = password.rotate(-1)
elif op[0] == OP.REVERSE:
x, y = op[1], op[2]
password = password.reverse(x, y)
elif op[0] == OP.MOVE:
x, y = op[1], op[2]
if reverse:
x, y = y, x
to_move = password[x]
password = String(password[:x] + password[x + 1 :])
password = String(password[:y] + to_move + password[y:])
return password
class Day(AOCDay):
inputs = [
[
("decab", "input21_test"),
("gfdhebac", "input21"),
],
[
("dhaegfbc", "input21"),
],
]
def parse_input(self) -> list[tuple[OP, Any, ...]]:
instr = []
for line in self.getInput():
parts = line.split()
if parts[0] == "swap":
if parts[1] == "position":
instr.append((OP.SWAP, int(parts[2]), int(parts[5])))
else:
instr.append((OP.SWAP, parts[2], parts[5]))
elif parts[0] == "rotate":
if parts[1] == "based":
instr.append((OP.ROTATE, parts[6]))
else:
instr.append((OP.ROTATE, int(parts[2]) * (-1 if parts[1] == "left" else 1)))
elif parts[0] == "reverse":
instr.append((OP.REVERSE, int(parts[2]), int(parts[4])))
else:
instr.append((OP.MOVE, int(parts[2]), int(parts[5])))
return instr
def part1(self) -> Any:
to_scramble = String("abcde") if self.is_test() else String("abcdefgh")
return scramble(to_scramble, self.parse_input())
def part2(self) -> Any:
to_unscramble = String("fbgdceah")
return scramble(to_unscramble, self.parse_input(), reverse=True)
if __name__ == "__main__":
day = Day(2016, 21)
day.run(verbose=True)

100
inputs/input21 Normal file
View File

@ -0,0 +1,100 @@
reverse positions 1 through 6
rotate based on position of letter a
swap position 4 with position 1
reverse positions 1 through 5
move position 5 to position 7
swap position 4 with position 0
swap position 4 with position 6
rotate based on position of letter a
swap position 0 with position 2
move position 5 to position 2
move position 7 to position 1
swap letter d with letter c
swap position 5 with position 3
reverse positions 3 through 7
rotate based on position of letter d
swap position 7 with position 5
rotate based on position of letter f
swap position 4 with position 1
swap position 3 with position 6
reverse positions 4 through 7
rotate based on position of letter c
move position 0 to position 5
swap position 7 with position 4
rotate based on position of letter f
reverse positions 1 through 3
move position 5 to position 3
rotate based on position of letter g
reverse positions 2 through 5
rotate right 0 steps
rotate left 0 steps
swap letter f with letter b
rotate based on position of letter h
move position 1 to position 3
reverse positions 3 through 6
rotate based on position of letter h
swap position 4 with position 3
swap letter b with letter h
swap letter a with letter h
reverse positions 1 through 6
swap position 3 with position 6
swap letter e with letter d
swap letter e with letter h
swap position 1 with position 5
rotate based on position of letter a
reverse positions 4 through 5
swap position 0 with position 4
reverse positions 0 through 3
move position 7 to position 2
swap letter e with letter c
swap position 3 with position 4
rotate left 3 steps
rotate left 7 steps
rotate based on position of letter e
reverse positions 5 through 6
move position 1 to position 5
move position 1 to position 2
rotate left 1 step
move position 7 to position 6
rotate left 0 steps
reverse positions 5 through 6
reverse positions 3 through 7
swap letter d with letter e
rotate right 3 steps
swap position 2 with position 1
swap position 5 with position 7
swap letter h with letter d
swap letter c with letter d
rotate based on position of letter d
swap letter d with letter g
reverse positions 0 through 1
rotate right 0 steps
swap position 2 with position 3
rotate left 4 steps
rotate left 5 steps
move position 7 to position 0
rotate right 1 step
swap letter g with letter f
rotate based on position of letter a
rotate based on position of letter b
swap letter g with letter e
rotate right 4 steps
rotate based on position of letter h
reverse positions 3 through 5
swap letter h with letter e
swap letter g with letter a
rotate based on position of letter c
reverse positions 0 through 4
rotate based on position of letter e
reverse positions 4 through 7
rotate left 4 steps
swap position 0 with position 6
reverse positions 1 through 6
rotate left 2 steps
swap position 5 with position 3
swap letter b with letter d
swap letter b with letter d
rotate based on position of letter d
rotate based on position of letter c
rotate based on position of letter h
move position 4 to position 7

8
inputs/input21_test Normal file
View File

@ -0,0 +1,8 @@
swap position 4 with position 0
swap letter d with letter b
reverse positions 0 through 4
rotate left 1 step
move position 1 to position 4
move position 3 to position 0
rotate based on position of letter b
rotate based on position of letter d