From e59deac7c97252af74bc4f6e18c42fb144af5876 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 20 Dec 2025 13:44:07 -0600 Subject: [PATCH] refactor: make not ugly --- cmd/10/button/button.go | 40 ++++++++++ cmd/10/machine/machine.go | 117 ++++++++++++++++++++++++++++ cmd/10/main.go | 155 +------------------------------------- 3 files changed, 160 insertions(+), 152 deletions(-) create mode 100644 cmd/10/button/button.go create mode 100644 cmd/10/machine/machine.go diff --git a/cmd/10/button/button.go b/cmd/10/button/button.go new file mode 100644 index 0000000..29f17c6 --- /dev/null +++ b/cmd/10/button/button.go @@ -0,0 +1,40 @@ +// Package button implements a button that can control multiple switches. +package button + +import ( + "fmt" + "regexp" + "strconv" +) + +type Button interface { + Switches() []int +} + +type button struct { + switches []int +} + +func (b button) String() string { + return fmt.Sprintf("%v", b.switches) +} + +func From(line string) button { + buttonRegex := regexp.MustCompile(`\d+`) + matches := buttonRegex.FindAllString(line, -1) + + switches := []int{} + + for _, m := range matches { + num, _ := strconv.Atoi(m) + switches = append(switches, num) + } + + return button{ + switches: switches, + } +} + +func (b button) Switches() []int { + return b.switches +} diff --git a/cmd/10/machine/machine.go b/cmd/10/machine/machine.go new file mode 100644 index 0000000..f2d21fa --- /dev/null +++ b/cmd/10/machine/machine.go @@ -0,0 +1,117 @@ +// Package machine defines a model for a machine and methods to manipulate it. +package machine + +import ( + "math" + "regexp" + "slices" + "strconv" + "strings" + + "github.com/StevanFreeborn/advent-of-code-2025/cmd/10/button" +) + +type Machine interface { + ConfigureLights() int +} + +type machine struct { + desiredLightState []bool + buttons []button.Button + desiredJoltages []int +} + +func From(line string) Machine { + parts := strings.Split(line, " ") + lastPartIndex := len(parts) - 1 + + lightDiagramPart := parts[0] + desiredLightState := []bool{} + + for _, c := range lightDiagramPart { + if c == '.' { + desiredLightState = append(desiredLightState, false) + } + + if c == '#' { + desiredLightState = append(desiredLightState, true) + } + } + + buttonsPart := parts[1:lastPartIndex] + + buttons := []button.Button{} + + for _, bs := range buttonsPart { + b := button.From(bs) + buttons = append(buttons, b) + } + + joltagesPart := parts[lastPartIndex] + desiredJoltages := []int{} + joltageRegex := regexp.MustCompile(`\d+`) + matches := joltageRegex.FindAllString(joltagesPart, -1) + + for _, m := range matches { + num, _ := strconv.Atoi(m) + desiredJoltages = append(desiredJoltages, num) + } + + return machine{ + desiredLightState: desiredLightState, + buttons: buttons, + desiredJoltages: desiredJoltages, + } +} + +func (m machine) ConfigureLights() int { + combinations := [][]bool{} + minPresses := math.MaxInt + numberOfButtons := len(m.buttons) + numberOfCombinations := int(math.Pow(2, float64(numberOfButtons))) + currentCombination := make([]bool, numberOfButtons) + + for range numberOfCombinations { + temp := make([]bool, numberOfButtons) + copy(temp, currentCombination) + + combinations = append(combinations, temp) + + for j := range numberOfButtons { + if currentCombination[j] == false { + currentCombination[j] = true + break + } else { + currentCombination[j] = false + } + } + } + + for _, currentCombination := range combinations { + currentPresses := 0 + initialLightState := make([]bool, len(m.desiredLightState)) + + for bi, bs := range currentCombination { + if bs == false { + continue + } + + currentPresses++ + switchesToToggle := m.buttons[bi].Switches() + + for _, switchToToggle := range switchesToToggle { + initialLightState[switchToToggle] = !initialLightState[switchToToggle] + } + } + + if slices.Equal(initialLightState, m.desiredLightState) == false { + continue + } + + if currentPresses < minPresses { + minPresses = currentPresses + } + } + + return minPresses +} diff --git a/cmd/10/main.go b/cmd/10/main.go index e1cd8ea..8f45ea2 100644 --- a/cmd/10/main.go +++ b/cmd/10/main.go @@ -1,165 +1,16 @@ package main import ( - "fmt" - "math" - "regexp" - "slices" - "strconv" - "strings" - + "github.com/StevanFreeborn/advent-of-code-2025/cmd/10/machine" "github.com/StevanFreeborn/advent-of-code-2025/internal/file" ) -type machine struct { - switches []bool - buttons []button -} - -func NewMachine(numberOfLights int, buttonsAsStrings []string) machine { - buttons := []button{} - - for _, bs := range buttonsAsStrings { - b := NewButton(bs) - buttons = append(buttons, b) - } - - switches := []bool{} - - for range numberOfLights { - switches = append(switches, false) - } - - return machine{ - buttons: buttons, - switches: switches, - } -} - -func (m machine) String() string { - var str strings.Builder - - str.WriteString("[MACHINE]\n") - - switchStr := fmt.Sprintf("[SWITCHES]: %v", m.switches) - str.WriteString(switchStr + "\n") - - str.WriteString("[BUTTONS]:\n") - - for _, b := range m.buttons { - str.WriteString(b.String() + "\n") - } - - str.WriteString("\n") - - return str.String() -} - -type button struct { - switchesControlled []int -} - -func (b button) String() string { - return fmt.Sprintf("%v", b.switchesControlled) -} - -func NewButton(line string) button { - buttonRegex := regexp.MustCompile(`\d+`) - matches := buttonRegex.FindAllString(line, -1) - - switchesControlled := []int{} - - for _, m := range matches { - num, _ := strconv.Atoi(m) - switchesControlled = append(switchesControlled, num) - } - - return button{ - switchesControlled: switchesControlled, - } -} - -func (m machine) Configure(desiredState []bool) int { - combinations := [][]bool{} - minPresses := math.MaxInt - numberOfButtons := len(m.buttons) - numberOfCombinations := int(math.Pow(2, float64(numberOfButtons))) - currentCombination := make([]bool, numberOfButtons) - - for range numberOfCombinations { - temp := make([]bool, numberOfButtons) - copy(temp, currentCombination) - - combinations = append(combinations, temp) - - for j := range numberOfButtons { - if currentCombination[j] == false { - currentCombination[j] = true - break - } else { - currentCombination[j] = false - } - } - } - - for _, currentCombination := range combinations { - currentPresses := 0 - switchesCopy := []bool{} - - for _, v := range m.switches { - switchesCopy = append(switchesCopy, v) - } - - for bi, bs := range currentCombination { - if bs == false { - continue - } - - currentPresses++ - switchesToToggle := m.buttons[bi].switchesControlled - - for _, switchToToggle := range switchesToToggle { - switchesCopy[switchToToggle] = !switchesCopy[switchToToggle] - } - } - - if slices.Equal(switchesCopy, desiredState) == false { - continue - } - - if currentPresses < minPresses { - minPresses = currentPresses - } - } - - return minPresses -} - func SolvePartOne(filePath string) int { total := 0 for line := range file.ReadLines(filePath) { - parts := strings.Split(line, " ") - lightDiagramPart := parts[0] - buttonsPart := parts[1 : len(parts)-1] - // NOTE: Parse joltage here - - lightDiagram := []bool{} - - for _, c := range lightDiagramPart { - if c == '.' { - lightDiagram = append(lightDiagram, false) - } - - if c == '#' { - lightDiagram = append(lightDiagram, true) - } - } - - numberOfLights := len(lightDiagram) - - machine := NewMachine(numberOfLights, buttonsPart) - buttonsPressed := machine.Configure(lightDiagram) + machine := machine.From(line) + buttonsPressed := machine.ConfigureLights() total += buttonsPressed }