class Change(val setOfCoins: Set<Int>) {
    // This is a good greedy implementation of the algorithm
    fun issue_greedy(x: Int): List<Int> {
        require((x > setOfCoins.min()!!) or (x == 0))
        var y = x
        val returnList = mutableListOf<Int>()

        while (y != 0) {
            val maxChange = setOfCoins.filter { y >= it }.max()
            returnList.add(maxChange ?: 0)
            y -= maxChange ?: 0
        }

        return returnList.reversed()
    }

    val resultMap: MutableMap<Int, List<Int>> = mutableMapOf<Int, List<Int>>()

    fun issue(x: Int): List<Int> {
        require((x >= setOfCoins.min()!!) or (x == 0))
        if (x == 0) {
            return emptyList()
        } else if (x in setOfCoins) {
            return listOf(x)
        } else if (x in resultMap){
            return resultMap[x]!!
        } else {
            for (i in setOfCoins.filter { it <= x }) {
                val firstCandidate = issue(x - i) + i
                if (resultMap[x]?.isEmpty() ?: true){
                    resultMap[x] = firstCandidate
                }
                if (firstCandidate.size < resultMap[x]?.size ?: 1000){
                    resultMap[x] = firstCandidate
                }
            }
        }

        return resultMap[x]!!.sorted()
    }
}


fun main(args: Array<String>) {
    print(Change(setOf(1, 5, 10, 21, 25)).issue(63))
    print(Change(setOf(1, 4, 15, 20, 50)).issue(23))
}