我需要通过这个单元测试:
@Test
fun dividingIntoFour() {
repeat(times = 100) {
val randomNumber = Random.nextInt(from = 50, until = 90)
val total = 100 - randomNumber
val numberList = divideIntoFourDistinctNumbersThatAddUptoTotal(total = total)
assert(numberList.sum() == total)
assert(!numberList.contains(0))
assert(numberList.all { it > 0 })
assert(numberList.distinct().size == 4)
}
}
通过案例:
该函数正确地将总和(即 100 减去 50 到 90 之间的随机数)分成四个不同的正整数,总和为总和,这适用于该函数的 100 次迭代。
失败案例:
这和我得到的一样接近——它要么通过,要么挂在最后一个 while 循环中:
fun divideIntoFourDistinctNumbersThatAddUptoTotal(total: Int): List<Int> {
var aTotal = total
var first = (aTotal / 4..aTotal / 2).random()
aTotal -= first
var second = (3..aTotal - 3).random()
while (second == first) {
second = (3..aTotal - 3).random()
}
aTotal -= second
var third = (3..aTotal).random()
while (third == first || third == second) {
third = (3..aTotal).random()
}
aTotal -= third
var fourth = aTotal
while (listOf(first, second, third, fourth).distinct().size != 4) {
if (fourth == first) {
fourth -= 1
first += 1
} else if (fourth == third) {
fourth -= 1
third += 1
} else if (fourth == second) {
fourth -= 1
second += 1
}
}
return listOf(first, second, third, fourth)
}
ChatGpt 在其 openai 网站和 github copilot 上都失败了。
使用基于随机获取一个数字,然后随机获取第二个数字,依此类推的算法来解决这个问题似乎是一项艰巨的任务,因为您将获得比例过高的包含递减数字的结果。但是如果四个数的排序没有关系,那就没问题了
如果不经常连续调用函数,那么在随机列表中简单搜索第一个解决方案可能就是解决方案。这可能会比你的算法慢一点(因为三个“洗牌”)。
repeat(times = 100) {
val total = (10..50).random()
val ints = divideIntoFourDistinctNumbersThatAddUptoTotal(total = total)
if (ints.sum() != total) println("Invalid total: $ints => $total")
if (ints.contains(0)) println("Contains zero: $ints => $total")
if (ints.distinct().size != 4) println("Not distinct: $ints => $total")
println("$total -> $ints")
}
fun divideIntoFourDistinctNumbersThatAddUptoTotal(total: Int): List<Int> {
val largestInt = total - (1 + 2 + 3)
val ints1 = IntArray(largestInt) { it + 1 }.apply { shuffle() }
val ints2 = IntArray(largestInt) { it + 1 }.apply { shuffle() }
val ints3 = IntArray(largestInt) { it + 1 }.apply { shuffle() }
for (i1 in ints1) {
for (i2 in ints2) {
if (i1 == i2) continue
val sum12 = i1 + i2
if (sum12 > total) continue
for (i3 in ints3) {
if (i1 == i3 || i2 == i3) continue
val sum123 = sum12 + i3
if (sum123 > total) continue
val i4 = total - sum123
if (i4 > 0 && i1 != i4 && i2 != i4 && i3 != i4) {
return listOf(i1, i2, i3, i4).sorted()
}
}
}
}
return emptyList() // Only for when 'total' is smaller than 10 (1 + 2 + 3 + 4)
}