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

  • Zarlin@lemmy.world
    link
    fedilink
    arrow-up
    2
    ·
    7 days 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 :)