summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2021-11-26 23:51:59 +0000
committerTomasz Kramkowski <tk@the-tk.com>2021-11-26 23:51:59 +0000
commitdeb9cd82db7f5b6a44f613feb0959110ce70c2e6 (patch)
treede0038e31cb65a8106fe30f4effdbcf883759683
parent0e8e49af605d3160645e773fdec53b7cf60cc068 (diff)
downloadaoc2015-deb9cd82db7f5b6a44f613feb0959110ce70c2e6.tar.gz
aoc2015-deb9cd82db7f5b6a44f613feb0959110ce70c2e6.tar.xz
aoc2015-deb9cd82db7f5b6a44f613feb0959110ce70c2e6.zip
solutions
-rw-r--r--22/solution.py42
-rw-r--r--23/solution.py49
-rw-r--r--24/solution.py43
-rw-r--r--7/solution.py30
4 files changed, 154 insertions, 10 deletions
diff --git a/22/solution.py b/22/solution.py
index 2859416..6df8379 100644
--- a/22/solution.py
+++ b/22/solution.py
@@ -1,2 +1,42 @@
+from functools import cache
+from collections import namedtuple
+
+Opponent = namedtuple('Opponent', ['hp', 'damage'])
+
+def part1(opponent: Opponent) -> int:
+ @cache
+ def min_cost(php: int, pmana: int, ohp: int, sld_timer: int, psn_timer: int, rch_timer: int) -> int | float:
+ psld = 0
+ def effects():
+ nonlocal ohp, pmana, psld, psn_timer, rch_timer, sld_timer
+ if sld_timer > 0:
+ sld_timer -= 1
+ psld = 7
+ else:
+ psld = 0
+ if psn_timer > 0:
+ psn_timer -= 1
+ ohp -= 3
+ if rch_timer > 0:
+ rch_timer -= 1
+ pmana += 101
+
+ def opponent_turn(cost: int) -> int | float:
+ effects()
+ nonlocal php
+ if ohp <= 0:
+ return cost
+ php -= min(1, opponent.attack - psld)
+ if php <= 0:
+ return float('inf')
+ return cost + min_cost(php, pmana, ohp, sld_timer, psn_timer, rch_timer)
+
+ effects()
+ if ohp <= 0:
+ return 0
+
if __name__ == '__main__':
- with open('input') as f: \ No newline at end of file
+ opponent = Opponent(51, 9)
+
+ print(part1(opponent))
+ #print(part2(opponent))
diff --git a/23/solution.py b/23/solution.py
new file mode 100644
index 0000000..00144bf
--- /dev/null
+++ b/23/solution.py
@@ -0,0 +1,49 @@
+def run(instructions, a=0, b=0):
+ ip = 0
+ regs = {
+ 'a': a,
+ 'b': b,
+ }
+
+ def set(r, v):
+ regs[r] = v
+ return 1
+
+ act = {
+ 'hlf': lambda r: set(r, regs[r] // 2),
+ 'tpl': lambda r: set(r, regs[r] * 3),
+ 'inc': lambda r: set(r, regs[r] + 1),
+ 'jmp': lambda offset: offset,
+ 'jie': lambda r, offset: offset if regs[r] % 2 == 0 else 1,
+ 'jio': lambda r, offset: offset if regs[r] == 1 else 1,
+ }
+
+ while 0 <= ip < len(instructions):
+ ins, ops = instructions[ip]
+ ip += act[ins](*ops)
+ # print(f'ins={ins}, ops={ops}, a={regs["a"]}, b={regs["b"]}, ip={ip}')
+
+ return regs
+
+def part1(instructions):
+ return run(instructions)['b']
+
+def part2(instructons):
+ return run(instructions, 1)['b']
+
+if __name__ == '__main__':
+ with open('input') as f:
+ instructions = list()
+ for line in f:
+ line = line.rstrip()
+ opcode, operands = line.split(' ', maxsplit=1)
+ def parse_operand(s: str) -> int | str:
+ if s[0] == '+':
+ return int(s[1:])
+ elif s[0] == '-':
+ return -int(s[1:])
+ return s
+ operands = tuple(parse_operand(op) for op in operands.split(', '))
+ instructions.append((opcode, operands))
+ print(part1(instructions))
+ print(part2(instructions))
diff --git a/24/solution.py b/24/solution.py
new file mode 100644
index 0000000..6aa9ebe
--- /dev/null
+++ b/24/solution.py
@@ -0,0 +1,43 @@
+from functools import reduce
+
+def cansum(packages, target):
+ if target == 0:
+ return True
+ if len(packages) == 0:
+ return False
+ p = next(iter(packages))
+ rest = packages - {p}
+ if p <= target:
+ return cansum(rest, target - p) or cansum(rest, target)
+ else:
+ return cansum(rest, target)
+
+def minimize(packages, pile, target, orig_target=None):
+ if orig_target is None:
+ orig_target = target
+ if target == 0 and cansum(packages, orig_target):
+ return len(pile), reduce(lambda a, b: a * b, pile, 1)
+ if len(packages) == 0:
+ return float('inf'), float('inf')
+ p = next(iter(packages))
+ rest = packages - {p}
+ if p <= target:
+ return min(
+ minimize(rest, pile | {p}, target - p, orig_target),
+ minimize(rest, pile, target, orig_target)
+ )
+ else:
+ return minimize(rest, pile, target)
+
+def part1(packages):
+ return minimize(frozenset(packages), frozenset(), sum(packages) // 3)
+
+def part2(packages):
+ return minimize(frozenset(packages), frozenset(), sum(packages) // 4)
+
+if __name__ == '__main__':
+ with open('input') as f:
+ packages = list(int(l.rstrip()) for l in f)
+ packages.reverse()
+ print(part1(packages))
+ print(part2(packages))
diff --git a/7/solution.py b/7/solution.py
index 77a1391..6eee284 100644
--- a/7/solution.py
+++ b/7/solution.py
@@ -15,34 +15,44 @@ class U16:
return U16(self.value << other.value)
def __str__(self):
return str(self.value)
+ def __repr__(self):
+ return f'{self.value}'
class Node:
- _value: U16 = None
+ _value: U16 | None = None
@property
def value(self) -> U16:
- if not self._value:
+ if self._value is None:
self._value = self.eval()
return self._value
- def eval(self, net: dict[Node]) -> U16:
- return self.eval()
- @absrtactmethod
+ @abstractmethod
def eval(self) -> U16:
pass
+ @abstractmethod
+ def __repr__(self) -> str:
+ pass
class Reference(Node):
- def __init__(self, name: str):
+ def __init__(self, net: dict[Node], name: str):
+ self.net = net
self.name = name
- def eval(self, net: dict[Node]) -> U16:
- return net[self.name].value
+ def eval(self) -> U16:
+ return self.net[self.name].value
+ def __repr__(self) -> str:
+ return f'Reference({self.name})'
class Constant(Node):
def __init__(self, value):
self._value = value
+ def __repr__(self) -> str:
+ return f'Constant({self.value})'
class BinaryOp(Node):
def __init__(self, left, right):
self.left = left
self.right = right
+ def __repr__(self) -> str:
+ return f'{self.__class__.__name__}({self.left}, {self.right})'
class And(BinaryOp):
def eval(self) -> U16:
@@ -65,6 +75,8 @@ class Not(Node):
self.node = node
def eval(self):
return ~self.node.value
+ def __repr__(self) -> str:
+ return 'Not({self.node})'
def parse_expr(net: dict[Node], expr: str) -> Node:
parts = expr.split(' ')
@@ -112,4 +124,4 @@ if __name__ == '__main__':
with open('input') as f:
inp = [line.strip() for line in f]
print(part1(inp))
- print(part2(inp)) \ No newline at end of file
+ print(part2(inp))