Advent of Code 2022: Day3

Back up

Stream Video

I forgot to record today. Doh!

Code

package aoc

import (
	"errors"
	"fmt"
	"io"
	"strings"

	"mono3/advent/lib/lineio"
	"mono3/common/tty"
)

const score = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

func findBadge(items map[rune]int) rune {
	for k, v := range items {
		if v == 3 {
			return k
		}
	}
	return '?'
}

// Each part gets the same input with reader pointing at the start of input.
var PuzzleParts = []func(r io.Reader) error{
	PuzzlePart1,
	PuzzlePart2,
}

func PuzzlePart1(r io.Reader) error {
	return solveit(r, 1)
}

func PuzzlePart2(r io.Reader) error {
	return solveit(r, 2)
}

func solveit(r io.Reader, part int) error {
	totalScore := 0
	elfGroupItems := map[rune]int{}

	if err := lineio.ForEach(r, func(ln int, line string) error {
		if len(line)%2 != 0 {
			return fmt.Errorf("odd line length (%d) %q", len(line), line)
		}

		one := line[:len(line)/2]
		two := line[len(line)/2:]
		if len(one) != len(two) {
			return fmt.Errorf("two compartments are not same size! %d vs %d", len(one), len(two))
		}

		if ln%3 == 0 && ln != 0 {
			badge := findBadge(elfGroupItems)
			pos := strings.IndexRune(score, badge)
			if part == 2 {
				totalScore += pos
			}
			elfGroupItems = map[rune]int{}
		}

		seen := map[rune]bool{}
		for _, r := range line {
			if !seen[r] {
				seen[r] = true
				elfGroupItems[r] += 1
			}
		}

		seen = map[rune]bool{}
		for _, r := range one {
			seen[r] = true
		}
		for _, r := range two {
			if seen[r] {
				pos := strings.IndexRune(score, r)
				if part == 1 {
					totalScore += pos
				}
				return nil
			}
		}

		tty.Printf("NO DUPLICATE line %d in %q\n", ln, line)
		return errors.New("no duplicates found!")
	}); err != nil {
		return err
	}

	badge := findBadge(elfGroupItems)
	score := strings.IndexRune(score, badge)
	if part == 2 {
		totalScore += score
	}

	tty.Printf("Total score for part %d: %d\n", part, totalScore)

	return nil
}

aimeeble@blog

the blog of aimeeble


By Aimee, 2022-12-03


Table of Contents: