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 }