package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	inp := StdinToStrings()
	run(inp)
}

var reg map[string]int

func run(inp []string) {
	reg = make(map[string]int)
	reg["a"] = 1
	var mulCount int

	var instCnt int
	for i := 0; i >= 0 && i < len(inp); i++ {
		instCnt++
		if instCnt%10 == 0 {
			ClearScreen()
			printInstructions(inp, i)
		}
		pts := strings.Split(inp[i], " ")
		if pts[1] == "h" || pts[2] == "h" {
			fmt.Println("Hit h")
		}
		switch pts[0] {
		case "set":
			setReg(pts[1], pts[2])
		case "sub":
			subReg(pts[1], pts[2])
		case "mul":
			mulCount++
			mulReg(pts[1], pts[2])
		case "jnz":
			i += jumpNotZero(pts[1], pts[2])
		}
	}

	fmt.Println("Result (H):", reg["h"])
}

func setReg(key string, val string) {
	reg[key] = getValue(val)
}

func subReg(key string, val string) {
	reg[key] = getValue(key) - getValue(val)
}

func mulReg(key string, val string) {
	reg[key] = getValue(key) * getValue(val)
}

func jumpNotZero(test string, jump string) int {
	var ret int
	if getValue(test) != 0 {
		ret = getValue(jump) - 1
	}
	return ret
}

func getValue(key string) int {
	var ret int
	var ok bool
	var err error
	if ret, err = strconv.Atoi(key); err != nil {
		// It's not a number
		if ret, ok = reg[key]; !ok {
			// The register is empty
			reg[key] = 0
			ret = 0
		}
	}
	return ret
}

func PrintRegisters() {
	fmt.Print("[ ")
	for i := 0; i < 26; i++ {
		getReg := string('a' + i)
		fmt.Printf("%s:%d ", getReg, getValue(getReg))
	}
	fmt.Print("]\n")
}

func printInstructions(inp []string, pos int) {
	PrintRegisters()
	for i := range inp {
		if i == pos {
			fmt.Print("> ", inp[i], "\n")
		} else {
			fmt.Print("  ", inp[i], "\n")
		}
	}
}

func ClearScreen() {
	fmt.Print("\033[H\033[2J")
}

func StdinToStrings() []string {
	var input []string
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		input = append(input, scanner.Text())
	}
	return input
}
