jlelse
/
aoc21
Archived
1
Fork 0
This repository has been archived on 2024-01-02. You can view files and clone it, but cannot push or open issues or pull requests.
aoc21/04/main.go

175 lines
3.9 KiB
Go
Raw Normal View History

2021-12-04 17:06:20 +00:00
package main
import (
"log"
"os"
"strconv"
"strings"
"github.com/thoas/go-funk"
)
func main() {
inputBytes, _ := os.ReadFile("input.txt")
inputs := strings.Split(string(inputBytes), "\n")
log.Println("Puzzle 1:", puzzle1(inputs))
log.Println("Puzzle 2:", puzzle2(inputs))
}
func puzzle1(input []string) int {
called, bingos := parseBingos(input)
// Iterate through called numbers
lastCalledNumber := -1
firstBingo := -1
callnumbers:
for _, calledNumber := range called {
lastCalledNumber = calledNumber
// Replace called number in every bingo with -1
for _, bingo := range bingos {
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
if bingo[i][j] == calledNumber {
bingo[i][j] = -1
}
}
}
}
// Check if any bingo has row or column with sum of just 0
for b, bingo := range bingos {
// Check rows
for i := 0; i < 5; i++ {
if funk.SumInt(bingo[i]) == -5 {
firstBingo = b
break callnumbers
}
}
// Check columns
for i := 0; i < 5; i++ {
if bingo[0][i]+bingo[1][i]+bingo[2][i]+bingo[3][i]+bingo[4][i] == -5 {
firstBingo = b
break callnumbers
}
}
}
}
// Get sum of remaining numbers in first bingo
sum := 0
for _, row := range bingos[firstBingo] {
for _, number := range row {
if number != -1 {
sum += number
}
}
}
// Return product of sum and last called number
return sum * lastCalledNumber
}
func puzzle2(input []string) int {
called, bingos := parseBingos(input)
// Iterate through called numbers
lastCalledNumber := -1
solvedBingos := []int{}
lastSolvedBingo := -1
callnumbers:
for _, calledNumber := range called {
lastCalledNumber = calledNumber
// Replace called number in every bingo with -1
for _, bingo := range bingos {
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
if bingo[i][j] == calledNumber {
bingo[i][j] = -1
}
}
}
}
// Check if any bingo has row or column with sum of just 0
bingoiter:
for b, bingo := range bingos {
// Skip solved bingos
if funk.ContainsInt(solvedBingos, b) {
continue bingoiter
}
// Check rows
for i := 0; i < 5; i++ {
if funk.SumInt(bingo[i]) == -5 {
// Add bingo to solved bingos
solvedBingos = append(solvedBingos, b)
lastSolvedBingo = b
continue bingoiter
}
}
// Check columns
for i := 0; i < 5; i++ {
if bingo[0][i]+bingo[1][i]+bingo[2][i]+bingo[3][i]+bingo[4][i] == -5 {
// Add bingo to solved bingos
solvedBingos = append(solvedBingos, b)
lastSolvedBingo = b
continue bingoiter
}
}
}
// Check if all bingos but are solved
if len(bingos) == len(solvedBingos) {
break callnumbers
}
}
// Get sum of remaining numbers in last solved bingo
sum := 0
for _, row := range bingos[lastSolvedBingo] {
for _, number := range row {
if number != -1 {
sum += number
}
}
}
// Return product of sum and last called number
return sum * lastCalledNumber
}
func parseBingos(input []string) (called []int, bingos [][][]int) {
// Parse called numbers
called = []int{}
for _, number := range strings.Split(input[0], ",") {
no, _ := strconv.Atoi(number)
called = append(called, no)
}
// Parse bingos
bingos = [][][]int{}
bingoCurrentRow := 0
currentBingo := [][]int{}
for _, line := range input[2:] {
// Trim spaces
line = strings.TrimSpace(line)
// Replace double spaces with single spaces
line = strings.ReplaceAll(line, " ", " ")
// Check if line is empty
if line == "" {
continue
}
// Parse row
row := []int{}
for i, number := range strings.Split(line, " ") {
if i > 4 {
break
}
no, _ := strconv.Atoi(number)
row = append(row, no)
}
// Add row to bingo
currentBingo = append(currentBingo, row)
// Check if bingo is complete
if bingoCurrentRow == 4 {
bingos = append(bingos, currentBingo)
bingoCurrentRow = 0
currentBingo = [][]int{}
} else {
bingoCurrentRow++
}
}
// Return called numbers and bingos
return
}