diff --git a/src/main/kotlin/besttravel/chooseBestSum.kt b/src/main/kotlin/besttravel/chooseBestSum.kt new file mode 100644 index 0000000..f08ba58 --- /dev/null +++ b/src/main/kotlin/besttravel/chooseBestSum.kt @@ -0,0 +1,42 @@ +package besttravel + +/** + * https://www.codewars.com/kata/55e7280b40e1c4a06d0000aa/train/kotlin + */ +fun chooseBestSum(t: Int, k: Int, ls: List): Int { + return ls.combinations(k) + .map { it.sum() } + .filter { it <= t } + .maxOrNull() ?: -1 +} + +fun List.combinations(k: Int, acc: List = emptyList()): List> { + if (k == 0) return listOf(acc) + if (isEmpty()) return emptyList() + + return drop(1) + .combinations(k - 1, acc + first()) + drop(1).combinations(k, acc) +} + +// best practice (a lot of faster) + +//fun chooseBestSum(t: Int, k: Int, ls: List): Int { +// return ls.findBestCombination(k, { it.sum() }, t)?.sum() ?: -1 +//} +// +//fun > List.findBestCombination( +// k: Int, +// f: (List) -> R?, +// max: R, +// found: List = emptyList(), +// n: Int = 0 +//): (List)? { +// val result = f(found) +// if (k == 0 && (result == null || result <= max)) return found +// if (result != null && result > max || n >= size) return null +// +// val a = findBestCombination(k - 1, f, max, found + get(n), n + 1) +// val b = findBestCombination(k, f, max, found, n + 1) +// +// return if (a == null) b else if (b == null) a else if (f(a)!! > f(b)!!) a else b +//} diff --git a/src/test/kotlin/besttravel/ChooseBestSumKtTest.kt b/src/test/kotlin/besttravel/ChooseBestSumKtTest.kt new file mode 100644 index 0000000..2ebea37 --- /dev/null +++ b/src/test/kotlin/besttravel/ChooseBestSumKtTest.kt @@ -0,0 +1,91 @@ +package besttravel + +import org.junit.Assert.assertEquals +import org.junit.Ignore +import org.junit.Test + +class SumOfKTest { + + @Test + fun basicTests1() { + println("****** Basic Tests small numbers******") + var ts = listOf(50, 55, 56, 57, 58) + val n = chooseBestSum(163, 3, ts) + assertEquals(163, n.toLong()) + ts = listOf(50) + val m = chooseBestSum(163, 3, ts) + assertEquals(-1, m) + } + + @Test + @Ignore("Performance test (~ 4 seconds on M3 Pro)") + fun hardPerformanceTest() { + val ts: List = listOf( + 931, 744, 763, 825, 713, 851, 867, 435, 726, 112, 847, 697, 547, 384, 897, 455, 242, 564, 873, 586, 336, + 934, 208, 557, 876, 644, 934, 753, 664, 725, 941, 754, 563, 972, 683, 636, 428, 943, 653, 862, 929, 645, + 251, 665, 120, 750, 420, 340, 931, 744, 763, 825, 713, 851, 867, 435, 726, 112, 847, 697, 547, 384, 897, + 455, 242, 564, 873, 586, 336, 934, 208, 557, 876, 644 + ) + + val start = System.currentTimeMillis() + val n: Int = chooseBestSum(3198, 5, ts) + val end = System.currentTimeMillis() + println("Time: " + (end - start) + " ms") + assertEquals(3198, n.toLong()) + } + + @Test + @Ignore("Performance test (~ 10 seconds on M3 Pro)") + fun harderPerformanceTest() { + val ts: List = listOf( + 931, 744, 763, 825, 713, 851, 867, 435, 726, 112, 847, 697, 547, 384, 897, 455, 242, 564, 873, 586, 336, + 934, 208, 557, 876, 644, 934, 753, 664, 725, 941, 754, 563, 972, 683, 636, 428, 943, 653, 862, 929, 645, + 251, 665, 120, 750, 420, 340, 931, 744, 763, 825, 713, 851, 867, 435, 726, 112, 847, 697, 547, 384, 897, + 455, 242, 564, 873, 586, 336, 934, 208, 557, 876, 644, 934, 753, 664, 725, 941, 754, 563, 972, 683, 636 + ) + + val start = System.currentTimeMillis() + val n: Int = chooseBestSum(3198, 5, ts) + val end = System.currentTimeMillis() + println("Time: " + (end - start) + " ms") + assertEquals(3198, n.toLong()) + } + + @Test + @Ignore("Performance test (~ 20 seconds on M3 Pro)") + fun evenHarderPerformanceTest() { + val ts: List = listOf( + 931, 744, 763, 825, 713, 851, 867, 435, 726, 112, 847, 697, 547, 384, 897, 455, 242, 564, 873, 586, 336, + 934, 208, 557, 876, 644, 934, 753, 664, 725, 941, 754, 563, 972, 683, 636, 428, 943, 653, 862, 929, 645, + 251, 665, 120, 750, 420, 340, 931, 744, 763, 825, 713, 851, 867, 435, 726, 112, 847, 697, 547, 384, 897, + 455, 242, 564, 873, 586, 336, 934, 208, 557, 876, 644, 934, 753, 664, 725, 941, 754, 563, 972, 683, 636, + 428, 943, 653, 862, 929, 645, 251, 665, 120, 750 + ) + + val start = System.currentTimeMillis() + val n: Int = chooseBestSum(3198, 5, ts) + val end = System.currentTimeMillis() + println("Time: " + (end - start) + " ms") + assertEquals(3198, n.toLong()) + } + + @Test + @Ignore("Performance test") + fun evenHardestPerformanceTest() { + val ts: List = listOf( + 931, 744, 763, 825, 713, 851, 867, 435, 726, 112, 847, 697, 547, 384, 897, 455, 242, 564, 873, 586, 336, + 934, 208, 557, 876, 644, 934, 753, 664, 725, 941, 754, 563, 972, 683, 636, 428, 943, 653, 862, 929, 645, + 251, 665, 120, 750, 420, 340, 931, 744, 763, 825, 713, 851, 867, 435, 726, 112, 847, 697, 547, 384, 897, + 455, 242, 564, 873, 586, 336, 934, 208, 557, 876, 644, 934, 753, 664, 725, 941, 754, 563, 972, 683, 636, + 428, 943, 653, 862, 929, 645, 251, 665, 120, 750, 420, 340, 931, 744, 763, 825, 713, 851, 867, 435, 726, + 112, 847, 697, 547, 384, 897, 455, 242, 564, 873, 586, 336, 934, 208, 557, 876, 644, 934, 753, 664, 725, + 941, 754, 563, 972, 683, 636, 428, 943, 653, 862, 929, 645, 251, 665, 120, 750, 420, 340, 931, 744, 763, + ) + + val start = System.currentTimeMillis() + val n: Int = chooseBestSum(3198, 5, ts) + val end = System.currentTimeMillis() + println("Time: " + (end - start) + " ms") + assertEquals(3198, n.toLong()) + } +}