句子中单词组的不同组合

时间:2018-07-18 01:54:10

标签: javascript arrays math set combinatorics

我试图提出一种算法,用于确定句子中所有单词组合的组合(不破坏单词的顺序)。

例如用这个句子:“测试用例短语” 不同的组合(分割任意数量的空间)将是:

['the test case phrase']
['the' , 'test case phrase']
['the test' , 'case phrase']
['the test case' , 'phrase']
['the' , 'test' , 'case phrase']
['the test' , 'case' , 'phrase']
['the' , 'test case', 'phrase']
['the' , 'test' , 'case' , 'phrase']

我最初是在考虑排列,但据我所知,这可能是我是否在寻找组合的重新排序组合。

我觉得这里有一个数学原理在工作,但我只是无法动弹……

仅供参考:我正在编写测试用例,并计划用Javascript实现解决方案

2 个答案:

答案 0 :(得分:3)

可以通过应用Star and Bars

的概念来解决您的问题

基本上,对于我们给出的示例,我们有四个词。我们不在乎它们是不同的,只是它们是语言。这些将是我们的明星。现在,用四个词,我们之间有3个空格,逗号可以分开(我们的小节)。我们最初从零个逗号开始,一直到最多三个逗号。

对于(逗号数)= 0,我们有:

3! / (0! (3 - 0) !) = 1

对于(逗号数)= 1,我们有:

3! / (1! (3 - 1) !) = 3

对于(逗号数)= 2,我们有:

3! / (2! (3 - 2) !) = 3

对于(逗号数)= 3,我们有:

3! / (3! (3 - 3) !) = 1

这总共提供了1 + 3 + 3 + 1 = 8个单词组合。

要在算法上进行攻击,您可以简单地遍历空格的每个组合,并在输入时插入逗号。这不应该那么困难。

我不了解javascript,因此我将在R中给出代码(注意,我不推荐在R中使用以下编码样式。.我这样做是为了更加透明其他语言):

words = c("the test case phrase")

## trivial case.. no commas
listOfWords = list(words)

## split on spaces
myWords = strsplit(words, " ")[[1]]
count = 1

for (i in 1:3) {

    myCombs = combn(3, i)

    for (j in 1:ncol(myCombs)) {

        tempWords = myWords

        for (k in 1:nrow(myCombs)) {
            tempWords[myCombs[k, j]] = paste(c(tempWords[myCombs[k, j]], ","), collapse = "")
        }

        count = count + 1
        listOfWords[[count]] = paste(tempWords, collapse = " ")
    }
}

这是输出:

listOfWords
[[1]]
[1] "the test case phrase"

[[2]]
[1] "the, test case phrase"

[[3]]
[1] "the test, case phrase"

[[4]]
[1] "the test case, phrase"

[[5]]
[1] "the, test, case phrase"

[[6]]
[1] "the, test case, phrase"

[[7]]
[1] "the test, case, phrase"

[[8]]
[1] "the, test, case, phrase" 

答案 1 :(得分:3)

作为javascript中的回溯递归函数,该作品非常干净。您遍历数组,并使用i到i-1的第一部分构建每个项目,然后在每个循环中递归其余部分,同时将结果添加到数组res

let str = "the test case phrase"

function mix(arr, res, start = []) {
  for (let i = 1; i < arr.length; i++) {        // You don't need a base case because when length is 0 the loop won't run
    let rest = arr.slice()                      // make a copy so we don't mess up the input
    let head = rest.splice(0, i).join(" ")      // take the head + the rest for o to i
    res.push([...start, head, rest.join(' ')])  // add it as an entry
    mix(rest, res, [...start, head])            // recurse on the rest
  }
  return res
}
let r = mix(str.split(" "), [str])      // we don't need to calculate the original string, so just start with it.
console.log(r.join('\n'))