Quest 9: Encoded in the Scales
- 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
Link to participate: https://everybody.codes/
You must log in or register to comment.
Nim
Very messy bruteforce.
I’ve had some problems with parsing in part 2 - I didn’t account for double digit numbers before dna sequences and that caused my code to work on example, but silently fail only on the real input. I’ve figured it out after ~30 minutes with some external help.
Part 3 runs in 700ms - not great, but not too bad either.
proc similarity(a, b: string): int = for i, c in a: if c == b[i]: inc result proc solve_part1*(input: string): Solution = var sim: seq[int] var dnaList: seq[string] for line in input.splitLines(): dnaList.add line[2..^1] for i in 0 .. dnaList.high: for j in i+1 .. dnaList.high: let s = similarity(dnaList[i], dnaList[j]) sim.add s sim.sort() result := sim[^2] * sim[^1] proc parentTest(ch, p1, p2: string): bool = for i, c in ch: if (c != p1[i]) and (c != p2[i]): return false true proc simTable(dnaList: seq[string]): seq[seq[int]] = result = newSeqWith(dnaList.len, newseq[int](dnaList.len)) for i in 0 .. dnaList.high: for j in i+1 .. dnaList.high: let s = similarity(dnaList[i], dnaList[j]) result[i][j] = s result[j][i] = s proc solve_part2*(input: string): Solution = var dnaList: seq[string] for line in input.splitLines(): dnaList.add line.split(':')[1] let sim = simTable(dnaList) var indices = toseq(0..dnaList.high) for i, childDna in dnaList: var indices = indices indices.del i block doTest: for k in 0 .. indices.high: for j in k+1 .. indices.high: let p1 = indices[k] let p2 = indices[j] if parentTest(childDna, dnaList[p1], dnaList[p2]): result.intVal += sim[i][p1] * sim[i][p2] break doTest proc solve_part3*(input: string): Solution = var dnaList: seq[string] for line in input.splitLines(): dnaList.add line.split(':')[1] var families: seq[set[int16]] var indices = toseq(0..dnaList.high) for ch, childDna in dnaList: var indices = indices indices.del ch block doTest: for k in 0 .. indices.high: for j in k+1 .. indices.high: let p1 = indices[k] let p2 = indices[j] if parentTest(childDna, dnaList[p1], dnaList[p2]): families.add {ch.int16, p1.int16, p2.int16} break doTest var combined: seq[set[int16]] while families.len > 0: combined.add families.pop() var i = 0 while i <= families.high: if (combined[^1] * families[i]).len > 0: combined[^1] = combined[^1] + families[i] families.del i i = 0 else: inc i let maxInd = combined.mapIt(it.len).maxIndex result := combined[maxInd].toseq.mapIt(it.int+1).sum()Full solution at Codeberg: solution.nim

