package day16

import parseInput
import splitToLines

/**
--- Day 16: Aunt Sue ---

Your Aunt Sue has given you a wonderful gift, and you'd like to send her a thank you card. However, there's a small problem: she signed it "From, <NAME>".

You have 500 Aunts named "Sue".

So, to avoid sending the card to the wrong person, you need to figure out which Aunt Sue (which you conveniently number 1 to 500, for sanity) gave you the gift. You open the present and, as luck would have it, good ol' Aunt Sue got you a My First Crime Scene Analysis Machine! Just what you wanted. Or needed, as the case may be.

The My First Crime Scene Analysis Machine (MFCSAM for short) can detect a few specific compounds in a given sample, as well as how many distinct kinds of those compounds there are. According to the instructions, these are what the MFCSAM can detect:

children, by human DNA age analysis.
cats. It doesn't differentiate individual breeds.
Several seemingly random breeds of dog: samoyeds, pomeranians, akitas, and vizslas.
goldfish. No other kinds of fish.
trees, all in one group.
cars, presumably by exhaust or gasoline or something.
perfumes, which is handy, since many of your Aunts Sue wear a few kinds.
In fact, many of your Aunts Sue have many of these. You put the wrapping from the gift into the MFCSAM. It beeps inquisitively at you a few times and then prints out a message on ticker tape:

children: 3
cats: 7
samoyeds: 2
pomeranians: 3
akitas: 0
vizslas: 0
goldfish: 5
trees: 3
cars: 2
perfumes: 1
You make a list of the things you can remember about each Aunt Sue. Things missing from your list aren't zero - you simply don't remember the value.

What is the number of the Sue that got you the gift?

--- Part Two ---

As you're about to send the thank you note, something in the MFCSAM's instructions catches your eye. Apparently, it has an outdated retroencabulator, and so the output from the machine isn't exact values - some of them indicate ranges.

In particular, the cats and trees readings indicates that there are greater than that many (due to the unpredictable nuclear decay of cat dander and tree pollen), while the pomeranians and goldfish readings indicate that there are fewer than that many (due to the modial interaction of magnetoreluctance).

What is the number of the real Aunt Sue?

 */

fun main(args: Array<String>) {
    val search1 = hashMapOf(
            "children" to 3..3,
            "cats" to 7..7,
            "samoyeds" to 2..2,
            "pomeranians" to 3..3,
            "akitas" to 0..0,
            "vizslas" to 0..0,
            "goldfish" to 5..5,
            "trees" to 3..3,
            "cars" to 2..2,
            "perfumes" to 1..1
    )
    val search2 = hashMapOf(
            "children" to 3..3,
            "cats" to 8..999,
            "samoyeds" to 2..2,
            "pomeranians" to 0..2,
            "akitas" to 0..0,
            "vizslas" to 0..0,
            "goldfish" to 0..4,
            "trees" to 4..999,
            "cars" to 2..2,
            "perfumes" to 1..1
    )

    val input = parseInput("day16-input.txt")

    println(findAuntNumber(input, search1))
    println(findAuntNumber(input, search2))
}

fun findAuntNumber(input: String, search: Map<String, IntRange>): Int? {
    return parseMFCSAM(input)
            .map { m -> m.number to search.count { m.items[it.key] in it.value } }
            .maxBy { it.second }
            ?.first
}

data class MFCSAM(val number: Int, val items: Map<String, Int>)

private fun parseMFCSAM(input: String) = input.splitToLines()
        .map {
            val number = Regex("""Sue (\d+):""").find(it)!!.groups[1]!!.value.toInt()
            val items = Regex("""(?:(\w+):\s(\d+),?)+""")
                    .findAll(it)
                    .map { it.groups[1]!!.value to it.groups[2]!!.value.toInt() }
                    .toMap()

            MFCSAM(number, items)
        }
