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 }