aoc2021/Sources/aoc2021/04.swift

104 lines
2.8 KiB
Swift
Raw Normal View History

2021-12-04 10:08:13 +00:00
//
// File.swift
//
//
// Created by Max Nuding on 04.12.21.
//
import Foundation
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, +)
}
}
struct Day04 {
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:09:56 +00:00
let boardsInitial = 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:09:56 +00:00
var boards = boardsInitial
runA(boards: &boards, inputNumbers: inputNumbers)
boards = boardsInitial
runB(boards: &boards, inputNumbers: inputNumbers)
2021-12-04 10:08:13 +00:00
}
func runA(boards: inout [Board], inputNumbers: [Int]) {
for inputNumber in inputNumbers {
for (idx, var board) in boards.enumerated() {
if board.crossOf(num: inputNumber) && board.checkHasWon() {
print(board.calculateScore() * inputNumber)
return
}
boards[idx] = board
}
}
}
2021-12-04 10:09:56 +00:00
func runB(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() {
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
}
}