{"id":22674258,"url":"https://github.com/argeento/advent-of-code-2024","last_synced_at":"2026-02-07T01:04:31.874Z","repository":{"id":265779013,"uuid":"894447754","full_name":"Argeento/advent-of-code-2024","owner":"Argeento","description":"My solutions to the AoC 2024 challenges written in Civet","archived":false,"fork":false,"pushed_at":"2024-12-23T13:02:10.000Z","size":97,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-12T13:57:58.125Z","etag":null,"topics":["advent-of-code","advent-of-code-2024","bun","civet"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Argeento.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-11-26T11:23:59.000Z","updated_at":"2024-12-23T13:02:14.000Z","dependencies_parsed_at":"2025-04-13T07:33:26.177Z","dependency_job_id":null,"html_url":"https://github.com/Argeento/advent-of-code-2024","commit_stats":null,"previous_names":["argeento/advent-of-code-2024"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Argeento/advent-of-code-2024","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2024","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2024/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2024/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2024/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Argeento","download_url":"https://codeload.github.com/Argeento/advent-of-code-2024/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2024/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265360327,"owners_count":23752682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["advent-of-code","advent-of-code-2024","bun","civet"],"created_at":"2024-12-09T17:14:29.847Z","updated_at":"2026-02-07T01:04:31.802Z","avatar_url":"https://github.com/Argeento.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Advent of Code 2024\n\nMy solutions to the [AoC 2024](https://adventofcode.com/2024) challenges written in [Civet](https://civet.dev).\n\n## Day 1: Historian Hysteria ⭐⭐\n\n```ts\n[left, right] := getLines(input).map toNumbers |\u003e rotate |\u003e .map .sort asc\n\nlog sum left.map (x, i) =\u003e abs x - right[i]\nlog sum left.map \u0026 * counter(right)[\u0026]\n```\n\n## Day 2: Red-Nosed Reports ⭐⭐\n\n```ts\nreports := input |\u003e getLines |\u003e .map toNumbers\n\nfunction isSafe (report: number[])\n  isAsc := report.1 - report.0 \u003e 0\n  for every i of [0...report# - 1]\n    (1 \u003c= report[i + int isAsc] - report[i + int !isAsc] \u003c= 3)\n \nlog len reports.filter isSafe\nlog len reports.filter (r) =\u003e r.some (_, i) =\u003e isSafe r.toSpliced i, 1\n```\n\n## Day 3: Mull It Over ⭐⭐\n\n```ts\nmul := multiply\ncalc := (s: string) =\u003e sum s.match(/mul\\(\\d+,\\d+\\)/g)!map eval .\n\nlog calc input\nlog sum input.match(/(^|do\\(\\))[\\s\\S]*?($|don't\\(\\))/g)!map calc\n```\n\n## Day 4: Ceres Search ⭐⭐\n\n```ts\npuzzle := getArray2d input\ndirs := flatten for x of [-1..1]\n  for y of [-1..1]\n    for l of [1..3]\n      [x * l, y * l]\n\nlog sum map2d puzzle, (y, x, char) =\u003e\n  return 0 unless char is 'X'\n  sum dirs.map \u0026.map(puzzle[y + \u0026.1]?[x + \u0026.0]).join('') is 'MAS'\n\nlog sum map2d puzzle, (y, x, char) =\u003e\n  return 0 unless char is 'A'\n  puzzle[y - 1]?[x - 1] + puzzle[y + 1]?[x + 1] is in ['MS', 'SM'] and\n  puzzle[y - 1]?[x + 1] + puzzle[y + 1]?[x - 1] is in ['MS', 'SM']\n```\n\n## Day 5: Print Queue ⭐⭐\n\n```ts\n[rules, updates] := input.split('\\n\\n').map(getLines).map .map toNumbers\n\nsumMiddles := (arr: number[][]) =\u003e sum arr.map \u0026[\u0026.#/2 | 0]\nisCorrect := (update: number[]) =\u003e for every i of [0...update.#-1]\n  rules.some matches update[i..i+1]\n\nlog sumMiddles updates.filter isCorrect\nlog sumMiddles updates.filter(negate isCorrect).map .sort (a, b) =\u003e\n  -rules.some matches [b, a]\n```\n\n## Day 6: Guard Gallivant ⭐⭐\n\n```ts\nboard := getArray2d input\nstart := findInArray2d board, '^' |\u003e as Point\n\nsimulate := (board: string[][], { x, y }: Point, dir = 0) =\u003e\n  visited := new Set [`${y}.${x}`]\n  positions := new Set [`${y}.${x}.${dir}`]\n\n  loop\n    board[y - 1]?[x] is '#' ? dir = 1 : y-- if dir is 0\n    board[y]?[x + 1] is '#' ? dir = 2 : x++ if dir is 1\n    board[y + 1]?[x] is '#' ? dir = 3 : y++ if dir is 2\n    board[y]?[x - 1] is '#' ? dir = 0 : x-- if dir is 3\n\n    break with { visited, -loop } unless board[y]?[x]\n    break with { visited, +loop } if positions.has `${y}.${x}.${dir}`\n\n    visited.add `${y}.${x}`\n    positions.add `${y}.${x}.${dir}`\n\n{ visited } := simulate board, start\n\nlog visited.size\nlog for sum pos of visited\n  tmp := set cloneDeep(board), pos, '#'\n  simulate tmp, start |\u003e .loop |\u003e int\n```\n\n## Day 7: Bridge Repair ⭐⭐\n\n```ts\nlines := getLines(input).map(toNumbers).map [\u0026.0, \u0026[1..]] as const\n\ncalc := (operators: string) =\u003e sum lines.map [test, values] =\u003e\n  test if for some perm of getPerms [...operators], values.#-1\n    x .= values.0\n    for op, i of perm\n      x += values[i+1] if op is '+'\n      x *= values[i+1] if op is '*'\n      x = +`${x}${values[i+1]}` if op is '|'\n    test is x\n\nlog calc '+*'\nlog calc '+*|'\n```\n\n## Day 8: Resonant Collinearity ⭐⭐\n\n```ts\ncity := getArray2d input\nisInCity := (p: Point) =\u003e 0 \u003c= p.x \u003c city# and 0 \u003c= p.y \u003c city#\npairs := uniq input.replace /\\n|\\./g, ''\n  |\u003e .map findAllInArray2d city, .\n  |\u003e .flatMap getPerms(., 2).filter \u0026.0 is not \u0026.1\n\nlog len uniq pairs.flatMap [p1, p2] =\u003e\n  p := subVector p1, subVector p2, p1\n  if isInCity p then [`${p.x},${p.y}`] else []\n\nlog len uniq pairs.flatMap [p1, p2] =\u003e\n  points := [addVector p1, subVector p2, p1]\n  loop\n    p := addVector points.-1, subVector p2, p1\n    if isInCity p then points.push p else break\n  points.map `${\u0026.x},${\u0026.y}`\n```\n\n## Day 9: Disk Fragmenter ⭐⭐\n\n```ts\ndisk := map input, int\nid .= 0\nfiles: [string, string][] := []\nblocks .= for join d, i of disk\n  if i % 2\n    '.'.repeat d  \n  else\n    file := String.fromCodePoint(256 + id++).repeat d\n    files.unshift [file, '.'.repeat file#]\n    file\n\ncompactBlocks := (blocks: string) =\u003e\n  while '.' is in blocks \n    last := blocks.-1\n    blocks = blocks[..-2]\n    blocks = blocks.replace '.', last unless last is '.'\n  blocks\n\ncompactFiles := (blocks: string) =\u003e\n  for [file, space] of files\n    fileIndex := blocks.indexOf file\n    spaceIndex := blocks.indexOf space\n    if spaceIndex \u003c fileIndex and spaceIndex \u003e -1\n      blocks = blocks[...spaceIndex] + file + blocks[spaceIndex + file#...fileIndex] + space + blocks[fileIndex + file#..]\n  blocks\n\nchecksum := (blocks: string) =\u003e sum for block, i of blocks\n  block is '.' or i * (block.codePointAt(0)! - 256)\n\nlog checksum compactBlocks blocks\nlog checksum compactFiles blocks\n```\n\n## Day 10: Hoof It ⭐⭐\n\n```ts\ngrid := getArray2d input |\u003e .map .map int\nheads := findAllInArray2d grid, 0\n\nfunction move ({ x, y }: Point): string[]\n  return [`${x},${y}`] if grid[y][x] is 9\n  adjacentCross grid, x, y\n    .filter \u0026.value is grid[y][x] + 1\n    .flatMap move .\n\nlog sum heads.map (head) =\u003e len uniq move head\nlog sum heads.map (head) =\u003e len      move head\n```\n\n## Day 11: Plutonian Pebbles ⭐⭐\n\n```ts\nstones .= toNumbers input\n\nblink := memo (stone: number, blinks: number): number =\u003e\n  str := stone.toString()\n  unless blinks-- then 1\n  else if stone is 0 then blink 1, blinks \n  else if str# % 2 is 0 then blink(+str[...str#/2], blinks) + blink(+str[str#/2..], blinks)\n  else blink stone * 2024, blinks\n\nlog sum map stones, blink ., 25\nlog sum map stones, blink ., 75\n```\n\n## Day 12: Garden Groups ⭐⭐\n\n```ts\ngarden := getArray2d input\nvisited := new Set\u003cstring\u003e\ntype Edge = [Point, Point]\n\nfindRegion := ({x, y}: Point, type: string, edges: Edge[] = []): [number, number, string, Edge[]] =\u003e \n  perimeter .= 0\n  area .= 1\n  key := `${x},${y}`\n  if visited.has(key) return [0, 0, type, edges] else visited.add key\n  for p of adjacentCross garden, x, y\n    if p.value is type\n      [nextArea, nextPerimeter] := findRegion p, type, edges\n      area += nextArea\n      perimeter += nextPerimeter\n    else \n      edges.push [{x, y}, p]\n      perimeter++\n  [area, perimeter, type, edges]\n\ncalcSides := (edges: Edge[]) =\u003e\n  v := edges.filter \u0026.0.x is \u0026.1.x |\u003e groupBy ., \u0026.0.y + \u0026.1.y * 2 |\u003e values |\u003e .map (a) =\u003e countAsc a.map \u0026.0.x\n  h := edges.filter \u0026.0.y is \u0026.1.y |\u003e groupBy ., \u0026.0.x + \u0026.1.x * 2 |\u003e values |\u003e .map (a) =\u003e countAsc a.map \u0026.0.y\n  sum v ++ h\n\ncountAsc := (arr: number[]) =\u003e\n  sum for i of [0...arr.sort(asc)#]\n    arr[i] + 1 is not arr[i + 1]\n\np1 .= 0\np2 .= 0\nmap2d garden, (x, y, value) =\u003e\n  [area, perimeter, _, edges ] := findRegion({x, y}, value)\n  p1 += area * perimeter\n  p2 += area * calcSides edges\n\nlog p1, p2\n```\n\n## Day 13: Claw Contraption ⭐⭐\n\n```ts\nmachines := chunk toNumbers(input), 6\ntokens := ([a, b, c, d, e, f]: number[]) =\u003e\n  (d*e-c*f) / (a*d-c*b) * 3 + (a*f-b*e) / (a*d-c*b) |\u003e \u0026 % 1 ? 0 : \u0026\n\nlog sum machines.map tokens\nlog sum machines.map(\u0026[..3] ++ \u0026[-2..].map \u0026+1e13).map tokens\n```\n\n## Day 14: Restroom Redoubt ⭐⭐\n\n```ts\nstart := chunk toNumbers(input), 4\ngetRobots := (t: number) =\u003e start.map [x0, y0, vx, vy] =\u003e\n  . (x0 + vx * t) %% 101\n  . (y0 + vy * t) %% 103\n\nquadrants:= [0, 0, 0, 0]\ngetRobots(100).forEach [x, y] =\u003e\n  quadrants.0++ if x \u003c 50 and y \u003c 51\n  quadrants.1++ if x \u003c 50 and y \u003e 51\n  quadrants.2++ if x \u003e 50 and y \u003c 51\n  quadrants.3++ if x \u003e 50 and y \u003e 51\n\nlog product quadrants\n\nfor t of [0...10000]\n  robots := getRobots t\n  for y of [0...103]\n    line := '.'.repeat(101).split ''\n    robotsInLine := robots.filter(\u0026.1 is y).map \u0026.0\n    for x of [0..101]\n      line[x] = '#' if x is in robotsInLine \n    throw t if '###########' is in line.join ''\n```\n\n## Day 15: Warehouse Woes ⭐⭐\n\n```ts\ndata := input.split '\\n\\n'\nmoves := data.1.replaceAll '\\n', ''\ngrid1 := getArray2d data.0\ngrid2 := getLines(data.0).map (line) =\u003e\n  line.replaceAll('#','##').replaceAll('.','..').replaceAll('O','[]').replace('@', '@.').split ''\n\ngetNextPoint := (p: Point, move: string) =\u003e\n  switch move\n    '\u003e' then x: p.x + 1, y: p.y\n    '\u003c' then x: p.x - 1, y: p.y\n    '^' then x: p.x, y: p.y - 1\n    else x: p.x, y: p.y + 1\n\nnextP1 := (p: Point, move: string) =\u003e\n  n := getNextPoint(p, move)\n  return false if grid1[n.y]![n.x] is '#'\n  if grid1[n.y]![n.x] is '.' or grid1[n.y]![n.x] is 'O' and nextP1 n, move\n    grid1[n.y]![n.x] = grid1[p.y]![p.x]\n    grid1[p.y]![p.x] = '.'\n    return true\n\nnextP2 := (p: Point, move: string) =\u003e\n  n := getNextPoint(p, move)\n  return false if grid2[n.y]![n.x] is '#'\n  \n  if grid2[n.y]![n.x] is '.' or move is in '\u003e\u003c' and nextP2 n, move\n    grid2[n.y]![n.x] = grid2[p.y]![p.x]\n    grid2[p.y]![p.x] = '.'\n    return true\n\n  return false if move is not in '^v' or not canMove(n, move)\n\n  dy := move is 'v' ? 1 : -1\n  if grid2[n.y]![n.x] is '[' and canMove({ x: n.x + 1, y: n.y }, move)\n      nextP2 n, move\n      nextP2 { y: n.y, x: n.x + 1}, move\n      grid2[n.y]![n.x] = '@'\n      grid2[n.y]![n.x + 1] = '.'\n      grid2[n.y + dy]![n.x] = '['\n      grid2[n.y + dy]![n.x + 1] = ']'\n      grid2[p.y]![p.x] = '.'\n      return true\n\n  if grid2[n.y]![n.x] is ']' and canMove({ x: n.x - 1, y: n.y }, move)\n      nextP2 n, move\n      nextP2 { y: n.y, x: n.x - 1}, move\n      grid2[n.y]![n.x] = '@'\n      grid2[n.y]![n.x - 1] = '.'\n      grid2[n.y + dy]![n.x] = ']'\n      grid2[n.y + dy]![n.x - 1] = '['\n      grid2[p.y]![p.x] = '.'\n      return true\n\ncanMove := (p: Point, move: string) =\u003e\n  n := getNextPoint(p, move)\n  return false if grid2[n.y]![n.x] is '#'\n  return true if grid2[n.y]![n.x] is '.'\n  return true if grid2[n.y]![n.x] is '[' and canMove(n, move) and canMove({ x: n.x + 1, y: n.y }, move)\n  return true if grid2[n.y]![n.x] is ']' and canMove(n, move) and canMove({ x: n.x - 1, y: n.y }, move)\n  \nfor move of moves\n  nextP1 findInArray2d(grid1, '@')!, move\n  nextP2 findInArray2d(grid2, '@')!, move\n\nlog for sum {x, y} of findAllInArray2d grid1, 'O'\n  x + y * 100\n\nlog for sum {x, y} of findAllInArray2d grid2, '['\n  x + y * 100\n```\n\n## Day 16: Reindeer Maze ⭐⭐\n\n```ts\nGraph from graphology\nHeap from heap\n{ dijkstra } from graphology-library/shortest-path\n\nmaze := getArray2d input\nstart := findInArray2d(maze, 'S')!\nend := findInArray2d(maze, 'E')!\ngraph := new Graph\n\ndirections := \n  . dx: 1, dy: 0\n  . dx: 0, dy: 1\n  . dx: -1, dy: 0\n  . dx: 0, dy: -1\n\nmap2d maze, (x, y, value) =\u003e\n  return if value is '#'\n  graph.addNode `${x},${y},${d}` for d of [0..3]\n\nmap2d maze, (x, y, value) =\u003e\n  return if value is '#'\n  for d of [0..3]\n    current := `${x},${y},${d}`\n    nx := x + directions[d].dx\n    ny := y + directions[d].dy\n\n    graph.addEdge current, `${nx},${ny},${d}`, weight: 1 if maze[ny]![nx] is not '#'\n    graph.addEdge current, `${x},${y},${(d-1) %% 4}`, weight: 1000\n    graph.addEdge current, `${x},${y},${(d+1) %% 4}`, weight: 1000\n\ncalcCost := (nodes: string[]) =\u003e \n  for sum i of [0...nodes# - 1]\n    nodes[i].split(',').-1 is nodes[i + 1].split(',').-1 ? 1 : 1000\n\nminCost := min for i of [0..3]\n  calcCost dijkstra.bidirectional(graph, `${start.x},${start.y},0`, `${end.x},${end.y},${i}`)!\n\ntype Distances = Record\u003cstring, { cost: number, prevNodes: string[] }\u003e\n\nfunction getDistances(graph: Graph, start: string)\n  distances: Distances := {}\n\n  graph.forEachNode (node) =\u003e distances[node] = cost: Infinity, prevNodes: []\n  distances[start].cost = 0\n\n  queue := new Heap\u003c{ node: string, cost: number }\u003e (a, b) =\u003e a.cost - b.cost\n  queue.push { cost: 0, node: start }\n\n  until queue.empty()\n    current := queue.pop()!\n    continue if distances[current.node].cost \u003c current.cost\n\n    graph.forEachOutEdge current.node, (_key, attrs, source, target) =\u003e\n      newCost := distances[source].cost + attrs.weight\n      if newCost \u003c distances[target].cost\n        distances[target].cost = newCost\n        distances[target].prevNodes = [source]\n        queue.push { cost: newCost, node: target }\n      else if newCost is distances[target].cost\n        distances[target].prevNodes.push source\n  distances\n\ndistances := getDistances graph, `${start.x},${start.y},0`\n\nfunction recreatePaths(distances: Distances, start: string, end: string): string[][]\n  return [[start]] if start is end\n  paths: string[][] := []\n\n  for node of distances[end].prevNodes\n    subPaths := recreatePaths distances, start, node\n    for subPath of subPaths\n      paths.push subPath ++ [end]\n\n  return paths\n\nlog minCost\n\n[0..3]\n  |\u003e .flatMap (dir) =\u003e recreatePaths distances, `${start.x},${start.y},0`, `${end.x},${end.y},${dir}`\n  |\u003e .filter (path) =\u003e calcCost(path) is minCost\n  |\u003e flatten\n  |\u003e .map .replace /,\\d*$/, ''\n  |\u003e new Set\n  |\u003e .size\n  |\u003e log\n```\n\n## Day 17: Chronospatial Computer ⭐⭐\n\n```ts\n[A, B, C, ...program] .= toNumbers(input).map BigInt\n\nfunction execute(A: bigint, B: bigint, C: bigint, program: bigint[])\n  output: bigint[] := []\n  index .= 0\n  combo := (x: bigint) =\u003e [0n, 1n, 2n, 3n, A, B, C][Number(x)]\n\n  run := (opcode: bigint, operand: bigint) =\u003e switch opcode\n    0n then A = A / 2n ** combo(operand)\n    1n then B ^= operand\n    2n then B = combo(operand) % 8n\n    3n then index = A is 0n ? index + 2 : Number(operand)\n    4n then B ^= C\n    5n then output.push combo(operand) % 8n\n    6n then B = A / 2n ** combo(operand)\n    7n then C = A / 2n ** combo(operand)\n\n  while index \u003c program#\n    opcode := program[index]\n    operand := program[index + 1]\n    run opcode, operand\n    index += 2 unless opcode is 3n\n\n  output\n\nlog execute(A, B, C, program).join()\n\nvals .= [0n]\nfor opcode of program.toReversed()\n  vals = vals.flatMap (prev) =\u003e\n    [0n, 1n, 2n, 3n, 4n, 5n, 6n, 7n]\n      .map prev * 8n + \u0026\n      .filter (A) =\u003e execute(A, 0n, 0n, program).0 is opcode\n\nlog min vals\n```\n\n## Day 18: RAM Run ⭐⭐\n\n```ts\nGraph from graphology\n{ dijkstra } from graphology-library/shortest-path\n\nbytes := chunk toNumbers(input), 2\n\nfunction findExit(bytes: number[][])\n  graph := new Graph\n  ram := for y of [0..70]\n    for x of [0..70]\n      bytes.find(\u0026.0 is x and \u0026.1 is y) ? '#' : '.'\n\n  map2d ram, (x, y) =\u003e\n    return if ram[y][x] is '#'\n    graph.addNode `${x},${y}`\n\n  map2d ram, (x, y) =\u003e\n    return if ram[y][x] is '#'\n    for p of adjacentCross ram, x, y\n      graph.addEdge `${x},${y}`, `${p.x},${p.y}` if p.value is '.'\n\n  dijkstra.bidirectional graph, '0,0', `70,70`\n\nlog findExit(bytes[0...1024])# - 1\n\ni .= 1024\nwhile findExit bytes[0..++i]\nlog bytes[i].join()\n```\n\n## Day 19: Linen Layout ⭐⭐\n\n```ts\n[data, _, ...designs] := getLines input\ntowels := data.split ', '\n\npossibilities := memo (design: string): number =\u003e\n  matches := towels.filter design.startsWith .\n  return int design# is 0 if matches# is 0\n  sum matches.map (match) =\u003e possibilities design[match#..]\n\nlog sum designs.map(possibilities).map !!\u0026\nlog sum designs.map(possibilities)\n```\n\n## Day 20: Race Condition ⭐⭐\n\n```ts\nGraph from graphology\n{ dijkstra } from graphology-library/shortest-path\n\ngrid := getArray2d input\nstart := findInArray2d(grid, 'S')!\nend := findInArray2d(grid, 'E')!\ngraph := new Graph\n\nmap2d grid, (x, y, value) =\u003e\n  return if value is '#'\n  graph.addNode `${x},${y}`\n\nmap2d grid, (x, y, value) =\u003e\n  return if value is '#'\n  for p of adjacentCross grid, x, y\n    continue if grid[p.y]?[p.x] is '#'\n    graph.addEdge `${x},${y}`, p.str\n\npath := dijkstra.bidirectional(graph, start.str, end.str).map toNumbers\n\nfunction possibleCheats(max: number)\n  flatten for [x, y], i of path\n    for [cx, cy], j of path[i+1..]\n      manhattan {x, y}, {x: cx, y: cy} |\u003e \u0026 \u003c= max ? j - \u0026 + 1 : 0\n\nlog len possibleCheats(2).filter \u0026 \u003e= 100\nlog len possibleCheats(20).filter \u0026 \u003e= 100\n```\n\n## Day 23: LAN Party ⭐⭐\n\n```ts\nfindCliques from @seregpie/bron-kerbosch\n{ UndirectedGraph } from graphology\n\nconnections := getLines(input).map .split('-') as [string, string]\ncomputers .= uniq flatten connections\ngraph := new UndirectedGraph\n\ncomputers.map (pc) =\u003e graph.addNode pc\nconnections.map [a, b] =\u003e graph.addEdge a, b\n\ntriples := uniq computers.flatMap (pc) =\u003e \n  neighbors := graph.mapNeighbors(pc, \u0026)\n  triples: string[] := []\n  for i of [0...neighbors#-1]\n    for j of [i+1...neighbors#]\n      if graph.hasEdge neighbors[i], neighbors[j]\n        triples.push [neighbors[i], neighbors[j], pc].sort().join ','\n  triples\n\nlog len triples.filter \u0026 is like /t[a-z]/\n\ncliques := findCliques(connections).sort (a, b) =\u003e b.# - a.#\n\nlog cliques.0.sort().join ','\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fargeento%2Fadvent-of-code-2024","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fargeento%2Fadvent-of-code-2024","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fargeento%2Fadvent-of-code-2024/lists"}