package main

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

var list []int
var skip, idx, length int

func main() {
	part := 2
	if len(os.Args) > 1 {
		if os.Args[1] == "-1" {
			part = 1
		}
	}
	length = 256
	for i := 0; i < length; i++ {
		list = append(list, i)
	}

	inp := StdinToString()
	if part == 1 {
		part1(inp)
	} else {
		part2(inp)
	}
}

func part1(inp string) {
	fmt.Println("= Part 1 =")
	lngths := strings.Split(inp, ",")
	for i := range lngths {
		round(Atoi(lngths[i]))
	}
	fmt.Println("Result:", list[0]*list[1])
}

func round(i int) {
	// if idx+i overflows, pull from the front
	var revList []int
	for j := idx; j < idx+i; j++ {
		revList = append([]int{list[j%length]}, revList...)
	}
	for j := 0; j < len(revList); j++ {
		list[(idx+j)%length] = revList[j]
	}

	idx += i + skip
	skip++
}

func part2(inp string) {
	inpBts := []byte(inp)
	inpBts = append(inpBts, []byte{17, 31, 73, 47, 23}...)
	for j := 0; j < 64; j++ {
		for i := range inpBts {
			round(int(inpBts[i]))
		}
	}
	// Now calculate the dense hash
	var dense []byte
	for i := 0; i < len(list); i += 16 {
		dense = append(dense, xorList(list[i:i+16]))
	}
	fmt.Printf("%x\n", dense)
}

func xorList(inp []int) byte {
	var ret byte
	for i := range inp {
		ret ^= byte(inp[i])
	}
	return ret
}

func StdinToString() string {
	var input string
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		input = scanner.Text()
	}
	return input
}

func Atoi(i string) int {
	var ret int
	var err error
	if ret, err = strconv.Atoi(i); err != nil {
		log.Fatal("Invalid Atoi")
	}
	return ret
}
