2021-12-18 19:07:09 +01:00
package main
import (
"AOC2021/src/helper"
"fmt"
"os"
2021-12-18 22:41:52 +01:00
"strings"
2021-12-18 19:07:09 +01:00
)
type snailNumber struct {
pair [ 2 ] * snailNumber
val int
nested int
}
func main ( ) {
args := os . Args [ 1 : ]
input , err := helper . GetInput ( args [ 0 ] )
if err != nil {
fmt . Println ( err )
}
var snailNumberArray [ ] snailNumber
for _ , row := range input {
number , _ := parseSnailNumber ( row [ 1 : ] , 0 )
snailNumberArray = append ( snailNumberArray , number )
}
2021-12-18 22:41:52 +01:00
fmt . Println ( part1 ( input ) )
2021-12-18 19:07:09 +01:00
2021-12-18 22:41:52 +01:00
max := 0
for i , _ := range input {
for j , _ := range input {
if i != j {
tmpResult := part1 ( [ ] string { input [ i ] , input [ j ] } )
if max < tmpResult {
max = tmpResult
}
}
}
}
fmt . Println ( max )
}
func part1 ( input [ ] string ) int {
currentNumber := replaceBracketsWithParenthesis ( input [ 0 ] )
for i := 1 ; i < len ( input ) ; i ++ {
currentNumber = addSnailNumberStrings ( currentNumber , replaceBracketsWithParenthesis ( input [ i ] ) )
currentNumber = doAll ( currentNumber )
}
reduce := true
testString := magicMagic ( currentNumber )
for reduce {
testString , reduce = reduceNumber ( testString )
}
return testString [ 0 ]
}
func reduceNumber ( snailNumber [ ] int ) ( [ ] int , bool ) {
index := 0
for index < len ( snailNumber ) - 2 {
if snailNumber [ index ] > - 1 && snailNumber [ index + 2 ] > - 1 {
tmpIntLeft := snailNumber [ index ]
tmpIntRight := snailNumber [ index + 2 ]
tmpInt := 3 * tmpIntLeft + 2 * tmpIntRight
returnArray := append ( snailNumber [ : index ] , snailNumber [ index + 4 : ] ... )
returnArray [ index - 1 ] = tmpInt
return returnArray , true
}
index ++
}
return snailNumber , false
}
func magicMagic ( number string ) [ ] int {
returnArray := [ ] int { }
for _ , char := range number {
switch char {
case ',' :
returnArray = append ( returnArray , - 2 )
case '(' :
returnArray = append ( returnArray , - 1 )
case ')' :
returnArray = append ( returnArray , - 3 )
default :
returnArray = append ( returnArray , int ( char - '0' ) )
}
}
return returnArray
}
func replaceBracketsWithParenthesis ( input string ) string {
input = strings . Replace ( input , "]" , ")" , - 1 )
input = strings . Replace ( input , "[" , "(" , - 1 )
return input
}
func doAll ( currentNumber string ) string {
run := true
for run {
exploded := true
splitted := false
for exploded {
currentNumber , exploded = checkExplode ( currentNumber )
}
currentNumber , splitted = checkSplit ( currentNumber )
run = splitted || exploded
}
return currentNumber
2021-12-18 19:07:09 +01:00
}
func addSnailNumberStrings ( left string , right string ) string {
2021-12-18 22:41:52 +01:00
return "(" + left + "," + right + ")"
2021-12-18 19:07:09 +01:00
}
func checkExplode ( snailNumberString string ) ( string , bool ) {
index := 0
openBracketCounter := 0
for index < len ( snailNumberString ) {
char := snailNumberString [ index ]
index ++
2021-12-18 22:41:52 +01:00
if char == '(' {
2021-12-18 19:07:09 +01:00
openBracketCounter ++
}
2021-12-18 22:41:52 +01:00
if char == ')' {
2021-12-18 19:07:09 +01:00
openBracketCounter --
}
if runeIsNumber ( rune ( char ) ) && openBracketCounter >= 5 {
return explode ( snailNumberString , index ) , true
}
}
return snailNumberString , false
}
2021-12-18 22:41:52 +01:00
func checkSplit ( snailNumberString string ) ( string , bool ) {
index := 0
for index < len ( snailNumberString ) {
if runeIsNumberOver9 ( rune ( snailNumberString [ index ] ) ) {
tmpInt := snailNumberString [ index ] - '0'
insertNewPair ( tmpInt , & snailNumberString , index )
return snailNumberString , true
}
index ++
}
return snailNumberString , false
}
2021-12-18 19:07:09 +01:00
func explode ( snailNumberString string , location int ) string {
2021-12-18 22:41:52 +01:00
returnString := snailNumberString [ : location - 2 ] + "0" + snailNumberString [ location + 3 : ]
2021-12-18 19:07:09 +01:00
addedLeft := false
2021-12-18 22:41:52 +01:00
index := location - 3
for index > 0 && ! addedLeft {
if runeIsNumber ( rune ( returnString [ index ] ) ) {
2021-12-18 19:07:09 +01:00
tmpRuneArray := [ ] rune ( returnString )
2021-12-18 22:41:52 +01:00
tmpInt := snailNumberString [ location - 1 ] - '0' + returnString [ index ] - '0'
tmpRuneArray [ index ] = rune ( tmpInt + '0' )
2021-12-18 19:07:09 +01:00
returnString = string ( tmpRuneArray )
2021-12-18 22:41:52 +01:00
index = location
2021-12-18 19:07:09 +01:00
addedLeft = true
}
index --
2021-12-18 22:41:52 +01:00
}
if index == 0 {
index = location - 1
2021-12-18 19:07:09 +01:00
}
addedRight := false
2021-12-18 22:41:52 +01:00
for ! addedRight && index < len ( returnString ) {
if runeIsNumber ( rune ( returnString [ index ] ) ) {
2021-12-18 19:07:09 +01:00
tmpRuneArray := [ ] rune ( returnString )
2021-12-18 22:41:52 +01:00
tmpInt := snailNumberString [ location + 1 ] - '0' + returnString [ index ] - '0'
tmpRuneArray [ index ] = rune ( tmpInt + '0' )
2021-12-18 19:07:09 +01:00
returnString = string ( tmpRuneArray )
addedRight = true
}
index ++
}
return returnString
}
2021-12-18 22:41:52 +01:00
func insertNewPair ( tmpInt uint8 , returnString * string , index int ) {
tmpNumberLeft := tmpInt / 2
tmpNumberRight := tmpNumberLeft + ( tmpInt % 2 )
tmpNewPairString := string ( [ ] rune { '(' , rune ( tmpNumberLeft ) + '0' , ',' , rune ( tmpNumberRight ) + '0' , ')' } )
* returnString = ( * returnString ) [ : index ] + tmpNewPairString + ( * returnString ) [ index + 1 : ]
}
2021-12-18 19:07:09 +01:00
func parseSnailNumber ( input string , nested int ) ( number snailNumber , index int ) {
index = 0
number . nested = nested
currentPairToFill := & number . pair [ 0 ]
for index < len ( input ) {
char := input [ index ]
index ++
if char == '[' {
tmpNumber , tmpIndex := parseSnailNumber ( input [ index : ] , nested + 1 )
index += tmpIndex
* currentPairToFill = & tmpNumber
}
if char == ',' {
currentPairToFill = & number . pair [ 1 ]
}
if runeIsNumber ( rune ( char ) ) {
( * currentPairToFill ) = & snailNumber { [ 2 ] * snailNumber { } , int ( char - '0' ) , nested + 1 }
}
if char == ']' {
return
}
}
return
}
func runeIsNumber ( char rune ) bool {
2021-12-18 22:41:52 +01:00
return char != 44 && char != 40 && char != 41
}
func runeIsNumberOver9 ( char rune ) bool {
return char != 44 && char != 40 && char != 41 && char > 57
2021-12-18 19:07:09 +01:00
}