this post was submitted on 05 Dec 2024
25 points (100.0% liked)

Advent Of Code

920 readers
1 users here now

An unofficial home for the advent of code community on programming.dev!

Advent of Code is an annual Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

AoC 2024

Solution Threads

M T W T F S S
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25

Rules/Guidelines

Relevant Communities

Relevant Links

Credits

Icon base by Lorc under CC BY 3.0 with modifications to add a gradient

console.log('Hello World')

founded 2 years ago
MODERATORS
 

Day 5: Print Queue

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

you are viewing a single comment's thread
view the rest of the comments
[–] zarlin 2 points 1 month ago

Nim

import ../aoc, strutils, sequtils, tables

type
  Rules = ref Table[int, seq[int]]

#check if an update sequence is valid
proc valid(update:seq[int], rules:Rules):bool =
  for pi, p in update:
    for r in rules.getOrDefault(p):
      let ri = update.find(r)
      if ri != -1 and ri < pi:
        return false
  return true

proc backtrack(p:int, index:int, update:seq[int], rules: Rules, sorted: var seq[int]):bool =
  if index == 0:
    sorted[index] = p
    return true
  
  for r in rules.getOrDefault(p):
    if r in update and r.backtrack(index-1, update, rules, sorted):
      sorted[index] = p
      return true
  
  return false

#fix an invalid sequence
proc fix(update:seq[int], rules: Rules):seq[int] =
  echo "fixing", update
  var sorted = newSeqWith(update.len, 0);
  for p in update:
    if p.backtrack(update.len-1, update, rules, sorted):
      return sorted
  return @[]

proc solve*(input:string): array[2,int] =
  let parts = input.split("\r\n\r\n");
  
  let rulePairs = parts[0].splitLines.mapIt(it.strip.split('|').map(parseInt))
  let updates = parts[1].splitLines.mapIt(it.split(',').map(parseInt))
  
  # fill rules table
  var rules = new Rules
  for rp in rulePairs:
    if rules.hasKey(rp[0]):
      rules[rp[0]].add rp[1];
    else:
      rules[rp[0]] = @[rp[1]]
      
  # fill reverse rules table
  var backRules = new Rules
  for rp in rulePairs:
    if backRules.hasKey(rp[1]):
      backRules[rp[1]].add rp[0];
    else:
      backRules[rp[1]] = @[rp[0]]
  
  for u in updates:
    if u.valid(rules):
      result[0] += u[u.len div 2]
    else:
      let uf = u.fix(backRules)
      result[1] += uf[uf.len div 2]

I thought of doing a sort at first, but dismissed it for some reason, so I came up with this slow and bulky recursive backtracking thing which traverses the rules as a graph until it reaches a depth equal to the given sequence. Not my finest work, but it does solve the puzzle :)