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 }