aoc2021/day8/p2improved.nim
Joey Yakimowich-Payne 4d1313ebb0 Add improved day8 code
2021-12-08 12:31:17 -07:00

79 lines
1.9 KiB
Nim

import os, math
import std/[strutils, sequtils]
type
Segment = enum sA, sB, sC, sD, sE, sF, sG
Digit = set[Segment]
func toDigit(chars: string): Digit =
chars.mapIt(Segment(ord(it) - ord('a'))).foldl(a + Digit({b}), Digit({}))
proc main() =
let fileName = paramStr(1)
# The main idea here is to use process of elimination to find each number
# uniquely. To do this, we can use sets to eliminate or isolate numbers
# that we don't know. Inspired by:
# https://github.com/ZoomRmc/aoc2021_nim/blob/main/src/aoc08.nim
var sum = 0
const maxSetSize = 2^(Segment.high.int + 1)
for line in fileName.lines:
let
lineSplit = line.split(" | ")
var
digitMap: array[maxSetSize, int]
allDigits = lineSplit[0].strip().splitWhitespace().map(toDigit)
displayDigits = lineSplit[1].strip().splitWhitespace().map(toDigit)
# 0, 1, 2, 3, 4, 5, 6, 7
let lenToNum = [-1, -1, 1, 7, 4, -1, -1, 8]
var
decoded: array[10, Digit]
group235: seq[Digit]
group069: seq[Digit]
for digit in allDigits:
case len(digit):
of 2..4, 7:
decoded[lenToNum[len(digit)]] = digit
of 5:
group235.add(digit)
of 6:
group069.add(digit)
else: discard
for digit in group235:
if (digit - decoded[4]).len == 3:
decoded[2] = digit
elif (digit - decoded[1]).len == 3:
decoded[3] = digit
else:
decoded[5] = digit
for digit in group069:
if (digit - decoded[4]).len == 2:
decoded[9] = digit
elif (digit - decoded[7]).len == 4:
decoded[6] = digit
else:
decoded[0] = digit
for i, digit in decoded:
digitMap[cast[int](digit)] = i
var i = 0
# wish I could access the index in mapIt :/
let mapped = displayDigits.mapIt:
let power = 10^(3-i)
i += 1
digitMap[cast[int](it)] * power
sum += mapped.foldl(a+b)
echo "Sum of digits: ", sum
main()