package main import ( "bufio" "fmt" "io" "math" "sort" "strconv" "strings" ) func countwinings(line string) int { var matches int before, after, _ := strings.Cut(line, "|") w := strings.Split(before, " ") o := strings.Split(after, " ") winnings := make([]int, 0, len(w)) obtained := make([]int, 0, len(o)) for i := range w { val, err := strconv.Atoi(strings.TrimSpace(w[i])) if err == nil { winnings = append(winnings, val) } } for i := range o { val, err := strconv.Atoi(strings.TrimSpace(o[i])) if err == nil { obtained = append(obtained, val) } } sort.Ints(winnings) sort.Ints(obtained) for i, j := 0, 0; i < len(winnings) && j < len(obtained); { if winnings[i] == obtained[j] { matches++ i++ j++ } else if winnings[i] > obtained[j] { j++ } else { i++ } } return matches } type day04 struct{} func (d day04) solve1(r io.Reader) string { var ( sum int scanner = bufio.NewScanner(r) ) for scanner.Scan() { _, line, _ := strings.Cut(scanner.Text(), ": ") matches := countwinings(line) if matches > 0 { sum += int(math.Pow(2, float64(matches)-1)) } } return fmt.Sprintf("%d", sum) } func expand(cursor, matches int, duplicates []int) []int { if cursor+matches > len(duplicates) { tmp := make([]int, cursor+matches) for i := range duplicates { tmp[i] = duplicates[i] } duplicates = tmp } for i := cursor; i < cursor+matches; i++ { duplicates[i] = duplicates[i] + 1 // only count duplicates if we are past the first card if cursor > 0 { duplicates[i] = duplicates[i] + duplicates[cursor-1] } } return duplicates } func (d day04) solve2(r io.Reader) string { var ( cursor int duplicates = make([]int, 0) scanner = bufio.NewScanner(r) ) for matches := -1; scanner.Scan() && matches != 0; cursor++ { _, line, _ := strings.Cut(scanner.Text(), ": ") matches := countwinings(line) duplicates = expand(cursor, matches, duplicates) } sum := cursor for _, c := range duplicates { sum += c } return fmt.Sprintf("%d", sum) }