Skip to content

Commit

Permalink
Solve 7
Browse files Browse the repository at this point in the history
  • Loading branch information
kyle.brown committed Dec 8, 2024
1 parent af440d6 commit dd23f69
Show file tree
Hide file tree
Showing 2 changed files with 340 additions and 0 deletions.
115 changes: 115 additions & 0 deletions 7/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package main

import (
"adventofcode2024/pkg/helper"
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
"time"
)

type calibrationData struct {
result int
numbers []int
}

func main() {
f, err := os.Open("./7/input.txt")
if err != nil {
panic(err)
}
cData := getData(f)
_ = f.Close()

start := time.Now()
res := sumValidCalibrationData(cData, false)
elapsed := time.Since(start)
fmt.Println(res)
fmt.Println(elapsed)

start2 := time.Now()
res2 := sumValidCalibrationData(cData, true)
elapsed2 := time.Since(start2)
fmt.Println(res2)
fmt.Println(elapsed2)
}

func sumValidCalibrationData(dataList []calibrationData, concatActive bool) int {
var acc int
for _, data := range dataList {
if isCalibrationDataPossible(data, concatActive) {
acc += data.result
}
}
return acc
}

type operator int

const (
ADD operator = iota
MULT
CONCAT
)

func isCalibrationDataPossible(data calibrationData, concatActive bool) bool {
operators := make([]operator, len(data.numbers)-1)
for {
acc := data.numbers[0]
for i := 1; i < len(data.numbers); i++ {
o := operators[i-1]
if o == ADD {
acc += data.numbers[i]
} else if o == CONCAT {
acc = helper.MustAtoI(strconv.Itoa(acc) + strconv.Itoa(data.numbers[i]))
} else {
acc *= data.numbers[i]
}
}
if acc == data.result {
return true
}
if !nextPermutation(operators, concatActive) {
return false
}
}
}

func nextPermutation(operators []operator, concatActive bool) bool {
i := 0
for ; i < len(operators); i++ {
o := operators[i]
if o == ADD {
operators[i] = MULT
return true
} else if concatActive && o == MULT {
operators[i] = CONCAT
return true
} else {
operators[i] = ADD
}
}
return !(i == len(operators) && operators[len(operators)-1] == ADD)
}

func getData(f io.Reader) []calibrationData {
input := bufio.NewScanner(f)

cData := make([]calibrationData, 0, 1000)
for input.Scan() {
line := input.Text()
parts := strings.Split(line, ":")
result := helper.MustAtoI(parts[0])
inputs := strings.Split(strings.TrimSpace(parts[1]), " ")
inputList := make([]int, 0, len(inputs))
for _, i := range inputs {
inputList = append(inputList, helper.MustAtoI(i))
}
cData = append(cData, calibrationData{result: result, numbers: inputList})
}

return cData
}
225 changes: 225 additions & 0 deletions 7/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package main

import (
"reflect"
"testing"
)

func Test_nextPermutation(t *testing.T) {
type args struct {
operators []operator
concatActive bool
}
type want struct {
result bool
operators []operator
}
tests := []struct {
name string
args args
want want
}{
{
name: "single",
args: args{
operators: []operator{ADD},
},
want: want{
operators: []operator{MULT},
result: true,
},
},
{
name: "single end of cycle",
args: args{
operators: []operator{MULT},
},
want: want{
operators: []operator{ADD},
result: false,
},
},
{
name: "double no carry",
args: args{
operators: []operator{ADD, ADD},
},
want: want{
operators: []operator{MULT, ADD},
result: true,
},
},
{
name: "double carry",
args: args{
operators: []operator{MULT, ADD},
},
want: want{
operators: []operator{ADD, MULT},
result: true,
},
},
{
name: "double v2",
args: args{
operators: []operator{ADD, MULT},
},
want: want{
operators: []operator{MULT, MULT},
result: true,
},
},
{
name: "double carry carry",
args: args{
operators: []operator{MULT, MULT},
},
want: want{
operators: []operator{ADD, ADD},
result: false,
},
},
{
name: "triple",
args: args{
operators: []operator{MULT, MULT, ADD},
},
want: want{
operators: []operator{ADD, ADD, MULT},
result: true,
},
},
{
name: "triple with concat",
args: args{
concatActive: true,
operators: []operator{MULT, MULT, ADD},
},
want: want{
operators: []operator{CONCAT, MULT, ADD},
result: true,
},
},
{
name: "triple with concat 2",
args: args{
concatActive: true,
operators: []operator{CONCAT, MULT, ADD},
},
want: want{
operators: []operator{ADD, CONCAT, ADD},
result: true,
},
},
{
name: "triple with concat 3",
args: args{
concatActive: true,
operators: []operator{ADD, CONCAT, ADD},
},
want: want{
operators: []operator{MULT, CONCAT, ADD},
result: true,
},
},
{
name: "triple with concat 4",
args: args{
concatActive: true,
operators: []operator{MULT, CONCAT, ADD},
},
want: want{
operators: []operator{CONCAT, CONCAT, ADD},
result: true,
},
},
{
name: "triple with concat 5",
args: args{
concatActive: true,
operators: []operator{CONCAT, CONCAT, ADD},
},
want: want{
operators: []operator{ADD, ADD, MULT},
result: true,
},
},
{
name: "triple with concat Z",
args: args{
concatActive: true,
operators: []operator{CONCAT, CONCAT, CONCAT},
},
want: want{
operators: []operator{ADD, ADD, ADD},
result: false,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := nextPermutation(tt.args.operators, tt.args.concatActive); got != tt.want.result {
t.Errorf("nextPermutation() = %v, want %v", got, tt.want)
}
if eq := reflect.DeepEqual(tt.args.operators, tt.want.operators); !eq {
t.Errorf("nextPermutation() array incorrect, got %v, want %v", tt.args.operators, tt.want.operators)
}
})
}
}

func Test_sumValidCalibrationData(t *testing.T) {
type args struct {
dataList []calibrationData
concatActive bool
}
tests := []struct {
name string
args args
want int
}{
{
name: "example",
args: args{
concatActive: false,
dataList: []calibrationData{
{result: 190, numbers: []int{10, 19}},
{result: 3267, numbers: []int{81, 40, 27}},
{result: 83, numbers: []int{17, 5}},
{result: 156, numbers: []int{15, 6}},
{result: 7290, numbers: []int{6, 8, 6, 15}},
{result: 161011, numbers: []int{16, 10, 13}},
{result: 192, numbers: []int{17, 8, 14}},
{result: 21037, numbers: []int{9, 7, 18, 13}},
{result: 292, numbers: []int{11, 6, 16, 20}},
},
},
want: 3749,
},
{
name: "example",
args: args{
concatActive: true,
dataList: []calibrationData{
{result: 190, numbers: []int{10, 19}},
{result: 3267, numbers: []int{81, 40, 27}},
{result: 83, numbers: []int{17, 5}},
{result: 156, numbers: []int{15, 6}},
{result: 7290, numbers: []int{6, 8, 6, 15}},
{result: 161011, numbers: []int{16, 10, 13}},
{result: 192, numbers: []int{17, 8, 14}},
{result: 21037, numbers: []int{9, 7, 18, 13}},
{result: 292, numbers: []int{11, 6, 16, 20}},
},
},
want: 11387,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := sumValidCalibrationData(tt.args.dataList, tt.args.concatActive); got != tt.want {
t.Errorf("sumValidCalibrationData() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit dd23f69

Please sign in to comment.