我有一个字符串“ ab”,我想生成a,b之间所有可能的点组合。例如,
在这种情况下,最多可以有3个点(没有两个连续的点),而最小点是0。“ ab”只是一个玩具示例,字符串的长度可以多达30个。 我不知道从哪里开始。任何帮助将不胜感激。预先感谢。
答案 0 :(得分:3)
这故意不是一个完整的答案,但这是一个很好的开始。
如果您有n
个字母,则可能有n + 1
个点,而2^(n + 1)
的位置可能是一个点或没有点。您只需要迭代这些可能性。我们首先使用2^(n + 1)
生成这些expand.grid
点图案:
input = "abc"
n = nchar(input)
dots = do.call(expand.grid, rep(list(c("", ".")), n + 1))
dots
# Var1 Var2 Var3 Var4
# 1
# 2 .
# 3 .
# 4 . .
# 5 .
# 6 . .
# 7 . .
# 8 . . .
# 9 .
# 10 . .
# 11 . .
# 12 . . .
# 13 . .
# 14 . . .
# 15 . . .
# 16 . . . .
我将为您做最后的工作-将您的输入字符串分解为单个字母strsplit(input, "")
,然后使用paste0
或类似的字母将字母与点组合起来。
您说输入的长度最多为30。结果将有2 ^ 31 = 2,147,483,648个组合,这是很多。在R中,您可能会遇到内存限制,具体取决于您的计算机。我会考虑您是否真的需要生成 all 个组合。通常更好的方法是使用迭代器(例如,参见iterators
包)。这可以帮助您生成所需的任意组合,而无需生成每个组合。
答案 1 :(得分:2)
这类似于 Stars and bars 。在这里,我们的字母类似于星星,点类似于棒:
## transform string into stars and bars format
ab
## add spaces around each letter
_a_b_
## substitute stars (i.e. asterisks) for letters
_*_*_
现在,我们只问一个问题:
给定 n 个空格,我们可以用几种方法用 0 填充这些空格到 n 条形?
正如@Gregor所指出的,这实际上是二项式系数的总和(假设 n 个字母):
sum(sapply(0:(n + 1), function(x) combinat::nCm(n + 1, x))) == 2^(n + 1)
使用基数R可以轻松实现所需结果:
myStr <- "abcd"
indStr <- strsplit(myStr, split = "")[[1]]
strTemplate <- vector("character", length = (length(indStr) * 2 + 1))
strTemplate[seq(2, length(strTemplate), 2)] <- indStr
strTemplate
[1] "" "a" "" "b" "" "c" "" "d" ""
dotVec <- seq(1L, length(strTemplate), 2L)
dotVec
[1] 1 3 5 7 9
unlist(lapply(1:length(dotVec), function(x) {
combn(dotVec, x, FUN = function(y) {
temp <- strTemplate
temp[y] <- "."
paste0(temp, collapse = "")
})
}))
[1] ".abcd" "a.bcd" "ab.cd" "abc.d" "abcd."
[6] ".a.bcd" ".ab.cd" ".abc.d" ".abcd." "a.b.cd"
[11] "a.bc.d" "a.bcd." "ab.c.d" "ab.cd." "abc.d."
[16] ".a.b.cd" ".a.bc.d" ".a.bcd." ".ab.c.d" ".ab.cd."
[21] ".abc.d." "a.b.c.d" "a.b.cd." "a.bc.d." "ab.c.d."
[26] ".a.b.c.d" ".a.b.cd." ".a.bc.d." ".ab.c.d." "a.b.c.d."
[31] ".a.b.c.d."