From 13ff73d6575ada33f8106ee1d339236f2bf02a5a Mon Sep 17 00:00:00 2001
From: Alexander Rundberg <alex@gwai.se>
Date: Wed, 18 Dec 2024 13:47:59 +0100
Subject: [PATCH] Add solution day 17 part 2

---
 README.md               |  2 +-
 solutions/day17/main.go | 69 ++++++++++++++++++++++++++++-------------
 2 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/README.md b/README.md
index db7ceb1..eea3d57 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ automatically rebuilt and redeployed every time the `common` module or their own
 | 01  | ⭐ ⭐      | 14  | ⭐ ⭐      |
 | 02  | ⭐ ⭐      | 15  | ⭐ ⭐      |
 | 03  | ⭐ ⭐      | 16  | ⭐ 🥸     |
-| 04  | ⭐ ⭐      | 17  | ⭐        |
+| 04  | ⭐ ⭐      | 17  | ⭐ ⭐      |
 | 05  | ⭐ ⭐      | 18  | ⭐ ⭐      |
 | 06  | ⭐ ⭐      | 19  |          |
 | 07  | ⭐ ⭐      | 20  |          |
diff --git a/solutions/day17/main.go b/solutions/day17/main.go
index c9ce79d..2e3e070 100644
--- a/solutions/day17/main.go
+++ b/solutions/day17/main.go
@@ -3,6 +3,8 @@ package main
 import (
 	"fmt"
 	"github.com/terminalnode/adventofcode2024/common"
+	"strconv"
+	"strings"
 )
 
 func main() {
@@ -28,38 +30,61 @@ func part2(
 		return fmt.Sprintf("Failed to parse machine: %v", err)
 	}
 
-	lenSeq := len(m.seq)
-	initA := int64(0)
+	maxIdx := len(m.seq) - 1
+	octArr := make([]int, len(m.seq))
+	octIdx := 0
 	initB := m.b
 	initC := m.c
-	for initA = 0; true; initA++ {
-		m.run(lenSeq)
-		if compareSeqOut(m, lenSeq) {
-			break
-		}
-		m.a = initA
+
+	for {
+		seqIdx := maxIdx - octIdx
+
+		// Rig the machine
+		octArr[octIdx] += 1
 		m.b = initB
 		m.c = initC
 		m.out = m.out[:0]
-		m.pos = 0
+
+		m.a, err = arrayToOct(octArr)
+		if err != nil {
+			return fmt.Sprintf("Failed to read %v as octal string: %v", octArr, err)
+		}
+
+		// Run the program and verify output
+		m.run(maxIdx + 1)
+		correct := m.out[seqIdx] == m.seq[seqIdx]
+
+		if octIdx == maxIdx && correct {
+			break
+		} else if correct {
+			octIdx++
+			octArr[octIdx] = -1
+		}
+
+		for octArr[octIdx] == 7 {
+			octArr[octIdx] = 0
+			octIdx--
+		}
 	}
 
-	return fmt.Sprintf("Registry A should be %d", initA-1)
+	final, err := arrayToOct(octArr)
+	if err != nil {
+		return fmt.Sprintf("Solved it, but failed to extract number: %v", err)
+	}
+	return fmt.Sprintf("Registry A should be %d", final)
 }
 
-func compareSeqOut(
-	m machine,
-	lenSeq int,
-) bool {
-	if len(m.out) != lenSeq {
-		return false
+func arrayToOct(
+	arr []int,
+) (int64, error) {
+	strArr := make([]string, len(arr))
+	for i, n := range arr {
+		strArr[i] = strconv.Itoa(n)
 	}
 
-	for i, seq := range m.seq {
-		if m.out[i] != seq {
-			return false
-		}
+	oct, err := strconv.ParseInt(strings.Join(strArr, ""), 8, 64)
+	if err != nil {
+		return 0, err
 	}
-
-	return true
+	return oct, nil
 }