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:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(line[:-1]) for line in f.readlines()]
|
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])
|
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]
|
fuel = [val // 3 - 2 for val in vals]
|
||||||
for f in fuel:
|
for f in fuel:
|
||||||
temp = f // 3 - 2
|
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:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(num) for num in f.readline().split(",")]
|
return [int(num) for num in f.readline().split(",")]
|
||||||
|
|
||||||
def getOutput(vals : list):
|
def part1(vals: list) -> int:
|
||||||
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):
|
|
||||||
memory = vals.copy()
|
memory = vals.copy()
|
||||||
memory[1], memory[2] = 12, 2
|
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 noun in range(100):
|
||||||
for verb in range(100):
|
for verb in range(100):
|
||||||
memory = vals.copy()
|
memory = vals.copy()
|
||||||
memory[1], memory[2] = noun, verb
|
memory[1], memory[2] = noun, verb
|
||||||
if getOutput(memory) == 19690720:
|
if intcode.getOutput(memory) == 19690720:
|
||||||
return 100 * noun + verb
|
return 100 * noun + verb
|
||||||
|
|
||||||
if __name__ == "__main__":
|
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:
|
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()]
|
return [Wire(val for val in line[:-1].split(",")) for line in f.readlines()]
|
||||||
|
|
||||||
class Wire:
|
def getIntersections(a, b) -> set:
|
||||||
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):
|
|
||||||
intersections = set()
|
intersections = set()
|
||||||
bFields = {(val[0], val[1]) for val in b.fields}
|
bFields = {(val[0], val[1]) for val in b.fields}
|
||||||
for point in a.fields:
|
for point in a.fields:
|
||||||
@ -31,12 +17,12 @@ def getIntersections(a , b):
|
|||||||
intersections.add(point)
|
intersections.add(point)
|
||||||
return intersections
|
return intersections
|
||||||
|
|
||||||
def getIntersectionDistance(intersections, i):
|
def getIntersectionDistance(intersections, i) -> int:
|
||||||
for intersection in intersections:
|
for intersection in intersections:
|
||||||
if intersection[0] == i[0] and intersection[1] == i[1]:
|
if intersection[0] == i[0] and intersection[1] == i[1]:
|
||||||
return intersection[2]
|
return intersection[2]
|
||||||
|
|
||||||
def part1(vals : list):
|
def part1(vals: list) -> int:
|
||||||
intersections = getIntersections(vals[0], vals[1])
|
intersections = getIntersections(vals[0], vals[1])
|
||||||
dists = []
|
dists = []
|
||||||
for i in intersections:
|
for i in intersections:
|
||||||
@ -44,7 +30,7 @@ def part1(vals : list):
|
|||||||
dists.sort()
|
dists.sort()
|
||||||
return dists[1]
|
return dists[1]
|
||||||
|
|
||||||
def part2(vals : list):
|
def part2(vals: list) -> int:
|
||||||
intersections = getIntersections(vals[0], vals[1])
|
intersections = getIntersections(vals[0], vals[1])
|
||||||
intersections2 = getIntersections(vals[1], vals[0])
|
intersections2 = getIntersections(vals[1], vals[0])
|
||||||
steps = []
|
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:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(vals) for vals in f.readline().split("-")]
|
return [int(vals) for vals in f.readline().split("-")]
|
||||||
|
|
||||||
def getNumbers(min, max):
|
def getNumbers(min: int, max: int) -> set:
|
||||||
result = set()
|
result = set()
|
||||||
for i in range(min, max+1):
|
for i in range(min, max+1):
|
||||||
nums = [i // 100000, (i // 10000) % 10, (i // 1000) % 10,
|
nums = [i // 100000, (i // 10000) % 10, (i // 1000) % 10,
|
||||||
@ -13,28 +16,28 @@ def getNumbers(min, max):
|
|||||||
result.add(i)
|
result.add(i)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def isNotDecreasing(nums):
|
def isNotDecreasing(nums: list) -> bool:
|
||||||
for x in range(1, 6):
|
for x in range(1, 6):
|
||||||
if nums[x] < nums[x - 1]:
|
if nums[x] < nums[x - 1]:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def hasDoubleAdjacentValue(nums):
|
def hasDoubleAdjacentValue(nums: list) -> bool:
|
||||||
for x in range(1, 5):
|
for x in range(1, 5):
|
||||||
if nums[x] == nums[x - 1] or nums[x] == nums[x + 1]:
|
if nums[x] == nums[x - 1] or nums[x] == nums[x + 1]:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def isNotPartOfBiggerGroup(nums):
|
def isNotPartOfBiggerGroup(nums: list) -> bool:
|
||||||
for x in range(1, 6):
|
for x in range(1, 6):
|
||||||
if nums[x] == nums[x - 1] and nums.count(nums[x]) == 2:
|
if nums[x] == nums[x - 1] and nums.count(nums[x]) == 2:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def part1(vals : list):
|
def part1(vals : list) -> int:
|
||||||
return len(getNumbers(vals[0], vals[1]))
|
return len(getNumbers(vals[0], vals[1]))
|
||||||
|
|
||||||
def part2(vals : list):
|
def part2(vals : list) -> int:
|
||||||
result = set()
|
result = set()
|
||||||
numbers = getNumbers(vals[0], vals[1] + 1)
|
numbers = getNumbers(vals[0], vals[1] + 1)
|
||||||
for i in numbers:
|
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:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(num) for num in f.readline().split(",")]
|
return [int(num) for num in f.readline().split(",")]
|
||||||
|
|
||||||
def parseCode(code):
|
def part1(vals: list) -> int:
|
||||||
DE = code % 100
|
return intcode.getOutput(vals.copy(), input=1)
|
||||||
C = code // 100 % 10
|
|
||||||
B = code // 1000 % 10
|
|
||||||
A = code // 10000 % 10
|
|
||||||
return (DE, C, B, A)
|
|
||||||
|
|
||||||
def getOutput(vals : list, input=0, getVals=False):
|
def part2(vals: list) -> int:
|
||||||
i = 0
|
return intcode.getOutput(vals.copy(), input=5)
|
||||||
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 test():
|
def test():
|
||||||
assert parseCode(1001) == (1, 0, 1, 0)
|
assert intcode.parseCode(1001) == (1, 0, 1, 0)
|
||||||
assert getOutput([1,0,0,0,99]) == 2
|
assert intcode.getOutput([1,0,0,0,99]) == 2
|
||||||
assert getOutput([1,1,1,4,99,5,6,0,99]) == 30
|
assert intcode.getOutput([1,1,1,4,99,5,6,0,99]) == 30
|
||||||
assert getOutput([3,0,4,0,99], input=42) == 42
|
assert intcode.getOutput([3,0,4,0,99], input=42) == 42
|
||||||
assert getOutput([1101,100,-1,4,0], getVals=True) == [1101,100,-1,4,99]
|
assert intcode.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 intcode.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 intcode.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 intcode.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 intcode.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 intcode.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 intcode.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 intcode.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 intcode.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.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,
|
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
|
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,
|
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
|
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,
|
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
|
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:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
lines = [data[:-1].split(")") for data in f.readlines()]
|
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]
|
if node in cache: return cache[node]
|
||||||
cache[node] = 0 if node not in data else 1 + countOrbits(data,cache,data[node])
|
cache[node] = 0 if node not in data else 1 + countOrbits(data,cache,data[node])
|
||||||
return cache[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
|
if cache[node1] > cache[node2]: node1, node2 = node2, node1
|
||||||
parents = set()
|
parents = set()
|
||||||
# get elements of shorter path
|
# get elements of shorter path
|
||||||
@ -23,10 +26,10 @@ def getIntersection(data, cache, node1, node2):
|
|||||||
node2 = data[node2]
|
node2 = data[node2]
|
||||||
return node2
|
return node2
|
||||||
|
|
||||||
def part1(vals : dict, cache):
|
def part1(vals : dict, cache) -> int:
|
||||||
return sum([countOrbits(vals,cache,val) for val in vals])
|
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")
|
intersection = getIntersection(vals,cache,"YOU","SAN")
|
||||||
return cache["YOU"] + cache["SAN"] - 2*cache[intersection] - 2
|
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):
|
def readFile() -> list:
|
||||||
pass
|
|
||||||
|
|
||||||
def readFile():
|
|
||||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(num) for num in f.readline().split(",")]
|
return [int(num) for num in f.readline().split(",")]
|
||||||
|
|
||||||
class Amp:
|
def amplify(vals: list, phaseSettings: tuple) -> int:
|
||||||
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):
|
|
||||||
amps = [Amp(vals, phaseSettings[i]) for i in range(5)]
|
amps = [Amp(vals, phaseSettings[i]) for i in range(5)]
|
||||||
amps[0].queue.put(0)
|
amps[0].queue.put(0)
|
||||||
|
|
||||||
@ -117,11 +32,11 @@ def amplify(vals : list, phaseSettings : tuple):
|
|||||||
|
|
||||||
return amps[4].output
|
return amps[4].output
|
||||||
|
|
||||||
def part1(vals : list):
|
def part1(vals: list) -> int:
|
||||||
return max([amplify(vals, (a, b, c, d, e)) for a,b,c,d,e in itertools.permutations([x for x in range(5)])])
|
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):
|
def part2(vals: list) -> int:
|
||||||
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)])])
|
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():
|
def test():
|
||||||
vals = [3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0]
|
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:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return f.read()[:-1]
|
return f.read()[:-1]
|
||||||
|
|
||||||
def getLayers(input, width, height):
|
def getLayers(input: str, width: int, height: int) -> list:
|
||||||
layers = []
|
layers = []
|
||||||
for i in range(0, len(input), width*height):
|
for i in range(0, len(input), width*height):
|
||||||
layers.append([input[i+width*x:i+width*(x+1)] for x in range(height)])
|
layers.append([input[i+width*x:i+width*(x+1)] for x in range(height)])
|
||||||
return layers
|
return layers
|
||||||
|
|
||||||
def getPicture(layers):
|
def getPicture(layers: list) -> str:
|
||||||
width, height = len(layers[0][0]), len(layers[0])
|
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)])
|
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:
|
for layer in layers:
|
||||||
if layer[h][w] != "2": return layer[h][w]
|
if layer[h][w] != "2":
|
||||||
|
return layer[h][w]
|
||||||
return "2"
|
return "2"
|
||||||
|
|
||||||
def part1(layers):
|
def part1(layers: list) -> int:
|
||||||
min, minLayer = None, None
|
min, minLayer = None, None
|
||||||
for layer in layers:
|
for layer in layers:
|
||||||
cnt = sum([l.count("0") for l in layer])
|
cnt = sum([l.count("0") for l in layer])
|
||||||
@ -27,7 +31,7 @@ def part1(layers):
|
|||||||
min, minLayer = cnt, layer
|
min, minLayer = cnt, layer
|
||||||
return sum([l.count("1") for l in minLayer]) * sum([l.count("2") for l in minLayer])
|
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)
|
picture = getPicture(layers)
|
||||||
return f"\n{picture.replace('0', ' ').replace('1', 'X')}"
|
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):
|
import sys, os
|
||||||
pass
|
sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
import intcode
|
||||||
|
|
||||||
class mylist(list):
|
def readFile() -> 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():
|
|
||||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [int(num) for num in f.readline().split(",")]
|
return [int(num) for num in f.readline().split(",")]
|
||||||
|
|
||||||
def getOutput(vals : list, input=0, base=0):
|
def part1(vals: list) -> int:
|
||||||
vals = mylist(vals)
|
return intcode.getOutput(vals.copy(), input=1)
|
||||||
i = 0
|
|
||||||
while 1:
|
|
||||||
opcode = (vals[i] % 100,
|
|
||||||
vals[i] // 100 % 10,
|
|
||||||
vals[i] // 1000 % 10,
|
|
||||||
vals[i] // 10000 % 10)
|
|
||||||
|
|
||||||
# 0 Parameter
|
def part2(vals: list) -> int:
|
||||||
if opcode[0] in [99]: # Termination
|
return intcode.getOutput(vals.copy(), input=2)
|
||||||
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 test():
|
def test():
|
||||||
assert getOutput([104,1125899906842624,99])[0] == 1125899906842624
|
assert intcode.getOutput([104,1125899906842624,99]) == 1125899906842624
|
||||||
assert len(getOutput([109,19,204,-34,99], base=2000)) == 1986
|
assert len(str(intcode.getOutput([1102,34915192,34915192,7,4,7,99,0]))) == 16
|
||||||
assert len(str(getOutput([1102,34915192,34915192,7,4,7,99,0])[0])) == 16
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test()
|
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:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
return [line[:-1] for line in f.readlines()]
|
return [line[:-1] for line in f.readlines()]
|
||||||
|
|
||||||
class Asteroid:
|
def getAsteroids(field: list, x: int, y: int) -> list:
|
||||||
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):
|
|
||||||
return [Asteroid(i,j,x,y) for j in range(len(field))
|
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)]
|
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)
|
asteroids = getAsteroids(field, x, y)
|
||||||
angles = set([asteroid.angle for asteroid in asteroids])
|
angles = set([asteroid.angle for asteroid in asteroids])
|
||||||
return len(angles)
|
return len(angles)
|
||||||
|
|
||||||
def part1(vals: list):
|
def part1(vals: list) -> tuple:
|
||||||
mx, my, max = 0, 0, 0
|
mx, my, max = 0, 0, 0
|
||||||
for y in range(len(vals)):
|
for y in range(len(vals)):
|
||||||
for x in range(len(vals[0])):
|
for x in range(len(vals[0])):
|
||||||
@ -36,14 +30,13 @@ def part1(vals: list):
|
|||||||
mx, my, max = x, y, tmp
|
mx, my, max = x, y, tmp
|
||||||
return mx, my, max
|
return mx, my, max
|
||||||
|
|
||||||
def selectStart(indices, current):
|
def selectStart(indices: list, current: float) -> int:
|
||||||
i = 0
|
i = 0
|
||||||
while indices[i] < current:
|
while indices[i] < current:
|
||||||
i += 1
|
i += 1
|
||||||
return i + 1
|
return i + 1
|
||||||
|
|
||||||
|
def part2(vals: list, x: int, y: int, count: int) -> int:
|
||||||
def part2(vals: list, x: int, y: int, count):
|
|
||||||
asteroids = getAsteroids(vals, x, y)
|
asteroids = getAsteroids(vals, x, y)
|
||||||
d = dict()
|
d = dict()
|
||||||
for asteroid in asteroids:
|
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 itertools import combinations
|
||||||
|
from moon import Moon
|
||||||
|
|
||||||
def readFile():
|
def readFile() -> list:
|
||||||
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
with open(f"{__file__.rstrip('code.py')}input.txt", "r") as f:
|
||||||
lines = [line[1:-2].replace(" ", "").split(",") for line in f.readlines()]
|
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]
|
return [(int(line[0][2:]), int(line[1][2:]), int(line[2][2:])) for line in lines]
|
||||||
|
|
||||||
def cmp(a,b):
|
def simulate(moons: list, steps: int = 1):
|
||||||
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):
|
|
||||||
for i in range(steps):
|
for i in range(steps):
|
||||||
for m, n in list(combinations(moons, 2)):
|
for m, n in list(combinations(moons, 2)):
|
||||||
m.changeGravity(n)
|
m.changeGravity(n)
|
||||||
@ -38,24 +19,24 @@ def simulate(moons : list, steps = 1):
|
|||||||
for moon in moons:
|
for moon in moons:
|
||||||
moon.move()
|
moon.move()
|
||||||
|
|
||||||
def lcm(x, y):
|
def lcm(x: int, y: int) -> int:
|
||||||
tmp = x * y
|
tmp = x * y
|
||||||
while y:
|
while y:
|
||||||
x, y = y, x % y
|
x, y = y, x % y
|
||||||
return tmp // x
|
return tmp // x
|
||||||
|
|
||||||
def part1(vals: list):
|
def part1(vals: list) -> int:
|
||||||
moons = [Moon(val) for val in vals]
|
moons = [Moon(val) for val in vals]
|
||||||
simulate(moons, 1000)
|
simulate(moons, 1000)
|
||||||
return sum([moon.energy()[2] for moon in moons])
|
return sum([moon.energy()[2] for moon in moons])
|
||||||
|
|
||||||
def part2(vals: list):
|
def part2(vals: list) -> int:
|
||||||
dims = [0, 0, 0]
|
dims = [0, 0, 0]
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
moons = [Moon(val) for val in vals]
|
moons = [Moon(val) for val in vals]
|
||||||
oPos = [moon.pos[i] for moon in moons]
|
oPos = [moon.pos[i] for moon in moons]
|
||||||
|
|
||||||
while 1:
|
while True:
|
||||||
simulate(moons)
|
simulate(moons)
|
||||||
dims[i] += 1
|
dims[i] += 1
|
||||||
if [moon.pos[i] for moon in moons] == oPos and \
|
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 |
|
| 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 | | |
|
| 03 | | || 04 | | |
|
||||||
| 05 | | || 06 | | |
|
| 05 | | || 06 | | |
|
||||||
| 07 | | || 08 | | |
|
| 07 | | || 08 | | |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user