我必须编写一个带两个数字的函数并执行此操作:
placeOneBlock 1 5
["feeee", "efeee", "eefee", "eeefe", "eeeef"]
因此,它使用n *“f”-s和m-n *“e”-s进行m长列表的每个排列。如果n> 1比“f”-s应该留在一组这样:
placeOneBlock 3 10
["fffeeeeeee", "efffeeeeee", "eefffeeeee", "eeefffeeee", "eeeefffeee", "eeeeefffee", "eeeeeefffe", "eeeeeeefff"]
我写了这个函数:
placeOneBlock n m = permutations (replicate n 'f' ++ replicate (m-n) 'e')
但是这将“e”-s视为独特的元素,因此比我需要的更多的排列,如果n>也不起作用。 1.我怎么能这样做?
答案 0 :(得分:2)
这是一个暗示。
每种可能的组合都有一些E,一些F和一些E,按此顺序。即,它是这种形式
replicate k 'e' ++ replicate n 'f' ++ replicate (m-n-k) 'e'
现在,让k
范围超过"右边"间隔,使用列表理解,你已经完成了。
答案 1 :(得分:1)
正如我在评论中提到的,这根本不是排列问题。相反,您希望遍历输入流,只选择一个位置来插入交叉字符块。如果输入流为空,则您无法选择,并且必须在末尾插入块。否则,您可以选择在当前位置插入块,或者稍后插入块,在这种情况下,您可以在块之前在主流中包含一个以上的项目。
replicate x 'e' ++ replicate y 'f' ++ replicate z 'e'
这个解决方案比chi的答案要复杂得多,后者建议为所有适当的x / y / z选择写Local
之类的东西。我的解决方案的一个好处是,修改处理多个块对象而不仅仅是一个或其他一些指示块合法的规则要简单得多。但是如果你没有预料到这种变化,那么chi的解决方案听起来不错。
答案 2 :(得分:0)
我想这与排列无关。这是一个简单的拆分和插入所有位置的工作。您可以按如下方式实施;
allSplits :: Int -> Int -> [String]
allSplits 0 m = [replicate m 'e']
allSplits n m | n >= m = [fs]
| otherwise = (fs ++ replicate (m-n) 'e') : map ('e':) (allSplits n (m-1))
where fs = replicate n 'f'
答案 3 :(得分:0)
以下是工作代码:
placeOneBlock 0 m = [replicate m 'e']
placeOneBlock n m | n == m = [fs]
| n > m = []
| otherwise = (fs ++ replicate (m-n) 'e') : map ('e':) (placeOneBlock n (m-1))
where fs = replicate n 'f'