question 7

This commit is contained in:
didier committed 2024-12-07 11:43:26 -05:00
1 parent cab7c95b59
commit 13c4a4fb4a
2 files changed
+200

No files matched your search

+197
View File
@@ -0,0 +1,197 @@
package main
import (
"fmt"
"strconv"
"strings"
)
const mockInput = "190: 10 19\n3267: 81 40 27\n83: 17 5\n156: 15 6\n7290: 6 8 6 15\n161011: 16 10 13\n192: 17 8 14\n21037: 9 7 18 13\n292: 11 6 16 20"
type ProblemRow struct {
res int
numbers []int
}
func parseRow(s string) *ProblemRow {
colonIdx := strings.Index(s, ":")
res, _ := strconv.Atoi(s[0:colonIdx])
numbers := toSliceOfInt(strings.Split(s[colonIdx+2:], " "))
return &ProblemRow{res, numbers}
}
func parseProblemInput(input string) []*ProblemRow {
ret := make([]*ProblemRow, 0)
for _, row := range strings.Split(input, "\n") {
ret = append(ret, parseRow(row))
}
return ret
}
func toSliceOfInt(split []string) []int {
ret := make([]int, len(split))
for i := 0; i < len(split); i++ {
ret[i], _ = strconv.Atoi(split[i])
}
return ret
}
type Operand int8
const (
PRODUCT Operand = iota
SUM
CONCAT
)
type OperandNode struct {
value Operand
nextNode *NumberNode
}
func (n *OperandNode) String() string {
opp := "+"
if n.value == PRODUCT {
opp = "*"
}
if n.value == CONCAT {
opp = "||"
}
return fmt.Sprintf("%s %s", opp, n.nextNode.String())
}
type NumberNode struct {
value int
nextNode *OperandNode
}
func (n *NumberNode) String() string {
rest := ""
if n.nextNode != nil {
rest = n.nextNode.String()
}
return fmt.Sprintf("%d %s", n.value, rest)
}
func process(node *NumberNode) int {
if node.nextNode == nil {
return node.value
}
if node.nextNode.value == SUM {
newValue := node.value + node.nextNode.nextNode.value
nextNext := node.nextNode.nextNode.nextNode
newNode := &NumberNode{newValue, nextNext}
return process(newNode)
}
if node.nextNode.value == PRODUCT {
newValue := node.value * node.nextNode.nextNode.value
nextNext := node.nextNode.nextNode.nextNode
newNode := &NumberNode{newValue, nextNext}
return process(newNode)
}
if node.nextNode.value == CONCAT {
newValue := concatInts(node.value, node.nextNode.nextNode.value)
nextNext := node.nextNode.nextNode.nextNode
newNode := &NumberNode{newValue, nextNext}
return process(newNode)
}
panic("Unknown Operand")
}
func concatInts(value, value2 int) int {
n := 1
for n <= value2 {
n = n * 10
}
return value2 + n*value
}
func createNodes(numbers []int, operands []Operand) *NumberNode {
if len(numbers)-1 != len(operands) {
panic("Number of operands must be 1 minus number of numbers")
}
var firstVNode *NumberNode = nil
var previousONode *OperandNode = nil
for i := 0; i < len(operands); i++ {
oNode := &OperandNode{operands[i], nil}
vNode := &NumberNode{numbers[i], oNode}
if firstVNode == nil {
firstVNode = vNode
}
if previousONode != nil {
previousONode.nextNode = vNode
}
previousONode = oNode
}
previousONode.nextNode = &NumberNode{numbers[len(numbers)-1], nil}
return firstVNode
}
func createAllPossibleChain(numbers []int, operands ...Operand) <-chan *NumberNode {
out := make(chan *NumberNode)
go func() {
for operators := range allPossibleOperators(len(numbers)-1, operands...) {
out <- createNodes(numbers, operators)
}
close(out)
}()
return out
}
func allPossibleOperators(n int, operands ...Operand) <-chan []Operand {
out := make(chan []Operand)
go func() {
defer close(out)
if n == 0 {
out <- []Operand{}
return
}
for _, operand := range operands {
for prefix := range allPossibleOperators(n-1, operands...) {
out <- append(prefix, operand)
}
}
}()
return out
}
func problem7A(input string) int {
ret := 0
for _, problemRow := range parseProblemInput(input) {
if isSolvable(problemRow, SUM, PRODUCT) {
ret += problemRow.res
}
}
return ret
}
func problem7B(input string) int64 {
var ret int64 = 0
for _, problemRow := range parseProblemInput(input) {
if isSolvable(problemRow, PRODUCT, SUM, CONCAT) {
ret += int64(problemRow.res)
}
}
return ret
}
func isSolvable(row *ProblemRow, operands ...Operand) bool {
fmt.Println("")
for node := range createAllPossibleChain(row.numbers, operands...) {
if process(node) == row.res {
return true
}
}
return false
}
func main() {
fmt.Printf("The answer to question 7A is %d \n", problem7A(realInput))
fmt.Printf("The answer to question 7B is %d \n", problem7B(mockInput))
}