aoc2021/Sources/04/04.swift

92 lines
2.4 KiB
Swift
Raw Permalink Normal View History

2021-12-04 10:08:13 +00:00
//
// File.swift
//
//
// Created by Max Nuding on 04.12.21.
//
import Foundation
2021-12-05 10:43:02 +00:00
import Runner
2021-12-04 10:08:13 +00:00
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 {
2021-12-04 10:21:54 +00:00
var found = false
defer {
hasWon = hasWon || found
}
found = numbers.contains { row in
2021-12-04 10:08:13 +00:00
row.allSatisfy { $0 == nil }
}
2021-12-04 10:21:54 +00:00
if found {
2021-12-04 10:08:13 +00:00
return true
}
2021-12-04 10:21:54 +00:00
found = numbers.indices.contains { columnIndex in
numbers.allSatisfy { $0[columnIndex] == nil }
2021-12-04 10:08:13 +00:00
}
2021-12-04 10:21:54 +00:00
hasWon = found
2021-12-04 10:08:13 +00:00
return hasWon
}
func calculateScore() -> Int {
numbers
.reduce([], +)
.compactMap { $0 }
.reduce(0, +)
}
}
2021-12-05 10:43:02 +00:00
struct Day04: Runnable {
2021-12-04 10:08:13 +00:00
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
2021-12-04 10:22:40 +00:00
var boards = lines
2021-12-04 10:08:13 +00:00
.split(separator: "")
.map { boardLines in
Board(numbers: boardLines.map { $0.split(separator: " ").map { num in Int(num)! } })
}
2021-12-04 10:22:40 +00:00
run(boards: &boards, inputNumbers: inputNumbers)
2021-12-04 10:08:13 +00:00
}
2021-12-04 10:22:40 +00:00
func run(boards: inout [Board], inputNumbers: [Int]) {
2021-12-04 10:21:54 +00:00
var countWon = 0
2021-12-04 10:09:56 +00:00
for inputNumber in inputNumbers {
for (idx, var board) in boards.enumerated() {
2021-12-04 10:21:54 +00:00
if board.crossOf(num: inputNumber) && !board.hasWon && board.checkHasWon() {
2021-12-04 10:22:40 +00:00
if countWon == 0 {
print(board.calculateScore() * inputNumber)
}
2021-12-04 10:21:54 +00:00
countWon += 1
}
if countWon == boards.count {
2021-12-04 10:09:56 +00:00
print(board.calculateScore() * inputNumber)
return
}
boards[idx] = board
}
}
2021-12-04 10:08:13 +00:00
}
}