Javascript 用JS/Coffeescript递归连接数组

Javascript 用JS/Coffeescript递归连接数组,javascript,recursion,coffeescript,Javascript,Recursion,Coffeescript,我正在尝试生成类似于以下内容的内容: 给定HINTS=[“a”、“s”、“d”、“f”、“g”、“h”、“j”、“k”、“l”和“;”]那么allHints(21)应该给出一个类似于以下内容的数组: allHints = -> for i in [0...anchors] do (i) -> if i > 9 (for y in [0...i % 9] do (y) ->

我正在尝试生成类似于以下内容的内容:

给定
HINTS=[“a”、“s”、“d”、“f”、“g”、“h”、“j”、“k”、“l”和“;”]
那么
allHints(21)
应该给出一个类似于以下内容的数组:

allHints = ->
  for i in [0...anchors]
    do (i) ->
      if i > 9
        (for y in [0...i % 9]
          do (y) ->
                       #changing this to HINTS[Math.round(i / 10)] as it should be produces weird results
            HINTS[y] + HINTS[i % 9 - 1])[0]
      else
        HINTS[i]


console.log allHints 19
[“a”、“s”、“d”、“f”、“g”、“h”、“j”、“k”、“l”、“a”、“as”、“ad”、“af”、“ag”、“ah”、“aj”、“ak”、“af”、“sa”、“ss”、“sd”…]

也就是说,所有元素一个接一个地连接在一起,形成单独的组合。如果可能的话,我想用某种递归来写这篇文章,因为这似乎是一个倾向于用这种方式解决的问题

我的解决方案是为嵌套两个循环,每个循环在每个组合中迭代9次(假设有多少个提示),但它似乎在第二次循环时被卡住了。我不太熟悉Coffeescripts的语法,但我尝试过类似的方法:

allHints = ->
  for i in [0...anchors]
    do (i) ->
      if i > 9
        (for y in [0...i % 9]
          do (y) ->
                       #changing this to HINTS[Math.round(i / 10)] as it should be produces weird results
            HINTS[y] + HINTS[i % 9 - 1])[0]
      else
        HINTS[i]


console.log allHints 19

但不幸的是,这为最后一个元素提供了一个
未定义的
。有人能帮我找出如何正确的for循环来生成数组吗?这是供参考的。

听起来您基本上想要一个双重嵌套循环,每次迭代每个字符时,您都要迭代每个字符,在这种情况下,您最好使用提示数组的长度,而不必自己计算内容

这个怎么样

var HINTS = ["a", "s", "d", "f", "g", "h", "j", "k", "l", ";"]

function allhints() {
  var all = Array(); // Create a new array
  all = all.concat(HINTS); // Add the individual hints
  for (var i=0; i<HINTS.length; i++) // for each character in HINTS
    for (var j=0; j<HINTS.length; j++) // with each character in HINTS
      all.push(HINTS[i] + HINTS[j]); // Append the two combined hint characters
  return all;
}
var提示=[“a”、“s”、“d”、“f”、“g”、“h”、“j”、“k”、“l”、“;”]
函数allhints(){
var all=Array();//创建一个新数组
all=all.concat(提示);//添加单个提示

对于(var i=0;i来说,听起来您基本上想要一个双嵌套循环,每次迭代每个字符时,您都要迭代每个字符,在这种情况下,您最好使用提示数组的长度,而不用自己计算内容

这个怎么样

var HINTS = ["a", "s", "d", "f", "g", "h", "j", "k", "l", ";"]

function allhints() {
  var all = Array(); // Create a new array
  all = all.concat(HINTS); // Add the individual hints
  for (var i=0; i<HINTS.length; i++) // for each character in HINTS
    for (var j=0; j<HINTS.length; j++) // with each character in HINTS
      all.push(HINTS[i] + HINTS[j]); // Append the two combined hint characters
  return all;
}
var提示=[“a”、“s”、“d”、“f”、“g”、“h”、“j”、“k”、“l”、“;”]
函数allhints(){
var all=Array();//创建一个新数组
all=all.concat(提示);//添加单个提示

对于(var i=0;i而言,您真正想要解决的问题是“如何生成集合的所有子集”,特别是“如何生成给定数组提示的所有子集”

最简单的方法是考虑集合中的每个元素都可以映射到二进制字符串。你的数组,提示,有10个元素,所以为了找到所有的子集,我们只需要从0000000000到1111111111的二进制数,然后选择我们要走的任何元素(例如,0000000个101将是“k”)。 下面的代码几乎完成了;我已经查看了它,似乎有一个bug(稍后我会看看是否可以调试它)

HINTS=[“a”、“s”、“d”、“f”、“g”、“h”、“j”、“k”、“l”、“;”]
var结果=[];
var-binCounter;
var提示;
for(var i=0;i
您真正想要解决的问题是“如何生成集合的所有子集”,特别是“如何生成给定数组
提示的所有子集”

最简单的方法是考虑集合中的每个元素都可以映射到二进制字符串。你的数组,提示,有10个元素,所以为了找到所有的子集,我们只需要从0000000000到1111111111的二进制数,然后选择我们要走的任何元素(例如,0000000个101将是“k”)。 下面的代码几乎完成了;我已经查看了它,似乎有一个bug(稍后我会看看是否可以调试它)

HINTS=[“a”、“s”、“d”、“f”、“g”、“h”、“j”、“k”、“l”、“;”]
var结果=[];
var-binCounter;
var提示;
for(var i=0;i
一种有点惯用的咖啡脚本解决方案:

HINTS = ["a", "s", "d", "f", "g", "h", "j", "k", "l", ";"]

allHints = (n) ->
  HINTS.concat(((b + a for a in HINTS) for b in HINTS)...)[0...n]
allHints = (n) ->
    ln = hints.length

    # return sliced array if n is less than it's length
    return hints.slice(0, n) if n <= ln

    # clone the array, find number of possible combinations
    clone = hints.slice()
    limit = Math.min(n, ln*ln)

    # add the combinations up to the requested length or limit
    for i in [ln...limit]
        clone[i] = hints[Math.floor(i / ln) - 1] + hints[i % ln]

    return clone
然后
allHints(12)
返回
['a','s','d','f','g','h','j','k','l',';','aa','as']

第一个splat(
)将嵌套理解创建的2D数组转换为
concat()
的1D数组参数列表


此解决方案显然不是很有效,因为它生成所有置换只是为了丢弃它不需要的任何置换。

有点习惯的CoffeeScript解决方案:

HINTS = ["a", "s", "d", "f", "g", "h", "j", "k", "l", ";"]

allHints = (n) ->
  HINTS.concat(((b + a for a in HINTS) for b in HINTS)...)[0...n]
allHints = (n) ->
    ln = hints.length

    # return sliced array if n is less than it's length
    return hints.slice(0, n) if n <= ln

    # clone the array, find number of possible combinations
    clone = hints.slice()
    limit = Math.min(n, ln*ln)

    # add the combinations up to the requested length or limit
    for i in [ln...limit]
        clone[i] = hints[Math.floor(i / ln) - 1] + hints[i % ln]

    return clone
然后
allHints(12)
返回
['a','s','d','f','g','h','j','k','l',';','aa','as']

第一个splat(
)将嵌套理解创建的2D数组转换为
concat()
的1D数组参数列表


这个解决方案显然不是很有效,因为它生成所有置换只是为了丢弃它不需要的任何置换。

问题似乎确实是生成给定集合的可能子集集。这有时被称为集合的幂集

基本上有3种可能的解决方案: 1) 二项式系数。参见 可以在Pyton的itertools中找到一个实现。二项式系数为您提供特定长度的子集。如果您将长度为0到原始集合长度的子集组合起来,您就完成了

2) 一种逐代“增长”子集的递归算法。参见京都议定书的答案。参见下面我更详细的版本。维基百科文章提到了帕斯卡三角形,这是一种对这种算法的暗示
allHints = (n) ->
    ln = hints.length

    # return sliced array if n is less than it's length
    return hints.slice(0, n) if n <= ln

    # clone the array, find number of possible combinations
    clone = hints.slice()
    limit = Math.min(n, ln*ln)

    # add the combinations up to the requested length or limit
    for i in [ln...limit]
        clone[i] = hints[Math.floor(i / ln) - 1] + hints[i % ln]

    return clone