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
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
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 :)