package main

import (
	"AOC2021/src/helper"
	"fmt"
	"os"
	"strings"
)

func main() {
	args := os.Args[1:]
	input, err := helper.GetInput(args[0])
	if err != nil {
		fmt.Println(err)
	}
	startPolymer := input[0]
	insertionRuleMap := make(map[string]rune)
	for _, row := range input[2:] {
		splitRow := strings.Split(row, " -> ")
		insertionRuleMap[splitRow[0]] = rune(splitRow[1][0])
	}
	runeMap := make(map[rune]int)
	pairMap := make(map[string]int)
	for i := 0; i < len(startPolymer); i++ {
		if i < len(startPolymer)-1 {
			pairMap[startPolymer[i:i+2]]++
		}
		runeMap[rune(startPolymer[i])]++
	}
	for i := 0; i < 10; i++ {
		pairMap = insert(pairMap, insertionRuleMap, &runeMap)
	}
	calculateResultNumber(runeMap, 99999)
	for i := 0; i < 30; i++ {
		pairMap = insert(pairMap, insertionRuleMap, &runeMap)
	}
	calculateResultNumber(runeMap, 99999999999999)
}

func calculateResultNumber(runeMap map[rune]int, minAmountDefault int) {
	maxAmount := 0
	minAmount := minAmountDefault
	for _, val := range runeMap {
		if val > maxAmount {
			maxAmount = val
		}
		if val < minAmount {
			minAmount = val
		}
	}
	fmt.Println(maxAmount - minAmount)
}

func insert(pairMap map[string]int, insertionRuleMap map[string]rune, runeMap *map[rune]int) map[string]int {
	newPairmap := make(map[string]int)
	for pair, amount := range pairMap {
		insertionValue := insertionRuleMap[pair]
		(*runeMap)[insertionValue] += amount
		newPairmap[string(insertionValue)+pair[1:]] += amount
		newPairmap[pair[:1]+string(insertionValue)] += amount
	}
	return newPairmap
}
