package main

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

type pwData struct {
	min  int
	max  int
	ch   rune
	hash string
}

func main() {
	if err := realMain(); err != nil {
		log.Println(err)
	}
}

func realMain() error {
	data, err := readInput("input.txt")
	if err != nil {
		return err
	}

	validold, err := countValidOld(data)
	if err != nil {
		return err
	}
	log.Println("VALID old:", validold)

	validnew, err := countValidNew(data)
	if err != nil {
		return err
	}
	log.Println("VALID new:", validnew)

	return nil
}

func countValidNew(data []pwData) (int, error) {
	var valid int
	for _, pw := range data {
		if pw.hash[pw.min-1] == byte(pw.ch) && pw.hash[pw.max-1] != byte(pw.ch) {
			valid++
		} else if pw.hash[pw.max-1] == byte(pw.ch) && pw.hash[pw.min-1] != byte(pw.ch) {
			valid++
		}
	}
	return valid, nil
}

func countValidOld(data []pwData) (int, error) {
	var valid int
	for _, pw := range data {
		var count int
		for _, c := range pw.hash {
			if c == pw.ch {
				count++
			}
		}
		if count <= pw.max && count >= pw.min {
			valid++
		}
	}
	return valid, nil
}

func readInput(f string) ([]pwData, error) {
	var ret []pwData
	fd, err := os.Open(f)
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	re := regexp.MustCompile(`(.*)-(.*) (\w): (.*)`)

	buff := bufio.NewScanner(fd)
	for buff.Scan() {
		curr := pwData{}
		res := re.FindStringSubmatch(buff.Text())
		if len(res) != 5 {
			return nil, fmt.Errorf("unexpected slice length")
		}
		curr.min, err = strconv.Atoi(res[1])
		if err != nil {
			return nil, err
		}
		curr.max, err = strconv.Atoi(res[2])
		if err != nil {
			return nil, err
		}
		curr.ch = rune(res[3][0])
		curr.hash = res[4]

		ret = append(ret, curr)
	}

	return ret, nil
}