AoC2021/src/day18/day18.go
2021-12-18 22:41:52 +01:00

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
}