

Haskell
Woo! I got on the leaderboard at last. I don’t think I’ve seen a problem like this one before, but fortunately it wasn’t as tricky as it seemed at first glance.
import Control.Monad
import Data.List
import Data.List.Split
import Data.Tuple
readInput :: String -> [(Int, Int)]
readInput = map fixOrder . (zip <*> tail) . map read . splitOn ","
where
fixOrder (x, y)
| x > y = (y, x)
| otherwise = (x, y)
crosses (a, b) (c, d) =
not (a == c || a == d || b == c || b == d)
&& ((a < c && c < b) /= (a < d && d < b))
part1 n = length . filter ((== n `quot` 2) . uncurry (-) . swap)
part2 n = sum . (zipWith countKnots <*> inits)
where
countKnots x strings = length $ filter (crosses x) strings
part3 n strings =
maximum [countCuts (a, b) | a <- [1 .. n - 1], b <- [a + 1 .. n]]
where
countCuts x = length $ filter (\s -> x == s || x `crosses` s) strings
main =
forM_
[ ("everybody_codes_e2025_q08_p1.txt", part1 32),
("everybody_codes_e2025_q08_p2.txt", part2 256),
("everybody_codes_e2025_q08_p3.txt", part3 256)
]
$ \(input, solve) -> readFile input >>= print . solve . readInput

Haskell
Not particularly optimized but good enough.