package main import ( "bufio" "errors" "fmt" "log" "math" "os" "strconv" "strings" ) func main() { file, err := os.Open("input.txt") if err != nil { log.Fatal(err) } defer file.Close() scanner := bufio.NewScanner(file) if !scanner.Scan() { log.Fatalln("Problem while read line.") return } stringarr := strings.Split(scanner.Text(), ",") var t2 = []int{} for _, i := range stringarr { j, err := strconv.Atoi(i) if err != nil { panic(err) } t2 = append(t2, j) } wip := make([]int, len(t2)) wip2 := make([]int, len(t2)) // ========= Finish now, we can solve the task ====== copy(wip, t2) SolvePuzzle1(wip) copy(wip2, t2) SolvePuzzle2(wip2) } func SolvePuzzle1(list []int) { rawr := []int{0, 1, 2, 3, 4} combinations := permutations(rawr) highestOutput := math.MinInt32 //highestInput := "" for _, combi := range combinations { output := RunAmplification(list, []int{int(combi[0]), int(combi[1]), int(combi[2]), int(combi[3]), int(combi[4])}) if output > highestOutput { //highestInput = combi highestOutput = output } } log.Println("Part1: " + strconv.Itoa(highestOutput)) } func SolvePuzzle2(list []int) { rawr := []int{5, 6, 7, 8, 9} combinations := permutations(rawr) highestOutput := math.MinInt32 //highestInput := "" for _, combi := range combinations { output := RunRecursiveAmplification(list, []int{combi[0], combi[1], combi[2], combi[3], combi[4]}) if output > highestOutput { //highestInput = combi highestOutput = output } } log.Println("Part2: " + strconv.Itoa(highestOutput)) } func RunAmplification(list []int, phases []int) int { signal := []string{"0"} for i := 0; i < 5; i++ { wip := make([]int, len(list)) copy(wip, list) inputs := make([]int, 0) inputs = append(inputs, phases[i]) for j := 0; j < len(signal); j++ { inputStr, _ := strconv.Atoi(signal[j]) inputs = append(inputs, inputStr) } output, err, _, _ := ParseArray(wip, inputs, 0) if err != nil { log.Printf("Problem at Amplification: %d", i+1) log.Fatal(err) } signal = output } sigInt, _ := strconv.Atoi(signal[0]) return sigInt } func RunRecursiveAmplification(list []int, phases []int) int { signal := []string{"0"} amplifier := make([][]int, 0) startIndex := make([]int, 0) for i := 0; i < 5; i++ { if len(amplifier) <= i { log.Println("APPPEND") wip := make([]int, len(list)) copy(wip, list) amplifier = append(amplifier, wip) startIndex = append(startIndex, 0) } inputs := make([]int, 0) inputs = append(inputs, phases[i]) for j := 0; j < len(signal); j++ { inputStr, _ := strconv.Atoi(signal[j]) inputs = append(inputs, inputStr) } output, err, cmdSuccess, ind := ParseArray(amplifier[i], inputs, startIndex[i]) startIndex[i] = ind if err != nil { log.Printf("Problem at Amplification: %d", i+1) log.Fatal(err) } signal = output if i == 4 { i = -1 if cmdSuccess { break } } } sigInt, _ := strconv.Atoi(signal[len(signal)-1]) fmt.Println(len(signal)) return sigInt } func ParseArray(list []int, inputs []int, startIndex int) ([]string, error, bool, int) { var ( output []string ) inputIndex := 0 output = make([]string, 0) log.Println("=================") for i := startIndex; i < len(list); i += 4 { log.Println(strconv.Itoa(i) + " -> " + strconv.Itoa(list[i])) cmd := list[i] sum := 0 mode1 := 0 mode2 := 0 //mode3 := 0 count := CountDigits(cmd) if count > 2 { cmdStr := strconv.Itoa(cmd) cmd, _ = strconv.Atoi(cmdStr[len(cmdStr)-2:]) if count >= 3 { mode1, _ = strconv.Atoi(cmdStr[len(cmdStr)-3 : len(cmdStr)-2]) } if count >= 4 { mode2, _ = strconv.Atoi(cmdStr[len(cmdStr)-4 : len(cmdStr)-3]) } if count >= 5 { //mode3, _ = strconv.Atoi(cmdStr[len(cmdStr)-4:len(cmdStr)-3]) } } if cmd == 99 { return output, nil, true, -2 } if cmd == 1 { num1 := -1 num2 := -1 if mode1 == 1 { num1 = list[i+1] } else { num1 = list[list[i+1]] } if mode2 == 1 { num2 = list[i+2] } else { num2 = list[list[i+2]] } sum = num1 + num2 list[list[i+3]] = sum } else if cmd == 2 { num1 := -1 num2 := -1 if mode1 == 1 { num1 = list[i+1] } else { num1 = list[list[i+1]] } if mode2 == 1 { num2 = list[i+2] } else { num2 = list[list[i+2]] } sum = num1 * num2 list[list[i+3]] = sum } else if cmd == 3 { if len(inputs) > inputIndex { input := inputs[inputIndex] inputIndex++ list[list[i+1]] = input } else { return output, nil, false, i } i = i - 2 } else if cmd == 4 { if mode1 == 1 { output = append(output, strconv.Itoa(list[i+1])) } else { output = append(output, strconv.Itoa(list[list[i+1]])) } i -= 2 } else if cmd == 5 { num1 := -1 if mode1 == 1 { num1 = list[i+1] } else { num1 = list[list[i+1]] } num2 := -1 if mode2 == 1 { num2 = list[i+2] } else { num2 = list[list[i+2]] } if num1 != 0 { i = num2 - 4 } else { i -= 1 } } else if cmd == 6 { num1 := -1 if mode1 == 1 { num1 = list[i+1] } else { num1 = list[list[i+1]] } num2 := -1 if mode2 == 1 { num2 = list[i+2] } else { num2 = list[list[i+2]] } if num1 == 0 { i = num2 - 4 } else { i -= 1 } } else if cmd == 7 { num1 := -1 if mode1 == 1 { num1 = list[i+1] } else { num1 = list[list[i+1]] } num2 := -1 if mode2 == 1 { num2 = list[i+2] } else { num2 = list[list[i+2]] } if num1 < num2 { list[list[i+3]] = 1 } else { list[list[i+3]] = 0 } } else if cmd == 8 { num1 := -1 if mode1 == 1 { num1 = list[i+1] } else { num1 = list[list[i+1]] } num2 := -1 if mode2 == 1 { num2 = list[i+2] } else { num2 = list[list[i+2]] } if num1 == num2 { list[list[i+3]] = 1 } else { list[list[i+3]] = 0 } } else { return output, errors.New("Wrong Command (" + strconv.Itoa(list[i]) + ") at position " + strconv.Itoa(i)), false, -1 } } log.Println("NONE") return output, nil, false, -1 } func CountDigits(i int) int { count := 0 for i != 0 { i /= 10 count = count + 1 } return count } func permutations(arr []int) [][]int { var helper func([]int, int) res := [][]int{} helper = func(arr []int, n int) { if n == 1 { tmp := make([]int, len(arr)) copy(tmp, arr) res = append(res, tmp) } else { for i := 0; i < n; i++ { helper(arr, n-1) if n%2 == 1 { tmp := arr[i] arr[i] = arr[n-1] arr[n-1] = tmp } else { tmp := arr[0] arr[0] = arr[n-1] arr[n-1] = tmp } } } } helper(arr, len(arr)) return res }