Day 6: Trash Compactor

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

you are viewing a single comment's thread
view the rest of the comments
[โ€“] 2 points 10 months ago

Go

Damn, I actually reeaally enjoy this one! I didn't expect the twist of part 2, but somehow it wasn't that hard to manage.

Here is my modern solution:

day06.go

package main

import (
	"aoc/utils"
	"fmt"
	"regexp"
	"slices"
	"strconv"
	"strings"
)

type operation int

func (o operation) compute(values []int) int {
	switch o {
	case add:
		sum := 0
		for _, val := range values {
			sum += val
		}
		return sum
	case mul:
		product := 1
		for _, val := range values {
			product *= val
		}
		return product
	}

	return 0
}

const (
	add operation = iota
	mul
)

var allOperationSymbols = []string{"+", "*"}

func operationFromSymbol(sym string) operation {
	switch sym {
	case "+":
		return add
	case "*":
		return mul
	default:
		panic(fmt.Sprintf("wtf is a %s?", sym))
	}
}

type problems struct {
	values     [][]int
	operations []operation
}

func (p *problems) feed(column string) {
	last := string(column[len(column)-1])
	done := false

	if slices.Contains(allOperationSymbols, last) {
		p.operations = append(p.operations, operationFromSymbol(last))
		column = column[:len(column)-1]
		done = true
	}

	val, _ := strconv.Atoi(strings.TrimSpace(column))
	idx := len(p.values) - 1
	p.values[idx] = append(p.values[idx], val)

	if done {
		p.values = append(p.values, []int{})
	}
}

func (p *problems) addLine(line string) (done bool) {
	parts := strings.Split(line, " ")
	parts = slices.DeleteFunc(parts, func(elem string) bool {
		return elem == ""
	})

	if slices.Contains(allOperationSymbols, parts[0]) {
		p.operations = make([]operation, len(parts))
		for idx, sym := range parts {
			p.operations[idx] = operationFromSymbol(sym)
		}
		done = true
	} else {
		if len(p.values) == 0 {
			lenparts := len(parts)
			p.values = make([][]int, lenparts)
			for idx := range lenparts {
				p.values[idx] = []int{}
			}
		}

		for idx, part := range parts {
			num, _ := strconv.Atoi(part)
			p.values[idx] = append(p.values[idx], num)
		}
		done = false
	}

	return done
}

func (p problems) solve() []int {
	solutions := make([]int, len(p.values))

	for idx, values := range p.values {
		op := p.operations[idx]
		solutions[idx] = op.compute(values)
	}

	return solutions
}

func stepOne(input chan string) (int, error) {
	modernProblems := problems{}
	for line := range input {
		done := modernProblems.addLine(line)
		if done {
			break
		}
	}

	modernSolutions := modernProblems.solve()
	sum := 0
	for _, solution := range modernSolutions {
		sum += solution
	}

	return sum, nil
}

func transposeInputChan(input chan string) []string {
	lines := [][]rune{}
	for line := range input {
		lines = append(lines, []rune(line))
	}

	linecount := len(lines)
	columncount := len(lines[0])
	transposed := make([][]rune, columncount)

	for idx := range transposed {
		transposed[idx] = make([]rune, linecount)
	}

	for row, line := range lines {
		for col, char := range line {
			transposed[col][row] = char
		}
	}

	columns := make([]string, len(transposed))
	for idx, col := range transposed {
		columns[idx] = string(col)
	}

	return columns
}

func stepTwo(input chan string) (int, error) {
	transposedInput := transposeInputChan(input)
	slices.Reverse(transposedInput)

	// problem-set with one empty problem.
	modernProblems := problems{
		values: [][]int{[]int{}},
	}

	for _, column := range transposedInput {
		if matched, _ := regexp.MatchString("^\\s*$", column); matched {
			continue
		}

		modernProblems.feed(column)
	}

	// Remove last useless empty problem.
	modernProblems.values = modernProblems.values[:len(modernProblems.values)-1]

	modernSolutions := modernProblems.solve()
	sum := 0
	for _, solution := range modernSolutions {
		sum += solution
	}

	return sum, nil
}

func main() {
	inputFile := utils.FilePath("day06.txt")
	utils.RunStep(utils.ONE, inputFile, stepOne)
	utils.RunStep(utils.TWO, inputFile, stepTwo)
}

  • source