我有一个列表
set num "20 10 40 50 25 15"
我希望对输出进行分组,以使每组的总和不超过60。 在这种情况下,输出:
{20 40} {10 50} {25 15}
我写了以下代码段
set num "20 10 40 50 25 15"
for {set i 0} {$i < 4} {incr i} {
for {set j 0} {$j < 4} {incr j} {
if {$i == $j} {continue}
if {[expr [lindex $num $i] + [lindex $num $j] ] == 60 } {
puts "[lindex $num $i] [lindex $num $j]"}
}
}
输出:
20 40
10 50
40 20
50 10
我正在尝试删除重复项,并尝试获得总和小于60的组合
答案 0 :(得分:1)
您需要做的是编写一个在列表中找到最大对的过程,第二个过程从列表中删除一对数字(同时注意重复),然后将它们组合在一起以进行整体任务。
以这种方式拆分任务是程序员学习要做的最重要的事情之一。正确处理需要实践和经验。
proc findPair {list limit} {
# Variables to hold our best matches so far
set maxval -inf; # Negative infinity is less than every other number
set maxpair {}
for {set idx1 0} {$idx1 < [llength $list]} {incr idx1} {
set v1 [lindex $list $idx1]
# Optimization: make idx2 always greater than idx1
for {set idx2 [expr {$idx1 + 1}]} {$idx2 < [llength $list]} {incr idx2} {
set v2 [lindex $list $idx2]
set sum [expr {$v1 + $v2}]
if {($sum <= $limit) && ($sum > $maxval)} {
# Save what we've found as our new best choice
set maxval $sum
set maxpair [list $v1 $v2]
}
}
}
# This variable now has the first, best option...
# ... or the empty list if we can't find anything that satisfies.
return $maxpair
}
您可能想考虑为什么我要确保$idx2
总是大于$idx1
(如果相反,会发生什么情况;为什么我不关心这种情况? )。
proc removePair {listvar pair} {
# Make variable in caller also be a variable here; THIS IS CLEVER MAGIC
upvar 1 $listvar list
foreach value $pair {
# Find where the value is
set idx [lsearch -exact $list $value]
# Remove the element at the $idx'th position
set list [lreplace $list $idx $idx]
}
}
现在有了这些,我们可以解决整个问题:
set numbers {20 10 40 50 25 15}
set limit 60
while {[llength $numbers] > 0} {
set pair [findPair $numbers $limit]
if {[llength $pair] > 0} {
# We've found another pair. Great! Print it out
puts "found pair: $pair"
# NO ‘$’ in front of ‘numbers’; we are passing the VARIABLE NAME not the contents
removePair numbers $pair
} else {
# No possible pairs left! This is a failure case
puts "remaining unpairable numbers: $numbers"
# Stop the search
break
}
}
输出是:
found pair: 20 40 found pair: 10 50 found pair: 25 15
我觉得还可以。
答案 1 :(得分:0)
我有一种印象,那就是这是经典的课程作业,问题是缺少与讨论适当解决方案相关的细节(例如,空间与时间复杂性的任何限制,重复的元素等)。
尽管多纳尔的回答本身是完整的,但这只是很多人可能提出的一个答案。这里有一个更常规的解决方案架构(假设正在寻找就地解决方案),包括:
[lsort]
)。incr
)。可能的骨架看起来像这样:
proc pairwiseByCappedPairSum {list limit} {
set list [lsort -integer $list]; # use -unique flag in case of duplicates
set fromStart 0
set fromEnd 0
while {$fromStart < ([llength $list]-$fromEnd-1)} {
set v1 [lindex $list $fromStart]
set v2 [lindex $list end-$fromEnd]
## ENTER YOUR FRAGMENT HERE:
## -------------------------
# if {...} {
# incr fromEnd
# } else {
# puts [list $v1 ...]
# incr fromStart
# }
}
}
完成后,以这种方式调用:
set num "20 10 40 50 25 15"
set limit 60
pairwiseByCappedPairSum $num $limit
它应该打印出来:
10 {15 20 25 40 50}
15 {20 25 40}
20 {25 40}
我觉得还可以。