2021 - Day 18
This commit is contained in:
parent
3abd4fa783
commit
742c215867
9
2021/18/go.mod
Normal file
9
2021/18/go.mod
Normal file
|
@ -0,0 +1,9 @@
|
|||
module AoC/2021/18
|
||||
|
||||
require AoC/2021/common v0.0.0
|
||||
|
||||
require github.com/joho/godotenv v1.4.0 // indirect
|
||||
|
||||
replace AoC/2021/common v0.0.0 => ../common
|
||||
|
||||
go 1.17
|
2
2021/18/go.sum
Normal file
2
2021/18/go.sum
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
290
2021/18/main.go
Normal file
290
2021/18/main.go
Normal file
|
@ -0,0 +1,290 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
aoc "AoC/2021/common"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type snailNumber struct {
|
||||
child [2]*snailNumber
|
||||
value [2]int
|
||||
|
||||
parent *snailNumber
|
||||
}
|
||||
|
||||
func (s *snailNumber) print() {
|
||||
depth := s.depth()
|
||||
for i := 0; i < depth-1; i++ {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
fmt.Printf("%d[\n", depth)
|
||||
|
||||
if s.child[0] == nil {
|
||||
for i := 0; i < depth; i++ {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
fmt.Printf("%d", s.value[0])
|
||||
} else {
|
||||
s.child[0].print()
|
||||
}
|
||||
fmt.Print("\n")
|
||||
if s.child[1] == nil {
|
||||
for i := 0; i < depth; i++ {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
fmt.Printf("%d", s.value[1])
|
||||
} else {
|
||||
s.child[1].print()
|
||||
}
|
||||
|
||||
fmt.Print("\n")
|
||||
for i := 0; i < depth-1; i++ {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
fmt.Print("]")
|
||||
|
||||
// We have reached the top level
|
||||
if s.parent == nil {
|
||||
fmt.Print("\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *snailNumber) depth() int {
|
||||
depth := 1
|
||||
{
|
||||
number := s
|
||||
for number.parent != nil {
|
||||
number = number.parent
|
||||
depth++
|
||||
}
|
||||
}
|
||||
|
||||
return depth
|
||||
}
|
||||
|
||||
func (s *snailNumber) explode() bool {
|
||||
depth := s.depth()
|
||||
|
||||
// Check if the number needs to explode
|
||||
if depth > 4 {
|
||||
// Set this entry in the paren to 0
|
||||
side := -1
|
||||
for i := 0; i < 2; i++ {
|
||||
if s.parent.child[i] == s {
|
||||
s.parent.child[i] = nil
|
||||
s.parent.value[i] = 0
|
||||
side = i
|
||||
}
|
||||
}
|
||||
|
||||
// We know that there is atleat one parent since we are >4 deep
|
||||
if s.parent.child[1-side] == nil {
|
||||
s.parent.value[1-side] += s.value[1-side]
|
||||
} else {
|
||||
num := s.parent.child[1-side]
|
||||
for true {
|
||||
if num.child[side] == nil {
|
||||
num.value[side] += s.value[1-side]
|
||||
break
|
||||
}
|
||||
num = num.child[side]
|
||||
}
|
||||
}
|
||||
|
||||
num := s.parent
|
||||
for true {
|
||||
if num.parent == nil {
|
||||
break
|
||||
}
|
||||
|
||||
ps := -1
|
||||
for i := 0; i < 2; i++ {
|
||||
if num.parent.child[i] == num {
|
||||
ps = i
|
||||
}
|
||||
}
|
||||
|
||||
if ps == 1-side {
|
||||
num = num.parent
|
||||
|
||||
if num.child[side] == nil {
|
||||
num.value[side] += s.value[side]
|
||||
} else {
|
||||
num := num.child[side]
|
||||
for true {
|
||||
if num.child[1-side] == nil {
|
||||
num.value[1-side] += s.value[side]
|
||||
break
|
||||
}
|
||||
num = num.child[1-side]
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
num = num.parent
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
if s.child[i] != nil {
|
||||
if s.child[i].explode() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *snailNumber) split() bool {
|
||||
for i := 0; i < 2; i++ {
|
||||
if s.child[i] == nil {
|
||||
if s.value[i] > 9 {
|
||||
lhs := math.Floor(float64(s.value[i]) / 2)
|
||||
rhs := math.Ceil(float64(s.value[i]) / 2)
|
||||
s.value[i] = 0
|
||||
s.child[i] = &snailNumber{value: [2]int{int(lhs), int(rhs)}, parent: s}
|
||||
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if s.child[i].split() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *snailNumber) magnitude() int {
|
||||
var partial [2]int
|
||||
for i := 0; i < 2; i++ {
|
||||
if s.child[i] == nil {
|
||||
partial[i] = s.value[i]
|
||||
} else {
|
||||
partial[i] = s.child[i].magnitude()
|
||||
}
|
||||
}
|
||||
|
||||
return 3 * partial[0] + 2 * partial[1]
|
||||
}
|
||||
|
||||
func (s *snailNumber) reduce() {
|
||||
for true {
|
||||
if s.explode() {
|
||||
// fmt.Println("After explode: "); top.print()
|
||||
continue
|
||||
}
|
||||
|
||||
if s.split() {
|
||||
// fmt.Println("After split: "); top.print()
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func add(a *snailNumber, b *snailNumber) *snailNumber {
|
||||
top := &snailNumber{}
|
||||
|
||||
top.child[0] = a
|
||||
a.parent = top
|
||||
|
||||
top.child[1] = b
|
||||
b.parent = top
|
||||
|
||||
top.reduce()
|
||||
|
||||
return top
|
||||
}
|
||||
|
||||
func parseSnailNumber(line string) *snailNumber {
|
||||
var top snailNumber
|
||||
number := &top
|
||||
side := 0
|
||||
for _, c := range line {
|
||||
switch c {
|
||||
case '[':
|
||||
number.child[side] = &snailNumber{parent: number}
|
||||
number = number.child[side]
|
||||
side = 0
|
||||
case ']':
|
||||
number = number.parent
|
||||
case ',':
|
||||
side = 1
|
||||
default:
|
||||
value, _ := strconv.Atoi(string(c))
|
||||
number.value[side] = value
|
||||
}
|
||||
}
|
||||
|
||||
top.child[0].parent = nil
|
||||
|
||||
top.child[0].reduce()
|
||||
|
||||
return top.child[0]
|
||||
}
|
||||
|
||||
func main() {
|
||||
challenge := aoc.New(2021, 18)
|
||||
|
||||
challenge.Test(`[[[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]]]`, []int{4140, 3993})
|
||||
|
||||
challenge.Solution(1, func (input *bufio.Scanner) int {
|
||||
var top *snailNumber
|
||||
for input.Scan() {
|
||||
line := input.Text()
|
||||
num := parseSnailNumber(line)
|
||||
|
||||
if top == nil {
|
||||
top = num
|
||||
} else {
|
||||
top = add(top, num)
|
||||
}
|
||||
}
|
||||
|
||||
return top.magnitude()
|
||||
})
|
||||
|
||||
challenge.Solution(2, func (input *bufio.Scanner) int {
|
||||
var lines []string
|
||||
for input.Scan() {
|
||||
lines = append(lines, input.Text())
|
||||
|
||||
}
|
||||
|
||||
largest := 0
|
||||
for _, li := range lines {
|
||||
for _, lj := range lines {
|
||||
if li != lj {
|
||||
numi := parseSnailNumber(li)
|
||||
numj := parseSnailNumber(lj)
|
||||
|
||||
magnitude := add(numi, numj).magnitude()
|
||||
if magnitude > largest {
|
||||
largest = magnitude
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return largest
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user