使用较少数量的循环,所有字符和所有长度的组合?

时间:2013-10-01 11:26:48

标签: tcl brute-force

Brain Teaser:我自己发起了这个问题,但完全陷入困境。

我想创建所有可能长度的所有字符的所有可能组合。假设,[a-z]组合1个长度,然后[a-z]组合2个长度,依此类推,直到达到最大长度。

这可以通过迭代循环很容易地完成。

3长度的例子:

proc triples list {
    foreach i $list {
        foreach j $list {
            foreach k $list {
                puts [list $i $j $k]
            }
        }
    }
}

但是,它应该解决使用较少的循环(循环需要是动态的)

set chars "abcdefghijklmnopqrstuvwxyz"
set chars [split $chars ""]

set complete_length [llength $chars]

set start 0
set maximum_length 15


while {1} {
    if {$start > $maximum_length} {
        break
    }
    for {set i [expr $maximum_length-$start]} {$i >= 0} {incr i -1} {
        # dump combinations
    }
    incr start
}

在这个块中,我应该应用什么算法或方法?任何建议/帮助/代码将不胜感激。

1 个答案:

答案 0 :(得分:0)

Sry,这不是一个答案,但希望无论如何都会有一些有趣的讨论:

“组合”这个词通常用得太普遍,因此可以用许多不同的方式来解释。假设您有26个不同元素的源列表,英文字母,并且您希望选择其中3个并且合并在3个元素的目的地列表中:

  • 您是否可以随时从源列表中选择任何字母,或者当您选择它们​​时元素会从中消失?定义“拾取”(在拾取过程中复制或移动的元素),或定义源值集(每个A-Z中有1个或无限量的A-Z)。
  • 目的地清单中的订单是否重要? AHM被视为与HAM相同的组合吗?定义“合并”。
  • 如果您有一个列表,其中并非所有元素都不同,例如{2 10 10 64 100},你有更多的可能性。定义您的一组值。

您的第一个示例打印permutations,而不是combinations。如果这就是你想要的,那么easiset方式就是一个递归过程。组合生成起来更复杂。

修改

我为Project Euler程序编写了这个程序。它选择所有元素,但也许你可以修改它来选择n。它将命令前缀作为参数,因此您不必存储所有排列。

package require Tcl 8.5.0

proc forEachPerm {list cmdPrefix} {
  _forEachPerm {} $list $cmdPrefix
}

proc _forEachPerm {head list cmdPrefix} {
  if {![llength $list]} {
    {*}$cmdPrefix $head
  } else {
    for {set i 0} {$i < [llength $list]} {incr i} {
      _forEachPerm [concat $head [lrange $list $i $i]] [lreplace $list $i $i] $cmdPrefix
    }
  }
}

# example use:
forEachPerm {a b c} {apply {{list} {puts [join $list]}}}