package day13

import (
	"regexp"
	"strconv"
	"strings"
)

type ClawMachine struct {
	Ax, Ay int
	Bx, By int
	Px, Py int
}

func Part1(input string) int {
	clawMachines := parseInput(input)
	total := 0
	for _, c := range clawMachines {
		x, y := solveSimEquations(c.Ax, c.Bx, c.Px, c.Ay, c.By, c.Py)
		total += x*3 + y
	}
	return total
}

func Part2(input string) int {
	clawMachines := parseInput(input)
	total := 0
	for _, c := range clawMachines {
		prizeX, prizeY := c.Px+10000000000000, c.Py+10000000000000
		det, x, y := c.Ax*c.By-c.Bx*c.Ay, prizeX*c.By-c.Bx*prizeY, c.Ax*prizeY-prizeX*c.Ay
		if det != 0 && x == (x/det)*det && y == (y/det)*det {
			total += (x/det)*3 + (y / det)
		}
	}

	return total
}

func parseInput(input string) []ClawMachine {
	clawMachines := strings.Split(strings.TrimSpace(input), "\n\n")
	output := make([]ClawMachine, 0, len(clawMachines))
	for _, c := range clawMachines {
		var clawMachine ClawMachine
		line := strings.Split(strings.TrimSpace(c), "\n")

		re := regexp.MustCompile(`X\+(\d+), Y\+(\d+)`)
		matches := re.FindStringSubmatch(line[0])
		clawMachine.Ax, _ = strconv.Atoi(matches[1])
		clawMachine.Ay, _ = strconv.Atoi(matches[2])

		matches = re.FindStringSubmatch(line[1])
		clawMachine.Bx, _ = strconv.Atoi(matches[1])
		clawMachine.By, _ = strconv.Atoi(matches[2])

		re = regexp.MustCompile(`X=(\d+), Y=(\d+)`)
		matches = re.FindStringSubmatch(line[2])
		clawMachine.Px, _ = strconv.Atoi(matches[1])
		clawMachine.Py, _ = strconv.Atoi(matches[2])

		output = append(output, clawMachine)
	}
	return output
}

func solveSimEquations(a1, b1, c1, a2, b2, c2 int) (int, int) {
	det := a1*b2 - a2*b1
	if det == 0 || (c1*b2-c2*b1)%det != 0 || (a1*c2-a2*c1)%det != 0 {
		return 0, 0
	}
	x := (c1*b2 - c2*b1) / det
	y := (a1*c2 - a2*c1) / det
	if x < 0 || x > 100 || y < 0 || y > 100 {
		return 0, 0
	}
	return x, y
}
