{"id":23249078,"url":"https://github.com/argeento/advent-of-code-2023","last_synced_at":"2026-03-20T01:03:30.066Z","repository":{"id":210137475,"uuid":"724660162","full_name":"Argeento/advent-of-code-2023","owner":"Argeento","description":"My solutions to AoC 2023 in Civet","archived":false,"fork":false,"pushed_at":"2023-12-15T06:08:23.000Z","size":91,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-12T07:26:38.718Z","etag":null,"topics":["advent-of-code","advent-of-code-2023","civet"],"latest_commit_sha":null,"homepage":"","language":null,"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}},"created_at":"2023-11-28T14:33:58.000Z","updated_at":"2023-12-19T08:21:39.000Z","dependencies_parsed_at":"2023-12-13T05:20:23.590Z","dependency_job_id":"82b1f4e7-31ba-47ae-9ea2-e632bc9b9dc8","html_url":"https://github.com/Argeento/advent-of-code-2023","commit_stats":null,"previous_names":["argeento/advent-of-code-2023"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2023","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2023/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2023/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Argeento%2Fadvent-of-code-2023/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Argeento","download_url":"https://codeload.github.com/Argeento/advent-of-code-2023/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247421136,"owners_count":20936236,"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-2023","civet"],"created_at":"2024-12-19T08:16:49.506Z","updated_at":"2026-01-28T06:04:14.449Z","avatar_url":"https://github.com/Argeento.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"Lang: [Civet](https://civet.dev)\n\n# Advent of Code 2023\n\nSomething is wrong with global snow production, and you've been selected to take a look.\nThe Elves have even given you a map; on it, they've used stars to mark the top fifty\nlocations that are likely to be having problems.\n\n## Day 15: Lens Library ⭐⭐\n\n```ts\n{ log, getInput, sum, toNumber, entries, values } from ../utils.civet\n\ncodes := getInput import.meta.url |\u003e .trim().split(',')\n\nfunction calcHash(code: string)\n  [...code].reduce (nr, c) =\u003e (nr + c.charCodeAt 0) * 17 % 256, 0\n\nlog 'Part 1', sum codes.map calcHash\n\nboxes := {}\nfor code of codes\n  label := code.replace /[^a-z]/g, ''\n  hash := calcHash label\n  (boxes[hash] ?= [])[label] = toNumber code\n  delete boxes[hash][label] if code.includes('-')\n\nfocusingPower .= 0\nfor [hash, lenses] of entries boxes\n  for focal, i of values lenses\n    focusingPower += (+hash + 1) * (i + 1) * focal\n\nlog 'Part 2', focusingPower \n```\n\n\n## Day 14: Parabolic Reflector Dish ⭐⭐\n\n```ts\n{ log, getLines, sum, cloneDeep, zip } from ../utils.civet\n\nstones .= getLines import.meta.url |\u003e .map .split ''\n\nfunction step(stones: string[][])\n  return .= 0\n  for y of [0...stones.length]\n    for x of [0...stones.0.length]\n      if stones[y][x] is 'O' and stones[y - 1]?[x] is '.'\n        stones[y][x] = '.'\n        stones[y - 1][x] = 'O'\n        return++\n\nfunction move(stones: string[][])\n  while step stones;\n  stones\n\nfunction calcWeight(stones: string[][])\n  sum for line, y of stones\n    line.filter(\u0026 is 'O').length * (stones.length - y)\n\nlog 'Part 1', calcWeight move cloneDeep stones\n\nfunction cycle()\n  for [0...4]\n    stones = zip(...move stones).map .reverse()\n\nmem := {}\ni .= 0\noffset .= 0\n\nloop\n  memKey := JSON.stringify stones\n  if mem[memKey]\n    offset = mem[memKey]\n    break\n  mem[memKey] = i++\n  cycle()\n\nfor [0...(1e9 - offset) % (i - offset)]\n  cycle()\n\nlog 'Part 2', calcWeight stones\n```\n\n\n## Day 13: Point of Incidence ⭐⭐\n\n```ts\n{ log, getInput, sum, zip } from ../utils.civet\n\npatterns := getInput import.meta.url\n  .split('\\n\\n').map \u0026.split('\\n')\n\nfunction diffs(str1: string, str2: string)\n  sum for c, i of str1\n    c is not str2[i]\n\nfunction rotate(pattern: string[])\n  zip(...pattern.map \u0026.split('')).flatMap \u0026.join('')\n\nfunction searchMirror(pattern: string[], possibleErrors: number)\n  for y of [0...pattern.length - 1]\n    errors .= 0\n    for i .= 0; y - i \u003e= 0 and y + i + 1 \u003c pattern.length; i++\n      errors += diffs pattern[y - i], pattern[y + i + 1]\n    return y + 1 if errors is possibleErrors\n  0\n\nfunction getNote(pattern: string[], possibleErrors: number)\n  100 * searchMirror(pattern, possibleErrors) +\n  searchMirror(rotate(pattern), possibleErrors)\n\nlog 'Part 1', sum patterns.map (p) =\u003e getNote p, 0\nlog 'Part 2', sum patterns.map (p) =\u003e getNote p, 1\n```\n\n\n## Day 12: Hot Springs ⭐⭐\n\n```ts\n{ log, getLines, toNumbers, sum } from ../utils.civet\n\nlines := getLines(import.meta.url).map \u0026.split ' '\nmem := {}\n\nfunction combinations(springs: string, groups: number[], counter = 0): number\n  memKey := springs + groups\n  return mem[memKey] if mem[memKey]\n  return '#' is in springs ? 0 : 1 unless groups.length\n  [nr, ...rest] := groups\n  for i .= 0; i \u003c= springs.length - rest.length - sum(rest) - nr; i++\n    break if '#' is in springs[0...i]\n    if '.' is not in springs[i...i + nr] and springs[i + nr] is not \"#\"\n      counter += combinations springs[i + nr + 1..], rest\n  mem[memKey] = counter\n\nlog 'Part 1', sum for [springs, groups] of lines\n  combinations springs, toNumbers groups\n\nlog 'Part 2', sum for [springs, groups] of lines\n  combinations \n    new Array(5).fill(springs).join('?'),\n    new Array(5).fill(toNumbers groups).flatMap (\u0026)\n```\n\n\n## Day 11: Cosmic Expansion ⭐⭐\n\n```ts\n{ log, getLines, sum } from ../utils.civet\n\nlines .= getLines import.meta.url\n\nexpandingRows := []\nfor line, y of lines\n  expandingRows.push y unless '#' is in line\n\nexpandingCols := []\nfor x of [0...lines.0.length]\n  expandingCols.push x if lines.every \u0026[x] is '.'\n\ngalaxies := []\nfor y of [0...lines.length]\n  for x of [0...lines.0.length]\n    galaxies.push [x, y] if lines[y][x] is '#'\n\nfunction getDistance([[x1, y1], [x2, y2]])\n  Math.abs(x1 - x2) + Math.abs(y1 - y2)\n\nfunction getPairs(galaxies: number[][])\n  for i of [0...galaxies.length]\n    for j of [i + 1...galaxies.length]\n      [galaxies[i], galaxies[j]]\n\nfunction expand(galaxies: number[][], multiplayer: number)\n  for [x, y] of galaxies\n    r := expandingRows.filter(\u0026 \u003c y).length\n    c := expandingCols.filter(\u0026 \u003c x).length\n    [x + c * (multiplayer - 1), y + r * (multiplayer - 1)]\n\nfunction sumDistances(galaxies: number[][], expandMultiplier: number)\n  galaxies = expand galaxies, expandMultiplier\n  sum getPairs(galaxies).flatMap (\u0026).map getDistance\n\nlog 'Part 1', sumDistances galaxies, 2\nlog 'Part 2', sumDistances galaxies, 1e6\n```\n\n\n## Day 10: Pipe Maze ⭐⭐\n\n```ts\npointInPolygon from 'point-in-polygon'\n{ log, getLines } from ../utils.civet\n\nlines := getLines import.meta.url\nstartY := lines.findIndex \u0026.includes 'S'\nstartX := lines[startY].indexOf 'S'\n\nlast .= [startX, startY]\ncurrent .= [startX, startY + 1]\npolygon := [current]\n\nwhile next := move current, last\n  last = current\n  polygon.push current = next\n\nfunction move([x, y]: number[], [prevX, prevY]: number[])\n  disabledDir .= switch prevX - x\n    \u003e 0 then 'E'\n    \u003c 0 then 'W'\n    else prevY - y \u003c 0 ? 'N' : 'S'\n\n  switch lines[y][x] + disabledDir\n    '-E' [x - 1, y]\n    '-W' [x + 1, y]\n    '|N' [x, y + 1]\n    '|S' [x, y - 1]\n    '7W' [x, y + 1]\n    '7S' [x - 1, y]\n    'LN' [x + 1, y]\n    'LE' [x, y - 1]\n    'JW' [x, y - 1]\n    'JN' [x - 1, y]\n    'FS' [x + 1, y]\n    'FE' [x, y + 1]\n\nlog 'Part 1', polygon.length / 2\n\narea .= 0\nfor y of [0...lines.length]\n  for x of [0...lines.length]\n    unless polygon.some [px, py] =\u003e px is x and py is y\n      area++ if pointInPolygon [x, y], polygon\n\nlog 'Part 2', area\n```\n\n\n## Day 9: Mirage Maintenance ⭐⭐\n\n```ts\n{ log, getLines, toNumbers, sum } from ../utils.civet\n\nlines := getLines(import.meta.url).map toNumbers\n\nfunction getSequence(arr: number[])\n  for i of [1...arr.length]\n    arr[i] - arr[i - 1]\n\nfunction predict(arr: number[])\n  arrs := [arr]\n  while sum arrs.-1\n    arrs.push getSequence arrs.-1\n  sum arrs.map .-1\n\nlog 'Part 1', sum lines.map predict\nlog 'Part 2', sum lines.map(.reverse()).map predict\n```\n\n\n## Day 8: Haunted Wasteland ⭐⭐\n\n```ts\n{ log, getInput, getLcm, keys } from ../utils.civet\n\ninput := getInput import.meta.url |\u003e .split '\\n\\n'\ninsNr .= 0\ngetIns := =\u003e input.0[insNr++ % input.0.length] is 'L' ? 0 : 1\nnodes := {}\n\nfor node of input.1.split('\\n').map .match /\\w+/g\n nodes[node.0] = node[1..]\n\nfunction movesNr(startNode: string, endNodes: string[])\n  return .= 0\n  name .= startNode\n  node .= nodes[startNode]\n  until name is in endNodes\n    return++\n    name = node[getIns()]\n    node = nodes[name]\n\nlog 'Part 1', movesNr 'AAA', ['ZZZ']\n\nstartNodes := keys(nodes).filter .endsWith 'A'\nendNodes := keys(nodes).filter .endsWith 'Z'\n\nlog 'Part 2', getLcm startNodes.map (start) =\u003e movesNr start, endNodes\n```\n\n\n## Day 7: Camel Cards ⭐⭐\n\n```ts\n{ log, getLines, int, sum, desc } from ../utils.civet\n\ntype Hand\n  cards: string\n  bid: number\n  type: number\n\nlines := getLines import.meta.url\n\nlog 'Part 1', sum getWins(lines, false)\nlog 'Part 2', sum getWins(lines, true)\n\nfunction getWins(lines: string[], joker: boolean)\n  lines\n    .map (line) =\u003e parseHand(line, joker)\n    .sort compareHands\n    .map (hand, i) =\u003e hand.bid * (i + 1)\n\nfunction parseHand(line: string, joker: boolean): Hand\n  [cards, bid] .= line.split ' '\n  cards: fixCardsStrength cards, joker\n  bid: int bid\n  type: getType cards, joker\n\nfunction getType(cards: string, joker: boolean)\n  counter := count cards.replaceAll joker ? 'J' : '', ''\n  if joker then (counter.0 ?= 0) += cards.match(/J/g)?.length ?? 0\n  switch counter\n    [5] 6\n    [4, 1] 5\n    [3, 2] 4\n    [3, 1, 1] 3\n    [2, 2, 1] 2\n    [2, 1, 1, 1] 1\n    [...] 0\n\nfunction count(cards: string)\n  counter: Record\u003cstring, number\u003e := {}\n  for card of cards.split('')\n    (counter[card] ?= 0)++\n  Object.values(counter).sort desc\n\nfunction compareHands(a: Hand, b: Hand)\n  a.type is b.type\n    ? a.cards \u003e b.cards ? 1 : -1\n    : a.type - b.type\n\nfunction fixCardsStrength(cards: string, joker: boolean)\n  cards\n    .replaceAll 'A', 'E'\n    .replaceAll 'K', 'D'\n    .replaceAll 'Q', 'C'\n    .replaceAll 'J', joker ? '1' : 'B'\n    .replaceAll 'T', 'A'\n```\n\n\n## Day 6: Wait For It ⭐⭐\n\n```ts\n{ log, getLines, toNumbers, toNumber, multiply } from ../utils.civet\n\nlines := getLines import.meta.url\n\nfunction timesWins(time: number, record: number)\n  return .= 0\n  for t of [1...time]\n    return++ if time - t \u003e record / t\n\nlog 'Part 1', multiply for i of [0...4]\n  timesWins\n    toNumbers(lines.0)[i],\n    toNumbers(lines.1)[i]\n\nlog 'Part 2', timesWins\n  toNumber lines.0.replaceAll ' ', ''\n  toNumber lines.1.replaceAll ' ', ''\n```\n\n\n## Day 5: If You Give A Seed A Fertilizer ⭐⭐\n\n```ts\n{ log, getInput, toNumbers, inRange, chunk, min } from ../utils.civet\n\ninput := getInput(import.meta.url).split '\\n\\n'\nseeds := toNumbers input.0\nmappings := input[1..].map \u0026.split('\\n')[1..].map toNumbers\n\nfunction translate(nr: number, map: number[][])\n  range := map.find (map) =\u003e inRange map.1, nr, map.1 + map.2\n  range ? nr + range.0 - range.1 : nr\n\nfunction getMin(seeds: number[])\n  min .= Infinity\n  for let seed of seeds\n    for map of mappings\n      seed = translate seed, map\n    min = seed if seed \u003c min\n  min\n\nlog 'Part 1', getMin seeds\nlog 'Part 2', min chunk(seeds, 2).map [start, length] =\u003e\n  getMin [start...start + length]\n\n// omptimzed part 2 -\u003e src/05/index2.civet\n```\n\n\n## Day 4: Scratchcards ⭐⭐\n\n```ts\n{ log, getLines, sum, toNumbers, values } from ../utils.civet\n\nlines := getLines import.meta.url\n\nfunction wins (line: string)\n  [wins, my] := line.split(':').1.split('|').map toNumbers\n  my.filter(\u0026 is in wins).length\n\nlog 'Part 1', sum for line of lines\n  wins line |\u003e (n) =\u003e n ? 1 \u003c\u003c n - 1 : 0\n\ncards := {}\nfor i in lines\n  cards[i] = 1\n\nfor line, i of lines\n  for j .= i + 1; j \u003c= i + wins line; j++\n    cards[j] += cards[i]\n\nlog 'Part 2', sum values cards\n```\n\n\n## Day 3: Gear Ratios ⭐⭐\n\n```ts\n{ log, getLines, sum, flatten, values } from ../utils.civet\n\nlines := getLines import.meta.url\nparts: Record\u003cstring, number[]\u003e := {}\n\nfor line, y of lines\n  for m of line.matchAll /\\d+/g\n    for y of [y - 1..y + 1]\n      for x of [m.index - 1..m.index + m.0.length]\n        unless /[0-9.]/.test lines[y]?.[x]\n          (parts.`${x},${y}` ?= []).push +m.0\n\nlog 'Part 1', sum flatten values parts\nlog 'Part 2', sum values(parts).map (x) =\u003e x.0 * x.1 ?= 0\n```\n\n\n## Day 2: Cube Conundrum ⭐⭐\n\n```ts\n{ log, getLines, max, sum, int, keys, multiply } from ../utils.civet\n\nlines := getLines import.meta.url\ngames := lines.map (line) =\u003e Array.from line.match /\\d+ ./g\nlimits := r:12, g:13, b:14\n\nlog 'Part 1', sum for game, id of games\n  if game.every (draw) =\u003e int(draw) \u003c= limits[draw.-1]\n    id + 1\n\nlog 'Part 2', sum games.map (game) =\u003e\n  multiply keys(limits).map (color) =\u003e\n    game.filter(.includes color).map(int) |\u003e max\n```\n\n\n## Day 1: Trebuchet?! ⭐⭐\n\n```ts\n{ getLines, log, sum, int } from ../utils.civet\n\nlines := getLines import.meta.url\n\nfunction parseValue(line: string)\n  nr := line.replace /[a-z]/g, ''\n  int nr.0 + nr.-1\n\nfunction convertWords(line: string)\n  line\n    .replaceAll 'one', 'o1e'\n    .replaceAll 'two', 't2o'\n    .replaceAll 'three', 't3e'\n    .replaceAll 'four', 'f4r'\n    .replaceAll 'five', 'f5e'\n    .replaceAll 'six', 's6x'\n    .replaceAll 'seven', 's7n'\n    .replaceAll 'eight', 'e8t'\n    .replaceAll 'nine', 'n9e'\n    .replaceAll 'zero', 'z0o'\n\nlog 'Part 1', sum lines.map(parseValue) \nlog 'Part 2', sum lines.map(convertWords).map(parseValue)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fargeento%2Fadvent-of-code-2023","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fargeento%2Fadvent-of-code-2023","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fargeento%2Fadvent-of-code-2023/lists"}