package day4 import ( "fmt" "os" "strconv" "strings" ) func Run() int { fmt.Println("in day 4") cards := ReadAllCards() fmt.Printf("> got cards %+v\n", cards) // result := 0 // for _, card := range cards { // // fmt.Printf("> checking card %+v with points %d", card, card.GetPoints()) // result += card.GetPoints() // } result := ActuallWinCounting(cards) return result } // starting from card #1 count how many winning points it has // then add copies to map of 'amount of cards i have' // multiplied to amount of current card i have, ok i guess func ActuallWinCounting(cards []Card) int { cardAmounts := make(map[int]int) // i had off-by-one error, with card 204 not being updated from 196 maxCard := len(cards) fmt.Printf("> counting winning, total cards are %d\ncards are %+v\n\n", maxCard, cards) for _, card := range cards { fmt.Printf("> checking card %d\n", card.Title) winningNums := card.GetWinNums() curCardAmount, found := cardAmounts[card.Title] if !found { curCardAmount = 1 cardAmounts[card.Title] = curCardAmount } fmt.Printf(">> from curCard %d winning points are %d. And it's amount is %d\n", card.Title, winningNums, curCardAmount) for i := 1; i <= winningNums; i++ { childCardNum := card.Title + i if childCardNum > maxCard { fmt.Printf(">>>> should skip increasing child card %d from curCard %d\n", childCardNum, card.Title) break } curAmount, found := cardAmounts[childCardNum] if !found { cardAmounts[childCardNum] = 1 + curCardAmount } else { cardAmounts[childCardNum] += curCardAmount } fmt.Printf(">> increasing child card %d from %d to %d by curCard %d\n", childCardNum, curAmount, cardAmounts[childCardNum], card.Title) } } var result int = 0 for _, amount := range cardAmounts { result += amount } fmt.Printf("> got card amounts: %+v\n", cardAmounts) return result } type Card struct { Title int WinningNums []int OwnNums []int } func ReadAllCards() []Card { filename := "day4/input" 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, 0, 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 { fmt.Printf(">> reading line %s\n", line) result := Card{} extractingTitle := strings.Split(line, ":") title := extractingTitle[0] numberPart := extractingTitle[1] titleNumStr := strings.Fields(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) } fmt.Printf(">>> returning %+v\n", result) return result } func (c *Card)GetWinNums() int { winningSet := make(map[int]any) for _, winNum := range c.WinningNums { winningSet[winNum] = struct{}{} } result := 0 for _, ownNum := range c.OwnNums { _, isWinning := winningSet[ownNum] if isWinning { result += 1 } } 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 }