Day 18 solution
This commit is contained in:
@@ -182,3 +182,12 @@ The solution for "seventeen" is:
|
|||||||
The max height is 35511
|
The max height is 35511
|
||||||
There are 3282 initial velocities that will hit the target
|
There are 3282 initial velocities that will hit the target
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Day eighteen
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ ./aoc2021 --eighteen
|
||||||
|
The solution for "eighteen" is:
|
||||||
|
The magnitude of the final sum is 4202
|
||||||
|
The largest magnitude of any two snail numbers is 4779
|
||||||
|
```
|
||||||
|
100
eighteen/input.txt
Normal file
100
eighteen/input.txt
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
[[[0,[4,4]],6],[[[7,6],6],[[5,3],[3,2]]]]
|
||||||
|
[[[[4,6],[1,7]],[5,8]],[[9,7],[9,6]]]
|
||||||
|
[[[2,[7,1]],[[8,2],[9,3]]],3]
|
||||||
|
[[[[2,1],6],2],4]
|
||||||
|
[[[[0,3],0],6],[[9,[0,8]],[[2,1],[0,2]]]]
|
||||||
|
[[[5,1],[[0,5],1]],[[[9,9],[8,7]],7]]
|
||||||
|
[[[[0,2],8],8],[0,[7,[2,7]]]]
|
||||||
|
[[[[3,8],[6,4]],[[2,0],2]],3]
|
||||||
|
[[[[1,5],3],[[5,3],[5,4]]],[[0,1],[[1,2],8]]]
|
||||||
|
[[[1,1],[[9,3],9]],[[9,[6,5]],[2,6]]]
|
||||||
|
[[[9,3],[6,[1,5]]],[[3,8],[[4,6],[8,0]]]]
|
||||||
|
[[3,[6,7]],[[3,0],[5,[3,4]]]]
|
||||||
|
[1,[2,[[4,1],[2,3]]]]
|
||||||
|
[[6,[7,8]],[[0,[0,3]],[6,7]]]
|
||||||
|
[[8,[[0,0],[9,3]]],[[2,6],[[9,1],[4,9]]]]
|
||||||
|
[[3,0],[[8,[7,1]],4]]
|
||||||
|
[[[1,0],[[9,7],[7,8]]],[[[0,0],5],[[4,9],4]]]
|
||||||
|
[[[[4,2],7],[[4,0],0]],[[[5,4],[6,7]],[0,[1,2]]]]
|
||||||
|
[[[4,[4,3]],[[1,4],[1,1]]],6]
|
||||||
|
[[[0,[5,9]],[[7,4],2]],[[9,1],[4,7]]]
|
||||||
|
[[[[5,5],[7,0]],[8,[5,3]]],[[0,[0,2]],[[1,3],[5,8]]]]
|
||||||
|
[[9,[[9,9],2]],[[9,6],[[4,7],5]]]
|
||||||
|
[[[[8,7],[5,3]],9],[3,[6,9]]]
|
||||||
|
[[3,[0,3]],[2,6]]
|
||||||
|
[[[2,[7,0]],[6,6]],[[7,0],[[3,8],[8,5]]]]
|
||||||
|
[[[2,6],[2,7]],[[3,6],[0,[9,5]]]]
|
||||||
|
[[[5,4],1],[5,[[4,9],5]]]
|
||||||
|
[[[6,3],6],[[[6,0],0],[[4,0],7]]]
|
||||||
|
[[[[4,1],2],[3,[9,0]]],[0,8]]
|
||||||
|
[[[2,[3,9]],[[8,3],8]],[[1,[2,2]],[8,[6,4]]]]
|
||||||
|
[[[[4,3],[5,2]],0],[9,[5,[7,5]]]]
|
||||||
|
[[[3,2],5],[[[6,3],9],[[2,0],[6,7]]]]
|
||||||
|
[[[3,9],[[0,6],[0,7]]],[6,[3,2]]]
|
||||||
|
[0,0]
|
||||||
|
[[[[0,3],9],[8,[3,9]]],[[0,2],[[0,1],[3,7]]]]
|
||||||
|
[[0,[4,[3,0]]],[[7,9],[5,[8,7]]]]
|
||||||
|
[[2,9],[[0,[2,2]],1]]
|
||||||
|
[[[[5,4],[1,7]],6],[2,[[5,3],[7,7]]]]
|
||||||
|
[[[[0,4],4],[[6,6],[1,4]]],4]
|
||||||
|
[[[[4,8],5],[[6,4],[2,3]]],[9,[[8,6],[4,0]]]]
|
||||||
|
[[1,[6,[1,9]]],[3,[[4,2],[1,8]]]]
|
||||||
|
[[[[3,7],[5,9]],[[3,8],[3,3]]],[[[7,8],3],[7,3]]]
|
||||||
|
[[[[0,4],5],[4,[9,0]]],[3,[[4,1],6]]]
|
||||||
|
[[[7,[2,1]],[[1,9],1]],[[[3,4],[8,6]],6]]
|
||||||
|
[[[4,1],[5,[8,2]]],[[[1,6],9],[[4,4],2]]]
|
||||||
|
[[[7,[6,4]],[[0,1],4]],[[5,2],[[9,5],[9,3]]]]
|
||||||
|
[[[4,2],[1,8]],2]
|
||||||
|
[[[1,6],5],[8,[2,[2,3]]]]
|
||||||
|
[[[[0,2],[5,0]],[7,[0,0]]],[[6,[5,9]],5]]
|
||||||
|
[[[7,6],[9,[2,4]]],[[5,[2,6]],2]]
|
||||||
|
[[[6,2],4],[[2,9],[[3,0],[4,3]]]]
|
||||||
|
[[8,[[6,4],[0,2]]],1]
|
||||||
|
[[[4,1],[7,5]],[9,[[2,4],4]]]
|
||||||
|
[[[[4,8],[7,5]],[1,[8,5]]],[[3,5],[[9,9],[4,2]]]]
|
||||||
|
[[[7,[8,4]],[4,[5,8]]],5]
|
||||||
|
[[7,9],[2,[[9,1],[7,1]]]]
|
||||||
|
[3,[[[5,8],[4,8]],[5,4]]]
|
||||||
|
[[[0,[5,5]],[[5,4],[5,4]]],[[9,6],[[9,4],[6,5]]]]
|
||||||
|
[[7,2],[1,[8,[1,7]]]]
|
||||||
|
[2,[9,[2,[2,3]]]]
|
||||||
|
[[[3,[5,1]],[8,[6,4]]],[[2,8],[[2,2],8]]]
|
||||||
|
[[[7,3],[0,4]],[[4,0],[6,[3,4]]]]
|
||||||
|
[[4,[2,[2,8]]],[4,[[7,1],9]]]
|
||||||
|
[[8,[[6,1],2]],[1,[[1,5],9]]]
|
||||||
|
[[0,[2,[9,4]]],[[[7,4],7],8]]
|
||||||
|
[[[2,[7,0]],5],[3,[4,4]]]
|
||||||
|
[[7,[4,[6,0]]],[[4,7],[[3,7],5]]]
|
||||||
|
[[2,[[8,0],[6,1]]],[[6,[6,1]],[3,9]]]
|
||||||
|
[[9,0],[[[3,7],0],[[5,8],4]]]
|
||||||
|
[6,[[[5,8],8],[3,[4,1]]]]
|
||||||
|
[[8,[[9,3],[8,4]]],[4,[8,2]]]
|
||||||
|
[[[[8,0],8],[3,7]],[[7,[4,3]],0]]
|
||||||
|
[[[7,[2,6]],[8,0]],[4,[[1,3],[4,1]]]]
|
||||||
|
[1,[[[4,9],[4,9]],[[7,0],[6,6]]]]
|
||||||
|
[9,4]
|
||||||
|
[[6,7],4]
|
||||||
|
[[2,[5,2]],[[2,4],[[4,6],[5,5]]]]
|
||||||
|
[[[5,2],[[5,5],[8,1]]],[[9,[1,6]],3]]
|
||||||
|
[[[[4,3],1],[8,9]],6]
|
||||||
|
[[[[3,2],[4,5]],4],[[[4,3],[0,0]],[[3,0],1]]]
|
||||||
|
[[6,7],[[8,5],[[7,2],4]]]
|
||||||
|
[[[[8,1],[5,8]],7],[[[5,2],[4,3]],1]]
|
||||||
|
[[2,[[4,9],5]],[1,1]]
|
||||||
|
[[9,1],[[[0,8],[1,8]],7]]
|
||||||
|
[[9,3],[6,4]]
|
||||||
|
[[8,[4,2]],[[7,[7,4]],[[0,9],[6,1]]]]
|
||||||
|
[[[[0,5],7],[[7,7],2]],[[2,[5,8]],[9,6]]]
|
||||||
|
[[[2,1],[7,[1,3]]],[[2,[7,1]],0]]
|
||||||
|
[[[8,[8,4]],[2,[4,3]]],[[2,[5,6]],[[2,0],[7,3]]]]
|
||||||
|
[[4,[[4,3],[5,2]]],[1,3]]
|
||||||
|
[[5,[5,0]],9]
|
||||||
|
[[[2,[7,6]],[1,8]],[[[5,2],2],0]]
|
||||||
|
[[2,[2,3]],[[9,8],[[0,1],[3,5]]]]
|
||||||
|
[[7,[[3,7],3]],[[[7,6],[4,8]],[[1,7],[8,6]]]]
|
||||||
|
[[[0,0],[[6,1],5]],[5,[5,4]]]
|
||||||
|
[[2,3],[4,[3,5]]]
|
||||||
|
[[8,[7,7]],[8,[4,[8,1]]]]
|
||||||
|
[[[[4,0],3],[[0,0],[0,0]]],[[[6,0],4],[[1,7],0]]]
|
||||||
|
[[[[6,4],[3,1]],[[2,8],[1,2]]],[4,[[6,5],4]]]
|
||||||
|
[[[[5,3],7],[4,[2,6]]],[[6,[4,5]],[1,[9,0]]]]
|
26
eighteen/main.go
Normal file
26
eighteen/main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package eighteen
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Eighteen struct {
|
||||||
|
snail snail
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(filepath string) *Eighteen {
|
||||||
|
eighteen := &Eighteen{
|
||||||
|
snail: snail{},
|
||||||
|
}
|
||||||
|
|
||||||
|
eighteen.snail.load(filepath)
|
||||||
|
return eighteen
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Eighteen) Answer() string {
|
||||||
|
sum := d.snail.sum()
|
||||||
|
|
||||||
|
return fmt.Sprintf("The magnitude of the final sum is %d", sum.magnitude())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Eighteen) FollowUp() string {
|
||||||
|
return fmt.Sprintf("The largest magnitude of any two snail numbers is %d", d.snail.largestMagnitude())
|
||||||
|
}
|
338
eighteen/snail.go
Normal file
338
eighteen/snail.go
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
package eighteen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type value struct {
|
||||||
|
p *pair
|
||||||
|
v int
|
||||||
|
}
|
||||||
|
|
||||||
|
type pair struct {
|
||||||
|
left value
|
||||||
|
right value
|
||||||
|
}
|
||||||
|
|
||||||
|
type snail struct {
|
||||||
|
input []value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snail) load(filename string) error {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
s.input = append(s.input, parse(scanner.Text()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snail) largestMagnitude() int {
|
||||||
|
max := 0
|
||||||
|
|
||||||
|
for i := 0; i < len(s.input) - 1; i++ {
|
||||||
|
for j := i + 1; j < len(s.input); j++ {
|
||||||
|
// i + j
|
||||||
|
sum1 := s.input[i].add(s.input[j])
|
||||||
|
mag := sum1.magnitude()
|
||||||
|
if mag > max {
|
||||||
|
max = mag
|
||||||
|
}
|
||||||
|
|
||||||
|
// j + i
|
||||||
|
sum2 := s.input[j].add(s.input[i])
|
||||||
|
mag = sum2.magnitude()
|
||||||
|
if mag > max {
|
||||||
|
max = mag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *snail) sum() value {
|
||||||
|
v := value{}
|
||||||
|
for i, n := range s.input {
|
||||||
|
if i == 0 {
|
||||||
|
v = n
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v = v.add(n)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *value) add(vb value) value {
|
||||||
|
sum := value{
|
||||||
|
p: &pair{
|
||||||
|
left: *v,
|
||||||
|
right: vb,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
reduced := sum.reduce()
|
||||||
|
for reduced != nil {
|
||||||
|
r := reduced.reduce()
|
||||||
|
if r == nil {
|
||||||
|
return *reduced
|
||||||
|
}
|
||||||
|
reduced = r
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *value) reduce() *value {
|
||||||
|
reduced := v.copy()
|
||||||
|
// Check for nests deeper than 4
|
||||||
|
if reduced.p != nil {
|
||||||
|
_, exploded, _, _ := reduced.p.explode(1)
|
||||||
|
if exploded {
|
||||||
|
return &reduced
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for values greater than 10
|
||||||
|
_, split := reduced.split()
|
||||||
|
if split {
|
||||||
|
return &reduced
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *value) magnitude() int {
|
||||||
|
if v.p == nil {
|
||||||
|
return v.v
|
||||||
|
}
|
||||||
|
|
||||||
|
return (3 * v.p.left.magnitude()) + (2 * v.p.right.magnitude())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pair) explode(depth int) (int, bool, bool, bool) {
|
||||||
|
if p == nil || (p.left.p == nil && p.right.p == nil) {
|
||||||
|
return 0, false, false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if depth == 4 {
|
||||||
|
if p.left.p != nil {
|
||||||
|
if p.right.p != nil {
|
||||||
|
p.right.p.increaseLeft(p.left.p.right.v, false)
|
||||||
|
} else {
|
||||||
|
p.right.v += p.left.p.right.v
|
||||||
|
}
|
||||||
|
rightVal := p.left.p.left.v
|
||||||
|
p.left.v = 0
|
||||||
|
p.left.p = nil
|
||||||
|
|
||||||
|
return rightVal, true, true, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.right.p != nil {
|
||||||
|
if p.left.p != nil {
|
||||||
|
p.left.p.increaseRight(p.right.p.left.v, false)
|
||||||
|
} else {
|
||||||
|
p.left.v += p.right.p.left.v
|
||||||
|
}
|
||||||
|
leftVal := p.right.p.right.v
|
||||||
|
p.right.v = 0
|
||||||
|
p.right.p = nil
|
||||||
|
|
||||||
|
return leftVal, true, false, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false, false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if left has nested pair
|
||||||
|
if p.left.p != nil {
|
||||||
|
offender, exploded, left, right := p.left.p.explode(depth + 1)
|
||||||
|
|
||||||
|
if exploded {
|
||||||
|
if right {
|
||||||
|
p.increaseRight(offender, false)
|
||||||
|
return offender, exploded, left, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return offender, exploded, left, right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if right has nested pair
|
||||||
|
if p.right.p != nil {
|
||||||
|
offender, exploded, left, right := p.right.p.explode(depth + 1)
|
||||||
|
|
||||||
|
if exploded {
|
||||||
|
if left {
|
||||||
|
p.increaseLeft(offender, false)
|
||||||
|
return 0, true, false, right
|
||||||
|
}
|
||||||
|
return offender, true, left, right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false, false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pair) increaseLeft(amount int, swapped bool) {
|
||||||
|
if p.left.p != nil {
|
||||||
|
if !swapped {
|
||||||
|
p.left.p.increaseRight(amount, true)
|
||||||
|
} else {
|
||||||
|
p.left.p.increaseLeft(amount, true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.left.v += amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pair) increaseRight(amount int, swapped bool) {
|
||||||
|
if p.right.p != nil {
|
||||||
|
if !swapped {
|
||||||
|
p.right.p.increaseLeft(amount, true)
|
||||||
|
} else {
|
||||||
|
p.right.p.increaseRight(amount, swapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.right.v += amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *value) split() (*pair, bool) {
|
||||||
|
if v.p == nil {
|
||||||
|
if v.v < 10 {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
left := v.v / 2
|
||||||
|
right := v.v / 2
|
||||||
|
if v.v%2 == 1 {
|
||||||
|
right++
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pair{
|
||||||
|
left: value{
|
||||||
|
v: left,
|
||||||
|
},
|
||||||
|
right: value{
|
||||||
|
v: right,
|
||||||
|
},
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check left
|
||||||
|
newPair, split := v.p.left.split()
|
||||||
|
if split {
|
||||||
|
if newPair != nil {
|
||||||
|
v.p.left.p = newPair
|
||||||
|
v.p.left.v = 0
|
||||||
|
}
|
||||||
|
return nil, split
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check left
|
||||||
|
newPair, split = v.p.right.split()
|
||||||
|
if split {
|
||||||
|
if newPair != nil {
|
||||||
|
v.p.right.p = newPair
|
||||||
|
v.p.right.v = 0
|
||||||
|
}
|
||||||
|
return nil, split
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pair) copy() *pair {
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pair{
|
||||||
|
left: p.left.copy(),
|
||||||
|
right: p.right.copy(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *value) copy() value {
|
||||||
|
return value{
|
||||||
|
p: v.p.copy(),
|
||||||
|
v: v.v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *value) print() string {
|
||||||
|
if v == nil {
|
||||||
|
return "No value to print"
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p == nil {
|
||||||
|
return fmt.Sprintf("%d", v.v)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := "["
|
||||||
|
s += v.p.left.print()
|
||||||
|
s += ","
|
||||||
|
s += v.p.right.print()
|
||||||
|
s += "]"
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(input string) value {
|
||||||
|
v := value{}
|
||||||
|
rawValue := ""
|
||||||
|
foundPair := false
|
||||||
|
bracketCount := 0
|
||||||
|
// Look for the comma in outermost pair
|
||||||
|
commaIndex := 0
|
||||||
|
for i, r := range input {
|
||||||
|
if bracketCount == 0 && r == '[' {
|
||||||
|
foundPair = true
|
||||||
|
rawValue = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r {
|
||||||
|
case '[':
|
||||||
|
bracketCount++
|
||||||
|
if bracketCount != 1 {
|
||||||
|
rawValue += string(r)
|
||||||
|
}
|
||||||
|
case ']':
|
||||||
|
bracketCount--
|
||||||
|
if bracketCount != 0 {
|
||||||
|
rawValue += string(r)
|
||||||
|
}
|
||||||
|
case ',':
|
||||||
|
if bracketCount == 1 {
|
||||||
|
commaIndex = i
|
||||||
|
}
|
||||||
|
rawValue += string(r)
|
||||||
|
default:
|
||||||
|
rawValue += string(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundPair {
|
||||||
|
v.p = &pair{
|
||||||
|
left: parse(rawValue[:commaIndex-1]),
|
||||||
|
right: parse(rawValue[commaIndex:]),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
number, err := strconv.Atoi(rawValue)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
v.v = number
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
339
eighteen/snail_test.go
Normal file
339
eighteen/snail_test.go
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
package eighteen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_read(t *testing.T) {
|
||||||
|
s := snail{}
|
||||||
|
if err := s.load("test_input.txt"); err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.input) != 10 {
|
||||||
|
t.Logf("Expected 10 inputs, found %d", len(s.input))
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_magnitude(t *testing.T) {
|
||||||
|
s := snail{}
|
||||||
|
s.load("test_input.txt")
|
||||||
|
|
||||||
|
sum := s.sum()
|
||||||
|
|
||||||
|
fmt.Println(sum.print())
|
||||||
|
mag := sum.magnitude()
|
||||||
|
|
||||||
|
if mag != 4140 {
|
||||||
|
t.Logf("Expected a magnitude of 4140, found %d", mag)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_magnitude2(t *testing.T) {
|
||||||
|
v := parse("[[[[0,7],4],[[7,8],[6,0]]],[8,1]]")
|
||||||
|
expected := 1384
|
||||||
|
|
||||||
|
mag := v.magnitude()
|
||||||
|
|
||||||
|
if mag != expected {
|
||||||
|
t.Logf("Expected magnitude %d, found %d", expected, mag)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_magnitude3(t *testing.T) {
|
||||||
|
v := parse("[[[[6,6],[7,6]],[[7,7],[7,0]]],[[[7,7],[7,7]],[[7,8],[9,9]]]]")
|
||||||
|
expected := 4140
|
||||||
|
|
||||||
|
mag := v.magnitude()
|
||||||
|
|
||||||
|
if mag != expected {
|
||||||
|
t.Logf("Expected magnitude %d, found %d", expected, mag)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_largestMagnitude(t *testing.T) {
|
||||||
|
s := snail{}
|
||||||
|
s.load("test_input.txt")
|
||||||
|
|
||||||
|
mag := s.largestMagnitude()
|
||||||
|
|
||||||
|
if mag != 3993 {
|
||||||
|
t.Logf("Expected largest magnitude of 3993, found %d", mag)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_sum(t *testing.T) {
|
||||||
|
s := snail{}
|
||||||
|
s.load("test_input2.txt")
|
||||||
|
|
||||||
|
sum := s.sum()
|
||||||
|
output := sum.print()
|
||||||
|
expected := "[[[[1,1],[2,2]],[3,3]],[4,4]]"
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Logf("Expected %q, found %q", expected, output)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_sum2(t *testing.T) {
|
||||||
|
s := snail{}
|
||||||
|
s.load("test_input3.txt")
|
||||||
|
|
||||||
|
sum := s.sum()
|
||||||
|
output := sum.print()
|
||||||
|
expected := "[[[[3,0],[5,3]],[4,4]],[5,5]]"
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Logf("Expected %q, found %q", expected, output)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_sum3(t *testing.T) {
|
||||||
|
s := snail{}
|
||||||
|
s.load("test_input4.txt")
|
||||||
|
|
||||||
|
sum := s.sum()
|
||||||
|
output := sum.print()
|
||||||
|
expected := "[[[[5,0],[7,4]],[5,5]],[6,6]]"
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Logf("Expected %q, found %q", expected, output)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_sum4(t *testing.T) {
|
||||||
|
s := snail{}
|
||||||
|
s.load("test_input5.txt")
|
||||||
|
|
||||||
|
sum := s.sum()
|
||||||
|
output := sum.print()
|
||||||
|
expected := "[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]"
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Logf("Expected %q, found %q", expected, output)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_sum5(t *testing.T) {
|
||||||
|
v1 := parse("[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]")
|
||||||
|
v2 := parse("[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]")
|
||||||
|
|
||||||
|
r := v1.add(v2)
|
||||||
|
expected := "[[[[4,0],[5,4]],[[7,7],[6,0]]],[[8,[7,7]],[[7,9],[5,0]]]]"
|
||||||
|
output := r.print()
|
||||||
|
|
||||||
|
if expected != output {
|
||||||
|
t.Logf("Expected %q, found %q", expected, output)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_reduce(t *testing.T) {
|
||||||
|
v := parse("[[[[[9,8],1],2],3],4]")
|
||||||
|
|
||||||
|
r := v.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r != nil {
|
||||||
|
t.Logf("Only expected a single reduction, found %s", r.print())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_reduce2(t *testing.T) {
|
||||||
|
v := parse("[7,[6,[5,[4,[3,2]]]]]")
|
||||||
|
|
||||||
|
r := v.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r != nil {
|
||||||
|
t.Logf("Only expected a single reduction, found %s", r.print())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_reduce3(t *testing.T) {
|
||||||
|
v := parse("[[6,[5,[4,[3,2]]]],1]")
|
||||||
|
|
||||||
|
r := v.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r != nil {
|
||||||
|
t.Logf("Only expected a single reduction, found %s", r.print())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_reduce4(t *testing.T) {
|
||||||
|
v := parse("[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]")
|
||||||
|
|
||||||
|
r := v.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r != nil {
|
||||||
|
t.Logf("Only expected two reductions, found %s", r.print())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_reduce5(t *testing.T) {
|
||||||
|
v := parse("[[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]]")
|
||||||
|
|
||||||
|
r := v.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r == nil {
|
||||||
|
t.Logf("Expected a reduction, didn't get one")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = r.reduce()
|
||||||
|
if r != nil {
|
||||||
|
t.Logf("Only expected five reductions, found %s", r.print())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_add(t *testing.T) {
|
||||||
|
first := parse("[1,2]")
|
||||||
|
second := parse("[[3,4],5]")
|
||||||
|
|
||||||
|
sum := first.add(second)
|
||||||
|
|
||||||
|
// Check that it equals [[1,2],[[3,4],5]]
|
||||||
|
if sum.p == nil || sum.p.left.p.left.v != 1 || sum.p.left.p.right.v != 2 {
|
||||||
|
t.Logf("Expected [1,2], found %s", sum.p.left.print())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that it equals [[1,2],[[3,4],5]]
|
||||||
|
if sum.p == nil || sum.p.right.p.right.v != 5 {
|
||||||
|
t.Logf("Expected [[3,4],5], found %s", sum.p.left.print())
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_parse(t *testing.T) {
|
||||||
|
s := "[1,2]"
|
||||||
|
|
||||||
|
v := parse(s)
|
||||||
|
if v.p == nil {
|
||||||
|
t.Logf("Expected a pair, found nothing")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p.left.v != 1 {
|
||||||
|
t.Logf("Expected 1, found %d", v.p.left.v)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p.right.v != 2 {
|
||||||
|
t.Logf("Expected 2, found %d", v.p.right.v)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_parse3(t *testing.T) {
|
||||||
|
s := "[9,[8,7]]"
|
||||||
|
|
||||||
|
v := parse(s)
|
||||||
|
if v.p == nil {
|
||||||
|
t.Logf("Expected a pair, found nothing")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p.right.p.left.v != 8 {
|
||||||
|
t.Logf("Expected 8, found %d", v.p.right.p.left.v)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p.right.p.right.v != 7 {
|
||||||
|
t.Logf("Expected 7, found %d", v.p.right.p.right.v)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p.left.v != 9 {
|
||||||
|
t.Logf("Expected 9, found %d", v.p.left.v)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_parse2(t *testing.T) {
|
||||||
|
s := "[[1,2],3]"
|
||||||
|
|
||||||
|
v := parse(s)
|
||||||
|
if v.p == nil {
|
||||||
|
t.Logf("Expected a pair, found nothing")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p.left.p.left.v != 1 {
|
||||||
|
t.Logf("Expected 1, found %d", v.p.left.p.left.v)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p.left.p.right.v != 2 {
|
||||||
|
t.Logf("Expected 2, found %d", v.p.left.p.right.v)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.p.right.v != 3 {
|
||||||
|
t.Logf("Expected 3, found %d", v.p.right.v)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
10
eighteen/test_input.txt
Normal file
10
eighteen/test_input.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
|
||||||
|
[[[5,[2,8]],4],[5,[[9,9],0]]]
|
||||||
|
[6,[[[6,2],[5,6]],[[7,6],[4,7]]]]
|
||||||
|
[[[6,[0,7]],[0,9]],[4,[9,[9,0]]]]
|
||||||
|
[[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]]
|
||||||
|
[[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]]
|
||||||
|
[[[[5,4],[7,7]],8],[[8,3],8]]
|
||||||
|
[[9,3],[[9,9],[6,[4,9]]]]
|
||||||
|
[[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]]
|
||||||
|
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]
|
4
eighteen/test_input2.txt
Normal file
4
eighteen/test_input2.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[1,1]
|
||||||
|
[2,2]
|
||||||
|
[3,3]
|
||||||
|
[4,4]
|
5
eighteen/test_input3.txt
Normal file
5
eighteen/test_input3.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[1,1]
|
||||||
|
[2,2]
|
||||||
|
[3,3]
|
||||||
|
[4,4]
|
||||||
|
[5,5]
|
6
eighteen/test_input4.txt
Normal file
6
eighteen/test_input4.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[1,1]
|
||||||
|
[2,2]
|
||||||
|
[3,3]
|
||||||
|
[4,4]
|
||||||
|
[5,5]
|
||||||
|
[6,6]
|
10
eighteen/test_input5.txt
Normal file
10
eighteen/test_input5.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]
|
||||||
|
[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]
|
||||||
|
[[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]]
|
||||||
|
[[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]]
|
||||||
|
[7,[5,[[3,8],[1,4]]]]
|
||||||
|
[[2,[2,2]],[8,[8,1]]]
|
||||||
|
[2,9]
|
||||||
|
[1,[[[9,3],9],[[9,0],[0,7]]]]
|
||||||
|
[[[5,[7,4]],7],1]
|
||||||
|
[[[[4,2],2],6],[8,7]]
|
3
main.go
3
main.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"unsupervised.ca/aoc2021/eight"
|
"unsupervised.ca/aoc2021/eight"
|
||||||
|
"unsupervised.ca/aoc2021/eighteen"
|
||||||
"unsupervised.ca/aoc2021/eleven"
|
"unsupervised.ca/aoc2021/eleven"
|
||||||
"unsupervised.ca/aoc2021/fifteen"
|
"unsupervised.ca/aoc2021/fifteen"
|
||||||
"unsupervised.ca/aoc2021/five"
|
"unsupervised.ca/aoc2021/five"
|
||||||
@@ -73,6 +74,8 @@ func main() {
|
|||||||
day = sixteen.Init("sixteen/input.txt")
|
day = sixteen.Init("sixteen/input.txt")
|
||||||
case "seventeen":
|
case "seventeen":
|
||||||
day = seventeen.Init("seventeen/input.txt")
|
day = seventeen.Init("seventeen/input.txt")
|
||||||
|
case "eighteen":
|
||||||
|
day = eighteen.Init("eighteen/input.txt")
|
||||||
default:
|
default:
|
||||||
fmt.Printf("%q does not have a solution.\n", flagParts[1])
|
fmt.Printf("%q does not have a solution.\n", flagParts[1])
|
||||||
help()
|
help()
|
||||||
|
Reference in New Issue
Block a user