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
|
|
|
}
|
|
|
|
}
|