Что вам нужно сделать, это написать процедуру, которая находит максимальную пару в списке, вторую процедуру, которая удаляет пару чисел из списка (при этом нужно быть осторожным с дубликатами), а затем собрать их вместе, чтобы сделать общееtask.
Разделение задач таким образом - одна из самых важных вещей, которую учат программисты.Чтобы понять это правильно, нужны практика и опыт.
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
, который выглядит хорошо для меня.