Intcode as a single file, add SPDX-License-Identifier

This commit is contained in:
Akumatic 2020-12-02 21:34:21 +01:00
parent 4ec62b1cdb
commit 10c048ab41
17 changed files with 386 additions and 387 deletions

View File

@ -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

View File

@ -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__":

View File

@ -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
View 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))

View File

@ -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:

View File

@ -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

View File

@ -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
View 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

View File

@ -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]

View File

@ -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')}"

View File

@ -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
View 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))

View File

@ -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:

View File

@ -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
View 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
View 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()

View File

@ -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 | | |