90 lines
2.7 KiB
Swift
90 lines
2.7 KiB
Swift
|
//
|
||
|
// File.swift
|
||
|
//
|
||
|
//
|
||
|
// Created by Max Nuding on 05.12.21.
|
||
|
//
|
||
|
|
||
|
import Foundation
|
||
|
import Runner
|
||
|
import Collections
|
||
|
|
||
|
struct Day08: Runnable {
|
||
|
let inputPath: String
|
||
|
|
||
|
func run() {
|
||
|
let input = try! String(contentsOfFile: inputPath)
|
||
|
let entries = input
|
||
|
.trimmingCharacters(in: .newlines)
|
||
|
.components(separatedBy: .newlines)
|
||
|
.map { $0.components(separatedBy: " | ") }
|
||
|
let lines = entries.reduce(into: [String:String](), { $0[$1.first!] = $1[1] })
|
||
|
runA(lines: lines)
|
||
|
print(lines.map { runB(line: $0) }.reduce(0, +))
|
||
|
}
|
||
|
|
||
|
func runA(lines: [String : String]) {
|
||
|
let outputSignals = lines.values
|
||
|
.flatMap { $0.components(separatedBy: .whitespaces) }
|
||
|
let uniqueOutputSignals = outputSignals
|
||
|
.filter { $0.count == 2 || $0.count == 3 || $0.count == 4 || $0.count == 7 }
|
||
|
.count
|
||
|
print(uniqueOutputSignals)
|
||
|
}
|
||
|
|
||
|
func runB(line: Dictionary<String,String>.Element) -> Int {
|
||
|
let uniqueInputSignalDict = line.key
|
||
|
.components(separatedBy: .whitespaces)
|
||
|
.reduce(into: [Int:String](), {
|
||
|
switch $1.count {
|
||
|
case 2:
|
||
|
$0[1] = $1
|
||
|
case 3:
|
||
|
$0[7] = $1
|
||
|
case 4:
|
||
|
$0[4] = $1
|
||
|
case 7:
|
||
|
$0[8] = $1
|
||
|
default:
|
||
|
break
|
||
|
}
|
||
|
})
|
||
|
let outputSignals = line.value.components(separatedBy: .whitespaces)
|
||
|
let len = Double(outputSignals.count - 1)
|
||
|
return outputSignals.enumerated()
|
||
|
.map { Int(pow(10.0, len - Double($0.offset))) * guessDigit(inputSignals: uniqueInputSignalDict, outputSignal: $0.element)! }
|
||
|
.reduce(0, +)
|
||
|
|
||
|
}
|
||
|
|
||
|
func guessDigit(inputSignals: [Int:String], outputSignal: String) -> Int? {
|
||
|
switch outputSignal.count {
|
||
|
case 2:
|
||
|
return 1
|
||
|
case 3:
|
||
|
return 7
|
||
|
case 4:
|
||
|
return 4
|
||
|
case 5:
|
||
|
if inputSignals[1]!.allSatisfy({ outputSignal.contains($0) }) {
|
||
|
return 3
|
||
|
}
|
||
|
let isTwo = inputSignals[8]!
|
||
|
.filter { !inputSignals[4]!.contains($0) }
|
||
|
.allSatisfy { outputSignal.contains($0) }
|
||
|
return isTwo ? 2 : 5
|
||
|
case 6:
|
||
|
if inputSignals[4]!.allSatisfy({ outputSignal.contains($0) }) {
|
||
|
return 9
|
||
|
}
|
||
|
let isZero = inputSignals[7]!.allSatisfy { outputSignal.contains($0) }
|
||
|
return isZero ? 0 : 6
|
||
|
case 7:
|
||
|
return 8
|
||
|
default:
|
||
|
print("Invalid output signal: \(outputSignal)")
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
}
|