Files

142 lines
3.1 KiB
Go

package dayfifteen
import (
"advent-of-code/internal/registry"
"fmt"
"os"
"strings"
)
func init() {
registry.Register("2015D15", ParseInput, PartOne, PartTwo)
}
func ParseInput(filepath string) []string {
content, _ := os.ReadFile(filepath)
return strings.Split(string(content), "\n")
}
type ingredient struct {
capacity int
durability int
flavor int
texture int
calories int
}
func parseIngredient(line string) ingredient {
parts := strings.Split(line, ": ")
props := strings.Split(parts[1], ", ")
var cap, dur, flav, tex, cal int
for _, prop := range props {
var name string
var value int
fmt.Sscanf(prop, "%s %d", &name, &value)
switch name {
case "capacity":
cap = value
case "durability":
dur = value
case "flavor":
flav = value
case "texture":
tex = value
case "calories":
cal = value
}
}
return ingredient{
capacity: cap,
durability: dur,
flavor: flav,
texture: tex,
calories: cal,
}
}
func calculateScore(ingredients []ingredient, amounts []int) int {
var capacity, durability, flavor, texture int
for idx, ing := range ingredients {
capacity += ing.capacity * amounts[idx]
durability += ing.durability * amounts[idx]
flavor += ing.flavor * amounts[idx]
texture += ing.texture * amounts[idx]
}
if capacity < 0 {
capacity = 0
}
if durability < 0 {
durability = 0
}
if flavor < 0 {
flavor = 0
}
if texture < 0 {
texture = 0
}
return capacity * durability * flavor * texture
}
func calculateCalories(ingredients []ingredient, amounts []int) int {
var calories int
for idx, ing := range ingredients {
calories += ing.calories * amounts[idx]
}
return calories
}
func PartOne(data []string) int {
var ingredients []ingredient
for _, line := range data {
ingredients = append(ingredients, parseIngredient(line))
}
amounts := make([]int, len(ingredients))
var findMaxScore func(remaining int, index int) int
findMaxScore = func(remaining int, index int) int {
if index == len(ingredients)-1 {
amounts[index] = remaining
return calculateScore(ingredients, amounts)
}
maxScore := 0
for idx := 0; idx <= remaining; idx++ {
amounts[index] = idx
score := findMaxScore(remaining-idx, index+1)
if score > maxScore {
maxScore = score
}
}
return maxScore
}
return findMaxScore(100, 0)
}
func PartTwo(data []string) int {
var ingredients []ingredient
for _, line := range data {
ingredients = append(ingredients, parseIngredient(line))
}
amounts := make([]int, len(ingredients))
var findMaxScoreWithCalories func(remaining int, index int) int
findMaxScoreWithCalories = func(remaining int, index int) int {
if index == len(ingredients)-1 {
amounts[index] = remaining
if calculateCalories(ingredients, amounts) == 500 {
return calculateScore(ingredients, amounts)
}
return 0
}
maxScore := 0
for idx := 0; idx <= remaining; idx++ {
amounts[index] = idx
score := findMaxScoreWithCalories(remaining-idx, index+1)
if score > maxScore {
maxScore = score
}
}
return maxScore
}
return findMaxScoreWithCalories(100, 0)
}