281 lines
5.6 KiB
Go
281 lines
5.6 KiB
Go
package main
|
|
|
|
import (
|
|
"AOC2022/helper"
|
|
"fmt"
|
|
"reflect"
|
|
"sort"
|
|
"strconv"
|
|
)
|
|
|
|
type Packet struct {
|
|
value int
|
|
values []Packet
|
|
}
|
|
|
|
func main() {
|
|
//args := os.Args[1:]
|
|
lines := helper.ReadTextFile("day13/input")
|
|
//part1(lines)
|
|
decodePacket2 := parse("[[2]]")
|
|
decodePacket6 := parse("[[6]]")
|
|
packets := []Packet{}
|
|
for i := 0; i < len(lines); i += 3 {
|
|
packets = append(packets, parse(lines[i]))
|
|
packets = append(packets, parse(lines[i+1]))
|
|
}
|
|
packets = append(packets, decodePacket2)
|
|
packets = append(packets, decodePacket6)
|
|
sort.Slice(packets, func(i, j int) bool {
|
|
result := compare(packets[i], packets[j])
|
|
if result == 0 {
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
result := 1
|
|
for i, packet := range packets {
|
|
if reflect.DeepEqual(packet, decodePacket2) {
|
|
result *= i + 1
|
|
fmt.Println(2)
|
|
fmt.Println(i + 1)
|
|
}
|
|
if reflect.DeepEqual(packet, decodePacket6) {
|
|
result *= i + 1
|
|
fmt.Println(6)
|
|
fmt.Println(i + 1)
|
|
}
|
|
}
|
|
fmt.Println(result)
|
|
|
|
}
|
|
|
|
func part1(lines []string) {
|
|
index := 1
|
|
result := 0
|
|
for i := 0; i < len(lines); i += 3 {
|
|
left := parse(lines[i][1 : len(lines[i])-1])
|
|
right := parse(lines[i+1][1 : len(lines[i+1])-1])
|
|
if compare(left, right) == 0 {
|
|
fmt.Println(index)
|
|
result += index
|
|
}
|
|
index++
|
|
}
|
|
fmt.Println(result)
|
|
}
|
|
|
|
// 2 same
|
|
// 1 left higher
|
|
// 0 left lower
|
|
func compare(left, right Packet) int {
|
|
if left.value != -1 && right.value != -1 {
|
|
if left.value < right.value {
|
|
return 0
|
|
}
|
|
if left.value > right.value {
|
|
return 1
|
|
}
|
|
if left.value == right.value {
|
|
return 2
|
|
}
|
|
}
|
|
if left.value == -1 && right.value == -1 {
|
|
for i := 0; i < len(left.values); i++ {
|
|
if !(i < len(right.values)) {
|
|
return 1
|
|
}
|
|
result := compare(left.values[i], right.values[i])
|
|
if result == 0 {
|
|
return 0
|
|
}
|
|
|
|
if result == 1 {
|
|
return 1
|
|
}
|
|
}
|
|
if len(right.values) > len(left.values) {
|
|
return 0
|
|
}
|
|
return 2
|
|
}
|
|
if left.value != -1 {
|
|
result := compare(Packet{value: -1, values: []Packet{{value: left.value, values: []Packet{}}}}, right)
|
|
if result == 0 {
|
|
return 0
|
|
}
|
|
|
|
if result == 1 {
|
|
return 1
|
|
}
|
|
|
|
}
|
|
if right.value != -1 {
|
|
result := compare(left, Packet{value: -1, values: []Packet{{value: right.value, values: []Packet{}}}})
|
|
|
|
if result == 0 {
|
|
return 0
|
|
}
|
|
|
|
if result == 1 {
|
|
return 1
|
|
}
|
|
}
|
|
return 2
|
|
}
|
|
|
|
func parse(input string) Packet {
|
|
packet := Packet{-1, []Packet{}}
|
|
for i := 0; i < len(input); {
|
|
switch input[i] {
|
|
case '[':
|
|
endOfCurrentArray := getEndofCurrentArray(input[1:], i)
|
|
currentArray := input[i+1 : endOfCurrentArray]
|
|
packet.values = append(packet.values, parse(currentArray))
|
|
i = endOfCurrentArray + 1
|
|
case ',':
|
|
i++
|
|
default:
|
|
endOfCurrentValue := getEndofCurrentValue(input, i)
|
|
currentValue := helper.RemoveError(strconv.Atoi(input[i:endOfCurrentValue]))
|
|
packet.values = append(packet.values, Packet{value: currentValue, values: []Packet{}})
|
|
i = endOfCurrentValue + 1
|
|
}
|
|
}
|
|
|
|
return packet
|
|
}
|
|
|
|
// 0 Right Order
|
|
//-1 Left Value too high
|
|
//-2 Right had no values left
|
|
func comparePair(left string, right string) int {
|
|
lefIndex := 0
|
|
rightIndex := 0
|
|
currentElemLeft := 0
|
|
currentElemRight := 0
|
|
leftElementType := 0
|
|
rightElementType := 0
|
|
for lefIndex < len(left)-1 {
|
|
lefIndex, leftElementType = getNextElement(left, lefIndex)
|
|
rightIndex, rightElementType = getNextElement(right, rightIndex)
|
|
if leftElementType == -1 {
|
|
return 0
|
|
}
|
|
if leftElementType == -2 {
|
|
for rightElementType != -2 && rightElementType != 0 {
|
|
rightIndex, rightElementType = getNextElement(right, rightIndex)
|
|
if rightElementType == -1 {
|
|
return -2
|
|
}
|
|
}
|
|
if rightElementType == 0 {
|
|
for leftElementType != 0 {
|
|
lefIndex, leftElementType = getNextElement(left, lefIndex)
|
|
if leftElementType == -1 || leftElementType == -3 {
|
|
return -2
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if leftElementType == -3 {
|
|
rightIndex = getEndofCurrentArray(right, rightIndex)
|
|
rightElementType = -3
|
|
}
|
|
if leftElementType == 0 {
|
|
for rightElementType != 0 {
|
|
rightIndex, rightElementType = getNextElement(right, rightIndex)
|
|
if rightElementType == -1 || rightElementType == -3 {
|
|
return -2
|
|
}
|
|
}
|
|
currentElemLeft, lefIndex = readElement(left, lefIndex)
|
|
currentElemRight, rightIndex = readElement(right, rightIndex)
|
|
if currentElemLeft > currentElemRight {
|
|
return -1
|
|
}
|
|
if currentElemLeft < currentElemRight {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// 0 Element
|
|
//-1 End Packet
|
|
//-2 Start Array
|
|
//-3 End Array
|
|
//-4 Seperator
|
|
func getNextElement(packet string, currentIndex int) (int, int) {
|
|
index := currentIndex + 1
|
|
for index < len(packet) {
|
|
switch packet[index] {
|
|
case ',':
|
|
return index, -4
|
|
break
|
|
case '[':
|
|
return index, -2
|
|
break
|
|
case ']':
|
|
if index < len(packet)-1 {
|
|
return index, -3
|
|
} else {
|
|
index++
|
|
}
|
|
break
|
|
default:
|
|
return index, 0
|
|
}
|
|
}
|
|
return index, -1
|
|
}
|
|
|
|
func getEndofCurrentArray(packet string, currentIndex int) int {
|
|
index := currentIndex
|
|
openedArrays := 1
|
|
for openedArrays > 0 && index < len(packet) {
|
|
switch packet[index] {
|
|
case ']':
|
|
openedArrays--
|
|
case '[':
|
|
openedArrays++
|
|
}
|
|
index++
|
|
}
|
|
if openedArrays == 0 {
|
|
return index
|
|
} else {
|
|
return -1
|
|
}
|
|
}
|
|
|
|
func getEndofCurrentValue(packet string, currentIndex int) int {
|
|
index := currentIndex
|
|
for index < len(packet) {
|
|
if packet[index] == ',' {
|
|
return index
|
|
}
|
|
index++
|
|
}
|
|
return index
|
|
}
|
|
|
|
func readElement(packet string, currentIndex int) (element, newIndex int) {
|
|
index := currentIndex
|
|
newIndex = 0
|
|
for newIndex == 0 {
|
|
switch packet[index] {
|
|
case ',':
|
|
newIndex = index
|
|
break
|
|
case ']':
|
|
newIndex = index
|
|
break
|
|
default:
|
|
index++
|
|
}
|
|
}
|
|
return helper.RemoveError(strconv.Atoi(packet[currentIndex:newIndex])), newIndex - 1
|
|
}
|