Advent-of-Code-2023/day4/dayFour.go

111 lines
2.3 KiB
Go

package day4
import (
"fmt"
"os"
"strconv"
"strings"
)
func Run() int {
fmt.Println("in day 4")
cards := ReadAllCards()
result := 0
for _, card := range cards {
fmt.Printf("> checking card %+v with points %d", card, card.GetPoints())
result += card.GetPoints()
}
return result
}
type Card struct {
Title int
WinningNums []int
OwnNums []int
}
func ReadAllCards() []Card {
filename := "day4/example"
bytes, err := os.ReadFile(filename)
if err != nil {
panic(fmt.Sprintf("can't read file %s", filename))
}
text := string(bytes)
lines := strings.Split(text, "\n")
result := make([]Card, len(lines))
for _, line := range lines {
if line == "" {
continue
}
result = append(result, ReadCard(line))
}
return result
}
// read line like 'Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53'
func ReadCard(line string) Card {
result := Card{}
extractingTitle := strings.Split(line, ":")
title := extractingTitle[0]
numberPart := extractingTitle[1]
titleNumStr := strings.Split(title, " ")[1]
titleNum, err := strconv.Atoi(titleNumStr)
if err != nil {
panic(fmt.Sprintf("error extracting card title: %s, %s", line, titleNumStr))
}
result.Title = titleNum
extractingNumbers := strings.Split(numberPart, "|")
for _, winningNumStr := range strings.Split( extractingNumbers[0], " " ) {
winningNumStr = strings.TrimSpace(winningNumStr)
if winningNumStr == "" {
continue
}
winningNum, err := strconv.Atoi(winningNumStr)
if err != nil {
panic(fmt.Sprintf("error extracting winning card num: %s from '%s'", line, winningNumStr))
}
result.WinningNums = append(result.WinningNums, winningNum)
}
for _, ownNumStr := range strings.Split( extractingNumbers[1], " " ) {
ownNumStr = strings.TrimSpace(ownNumStr)
if ownNumStr == "" {
continue
}
ownNum, err := strconv.Atoi(ownNumStr)
if err != nil {
panic(fmt.Sprintf("error extracting own card num: %s, %s", line, ownNumStr))
}
result.OwnNums = append(result.OwnNums, ownNum)
}
return result
}
func (c *Card)GetPoints() int {
winningSet := make(map[int]any)
for _, winNum := range c.WinningNums {
winningSet[winNum] = struct{}{}
}
result := 0
hasMatch := false
for _, ownNum := range c.OwnNums {
_, isWinning := winningSet[ownNum]
if isWinning {
if !hasMatch {
result = 1
hasMatch = true
} else {
result *= 2
}
}
}
return result
}