我正在尝试以以下方式获取单词的所有可能组合,而无需使用任何导入:
例如...
Input: Bang
Output: [['B','ang'], ['Ba','ng'], ['Ban','g'], ['B','a','ng'], ['B','an','g'], ['Ba','n','g'], ['B','a','n','g']]
这个问题困扰了我一段时间,我似乎无法弄清楚执行此操作的算法。
下面的代码是我所做的,但这给出了字符串的所有可能组合,但不是我所需要的方式。
我试图在haskell中实现此python代码,但无法完成。基本上是相同的问题,但是在haskell中没有循环。
Splitting a word into all possible 'subwords' - All possible combinations
下面的代码输出是...
[“ sun”,“ su”,“ s”,“ un”,“ u”,“ n”]
不是
[[“ s”,“ un”],[“ s”,“ u”,“ n”],[“ su”,“ n”]]
-----------------------------------------------------
substring :: String -> [String]
substring [] = []
substring xs = subs xs ++ substring (tail xs)
where
subs xs = foldl step [] xs
step [] a = [[a]]
step acc a = (head acc ++ [a]) : acc
---------------EXAMPLES OF EXPECTED RESULTS BELOW----------------------------------
Input: Bang
Output: [['B','ang'], ['Ba','ng'], ['Ban','g'], ['B','a','ng'], ['B','an','g'], ['Ba','n','g'], ['B','a','n','g']]
Input: Sun
Output: [["s","un"],["s","u","n"],["su","n"]]
答案 0 :(得分:2)
请注意,您尝试的类型签名是错误的。您需要所有子词拆分的组合,这是一个字符串列表的列表,但是您的类型只是一个字符串列表的列表。
这将起作用:
onHead :: (a -> a) -> [a] -> [a]
onHead _ [] = []
onHead f (x:xs) = f x:xs
combos :: [a] -> [[[a]]]
combos [] = [[]]
combos [x] = [[[x]]]
combos (x:xs) = [([x]:), onHead (x:)] <*> combos xs
onHead
应该是不言自明的:在列表的开头执行给定的功能。 combos
的重复过程如下:字符串的子词是其尾部的子词,每个子词都有两种可能性:头是其自己的子词,或者被钉在第一个子词的开头。
更新:这是另一种(IMO清洁器)方法:
combos :: Foldable t => t a -> [[[a]]]
combos = foldr (concatMap . go) [[]]
where go x l = ([x]:l):case l of
[] -> []
h:t -> [(x:h):t]
它使用与上述相同的技术,只是实现了更简洁的实现。
答案 1 :(得分:1)
递归可以为您提供帮助。假设我们有一个非空列表x : xs
。我们想知道subString (x : xs)
。我们将解决方案递归应用于xs
,因此subString xs
是xs
的所有解决方案的列表。但是,我们仍然只有那个x
。完全有两种方法可以将x
的解决方案带回x : xs
,其中涵盖了subString (x : xs)
的整个解决方案集:
x
带回而没有将其附加到其邻居。如果我们有x : xs = "Bang"
,则x
将是'B'
,而xs
将是"ang"
,而subString "ang"
将是[["ang"],["an","g"],["a","ng"],["a","n","g"]]
。这是由[[x] : u | u <- subString xs]
完成的。这里的u
是字符串列表,例如["a","ng"]
。因为x
是一个字符,所以我们必须将其转换为字符串,这是通过[x]
完成的,将其附加到列表的开头是[x] : u
,因此["B","a","ng"]
。列表推导将对subString xs
中的所有元素执行此操作。 x
重新附加到其邻居。 subString xs
的任意解决方案看起来像u : us
。我们想将x
附加到u : us
的第一个元素u
上。 x : u
这样。例如u : us = ["a","n","g"]
,因此u
将是"a"
,而us
将是["n","g"]
。将'B'
附加到"a"
由'B' : "a"
完成,将得到"Ba"
。我们必须将"Ba
放回列表中,以便(x : u) : us
。列表comp [rehension看起来像[(x : u) : us | (u : us) <- subString xs]
。我们仍然只剩下一个字符的字符串。我们为此写[x]
,其中x
是单个字符。因此subString [x]
将是[[[x]]]
。
我们必须将解决方案结合在一起
subString :: String -> [[String]]
subString [x] = [[[x]]]
subString (x : xs) = [(x : u) : us | (u : us) <- subString xs] ++ [[x] : u | u <- subString xs]
示例
*Main> subString "Bang"
[["Bang"],["Ban","g"],["Ba","ng"],["Ba","n","g"],["B","ang"],["B","an","g"],["B","a","ng"],["B","a","n","g"]]