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 }