Advent of Code 2025

Compare changes

Choose any two refs to compare.

Changed files
+140 -9
src
+48 -7
src/Day10.hs
···
else
(0 : go (n+1) (b:bs))
-
gaussJordan :: Map (Int,Int) (Ratio Int) -> Map Int (Ratio Int) -> (Map (Int,Int) (Ratio Int), Map Int (Ratio Int), Int)
-
gaussJordan m g = error "GJ"
+
type Matrix = (Int, Int, Map (Int,Int) (Ratio Int))
+
+
cols :: Matrix -> Int
+
cols (_, c, _) = c - 1
+
+
rows :: Matrix -> Int
+
rows (r, _, _) = r
+
+
mat :: Matrix -> Map (Int,Int) (Ratio Int)
+
mat (_, _, m) = m
+
+
minimum' :: Ord a => [a] -> Maybe a
+
minimum' [] = Nothing
+
minimum' as = Just $ minimum as
+
+
pivotCell :: Matrix -> Int -> Int -> Maybe (Int, Int)
+
pivotCell m minRow minCol =
+
minimum' [(i,j) | i <- [minCol..cols m - 1],
+
j <- [minRow..rows m - 1],
+
(mat m) Map.! (i,j) /= 0]
+
+
eraseColumn :: Int -> Int -> Matrix -> Matrix
+
eraseColumn i j m = error "TODO"
+
+
swapCols :: Int -> Int -> Matrix -> Matrix
+
swapCols i i' m = error "TODO"
+
-- let (r,c,d) = m
+
-- d' = Map.fromList
+
-- ([((i,j), d Map.! (i',j)) | j <- [0..rows - 1]] ++
+
-- [((i',j), d Map.! (i,j)) | j <- [0..rows - 1]])
+
-- in (r,c,Map.union d' d)
+
+
gaussJordan :: Map (Int,Int) (Ratio Int) -> Map (Int,Int) (Ratio Int)
+
gaussJordan mat = error "TODO" -- go mat 0 0
+
-- where go m minRow minCol =
+
-- case pivotCell m minRow minCol of
+
-- Nothing -> m
+
-- Just (i,j) ->
+
-- let m' = eraseColumn minCol minRow $
+
-- normalizeRow minCol minRow $
+
-- swapRows j minRow $
+
-- swapCols i minCol m
+
-- in go m' (minRow + 1) (minCol + 1)
solveMachine2 :: [Button] -> [Int] -> Maybe Int
-
solveMachine2 buttons goal =
-
let mat = Map.fromList [((i,j),1 % 1) | (i,b) <- zip [0..] buttons, j <- b]
-
g = Map.fromList $ zip [0..] (map (% 1) goal)
-
(mat', g', rank) = gaussJordan mat g
-
in Just 0
+
solveMachine2 buttons goal = error "TODO"
+
-- let mat = Map.fromList [((i,j),1 % 1) | (i,b) <- zip [0..] buttons, j <- b]
+
-- g = Map.fromList $ zip [0..] (map (% 1) goal)
+
-- (mat', g', rank) = gaussJordan mat g
+
-- in Just 0
part2 :: String -> String
part2 input =
+78
src/Day10_part2.py
···
+
import sys
+
import itertools
+
+
def parseIntList(s):
+
return list(map(int, s[1:-1].split(",")))
+
+
def parseMachine(line):
+
words = line.split(" ")
+
buttons = list(map(parseIntList, words[1:-1]))
+
goal = parseIntList(words[-1])
+
return (buttons, goal)
+
+
def solveMachine(machine):
+
(buttons, goal) = machine
+
rows = len(goal)
+
cols = len(buttons) + 1
+
matrix = [[0 for _ in range(rows)] for _ in range(cols)]
+
for i,button in enumerate(buttons):
+
for b in button:
+
matrix[i][b] = 1
+
for i in range(rows):
+
matrix[cols-1][i] = -goal[i]
+
maxPresses = max(goal)
+
# Row reduce matrix
+
curRow,curCol = 0,0
+
freeVars = []
+
while curRow < rows and curCol < cols:
+
pivotRow = None
+
for i in range(curRow, rows):
+
if matrix[curCol][i] != 0:
+
pivotRow = i
+
break
+
if pivotRow is None:
+
freeVars.append(curCol)
+
curCol += 1
+
continue
+
for i in range(cols):
+
matrix[i][curRow], matrix[i][pivotRow] = matrix[i][pivotRow], matrix[i][curRow]
+
for j in range(rows):
+
if j == curRow:
+
continue
+
a,b = matrix[curCol][curRow],-matrix[curCol][j]
+
for i in range(cols):
+
matrix[i][j] = a*matrix[i][j] + b*matrix[i][curRow]
+
curRow += 1
+
curCol += 1
+
while curCol < cols:
+
freeVars.append(curCol)
+
curCol += 1
+
# The last col is going to be fixed at 1
+
freeVars.pop()
+
minMoves = maxPresses * len(buttons)
+
for freeAssignment in itertools.product(range(maxPresses+1), repeat=len(freeVars)):
+
varAssignment = [None for i in range(cols)]
+
varAssignment[-1] = 1
+
valid = True
+
for i,v in enumerate(freeVars):
+
varAssignment[v] = freeAssignment[i]
+
for j in range(rows-1,-1,-1):
+
nonZeroCols = [i for i in range(cols) if matrix[i][j] != 0]
+
if len(nonZeroCols) == 0:
+
continue
+
rhs = -sum([varAssignment[c]*matrix[c][j] for c in nonZeroCols[1:]])
+
lhs = matrix[nonZeroCols[0]][j]
+
if rhs % lhs != 0:
+
valid = False
+
break
+
if rhs // lhs < 0:
+
valid = False
+
break
+
varAssignment[nonZeroCols[0]] = rhs // lhs
+
if not valid:
+
continue
+
minMoves = min(minMoves, sum(varAssignment) - 1)
+
return minMoves
+
+
machines = [parseMachine(line) for line in open(sys.argv[1]).read().strip().split("\n")]
+
print(sum(map(solveMachine, machines)))
+14 -2
src/Day12.hs
···
module Day12 where
+
parse :: String -> [(Int,Int,[Int])]
+
parse = map parseLine . drop 30 . lines
+
where parseLine line =
+
let w = words line
+
(size,counts) = (head w, map read $ tail w)
+
cols = read $ take 2 size
+
rows = read $ take 2 $ drop 3 size
+
in (cols, rows, counts)
+
part1 :: String -> String
-
part1 _ = "Day 12 part 1"
+
part1 input =
+
let regions = parse input
+
slack (cols, rows, counts) = cols * rows - 7 * (counts !! 0) - 7 * (counts !! 1) - 7 * (counts !! 2) - 5 * (counts !! 3) - 7 * (counts !! 4) - 6 * (counts !! 5)
+
in show $ length $ filter (> 0) $ map slack regions
part2 :: String -> String
-
part2 _ = "Day 12 part 2"
+
part2 _ = "You win!"