adventofcode2021/day08/part2.nim

107 lines
2.8 KiB
Nim

# Copyright 2021 Christian Ulrich
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# usage: ./part1 < input
import math
import sequtils
import strutils
type Segment = enum
a, b, c, d, e, f, g
const SegmentCounts = [6, 2, 5, 5, 4, 5, 6, 3, 7, 6]
# 0: {A, B, C, E, F, G}
# 1*: {C, F}
# 2: {A, C, D, E, G}
# 3: {A, C, D, F, G}
# 4*: {B, C, D, F}
# 5: {A, B, D, F, G}
# 6: {A, B, D, E, F, G}
# 7*: {A, C, F}
# 8*: {A, B, C, D, E, F, G}
# 9: {A, B, C, D, F, G}
proc deduceDigits(patterns: seq[set[Segment]]): array[10, set[Segment]] =
for pattern in patterns:
case pattern.len()
of SegmentCounts[1]:
result[1] = pattern
of SegmentCounts[4]:
result[4] = pattern
of SegmentCounts[7]:
result[7] = pattern
of SegmentCounts[8]:
result[8] = pattern
else:
discard
for pattern in patterns:
case pattern.len()
of 5:
if result[1] <= pattern:
result[3] = pattern
else:
case len(result[4] * pattern)
of 2:
result[2] = pattern
of 3:
result[5] = pattern
else:
assert(false)
of 6:
if result[4] <= pattern:
result[9] = pattern
else:
case len(result[7] * pattern)
of 2:
result[6] = pattern
of 3:
result[0] = pattern
else:
assert(false)
else:
discard
proc parsePattern(pattern: string): set[Segment] =
for c in pattern:
result.incl(parseEnum[Segment]($c))
proc outputValue(): int =
var line = ""
while readLine(stdin, line):
let parts = line.split('|', 1)
if parts.len() != 2:
raise newException(ValueError, "invalid line")
var
inputPatterns = parts[0].splitWhitespace().map(parsePattern)
outputPatterns = parts[1].splitWhitespace().map(parsePattern)
let digits = deduceDigits(inputPatterns)
for i in 0 ..< outputPatterns.len():
let findResult = digits.find(outputPatterns[^(i + 1)])
if findResult < 0:
raise newException(ValueError, "invalid output pattern")
result += 10 ^ i * findResult
proc main(): int =
try:
echo outputValue()
except Exception as error:
echo error.msg
result = -1
when isMainModule:
quit(main())