diff --git a/2024/12/solution.py b/2024/12/solution.py index ae3db3b..a0a5b41 100644 --- a/2024/12/solution.py +++ b/2024/12/solution.py @@ -14,33 +14,27 @@ input_f = 'input' # # ######################################### -def get_neighbors(grid,node,visited): - #print('@',node,' - Visited',visited) +directions = { + 'up': (-1, 0), + 'down': (1, 0), + 'left': (0, -1), + 'right': (0, 1), +} - directions = ['up','down','left','right'] - offsets = { - 'up': (-1, 0), - 'down': (1, 0), - 'left': (0, -1), - 'right': (0, 1), - } +def get_neighbors(grid,node,visited): neighbors = [] - for d in directions: + for d in directions.keys(): t = get_value_in_direction(grid,node) if get_value_in_direction(grid,node,d) == t: - n = addTuples(offsets[d],node) + n = addTuples(directions[d],node) if n not in visited: neighbors.append(n) - #print(n) visited.append(n) neighbors+=get_neighbors(grid,n,visited) return neighbors def part1(): grid = toGrid(input_f) - - #nprint(grid) - values = {} visited = [] total_plots = [] for r,row in enumerate(grid): @@ -54,20 +48,15 @@ def part1(): plot += x if pos not in plot: plot.append(pos) - if current not in values: - values[current] = [] total_plots.append(plot) - directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] result = 0 for v in total_plots: - sides = 0 for x,y in v: - - for dx, dy in directions: + for dx, dy in directions.values(): neighbor = (x + dx, y + dy) if neighbor in v: sides += 1 @@ -88,29 +77,6 @@ print('Part 1:',part1(), '\t', round((time.time() - start_time)*1000), 'ms') # # ######################################### -def get_neighbors_and_corners(grid,node,visited): - - directions = ['up','down','left','right'] - offsets = { - 'up': (-1, 0), - 'down': (1, 0), - 'left': (0, -1), - 'right': (0, 1), - } - neighbors = [] - for d in directions: - if get_value_in_direction(grid,node,d) == get_value_in_direction(grid,node): - n = addTuples(offsets[d],node) - if n not in visited: - neighbors.append(n) - visited.append(n) - neighbors += get_neighbors_and_corners(grid,n,visited) - - return neighbors - -def rotate_90_clockwise(grid:list) -> list: - return [list(row) for row in zip(*grid[::-1])] - def part2(): grid = toGrid(input_f) #print(grid) @@ -126,7 +92,7 @@ def part2(): current = get_value_in_direction(grid,pos) if pos not in visited: - x = get_neighbors_and_corners(grid,pos,visited) + x = get_neighbors(grid,pos,visited) plot += x if pos not in plot: plot.append(pos) diff --git a/2024/13/13.md b/2024/13/13.md new file mode 100644 index 0000000..18ffa52 --- /dev/null +++ b/2024/13/13.md @@ -0,0 +1,126 @@ +## \-\-- Day 13: Claw Contraption \-\-- + +Next up: the [lobby](/2020/day/24) of a resort on a tropical island. The +Historians take a moment to admire the hexagonal floor tiles before +spreading out. + +Fortunately, it looks like the resort has a new +[arcade](https://en.wikipedia.org/wiki/Amusement_arcade)! Maybe you can +win some prizes from the [claw +machines](https://en.wikipedia.org/wiki/Claw_machine)? + +The claw machines here are a little unusual. Instead of a joystick or +directional buttons to control the claw, these machines have two buttons +labeled `A` and `B`. Worse, you can\'t just put in a token and play; it +costs *3 tokens* to push the `A` button and *1 token* to push the `B` +button. + +With a little experimentation, you figure out that each machine\'s +buttons are configured to move the claw a specific amount to the *right* +(along the `X` axis) and a specific amount *forward* (along the `Y` +axis) each time that button is pressed. + +Each machine contains one *prize*; to win the prize, the claw must be +positioned *exactly* above the prize on both the `X` and `Y` axes. + +You wonder: what is the smallest number of tokens you would have to +spend to win as many prizes as possible? You assemble a list of every +machine\'s button behavior and prize location (your puzzle input). For +example: + + Button A: X+94, Y+34 + Button B: X+22, Y+67 + Prize: X=8400, Y=5400 + + Button A: X+26, Y+66 + Button B: X+67, Y+21 + Prize: X=12748, Y=12176 + + Button A: X+17, Y+86 + Button B: X+84, Y+37 + Prize: X=7870, Y=6450 + + Button A: X+69, Y+23 + Button B: X+27, Y+71 + Prize: X=18641, Y=10279 + +This list describes the button configuration and prize location of four +different claw machines. + +For now, consider just the first claw machine in the list: + +- Pushing the machine\'s `A` button would move the claw `94` units + along the `X` axis and `34` units along the `Y` axis. +- Pushing the `B` button would move the claw `22` units along the `X` + axis and `67` units along the `Y` axis. +- The prize is located at `X=8400`, `Y=5400`; this means that from the + claw\'s initial position, it would need to move exactly `8400` units + along the `X` axis and exactly `5400` units along the `Y` axis to be + perfectly aligned with the prize in this machine. + +The cheapest way to win the prize is by pushing the `A` button `80` +times and the `B` button `40` times. This would line up the claw along +the `X` axis (because `80*94 + 40*22 = 8400`) and along the `Y` axis +(because `80*34 + 40*67 = 5400`). Doing this would cost `80*3` tokens +for the `A` presses and +`40*1` for the `B` presses, a total of `280` tokens. + +For the second and fourth claw machines, there is no combination of A +and B presses that will ever win a prize. + +For the third claw machine, the cheapest way to win the prize is by +pushing the `A` button `38` times and the `B` button `86` times. Doing +this would cost a total of `200` tokens. + +So, the most prizes you could possibly win is two; the minimum tokens +you would have to spend to win all (two) prizes is `480`. + +You estimate that each button would need to be pressed *no more than +`100` times* to win a prize. How else would someone be expected to play? + +Figure out how to win as many prizes as possible. *What is the fewest +tokens you would have to spend to win all possible prizes?* + +Your puzzle answer was `30973`. + +The first half of this puzzle is complete! It provides one gold star: \* + +## \-\-- Part Two \-\-- {#part2} + +As you go to win the first prize, you discover that the claw is nowhere +near where you expected it would be. Due to a unit conversion error in +your measurements, the position of every prize is actually +`10000000000000` higher on both the `X` and `Y` axis! + +Add `10000000000000` to the `X` and `Y` position of every prize. After +making this change, the example above would now look like this: + + Button A: X+94, Y+34 + Button B: X+22, Y+67 + Prize: X=10000000008400, Y=10000000005400 + + Button A: X+26, Y+66 + Button B: X+67, Y+21 + Prize: X=10000000012748, Y=10000000012176 + + Button A: X+17, Y+86 + Button B: X+84, Y+37 + Prize: X=10000000007870, Y=10000000006450 + + Button A: X+69, Y+23 + Button B: X+27, Y+71 + Prize: X=10000000018641, Y=10000000010279 + +Now, it is only possible to win a prize on the second and fourth claw +machines. Unfortunately, it will take *many more than `100` presses* to +do so. + +Using the corrected prize coordinates, figure out how to win as many +prizes as possible. *What is the fewest tokens you would have to spend +to win all possible prizes?* + +Answer: + +Although it hasn\'t changed, you can still [get your puzzle +input](13/input). + diff --git a/2024/13/solution.py b/2024/13/solution.py new file mode 100644 index 0000000..46a1eec --- /dev/null +++ b/2024/13/solution.py @@ -0,0 +1,69 @@ +#!/bin/python3 +import sys,time,re +from sympy import * +from pprint import pprint +sys.path.insert(0, '../../') +from fred import list2int,get_re,nprint,lprint,loadFile +start_time = time.time() + +input_f = 'input' + +######################################### +# # +# Part 1 # +# # +######################################### +def part1(): + + instructions = [] + + with open(input_f) as file: + for line in file: + match = get_re(r".*X[\+|=](\d+), Y[\+|=](\d+)",line.rstrip()) + if match: + instructions.append(list2int([match.group(1),match.group(2)])) + + #print(instructions) + a_cost = 3 + b_cost = 1 + + a = () + b = () + r = () + x,y = symbols('x y',integer=True) + result = 0 + + for idx, inst in enumerate(instructions): + #print(inst) + + if idx%3 == 0: + a = (inst[0],inst[1]) + elif idx%3 == 1: + b = (inst[0],inst[1]) + elif idx%3 == 2: + r = (inst[0],inst[1]) + eq1 = Eq(a[0]*x + b[0]*y,r[0]) + eq2 = Eq(a[1]*x + b[1]*y,r[1]) + + s = solve((eq1,eq2),(x,y)) + #print(s) + if s: + result += s[x]*a_cost + result += s[y]*b_cost + #input() + return result + +start_time = time.time() +print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms') + + +######################################### +# # +# Part 2 # +# # +######################################### +def part1(): + return + +start_time = time.time() +print('Part 2:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms') \ No newline at end of file diff --git a/__pycache__/fred.cpython-311.pyc b/__pycache__/fred.cpython-311.pyc index 686326e..a2efa71 100644 Binary files a/__pycache__/fred.cpython-311.pyc and b/__pycache__/fred.cpython-311.pyc differ diff --git a/fred.py b/fred.py index 887d4b4..fc21341 100644 --- a/fred.py +++ b/fred.py @@ -313,7 +313,7 @@ def grid_valid(x, y, grid): cols = len(grid[0]) return 0 <= x < rows and 0 <= y < cols -def get_re(pattern, str): +def get_re(pattern, line): """ Returns a match object if the pattern matches the string, else None. @@ -327,10 +327,10 @@ def get_re(pattern, str): Raises: TypeError: If str is not a string. """ - if not isinstance(str, str): + if not isinstance(line, str): raise TypeError("Input string must be of type str.") - match = re.match(pattern, str) + match = re.match(pattern, line) if match: return match return None