根据tcl中的总和对列表中的元素进行分组

根据tcl中的总和对列表中的元素进行分组,tcl,Tcl,我有一张单子 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}

我有一张单子

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]"}
    }
}

我正在尝试删除重复项,并尝试获得总和小于60的组合,您需要做的是编写一个过程,在列表中查找最大对,第二个过程从列表中删除一对数字(同时小心重复项)然后把它们放在一起完成整个任务

以这种方式分割任务是程序员学习做的最重要的事情之一。正确的做法需要实践和经验

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
}
现在我们有了这些,我们可以解决整个问题:

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 配对号码:20 40 配对号码:1050 配对号码:2515
这在我看来还行。

我有一个共同的印象,这是一个经典的课程作业,而且这个问题缺少与讨论适当解决方案相关的细节(例如,空间与时间复杂性的任何限制、重复元素等)

虽然多纳尔的答案本身是完整的,但这只是众多答案中的一个。这里更为传统的解决方案模式(假设寻求就地解决方案)包括:

  • 从排序列表开始(将总体复杂性设置为Tcl的
    [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
            # }
        }
    }
    
    应打印出:

    10 {15 20 25 40 50}
    15 {20 25 40}
    20 {25 40}
    

    我觉得没问题。

    请阅读并编辑您的问题。欢迎使用堆栈溢出!请阅读并阅读,特别是如何提问。你在这里的最佳选择是做你的研究,搜索相关的话题,然后尝试一下。在做了更多的研究和搜索之后,发布一篇你的尝试的文章,并明确指出你的困境,这可以帮助你得到更好的答案。这是一个有趣的小问题(如果有点不明确),但听起来确实很像你为一个班级做的事情,我们不想干扰你的教育。你能告诉我们你试过什么吗,这样我们就可以帮助你修复你所做的,而不是直接为你解决问题了吗?嗨,多纳尔,我已经发布了我试过的代码。如果您有任何建议,我们将不胜感激。谢谢您编辑您的问题,它看起来好多了。我又做了一些修改。在解决方案中留下一些待办事项和空白不是比给出一个完整的解决方案更好吗?看完之后,我只是问一下这里的惯例是什么
    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}