2021 Day 4 & Day 5 Complete
This commit is contained in:
197
2021/day04/main.go
Normal file
197
2021/day04/main.go
Normal file
@@ -0,0 +1,197 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
func main() {
|
||||
inp := h.StdinToStringSlice()
|
||||
boards := buildBoards(inp[1:])
|
||||
draws := parseDraws(inp[0])
|
||||
//part1(boards, draws)
|
||||
part2(boards, draws)
|
||||
}
|
||||
|
||||
func part1(boards []Board, draws []int) {
|
||||
var winners []Board
|
||||
for i := range draws {
|
||||
for b := range boards {
|
||||
if boards[b].Mark(draws[i]) {
|
||||
winners = append(winners, boards[b])
|
||||
}
|
||||
}
|
||||
if len(winners) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
for w := range winners {
|
||||
fmt.Println("# Part 1")
|
||||
fmt.Println(winners[w])
|
||||
fmt.Println(winners[w].Score())
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func part2(boards []Board, draws []int) {
|
||||
var winners []Board
|
||||
for i := range draws {
|
||||
for b := range boards {
|
||||
if boards[b].Mark(draws[i]) {
|
||||
winners = append(winners, boards[b])
|
||||
}
|
||||
}
|
||||
// Remove all winners from boards
|
||||
for i := range winners {
|
||||
for b := range boards {
|
||||
if winners[i].String() == boards[b].String() {
|
||||
boards = append(boards[:b], boards[b+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(boards) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Println("# Part 2")
|
||||
fmt.Println("Last Winner")
|
||||
fmt.Println(winners[len(winners)-1])
|
||||
fmt.Println(winners[len(winners)-1].Score())
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func parseDraws(inp string) []int {
|
||||
var ret []int
|
||||
pts := strings.Split(inp, ",")
|
||||
for i := range pts {
|
||||
ret = append(ret, h.Atoi(pts[i]))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type Spot struct {
|
||||
value int
|
||||
marked bool
|
||||
}
|
||||
|
||||
type Board struct {
|
||||
spots map[h.Coordinate]Spot
|
||||
draws []int
|
||||
}
|
||||
|
||||
func NewBoard(inp []string) Board {
|
||||
b := Board{
|
||||
spots: make(map[h.Coordinate]Spot),
|
||||
}
|
||||
for y := range inp {
|
||||
row := strings.Fields(strings.TrimSpace(inp[y]))
|
||||
for x := range row {
|
||||
v := h.Atoi(row[x])
|
||||
b.spots[h.Coordinate{X: x, Y: y}] = Spot{value: v}
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func buildBoards(inp []string) []Board {
|
||||
var boards []Board
|
||||
var boardStr []string
|
||||
for i := range inp {
|
||||
if inp[i] == "" {
|
||||
// start/end of a board
|
||||
if len(boardStr) == 5 {
|
||||
boards = append(boards, NewBoard(boardStr))
|
||||
}
|
||||
boardStr = []string{}
|
||||
} else {
|
||||
boardStr = append(boardStr, inp[i])
|
||||
}
|
||||
}
|
||||
if len(boardStr) == 5 {
|
||||
boards = append(boards, NewBoard(boardStr))
|
||||
}
|
||||
|
||||
return boards
|
||||
}
|
||||
|
||||
// Mark adds a number to the draws and returns whether this board has won
|
||||
func (b *Board) Mark(v int) bool {
|
||||
b.draws = append(b.draws, v)
|
||||
for k := range b.spots {
|
||||
s := b.spots[k]
|
||||
if b.spots[k].value == v {
|
||||
s.marked = true
|
||||
b.spots[k] = s
|
||||
return b.Won()
|
||||
}
|
||||
}
|
||||
return b.Won()
|
||||
}
|
||||
|
||||
func (b *Board) Won() bool {
|
||||
for y := 0; y < 5; y++ {
|
||||
if b.CheckRowForWin(y) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for x := 0; x < 5; x++ {
|
||||
if b.CheckColForWin(x) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *Board) CheckRowForWin(y int) bool {
|
||||
for x := 0; x < 5; x++ {
|
||||
if b.spots[c(x, y)].marked == false {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (b *Board) CheckColForWin(x int) bool {
|
||||
for y := 0; y < 5; y++ {
|
||||
if b.spots[c(x, y)].marked == false {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (b *Board) Score() int {
|
||||
var unmarked int
|
||||
for y := 0; y < 5; y++ {
|
||||
for x := 0; x < 5; x++ {
|
||||
if b.spots[c(x, y)].marked == false {
|
||||
unmarked += b.spots[c(x, y)].value
|
||||
}
|
||||
}
|
||||
}
|
||||
return unmarked * b.draws[len(b.draws)-1]
|
||||
}
|
||||
|
||||
func (b Board) String() string {
|
||||
var ret string
|
||||
for y := 0; y < 5; y++ {
|
||||
for x := 0; x < 5; x++ {
|
||||
c := c(x, y)
|
||||
marked := " "
|
||||
if b.spots[c].marked {
|
||||
marked = "X"
|
||||
}
|
||||
ret = fmt.Sprintf("%s%s: %2d[%v] ", ret, c, b.spots[c].value, marked)
|
||||
}
|
||||
ret = ret + "\n"
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func c(x, y int) h.Coordinate {
|
||||
return h.Coordinate{X: x, Y: y}
|
||||
}
|
||||
Reference in New Issue
Block a user