aoc2021/Sources/04/04.swift
2021-12-05 11:43:49 +01:00

92 lines
2.4 KiB
Swift

//
// File.swift
//
//
// Created by Max Nuding on 04.12.21.
//
import Foundation
import Runner
struct Board {
var numbers: [[Int?]]
var hasWon = false
mutating func crossOf(num: Int) -> Bool {
for (rowNumber, row) in numbers.enumerated() {
if let colNumber = row.firstIndex(of: num) {
numbers[rowNumber][colNumber] = nil
//print("Found at: \(rowNumber),\(colNumber)")
return true
}
}
return false
}
mutating func checkHasWon() -> Bool {
var found = false
defer {
hasWon = hasWon || found
}
found = numbers.contains { row in
row.allSatisfy { $0 == nil }
}
if found {
return true
}
found = numbers.indices.contains { columnIndex in
numbers.allSatisfy { $0[columnIndex] == nil }
}
hasWon = found
return hasWon
}
func calculateScore() -> Int {
numbers
.reduce([], +)
.compactMap { $0 }
.reduce(0, +)
}
}
struct Day04: Runnable {
let inputPath: String
func run() {
let input = try! String(contentsOfFile: inputPath)
var lines = input
.components(separatedBy: .newlines)
let inputNumbers = lines
.removeFirst()
.split(separator: ",")
.map { Int($0)! }
_ = lines.removeFirst() //empty seperator line
var boards = lines
.split(separator: "")
.map { boardLines in
Board(numbers: boardLines.map { $0.split(separator: " ").map { num in Int(num)! } })
}
run(boards: &boards, inputNumbers: inputNumbers)
}
func run(boards: inout [Board], inputNumbers: [Int]) {
var countWon = 0
for inputNumber in inputNumbers {
for (idx, var board) in boards.enumerated() {
if board.crossOf(num: inputNumber) && !board.hasWon && board.checkHasWon() {
if countWon == 0 {
print(board.calculateScore() * inputNumber)
}
countWon += 1
}
if countWon == boards.count {
print(board.calculateScore() * inputNumber)
return
}
boards[idx] = board
}
}
}
}