Intcode as a single file, add SPDX-License-Identifier
This commit is contained in:
parent
4ec62b1cdb
commit
10c048ab41
@ -1,13 +1,16 @@
|
||||
""" https://adventofcode.com/2019/day/1 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/1
|
||||
|
||||
def readFile():
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return [int(line[:-1]) for line in f.readlines()]
|
||||
|
||||
def part1(vals : list):
|
||||
def part1(vals: list) -> int:
|
||||
return sum([val // 3 - 2 for val in vals])
|
||||
|
||||
def part2(vals : list):
|
||||
def part2(vals: list) -> int:
|
||||
fuel = [val // 3 - 2 for val in vals]
|
||||
for f in fuel:
|
||||
temp = f // 3 - 2
|
||||
|
@ -1,30 +1,27 @@
|
||||
""" https://adventofcode.com/2019/day/2 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/2
|
||||
|
||||
def readFile():
|
||||
import sys, os
|
||||
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import intcode
|
||||
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return [int(num) for num in f.readline().split(",")]
|
||||
|
||||
def getOutput(vals : list):
|
||||
for i in range(0, len(vals), 4):
|
||||
if vals[i] == 99:
|
||||
break
|
||||
elif vals[i] == 1:
|
||||
vals[vals[i+3]] = vals[vals[i+1]] + vals[vals[i+2]]
|
||||
else: # vals[i] == 2
|
||||
vals[vals[i+3]] = vals[vals[i+1]] * vals[vals[i+2]]
|
||||
return vals[0]
|
||||
|
||||
def part1(vals : list):
|
||||
def part1(vals: list) -> int:
|
||||
memory = vals.copy()
|
||||
memory[1], memory[2] = 12, 2
|
||||
return getOutput(memory)
|
||||
return intcode.getOutput(memory)
|
||||
|
||||
def part2(vals : list):
|
||||
def part2(vals: list) -> int:
|
||||
for noun in range(100):
|
||||
for verb in range(100):
|
||||
memory = vals.copy()
|
||||
memory[1], memory[2] = noun, verb
|
||||
if getOutput(memory) == 19690720:
|
||||
if intcode.getOutput(memory) == 19690720:
|
||||
return 100 * noun + verb
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -1,29 +1,15 @@
|
||||
""" https://adventofcode.com/2019/day/3 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/3
|
||||
|
||||
def readFile():
|
||||
from wire import Wire
|
||||
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return [Wire(val for val in line[:-1].split(",")) for line in f.readlines()]
|
||||
|
||||
class Wire:
|
||||
def __init__(self, input):
|
||||
self.input = input
|
||||
self.fields = {(0, 0, 0)}
|
||||
self.__initFields()
|
||||
|
||||
def __initFields(self):
|
||||
x, y, step = 0, 0, 0
|
||||
for i in self.input:
|
||||
dir = i[0]
|
||||
len = int(i[1:])
|
||||
dx = 1 if dir == "R" else -1 if dir == "L" else 0
|
||||
dy = 1 if dir == "U" else -1 if dir == "D" else 0
|
||||
for r in range(0, len):
|
||||
x += dx
|
||||
y += dy
|
||||
step += 1
|
||||
self.fields.add((x, y, step))
|
||||
|
||||
def getIntersections(a , b):
|
||||
def getIntersections(a, b) -> set:
|
||||
intersections = set()
|
||||
bFields = {(val[0], val[1]) for val in b.fields}
|
||||
for point in a.fields:
|
||||
@ -31,12 +17,12 @@ def getIntersections(a , b):
|
||||
intersections.add(point)
|
||||
return intersections
|
||||
|
||||
def getIntersectionDistance(intersections, i):
|
||||
def getIntersectionDistance(intersections, i) -> int:
|
||||
for intersection in intersections:
|
||||
if intersection[0] == i[0] and intersection[1] == i[1]:
|
||||
return intersection[2]
|
||||
|
||||
def part1(vals : list):
|
||||
def part1(vals: list) -> int:
|
||||
intersections = getIntersections(vals[0], vals[1])
|
||||
dists = []
|
||||
for i in intersections:
|
||||
@ -44,7 +30,7 @@ def part1(vals : list):
|
||||
dists.sort()
|
||||
return dists[1]
|
||||
|
||||
def part2(vals : list):
|
||||
def part2(vals: list) -> int:
|
||||
intersections = getIntersections(vals[0], vals[1])
|
||||
intersections2 = getIntersections(vals[1], vals[0])
|
||||
steps = []
|
||||
|
21
2019/03/wire.py
Normal file
21
2019/03/wire.py
Normal file
@ -0,0 +1,21 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
|
||||
class Wire:
|
||||
def __init__(self, input):
|
||||
self.input = input
|
||||
self.fields = {(0, 0, 0)}
|
||||
self.__initFields()
|
||||
|
||||
def __initFields(self):
|
||||
x, y, step = 0, 0, 0
|
||||
for i in self.input:
|
||||
dir = i[0]
|
||||
len = int(i[1:])
|
||||
dx = 1 if dir == "R" else -1 if dir == "L" else 0
|
||||
dy = 1 if dir == "U" else -1 if dir == "D" else 0
|
||||
for r in range(0, len):
|
||||
x += dx
|
||||
y += dy
|
||||
step += 1
|
||||
self.fields.add((x, y, step))
|
@ -1,10 +1,13 @@
|
||||
""" https://adventofcode.com/2019/day/4 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/4
|
||||
|
||||
def readFile():
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return [int(vals) for vals in f.readline().split("-")]
|
||||
|
||||
def getNumbers(min, max):
|
||||
def getNumbers(min: int, max: int) -> set:
|
||||
result = set()
|
||||
for i in range(min, max+1):
|
||||
nums = [i // 100000, (i // 10000) % 10, (i // 1000) % 10,
|
||||
@ -13,28 +16,28 @@ def getNumbers(min, max):
|
||||
result.add(i)
|
||||
return result
|
||||
|
||||
def isNotDecreasing(nums):
|
||||
def isNotDecreasing(nums: list) -> bool:
|
||||
for x in range(1, 6):
|
||||
if nums[x] < nums[x - 1]:
|
||||
return False
|
||||
return True
|
||||
|
||||
def hasDoubleAdjacentValue(nums):
|
||||
def hasDoubleAdjacentValue(nums: list) -> bool:
|
||||
for x in range(1, 5):
|
||||
if nums[x] == nums[x - 1] or nums[x] == nums[x + 1]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def isNotPartOfBiggerGroup(nums):
|
||||
def isNotPartOfBiggerGroup(nums: list) -> bool:
|
||||
for x in range(1, 6):
|
||||
if nums[x] == nums[x - 1] and nums.count(nums[x]) == 2:
|
||||
return True
|
||||
return False
|
||||
|
||||
def part1(vals : list):
|
||||
def part1(vals : list) -> int:
|
||||
return len(getNumbers(vals[0], vals[1]))
|
||||
|
||||
def part2(vals : list):
|
||||
def part2(vals : list) -> int:
|
||||
result = set()
|
||||
numbers = getNumbers(vals[0], vals[1] + 1)
|
||||
for i in numbers:
|
||||
|
120
2019/05/code.py
120
2019/05/code.py
@ -1,105 +1,43 @@
|
||||
""" https://adventofcode.com/2019/day/5 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/5
|
||||
|
||||
def readFile():
|
||||
import sys, os
|
||||
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import intcode
|
||||
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return [int(num) for num in f.readline().split(",")]
|
||||
|
||||
def parseCode(code):
|
||||
DE = code % 100
|
||||
C = code // 100 % 10
|
||||
B = code // 1000 % 10
|
||||
A = code // 10000 % 10
|
||||
return (DE, C, B, A)
|
||||
def part1(vals: list) -> int:
|
||||
return intcode.getOutput(vals.copy(), input=1)
|
||||
|
||||
def getOutput(vals : list, input=0, getVals=False):
|
||||
i = 0
|
||||
while 1:
|
||||
opcode = parseCode(vals[i])
|
||||
# 99 : Termination
|
||||
# 0 Parameter
|
||||
if opcode[0] == 99:
|
||||
if getVals:
|
||||
return vals
|
||||
return vals[0]
|
||||
|
||||
# 1 : Addition
|
||||
# 3 parameter
|
||||
elif opcode[0] == 1:
|
||||
load1 = vals[i+1] if opcode[1] == 0 else i+1
|
||||
load2 = vals[i+2] if opcode[2] == 0 else i+2
|
||||
vals[vals[i+3]] = vals[load1] + vals[load2]
|
||||
i += 4
|
||||
|
||||
# 2 : Multiplication
|
||||
# 3 parameter
|
||||
elif opcode[0] == 2:
|
||||
load1 = vals[i+1] if opcode[1] == 0 else i+1
|
||||
load2 = vals[i+2] if opcode[2] == 0 else i+2
|
||||
vals[vals[i+3]] = vals[load1] * vals[load2]
|
||||
i += 4
|
||||
|
||||
# 3 : Input
|
||||
# 1 parameter
|
||||
elif opcode[0] == 3:
|
||||
vals[vals[i+1]] = input
|
||||
i += 2
|
||||
|
||||
# 4 : Output
|
||||
# 1 parameter
|
||||
elif opcode[0] == 4:
|
||||
load = vals[i+1] if opcode[1] == 0 else i+1
|
||||
vals[0] = vals[load]
|
||||
i += 2
|
||||
|
||||
# 5 : Jump-if-true
|
||||
# 6 : Jump-if-false
|
||||
# 2 parameter
|
||||
elif opcode[0] in [5, 6]:
|
||||
load1 = vals[i+1] if opcode[1] == 0 else i+1
|
||||
if opcode[0] == 5 and vals[load1] or \
|
||||
opcode[0] == 6 and not vals[load1]:
|
||||
load2 = vals[i+2] if opcode[2] == 0 else i+2
|
||||
i = vals[load2]
|
||||
else:
|
||||
i += 3
|
||||
|
||||
# 7 : less-than
|
||||
# 8 : equals
|
||||
# 3 parameter
|
||||
elif opcode[0] in [7, 8]:
|
||||
load1 = vals[i+1] if opcode[1] == 0 else i+1
|
||||
load2 = vals[i+2] if opcode[2] == 0 else i+2
|
||||
vals[vals[i+3]] = 1 if opcode[0] == 7 and vals[load1] < vals[load2] or \
|
||||
opcode[0] == 8 and vals[load1] == vals[load2] else 0
|
||||
i += 4
|
||||
|
||||
def part1(vals : list):
|
||||
return getOutput(vals.copy(), input=1)
|
||||
|
||||
def part2(vals : list):
|
||||
return getOutput(vals.copy(), input=5)
|
||||
def part2(vals: list) -> int:
|
||||
return intcode.getOutput(vals.copy(), input=5)
|
||||
|
||||
def test():
|
||||
assert parseCode(1001) == (1, 0, 1, 0)
|
||||
assert getOutput([1,0,0,0,99]) == 2
|
||||
assert getOutput([1,1,1,4,99,5,6,0,99]) == 30
|
||||
assert getOutput([3,0,4,0,99], input=42) == 42
|
||||
assert getOutput([1101,100,-1,4,0], getVals=True) == [1101,100,-1,4,99]
|
||||
assert getOutput([3,9,8,9,10,9,4,9,99,-1,8], input=0) == 0
|
||||
assert getOutput([3,9,8,9,10,9,4,9,99,-1,8], input=8) == 1
|
||||
assert getOutput([3,9,7,9,10,9,4,9,99,-1,8], input=0) == 1
|
||||
assert getOutput([3,9,7,9,10,9,4,9,99,-1,8], input=8) == 0
|
||||
assert getOutput([3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9], input=0) == 0
|
||||
assert getOutput([3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9], input=1) == 1
|
||||
assert getOutput([3,3,1105,-1,9,1101,0,0,12,4,12,99,1], input=0) == 0
|
||||
assert getOutput([3,3,1105,-1,9,1101,0,0,12,4,12,99,1], input=1) == 1
|
||||
assert getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||
assert intcode.parseCode(1001) == (1, 0, 1, 0)
|
||||
assert intcode.getOutput([1,0,0,0,99]) == 2
|
||||
assert intcode.getOutput([1,1,1,4,99,5,6,0,99]) == 30
|
||||
assert intcode.getOutput([3,0,4,0,99], input=42) == 42
|
||||
assert intcode.getOutput([1101,100,-1,4,0], getVals=True) == [1101,100,-1,4,99]
|
||||
assert intcode.getOutput([3,9,8,9,10,9,4,9,99,-1,8], input=0) == 0
|
||||
assert intcode.getOutput([3,9,8,9,10,9,4,9,99,-1,8], input=8) == 1
|
||||
assert intcode.getOutput([3,9,7,9,10,9,4,9,99,-1,8], input=0) == 1
|
||||
assert intcode.getOutput([3,9,7,9,10,9,4,9,99,-1,8], input=8) == 0
|
||||
assert intcode.getOutput([3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9], input=0) == 0
|
||||
assert intcode.getOutput([3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9], input=1) == 1
|
||||
assert intcode.getOutput([3,3,1105,-1,9,1101,0,0,12,4,12,99,1], input=0) == 0
|
||||
assert intcode.getOutput([3,3,1105,-1,9,1101,0,0,12,4,12,99,1], input=1) == 1
|
||||
assert intcode.getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,
|
||||
1101,1000,1,20,4,20,1105,1,46,98,99], input=0) == 999
|
||||
assert getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||
assert intcode.getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,
|
||||
1101,1000,1,20,4,20,1105,1,46,98,99], input=8) == 1000
|
||||
assert getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||
assert intcode.getOutput([3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,
|
||||
1101,1000,1,20,4,20,1105,1,46,98,99], input=9) == 1001
|
||||
|
||||
|
@ -1,16 +1,19 @@
|
||||
""" https://adventofcode.com/2019/day/6 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/6
|
||||
|
||||
def readFile():
|
||||
def readFile() -> dict:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
lines = [data[:-1].split(")") for data in f.readlines()]
|
||||
return {line[1] : line[0] for line in lines}
|
||||
return {line[1]: line[0] for line in lines}
|
||||
|
||||
def countOrbits(data, cache, node):
|
||||
def countOrbits(data: dict, cache: dict, node: str) -> int:
|
||||
if node in cache: return cache[node]
|
||||
cache[node] = 0 if node not in data else 1 + countOrbits(data,cache,data[node])
|
||||
return cache[node]
|
||||
|
||||
def getIntersection(data, cache, node1, node2):
|
||||
def getIntersection(data: dict, cache: dict, node1: str, node2: str) -> str:
|
||||
if cache[node1] > cache[node2]: node1, node2 = node2, node1
|
||||
parents = set()
|
||||
# get elements of shorter path
|
||||
@ -23,10 +26,10 @@ def getIntersection(data, cache, node1, node2):
|
||||
node2 = data[node2]
|
||||
return node2
|
||||
|
||||
def part1(vals : dict, cache):
|
||||
def part1(vals : dict, cache) -> int:
|
||||
return sum([countOrbits(vals,cache,val) for val in vals])
|
||||
|
||||
def part2(vals : dict, cache):
|
||||
def part2(vals : dict, cache) -> int:
|
||||
intersection = getIntersection(vals,cache,"YOU","SAN")
|
||||
return cache["YOU"] + cache["SAN"] - 2*cache[intersection] - 2
|
||||
|
||||
|
93
2019/07/amp.py
Normal file
93
2019/07/amp.py
Normal file
@ -0,0 +1,93 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
|
||||
import queue
|
||||
|
||||
class InvalidOpcode(Exception):
|
||||
pass
|
||||
|
||||
class Amp:
|
||||
def __init__(self, vals, phase):
|
||||
self.vals = vals.copy()
|
||||
self.phase = phase
|
||||
self.queue = queue.Queue()
|
||||
self.output, self.prev, self.next = None, None, None
|
||||
self.phased, self.term = False, False
|
||||
self.i = 0
|
||||
|
||||
def run(self):
|
||||
while 1:
|
||||
opcode = (self.vals[self.i] % 100, self.vals[self.i] // 100 % 10,
|
||||
self.vals[self.i] // 1000 % 10, self.vals[self.i] // 10000 % 10)
|
||||
|
||||
# 99 : Termination
|
||||
# 0 Parameter
|
||||
if opcode[0] == 99:
|
||||
self.output = self.vals[0]
|
||||
self.term = True
|
||||
break
|
||||
|
||||
# 1 : Addition
|
||||
# 3 parameter
|
||||
elif opcode[0] == 1:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
b = self.vals[self.i+2] if opcode[2] == 0 else self.i+2
|
||||
self.vals[self.vals[self.i+3]] = self.vals[a] + self.vals[b]
|
||||
self.i += 4
|
||||
|
||||
# 2 : Multiplication
|
||||
# 3 parameter
|
||||
elif opcode[0] == 2:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
b = self.vals[self.i+2] if opcode[2] == 0 else self.i+2
|
||||
self.vals[self.vals[self.i+3]] = self.vals[a] * self.vals[b]
|
||||
self.i += 4
|
||||
|
||||
# 3 : Input
|
||||
# 1 parameter
|
||||
elif opcode[0] == 3:
|
||||
if self.phased:
|
||||
try:
|
||||
if self.prev and self.prev.output:
|
||||
self.vals[self.vals[self.i+1]] = self.prev.output
|
||||
else:
|
||||
self.vals[self.vals[self.i+1]] = self.queue.get(block=False)
|
||||
except queue.Empty:
|
||||
break
|
||||
else:
|
||||
self.vals[self.vals[self.i+1]], self.phased = self.phase, True
|
||||
self.i += 2
|
||||
|
||||
# 4 : Output
|
||||
# 1 parameter
|
||||
elif opcode[0] == 4:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
self.vals[0] = self.vals[a]
|
||||
if self.next:
|
||||
self.next.queue.put(self.vals[0])
|
||||
self.i += 2
|
||||
|
||||
# 5 : Jump-if-true
|
||||
# 6 : Jump-if-false
|
||||
# 2 parameter
|
||||
elif opcode[0] in [5, 6]:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
if opcode[0] == 5 and self.vals[a] or \
|
||||
opcode[0] == 6 and not self.vals[a]:
|
||||
b = self.vals[self.i+2] if opcode[2] == 0 else self.i+2
|
||||
self.i = self.vals[b]
|
||||
else:
|
||||
self.i += 3
|
||||
|
||||
# 7 : less-than
|
||||
# 8 : equals
|
||||
# 3 parameter
|
||||
elif opcode[0] in [7, 8]:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
b = self.vals[self.i+2] if opcode[2] == 0 else self.i+2
|
||||
self.vals[self.vals[self.i+3]] = 1 if opcode[0] == 7 and self.vals[a] < \
|
||||
self.vals[b] or opcode[0] == 8 and self.vals[a] == self.vals[b] else 0
|
||||
self.i += 4
|
||||
|
||||
else:
|
||||
raise InvalidOpcode
|
109
2019/07/code.py
109
2019/07/code.py
@ -1,101 +1,16 @@
|
||||
""" https://adventofcode.com/2019/day/7 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/7
|
||||
|
||||
import queue, itertools
|
||||
from itertools import permutations
|
||||
from amp import Amp
|
||||
|
||||
class InvalidOpcode(Exception):
|
||||
pass
|
||||
|
||||
def readFile():
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return [int(num) for num in f.readline().split(",")]
|
||||
|
||||
class Amp:
|
||||
def __init__(self, vals, phase):
|
||||
self.vals = vals.copy()
|
||||
self.phase = phase
|
||||
self.queue = queue.Queue()
|
||||
self.output, self.prev, self.next = None, None, None
|
||||
self.phased, self.term = False, False
|
||||
self.i = 0
|
||||
|
||||
def run(self):
|
||||
while 1:
|
||||
opcode = (self.vals[self.i] % 100, self.vals[self.i] // 100 % 10,
|
||||
self.vals[self.i] // 1000 % 10, self.vals[self.i] // 10000 % 10)
|
||||
|
||||
# 99 : Termination
|
||||
# 0 Parameter
|
||||
if opcode[0] == 99:
|
||||
self.output = self.vals[0]
|
||||
self.term = True
|
||||
break
|
||||
|
||||
# 1 : Addition
|
||||
# 3 parameter
|
||||
elif opcode[0] == 1:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
b = self.vals[self.i+2] if opcode[2] == 0 else self.i+2
|
||||
self.vals[self.vals[self.i+3]] = self.vals[a] + self.vals[b]
|
||||
self.i += 4
|
||||
|
||||
# 2 : Multiplication
|
||||
# 3 parameter
|
||||
elif opcode[0] == 2:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
b = self.vals[self.i+2] if opcode[2] == 0 else self.i+2
|
||||
self.vals[self.vals[self.i+3]] = self.vals[a] * self.vals[b]
|
||||
self.i += 4
|
||||
|
||||
# 3 : Input
|
||||
# 1 parameter
|
||||
elif opcode[0] == 3:
|
||||
if self.phased:
|
||||
try:
|
||||
if self.prev and self.prev.output:
|
||||
self.vals[self.vals[self.i+1]] = self.prev.output
|
||||
else:
|
||||
self.vals[self.vals[self.i+1]] = self.queue.get(block=False)
|
||||
except queue.Empty:
|
||||
break
|
||||
else:
|
||||
self.vals[self.vals[self.i+1]], self.phased = self.phase, True
|
||||
self.i += 2
|
||||
|
||||
# 4 : Output
|
||||
# 1 parameter
|
||||
elif opcode[0] == 4:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
self.vals[0] = self.vals[a]
|
||||
if self.next:
|
||||
self.next.queue.put(self.vals[0])
|
||||
self.i += 2
|
||||
|
||||
# 5 : Jump-if-true
|
||||
# 6 : Jump-if-false
|
||||
# 2 parameter
|
||||
elif opcode[0] in [5, 6]:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
if opcode[0] == 5 and self.vals[a] or \
|
||||
opcode[0] == 6 and not self.vals[a]:
|
||||
b = self.vals[self.i+2] if opcode[2] == 0 else self.i+2
|
||||
self.i = self.vals[b]
|
||||
else:
|
||||
self.i += 3
|
||||
|
||||
# 7 : less-than
|
||||
# 8 : equals
|
||||
# 3 parameter
|
||||
elif opcode[0] in [7, 8]:
|
||||
a = self.vals[self.i+1] if opcode[1] == 0 else self.i+1
|
||||
b = self.vals[self.i+2] if opcode[2] == 0 else self.i+2
|
||||
self.vals[self.vals[self.i+3]] = 1 if opcode[0] == 7 and self.vals[a] < \
|
||||
self.vals[b] or opcode[0] == 8 and self.vals[a] == self.vals[b] else 0
|
||||
self.i += 4
|
||||
|
||||
else:
|
||||
raise InvalidOpcode
|
||||
|
||||
def amplify(vals : list, phaseSettings : tuple):
|
||||
def amplify(vals: list, phaseSettings: tuple) -> int:
|
||||
amps = [Amp(vals, phaseSettings[i]) for i in range(5)]
|
||||
amps[0].queue.put(0)
|
||||
|
||||
@ -117,11 +32,11 @@ def amplify(vals : list, phaseSettings : tuple):
|
||||
|
||||
return amps[4].output
|
||||
|
||||
def part1(vals : list):
|
||||
return max([amplify(vals, (a, b, c, d, e)) for a,b,c,d,e in itertools.permutations([x for x in range(5)])])
|
||||
def part1(vals: list) -> int:
|
||||
return max([amplify(vals, (a, b, c, d, e)) for a,b,c,d,e in permutations([x for x in range(5)])])
|
||||
|
||||
def part2(vals : list):
|
||||
return max([amplify(vals, (a, b, c, d, e)) for a,b,c,d,e in itertools.permutations([x for x in range(5,10)])])
|
||||
def part2(vals: list) -> int:
|
||||
return max([amplify(vals, (a, b, c, d, e)) for a,b,c,d,e in permutations([x for x in range(5,10)])])
|
||||
|
||||
def test():
|
||||
vals = [3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0]
|
||||
|
@ -1,25 +1,29 @@
|
||||
""" https://adventofcode.com/2019/day/8 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/8
|
||||
|
||||
def readFile():
|
||||
def readFile() -> str:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return f.read()[:-1]
|
||||
|
||||
def getLayers(input, width, height):
|
||||
def getLayers(input: str, width: int, height: int) -> list:
|
||||
layers = []
|
||||
for i in range(0, len(input), width*height):
|
||||
layers.append([input[i+width*x:i+width*(x+1)] for x in range(height)])
|
||||
return layers
|
||||
|
||||
def getPicture(layers):
|
||||
def getPicture(layers: list) -> str:
|
||||
width, height = len(layers[0][0]), len(layers[0])
|
||||
return "\n".join(["".join([getColor(layers, w, h) for w in range(width)]) for h in range(height)])
|
||||
|
||||
def getColor(layers, w, h):
|
||||
def getColor(layers: list, w: int, h: int) -> str:
|
||||
for layer in layers:
|
||||
if layer[h][w] != "2": return layer[h][w]
|
||||
if layer[h][w] != "2":
|
||||
return layer[h][w]
|
||||
return "2"
|
||||
|
||||
def part1(layers):
|
||||
def part1(layers: list) -> int:
|
||||
min, minLayer = None, None
|
||||
for layer in layers:
|
||||
cnt = sum([l.count("0") for l in layer])
|
||||
@ -27,7 +31,7 @@ def part1(layers):
|
||||
min, minLayer = cnt, layer
|
||||
return sum([l.count("1") for l in minLayer]) * sum([l.count("2") for l in minLayer])
|
||||
|
||||
def part2(layers):
|
||||
def part2(layers: list) -> str:
|
||||
picture = getPicture(layers)
|
||||
return f"\n{picture.replace('0', ' ').replace('1', 'X')}"
|
||||
|
||||
|
@ -1,92 +1,25 @@
|
||||
""" https://adventofcode.com/2019/day/9 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/9
|
||||
|
||||
class InvalidOpcode(Exception):
|
||||
pass
|
||||
import sys, os
|
||||
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import intcode
|
||||
|
||||
class mylist(list):
|
||||
def __getitem__(self, item):
|
||||
try:
|
||||
return super(mylist,self).__getitem__(item)
|
||||
except IndexError as e:
|
||||
if item < 0: raise IndexError()
|
||||
super(mylist,self).extend([0]*(item + 1 - super(mylist,self).__len__()))
|
||||
return super(mylist,self).__getitem__(item)
|
||||
|
||||
def __setitem__(self, idx, val):
|
||||
try:
|
||||
return super(mylist,self).__setitem__(idx,val)
|
||||
except IndexError as e:
|
||||
if idx < 0: raise IndexError()
|
||||
super(mylist,self).extend([0]*(idx + 1 - super(mylist,self).__len__()))
|
||||
return super(mylist,self).__setitem__(idx,val)
|
||||
|
||||
def readFile():
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return [int(num) for num in f.readline().split(",")]
|
||||
|
||||
def getOutput(vals : list, input=0, base=0):
|
||||
vals = mylist(vals)
|
||||
i = 0
|
||||
while 1:
|
||||
opcode = (vals[i] % 100,
|
||||
vals[i] // 100 % 10,
|
||||
vals[i] // 1000 % 10,
|
||||
vals[i] // 10000 % 10)
|
||||
def part1(vals: list) -> int:
|
||||
return intcode.getOutput(vals.copy(), input=1)
|
||||
|
||||
# 0 Parameter
|
||||
if opcode[0] in [99]: # Termination
|
||||
return vals
|
||||
|
||||
# 1 Parameter
|
||||
elif opcode[0] in [3,4,9]:
|
||||
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
||||
if opcode[0] == 3: # Input
|
||||
vals[a] = input
|
||||
elif opcode[0] == 4: # Output
|
||||
vals[0] = vals[a]
|
||||
elif opcode[0] == 9: # Adjust Base
|
||||
base += vals[a]
|
||||
i += 2
|
||||
|
||||
# 2 Parameter
|
||||
elif opcode[0] in [5,6]:
|
||||
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
||||
b = vals[i+2] if not opcode[2] else i+2 if opcode[2] == 1 else base+vals[i+2]
|
||||
if opcode[0] == 5 and vals[a] != 0: # Jump-if-true
|
||||
i = vals[b]
|
||||
elif opcode[0] == 6 and vals[a] == 0: # Jump-if-false
|
||||
i = vals[b]
|
||||
else:
|
||||
i += 3
|
||||
|
||||
# 3 Parameter
|
||||
elif opcode[0] in [1,2,7,8]:
|
||||
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
||||
b = vals[i+2] if not opcode[2] else i+2 if opcode[2] == 1 else base+vals[i+2]
|
||||
c = vals[i+3] if not opcode[3] else i+3 if opcode[3] == 1 else base+vals[i+3]
|
||||
if opcode[0] == 1: # Addition
|
||||
vals[c] = vals[a] + vals[b]
|
||||
elif opcode[0] == 2: # Multiplication
|
||||
vals[c] = vals[a] * vals[b]
|
||||
elif opcode[0] == 7: # Less Than
|
||||
vals[c] = int(vals[a] < vals[b])
|
||||
elif opcode[0] == 8: # Equals
|
||||
vals[c] = int(vals[a] == vals[b])
|
||||
i += 4
|
||||
|
||||
else:
|
||||
raise InvalidOpcode()
|
||||
|
||||
def part1(vals : list):
|
||||
return getOutput(vals.copy(), input=1)[0]
|
||||
|
||||
def part2(vals : list):
|
||||
return getOutput(vals.copy(), input=2)[0]
|
||||
def part2(vals: list) -> int:
|
||||
return intcode.getOutput(vals.copy(), input=2)
|
||||
|
||||
def test():
|
||||
assert getOutput([104,1125899906842624,99])[0] == 1125899906842624
|
||||
assert len(getOutput([109,19,204,-34,99], base=2000)) == 1986
|
||||
assert len(str(getOutput([1102,34915192,34915192,7,4,7,99,0])[0])) == 16
|
||||
assert intcode.getOutput([104,1125899906842624,99]) == 1125899906842624
|
||||
assert len(str(intcode.getOutput([1102,34915192,34915192,7,4,7,99,0]))) == 16
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
|
14
2019/10/asteroid.py
Normal file
14
2019/10/asteroid.py
Normal file
@ -0,0 +1,14 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
|
||||
from math import atan2, sqrt
|
||||
|
||||
class Asteroid:
|
||||
def __init__(self, x: int, y: int, ox: int, oy: int):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.dist = sqrt((x - ox)**2 + (y - oy)**2)
|
||||
self.angle = atan2(y - oy, x - ox)
|
||||
|
||||
def __str__(self):
|
||||
return str((self.x, self.y))
|
@ -1,31 +1,25 @@
|
||||
""" https://adventofcode.com/2019/day/10 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/10
|
||||
|
||||
from math import atan2, sqrt, pi
|
||||
from asteroid import Asteroid
|
||||
from math import pi
|
||||
|
||||
def readFile():
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
return [line[:-1] for line in f.readlines()]
|
||||
|
||||
class Asteroid:
|
||||
def __init__(self, x: int, y: int, ox: int, oy: int):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.dist = sqrt((x - ox)**2 + (y - oy)**2)
|
||||
self.angle = atan2(y - oy, x - ox)
|
||||
|
||||
def __str__(self):
|
||||
return str((self.x, self.y))
|
||||
|
||||
def getAsteroids(field: list, x: int, y: int):
|
||||
def getAsteroids(field: list, x: int, y: int) -> list:
|
||||
return [Asteroid(i,j,x,y) for j in range(len(field))
|
||||
for i in range(len(field[j])) if field[j][i] != "." and (i,j) != (x,y)]
|
||||
|
||||
def getVisibleAsteroids(field: list, x: int, y: int):
|
||||
def getVisibleAsteroids(field: list, x: int, y: int) -> int:
|
||||
asteroids = getAsteroids(field, x, y)
|
||||
angles = set([asteroid.angle for asteroid in asteroids])
|
||||
return len(angles)
|
||||
|
||||
def part1(vals: list):
|
||||
def part1(vals: list) -> tuple:
|
||||
mx, my, max = 0, 0, 0
|
||||
for y in range(len(vals)):
|
||||
for x in range(len(vals[0])):
|
||||
@ -36,14 +30,13 @@ def part1(vals: list):
|
||||
mx, my, max = x, y, tmp
|
||||
return mx, my, max
|
||||
|
||||
def selectStart(indices, current):
|
||||
def selectStart(indices: list, current: float) -> int:
|
||||
i = 0
|
||||
while indices[i] < current:
|
||||
i += 1
|
||||
return i + 1
|
||||
|
||||
|
||||
def part2(vals: list, x: int, y: int, count):
|
||||
def part2(vals: list, x: int, y: int, count: int) -> int:
|
||||
asteroids = getAsteroids(vals, x, y)
|
||||
d = dict()
|
||||
for asteroid in asteroids:
|
||||
|
@ -1,36 +1,17 @@
|
||||
""" https://adventofcode.com/2019/day/12 """
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2019/day/12
|
||||
|
||||
from itertools import combinations
|
||||
from moon import Moon
|
||||
|
||||
def readFile():
|
||||
def readFile() -> list:
|
||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||
lines = [line[1:-2].replace(" ", "").split(",") for line in f.readlines()]
|
||||
return [(int(line[0][2:]), int(line[1][2:]), int(line[2][2:])) for line in lines]
|
||||
|
||||
def cmp(a,b):
|
||||
return 0 if a == b else -1 if a < b else 1
|
||||
|
||||
class Moon:
|
||||
def __init__(self, pos):
|
||||
self.pos = list(pos)
|
||||
self.vel = [0] * 3
|
||||
|
||||
def changeGravity(self, other):
|
||||
for i in range(3):
|
||||
d = cmp(self.pos[i], other.pos[i])
|
||||
self.vel[i] -= d
|
||||
other.vel[i] += d
|
||||
|
||||
def move(self):
|
||||
for i in range(3):
|
||||
self.pos[i] += self.vel[i]
|
||||
|
||||
def energy(self):
|
||||
pot = sum([abs(p) for p in self.pos])
|
||||
kin = sum([abs(v) for v in self.vel])
|
||||
return pot, kin, pot * kin
|
||||
|
||||
def simulate(moons : list, steps = 1):
|
||||
def simulate(moons: list, steps: int = 1):
|
||||
for i in range(steps):
|
||||
for m, n in list(combinations(moons, 2)):
|
||||
m.changeGravity(n)
|
||||
@ -38,24 +19,24 @@ def simulate(moons : list, steps = 1):
|
||||
for moon in moons:
|
||||
moon.move()
|
||||
|
||||
def lcm(x, y):
|
||||
def lcm(x: int, y: int) -> int:
|
||||
tmp = x * y
|
||||
while y:
|
||||
x, y = y, x % y
|
||||
return tmp // x
|
||||
|
||||
def part1(vals: list):
|
||||
def part1(vals: list) -> int:
|
||||
moons = [Moon(val) for val in vals]
|
||||
simulate(moons, 1000)
|
||||
return sum([moon.energy()[2] for moon in moons])
|
||||
|
||||
def part2(vals: list):
|
||||
def part2(vals: list) -> int:
|
||||
dims = [0, 0, 0]
|
||||
for i in range(3):
|
||||
moons = [Moon(val) for val in vals]
|
||||
oPos = [moon.pos[i] for moon in moons]
|
||||
|
||||
while 1:
|
||||
while True:
|
||||
simulate(moons)
|
||||
dims[i] += 1
|
||||
if [moon.pos[i] for moon in moons] == oPos and \
|
||||
|
25
2019/12/moon.py
Normal file
25
2019/12/moon.py
Normal file
@ -0,0 +1,25 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
|
||||
def cmp(a: int, b: int) -> int:
|
||||
return 0 if a == b else -1 if a < b else 1
|
||||
|
||||
class Moon:
|
||||
def __init__(self, pos):
|
||||
self.pos = list(pos)
|
||||
self.vel = [0] * 3
|
||||
|
||||
def changeGravity(self, other):
|
||||
for i in range(3):
|
||||
d = cmp(self.pos[i], other.pos[i])
|
||||
self.vel[i] -= d
|
||||
other.vel[i] += d
|
||||
|
||||
def move(self):
|
||||
for i in range(3):
|
||||
self.pos[i] += self.vel[i]
|
||||
|
||||
def energy(self):
|
||||
pot = sum([abs(p) for p in self.pos])
|
||||
kin = sum([abs(v) for v in self.vel])
|
||||
return pot, kin, pot * kin
|
90
2019/intcode.py
Normal file
90
2019/intcode.py
Normal file
@ -0,0 +1,90 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2019 Akumatic
|
||||
|
||||
class InvalidOpcode(Exception):
|
||||
pass
|
||||
|
||||
class IndexError(Exception):
|
||||
pass
|
||||
|
||||
class Data:
|
||||
def __init__(self, vals: list):
|
||||
self._data = {i:vals[i] for i in range(len(vals))}
|
||||
|
||||
def __getitem__(self, idx):
|
||||
if idx < 0:
|
||||
raise IndexError("Negative Index")
|
||||
if idx in self._data:
|
||||
return self._data[idx]
|
||||
self._data[idx] = 0
|
||||
return 0
|
||||
|
||||
def __setitem__(self, idx, val):
|
||||
if idx < 0:
|
||||
raise IndexError("Negative Index")
|
||||
self._data[idx] = val
|
||||
|
||||
def toList(self):
|
||||
return list(self._data.values())
|
||||
|
||||
def parseCode(i: int) -> tuple:
|
||||
return (i % 100, i // 100 % 10, i // 1000 % 10, i // 10000 % 10)
|
||||
|
||||
def getOutput(vals: list, input=0, base=0, full_out: bool = False,
|
||||
getVals: bool = False, output: bool=False) -> int:
|
||||
vals = Data(vals)
|
||||
i = 0
|
||||
out = []
|
||||
while True:
|
||||
opcode = parseCode(vals[i])
|
||||
|
||||
# 0 Parameter
|
||||
if opcode[0] == 99: # Termination
|
||||
if output:
|
||||
return out
|
||||
if getVals:
|
||||
return vals.toList()
|
||||
if full_out:
|
||||
return vals, out
|
||||
return vals[0]
|
||||
|
||||
# 1 Parameter
|
||||
elif opcode[0] in (3,4,9):
|
||||
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
||||
if opcode[0] == 3: # Input
|
||||
vals[a] = input
|
||||
elif opcode[0] == 4: # Output
|
||||
vals[0] = vals[a]
|
||||
out.append(vals[0])
|
||||
elif opcode[0] == 9: # Adjust Base
|
||||
base += vals[a]
|
||||
i += 2
|
||||
|
||||
# 2 Parameter
|
||||
elif opcode[0] in (5,6):
|
||||
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
||||
b = vals[i+2] if not opcode[2] else i+2 if opcode[2] == 1 else base+vals[i+2]
|
||||
if opcode[0] == 5 and vals[a] != 0: # Jump-if-true
|
||||
i = vals[b]
|
||||
elif opcode[0] == 6 and vals[a] == 0: # Jump-if-false
|
||||
i = vals[b]
|
||||
else:
|
||||
i += 3
|
||||
|
||||
# 3 Parameter
|
||||
elif opcode[0] in (1,2,7,8):
|
||||
a = vals[i+1] if not opcode[1] else i+1 if opcode[1] == 1 else base+vals[i+1]
|
||||
b = vals[i+2] if not opcode[2] else i+2 if opcode[2] == 1 else base+vals[i+2]
|
||||
c = vals[i+3] if not opcode[3] else i+3 if opcode[3] == 1 else base+vals[i+3]
|
||||
if opcode[0] == 1: # Addition
|
||||
vals[c] = vals[a] + vals[b]
|
||||
elif opcode[0] == 2: # Multiplication
|
||||
vals[c] = vals[a] * vals[b]
|
||||
elif opcode[0] == 7: # Less Than
|
||||
vals[c] = int(vals[a] < vals[b])
|
||||
elif opcode[0] == 8: # Equals
|
||||
vals[c] = int(vals[a] == vals[b])
|
||||
i += 4
|
||||
|
||||
else:
|
||||
raise InvalidOpcode()
|
@ -15,7 +15,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day
|
||||
|
||||
| Day | Part 1 | Part 2 ||Day | Part 1 | Part 2 |
|
||||
| --- | --- | --- |---| --- | --- | --- |
|
||||
| 01 | :white_check_mark: | :white_check_mark: || 02 | | |
|
||||
| 01 | :white_check_mark: | :white_check_mark: || 02 | :white_check_mark: | :white_check_mark: |
|
||||
| 03 | | || 04 | | |
|
||||
| 05 | | || 06 | | |
|
||||
| 07 | | || 08 | | |
|
||||
|
Loading…
x
Reference in New Issue
Block a user