217 lines
5.2 KiB
Go
217 lines
5.2 KiB
Go
package main
|
|
|
|
import (
|
|
"AOC2021/src/helper"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
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)
|
|
}
|
|
fmt.Println(part1(input))
|
|
|
|
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
|
|
}
|
|
|
|
func addSnailNumberStrings(left string, right string) string {
|
|
return "(" + left + "," + right + ")"
|
|
}
|
|
|
|
func checkExplode(snailNumberString string) (string, bool) {
|
|
index := 0
|
|
openBracketCounter := 0
|
|
for index < len(snailNumberString) {
|
|
char := snailNumberString[index]
|
|
index++
|
|
if char == '(' {
|
|
openBracketCounter++
|
|
}
|
|
if char == ')' {
|
|
openBracketCounter--
|
|
}
|
|
if runeIsNumber(rune(char)) && openBracketCounter >= 5 {
|
|
return explode(snailNumberString, index), true
|
|
}
|
|
}
|
|
return snailNumberString, false
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func explode(snailNumberString string, location int) string {
|
|
returnString := snailNumberString[:location-2] + "0" + snailNumberString[location+3:]
|
|
addedLeft := false
|
|
index := location - 3
|
|
for index > 0 && !addedLeft {
|
|
if runeIsNumber(rune(returnString[index])) {
|
|
tmpRuneArray := []rune(returnString)
|
|
tmpInt := snailNumberString[location-1] - '0' + returnString[index] - '0'
|
|
tmpRuneArray[index] = rune(tmpInt + '0')
|
|
returnString = string(tmpRuneArray)
|
|
index = location
|
|
addedLeft = true
|
|
}
|
|
index--
|
|
}
|
|
if index == 0 {
|
|
index = location - 1
|
|
}
|
|
addedRight := false
|
|
for !addedRight && index < len(returnString) {
|
|
if runeIsNumber(rune(returnString[index])) {
|
|
tmpRuneArray := []rune(returnString)
|
|
tmpInt := snailNumberString[location+1] - '0' + returnString[index] - '0'
|
|
tmpRuneArray[index] = rune(tmpInt + '0')
|
|
returnString = string(tmpRuneArray)
|
|
addedRight = true
|
|
}
|
|
index++
|
|
}
|
|
return returnString
|
|
}
|
|
|
|
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:]
|
|
}
|
|
|
|
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 {
|
|
return char != 44 && char != 40 && char != 41
|
|
}
|
|
|
|
func runeIsNumberOver9(char rune) bool {
|
|
return char != 44 && char != 40 && char != 41 && char > 57
|
|
}
|