def part_1(raw: str, ints: list[int], strs: list[str]): match strs: case [lengths, nums]: nums = aoc.ints(nums) case [lengths]: nums = list(range(256)) lengths = aoc.ints(lengths) pos = 0 skip = 0 for length in lengths: indices = list(range(pos, pos + length)) temp = [] for i in indices: temp.append(nums[i % len(nums)]) for i in indices: nums[i % len(nums)] = temp.pop() pos += (length + skip) % len(nums) skip += 1 return nums[0] * nums[1]
def part_2(raw: str, ints: list[int], strs: list[str]): _, _, x_range, y_range = raw.split() x0, x1 = aoc.ints(x_range.split("=")[1].strip(",").split("..")) y0, y1 = sorted(aoc.ints(y_range.split("=")[1].split(".."))) cords = [] total = 0 for vx0 in range(1, x1 + 1): for vy0 in range(-max(abs(y1), abs(y0)), max(abs(y1), abs(y0)) + 1): t = 1 y_max = 0 while x(vx0, t) <= x1: y_max = max(y(vy0, t), y_max) if y0 <= y(vy0, t) <= y1 and x0 <= x(vx0, t) <= x1: cords.append((vx0, vy0)) total += 1 break if vx(vx0, t) == 0 and vy(vy0, t) < 0 and y(vy0, t) < min(y1, y0): break t += 1 return total
def part_2(raw: str, ints: list[int], strs: list[str]): t = 0 for line in strs: l, w, h = aoc.ints(line) x, y = sorted(aoc.ints(line))[:2] a = 2 * x + 2 * y b = l * w * h t += a + b return t
def part_2(raw: str, ints: List[int], strs: List[str]): banks = aoc.ints(strs[0]) mem = set(" ".join([str(b) for b in banks])) steps = 0 seen = "" while True: s = banks.index(max(banks)) banks[s], cash = 0, banks[s] for i in itertools.cycle(range(len(banks))): if cash == 0: break i += s + 1 i = i % len(banks) banks[i] += 1 cash -= 1 steps += 1 banks_str = " ".join([str(b) for b in banks]) if banks_str in mem: if not seen: seen = banks_str steps = 0 elif banks_str == seen: return steps if not seen: mem.add(banks_str)
def part_2(raw: str, ints: list[int], strs: list[str]): grid = aoc.Grid.of(Light, height=1000, width=1000) for line in strs: line, b = line.split(" through ") inst, a = line.rsplit(" ", 1) subgrid = grid.subgrid(aoc.ints(a.split(",")), aoc.ints(b.split(","))) match inst: case "turn on": subgrid.for_each(Light.turn_on_2) case "turn off": subgrid.for_each(Light.turn_off_2) case "toggle": subgrid.for_each(Light.toggle_2) return sum([l.brightness for l in grid.values()])
def part_1(raw: str, ints: list[int], strs: list[str]): bings = aoc.ints(strs[0]) boards = [BingoBoard.populate(s) for s in raw.split("\n\n")[1:]] for b, bing in enumerate(bings, 1): for board in boards: board.bing(bing) if board.winner(): return sum(b.value for b in board.unbinged()) * bing
def part_2(raw: str, ints: List[int], strs: List[str]): s = 0 for line in strs: nums = aoc.ints(line) for a, b in itertools.combinations(nums, 2): a , b = (a, b) if a > b else (b , a) s += int(a / b) if a % b == 0 else 0 return s
def part_1(raw: str, ints: list[int], strs: list[str]): t = 0 for l in strs: l, w, h = aoc.ints(l) a = l * w b = w * h c = h * l t += 2 * a + 2 * b + 2 * c + min(a, b, c) return t
def part_1(raw: str, ints: list[int], strs: list[str]): _, _, x_range, y_range = raw.split() x0, x1 = aoc.ints(x_range.split("=")[1].strip(",").split("..")) y0, y1 = sorted(aoc.ints(y_range.split("=")[1].split(".."))) highest_y = float("-inf") for vx0 in range(1, x1): for vy0 in range(-max(abs(y1), abs(y0)), max(abs(y1), abs(y0))): t = 1 y_max = 0 while x(vx0, t) < x1: y_max = max(y(vy0, t), y_max) if y0 <= y(vy0, t) <= y1 and x0 <= x(vx0, t) <= x1: highest_y = max(y_max, highest_y) break if vx(vx0, t) == 0 and vy(vy0, t) < 0 and y(vy0, t) < y1: break t += 1 return highest_y
def part_2(raw: str, ints: list[int], strs: list[str]): points = defaultdict(bool) inst, folds = raw.split("\n\n") width = 0 height = 0 for line in inst.splitlines(): x, y = aoc.ints(line.split(",")) points[x, y] = True width = max(x, width) height = max(y, height) width = width + 1 height = height + 1 for f in folds.splitlines(): axis, n = f.split()[-1].split("=") num = int(n) if axis == "y": for y in range(num + 1, height): for x in range(width): d = y - num merge = (x, y) dest = (x, num - d) points[dest] |= points[merge] height = num elif axis == "x": for x in range(num + 1, width): for y in range(height): d = x - num merge = (x, y) points[(num - d, y)] |= points[merge] width = num hash_and_dots: list[str] = [] for y in range(height): row = '' for x in range(width): row += '#' if points[(x, y)] else "." hash_and_dots.append(row) print('\n'.join(hash_and_dots)) return "O"
def part_1(raw: str, ints: list[int], strs: list[str]): points = defaultdict(bool) inst, folds = raw.split("\n\n") width = 0 height = 0 for line in inst.splitlines(): x, y = aoc.ints(line.split(",")) points[(x, y)] = True width = max(x, width) height = max(y, height) width = width + 1 height = height + 1 for f in folds.splitlines(): axis, n = f.split()[-1].split("=") num = int(n) if axis == "y": for y in range(num + 1, height): for x in range(width): points[(x, 2 * num - y)] |= points[(x, y)] height = num elif axis == "x": for x in range(num + 1, width): for y in range(height): points[(2 * num - x, y)] |= points[(x, y)] width = num break total = 0 for y in range(height): for x in range(width): total += points[(x, y)] return total
def part_2(raw: str, ints: list[int], strs: list[str]): bings = aoc.ints(strs[0]) boards = [BingoBoard.populate(s) for s in raw.split("\n\n")[1:]] winners: list[int] = [] for bing in bings: for i, board in enumerate(boards, 1): board.bing(bing) # if i == 2: # print(f"Bing: {bing}") # board.display() if i not in winners and board.winner(): score = sum(b.value for b in board.unbinged()) * bing winners.append(i) print(f"Board {i} score: {score}") print("--------------------") board.display() return score
def part_1(raw: str, ints: List[int], strs: List[str]): chk = 0 for l in strs: nums = aoc.ints(l) chk += max(nums) - min(nums) return chk