diff --git a/src/day16/day16.go b/src/day16/day16.go new file mode 100644 index 0000000..585ee13 --- /dev/null +++ b/src/day16/day16.go @@ -0,0 +1,172 @@ +package main + +import ( + "fmt" + "os" + "strconv" + "strings" +) + +type packageStruct struct { + version int64 + typeID int64 + operator string + value int64 + subPackages []packageStruct +} + +func main() { + args := os.Args[1:] + input := args[0] + binaryNumberString := parseHexToBit(input) + pack, _ := parsePackage(binaryNumberString) + fmt.Println(pack) + sum := int64(0) + sumVers(pack, &sum) + fmt.Println(sum) + fmt.Println(calculatePart2(pack)) +} + +func calculatePart2(pack packageStruct) int64 { + switch pack.typeID { + case 0: + sum := int64(0) + for _, p := range pack.subPackages { + sum += calculatePart2(p) + } + return sum + case 1: + sum := int64(1) + for _, p := range pack.subPackages { + sum *= calculatePart2(p) + } + return sum + case 2: + min := calculatePart2(pack.subPackages[0]) + for _, p := range pack.subPackages { + valueOfSubPackage := calculatePart2(p) + if min > valueOfSubPackage { + min = valueOfSubPackage + } + } + return min + case 3: + max := calculatePart2(pack.subPackages[0]) + for _, p := range pack.subPackages { + valueOfSubPackage := calculatePart2(p) + if max < valueOfSubPackage { + max = valueOfSubPackage + } + } + return max + case 5: + if calculatePart2(pack.subPackages[0]) > calculatePart2(pack.subPackages[1]) { + return 1 + } else { + return 0 + } + case 6: + if calculatePart2(pack.subPackages[0]) < calculatePart2(pack.subPackages[1]) { + return 1 + } else { + return 0 + } + case 7: + if calculatePart2(pack.subPackages[0]) == calculatePart2(pack.subPackages[1]) { + return 1 + } else { + return 0 + } + default: + return pack.value + } +} + +func sumVers(pack packageStruct, sum *int64) { + *sum += pack.version + for _, p := range pack.subPackages { + sumVers(p, sum) + } +} + +func parseHexToBit(hex string) string { + returnString := "" + for _, char := range hex { + number, _ := strconv.ParseInt(string(char), 16, 0) + returnString += padBinaryNumber(strconv.FormatInt(number, 2)) + } + return returnString +} + +func padBinaryNumber(binaryNumberString string) string { + if (len(binaryNumberString) % 4) > 0 { + amountPaddingZeros := 4 - (len(binaryNumberString) % 4) + binaryNumberString = strings.Repeat("0", amountPaddingZeros) + binaryNumberString + } + return binaryNumberString +} + +func parsePackage(binaryNumberString string) (pack packageStruct, index int64) { + index = 0 + pack.version, _ = strconv.ParseInt(binaryNumberString[:3], 2, 0) + pack.typeID, _ = strconv.ParseInt(binaryNumberString[3:6], 2, 0) + index += 6 + if pack.typeID == 4 { + indexAdd := int64(0) + pack.value, indexAdd = parseLiteralValue(binaryNumberString[6:]) + index += indexAdd + return + } + subPackages, indexAdd := parseOperator(binaryNumberString[6:]) + pack.subPackages = subPackages + index += indexAdd + return +} + +func parseLiteralValue(packageString string) (value int64, index int64) { + index = 0 + number := "" + for { + number += packageString[index+1 : index+5] + if packageString[index] == '0' { + value, _ = strconv.ParseInt(number, 2, 0) + index += 5 + return + } + index += 5 + } +} + +func parseOperator(packageString string) (packs []packageStruct, index int64) { + index = 1 + lengthTypeID := packageString[0] + if lengthTypeID == '0' { + lengthSubPackets, _ := strconv.ParseInt(packageString[index+1:index+15], 2, 0) + index += 15 + subPackageBinary := packageString[index : index+lengthSubPackets] + subPackageIndex := int64(0) + for subPackageIndex < lengthSubPackets { + pack, i := parsePackage(subPackageBinary[subPackageIndex:]) + packs = append(packs, pack) + subPackageIndex += i + } + index += lengthSubPackets + return + } + if lengthTypeID == '1' { + neededSubPackets, _ := strconv.ParseInt(packageString[index+1:index+11], 2, 0) + index += 11 + subPackageBinary := packageString[index:] + subPackageIndex := int64(0) + countSubPackets := int64(0) + for countSubPackets < neededSubPackets { + pack, i := parsePackage(subPackageBinary[subPackageIndex:]) + packs = append(packs, pack) + subPackageIndex += i + countSubPackets++ + } + index += subPackageIndex + return + } + return +}