package main import ( "AOC2021/src/helper" "fmt" "os" "sort" "strconv" "strings" ) func main() { args := os.Args[1:] input, err := helper.GetInput(args[0]) if err != nil { fmt.Println(err) } commandsSplitAtInput := [][]string{} for _, command := range input { if helper.ContainsCharacter(command, "inp") { commandsSplitAtInput = append(commandsSplitAtInput, []string{}) } commandsSplitAtInput[len(commandsSplitAtInput)-1] = append(commandsSplitAtInput[len(commandsSplitAtInput)-1], command) } vars := [][3]int{} for _, commmands := range commandsSplitAtInput { var1, _ := strconv.Atoi(strings.Split(commmands[5], " ")[2]) var2, _ := strconv.Atoi(strings.Split(commmands[15], " ")[2]) var3, _ := strconv.Atoi(strings.Split(commmands[4], " ")[2]) vars = append(vars, [3]int{var1, var2, var3}) } possibleNumbers := make(map[string]int) possibleNumbers[""] = 0 for i := 0; i < 14; i++ { possibleNumbers = getAllPossibleNumbers(possibleNumbers, vars) } possibleNumbersInt := []int{} for possibleNumberString, z := range possibleNumbers { if z == 0 { possibleNumberInt, _ := strconv.Atoi(possibleNumberString) possibleNumbersInt = append(possibleNumbersInt, possibleNumberInt) } } sort.Ints(possibleNumbersInt) fmt.Println(possibleNumbersInt[len(possibleNumbersInt)-1]) fmt.Println(possibleNumbersInt[0]) // //possibleNumbers := make(map[string]int) //possibleNumbers[""] = 10 //testNumber := []int{9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} //fmt.Println(checkNumber(testNumber, vars, 0, 0)) //alu := make(map[rune]int) //alu['w'] = 0 //alu['x'] = 0 //alu['y'] = 0 //alu['z'] = 0 //for i, digit := range testNumber { // step(&alu, commandsSplitAtInput[i], digit) //} //fmt.Println(alu) } func getAllPossibleNumbers(possibleNumbers map[string]int, vars [][3]int) map[string]int { newPossibleNumbers := make(map[string]int) for possibleNumber, z := range possibleNumbers { tmpNewPossibleNumber := getPossibleNumbers(vars, z, possibleNumber) for k, v := range tmpNewPossibleNumber { newPossibleNumbers[k] = v } } return newPossibleNumbers } func getPossibleNumbers(vars [][3]int, z int, pastDigits string) map[string]int { digitsWithZ := make(map[string]int) for i := 1; i < 10; i++ { resultZ := checkNumber([]int{i}, vars, z, len(pastDigits)) if resultZ != -1 { digitsWithZ[pastDigits+strconv.Itoa(i)] = resultZ } } return digitsWithZ } func checkNumber(number []int, vars [][3]int, z int, amountPastDigits int) int { currentVars := amountPastDigits for _, digit := range number { if vars[currentVars][0] < 0 && (z%26)+vars[currentVars][0] != digit { return -1 } z, _ = stepSimplified(z, digit, vars[currentVars]) if z < 0 { return -1 } currentVars++ } return z } func stepSimplified(z, w int, vars [3]int) (int, int) { newZ := z / vars[2] if (z%26)+vars[0] == w { z = newZ } else { z = (26 * newZ) + vars[1] + w } return z, w } func step(alu *map[rune]int, commands []string, inputVal int) { for _, command := range commands { splitCommand := strings.Split(command, " ") switch splitCommand[0] { case "inp": (*alu)[rune(splitCommand[1][0])] = inputVal break case "mul": (*alu)[rune(splitCommand[1][0])] = (*alu)[rune(splitCommand[1][0])] * getRightValue(alu, splitCommand[2]) break case "add": (*alu)[rune(splitCommand[1][0])] = (*alu)[rune(splitCommand[1][0])] + getRightValue(alu, splitCommand[2]) break case "div": (*alu)[rune(splitCommand[1][0])] = (*alu)[rune(splitCommand[1][0])] / getRightValue(alu, splitCommand[2]) break case "mod": (*alu)[rune(splitCommand[1][0])] = (*alu)[rune(splitCommand[1][0])] % getRightValue(alu, splitCommand[2]) break case "eql": if (*alu)[rune(splitCommand[1][0])] == getRightValue(alu, splitCommand[2]) { (*alu)[rune(splitCommand[1][0])] = 1 } else { (*alu)[rune(splitCommand[1][0])] = 0 } } } } func getRightValue(alu *map[rune]int, commandRight string) int { intValue, err := strconv.Atoi(commandRight) if err != nil { return (*alu)[rune(commandRight[0])] } else { return intValue } }