package day17

import (
	"encoding/json"
	"fmt"
	"regexp"
	"strings"
	"golang.org/x/exp/slices"


	"adventofcode2024/utils"

)

type Opcode int

const (
	adv     Opcode = 0
	bxl		Opcode = 1
	bst   	Opcode = 2
	jnx     Opcode = 3
	bxc     Opcode = 4
	out	 	Opcode = 5
	bdv 	Opcode = 6
	cdv 	Opcode = 7

)

func Part1(input string) string {	
	m := regexp.MustCompile(`[\d,]+`).FindAllString(input, -1)
	a := utils.MustAtoi(m[0])
	b := utils.MustAtoi(m[1])
	c := utils.MustAtoi(m[2])

	var pgm []int
	json.Unmarshal([]byte("["+m[3]+"]"), &pgm)

	fmt.Printf("%d %d %d %v\n", a, b, c, pgm)
	out := fmt.Sprint(run(a, b, c, pgm))
	out = fmt.Sprint(strings.Trim(strings.ReplaceAll(out, " ", ","), "[]"))
	return out
}

func Part2(input string) int {
	m := regexp.MustCompile(`[\d,]+`).FindAllString(input, -1)
	b := utils.MustAtoi(m[1])
	c := utils.MustAtoi(m[2])

	var pgm []int
	json.Unmarshal([]byte("["+m[3]+"]"), &pgm)

	fmt.Printf("%d %d %v\n", b, c, pgm)

	a := 0
	for n := len(pgm) - 1; n >= 0; n-- {
		a <<= 3
		for !slices.Equal(run(a, b, c, pgm), pgm[n:]) {
			a++
		}
	}
	return a
}

func run(a, b, c int, pgm []int) (output []int) {
	for ip := 0; ip < len(pgm); ip += 2 {
		operand := pgm[ip+1]
		combo := []int{0, 1, 2, 3, a, b, c}[operand]

		switch pgm[ip] {
		case int(adv):
			a >>= combo
		case int(bxl):
			b ^= operand
		case int(bst):
			b = combo % 8
		case int(jnx):
			if a != 0 {
				ip = operand - 2
			}
		case int(bxc):
			b ^= c
		case int(out):
			output = append(output, combo%8)
		case int(bdv):
			b = a >> combo
		case int(cdv):
			c = a >> combo
		}
	}
	return output
}