如何定义旋转函数
如何定义一个旋转函数来生成给定列表的所有旋转?
例如:旋转 [1,2,3,4] =[[1,2,3,4],[2,3,4,1],[3,4,1,2],[4 ,1,2,3]]
我编写了一个可以重新排列顺序的移位函数
shift ::[Int]->[Int]
shift x=tail ++ take 1 x
,但我不知道如何生成这些新数组并将它们附加在一起。
How to define a rotates function that generates all rotations of the given list?
For example: rotates [1,2,3,4] =[[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]]
I wrote a shift function that can rearrange the order
shift ::[Int]->[Int]
shift x=tail ++ take 1 x
but I don't how to generate these new arrays and append them together.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
计算列表所有旋转的另一种方法是使用预定义函数
tails
和inits
。函数tails
生成列表中所有最终段的列表,而inits
生成所有初始段的列表。例如,也就是说,如果我们按照缩进指示逐点连接这些列表,我们就会得到所有旋转。我们只得到原始列表两次,即一次通过将空的初始段附加到原始列表的末尾,一次通过将空的最终段附加到原始列表的前面。因此,我们使用函数
init
来删除将zipWith
应用到列表的 tails 和 inits 的结果的最后一个元素。函数 zipWith 将其第一个参数逐点应用于提供的列表。该解决方案比其他解决方案具有优势,因为它不使用
length
。函数length
相当严格,因为它在完全评估其参数的列表结构之前不会产生结果。例如,如果我们评估应用程序,即计算自然数无限列表的所有旋转,ghci 会愉快地开始打印无限列表作为第一个结果。相反,像这里建议的基于
length
的实现不会终止,因为它计算无限列表的长度。Another way to calculate all rotations of a list is to use the predefined functions
tails
andinits
. The functiontails
yields a list of all final segments of a list whileinits
yields a list of all initial segments. For example,That is, if we concatenate these lists pointwise as indicated by the indentation we get all rotations. We only get the original list twice, namely, once by appending the empty initial segment at the end of original list and once by appending the empty final segment to the front of the original list. Therefore, we use the function
init
to drop the last element of the result of applyingzipWith
to the tails and inits of a list. The functionzipWith
applies its first argument pointwise to the provided lists.This solution has an advantage over the other solutions as it does not use
length
. The functionlength
is quite strict in the sense that it does not yield a result before it has evaluated the list structure of its argument completely. For example, if we evaluate the applicationthat is, we calculate all rotations of the infinite list of natural numbers, ghci happily starts printing the infinite list as first result. In contrast, an implementation that is based on
length
like suggested here does not terminate as it calculates the length of the infinite list.iterate f x
返回流(“无限列表”)[x, fx, f (fx), ...]
。n
元素列表有n
次旋转,因此我们采用
其中的前n
次。iterate f x
returns the stream ("infinite list")[x, f x, f (f x), ...]
. There aren
rotations of ann
-element list, so wetake
the firstn
of them.以下
产量
正如您所期望的那样。
我认为这是相当可读的,尽管不是特别有效(没有记忆以前的班次)。
如果您关心效率,那么
将允许您重用之前班次的结果,并避免重新计算它们。
请注意,迭代返回一个无限列表,并且由于惰性计算,我们只将其计算到列表中的长度为l。
请注意,在第一部分中,我扩展了您的移位函数来询问移位多少,然后我对
allRotations
进行了列表理解。The following
yields
which is as you expect.
I think this is fairly readable, although not particularly efficient (no memoisation of previous shifts occurs).
If you care about efficiency, then
will allow you to reuse the results of previous shifts, and avoid recomputing them.
Note that
iterate
returns an infinite list, and due to lazy evaluation, we only ever evaluate it up tolength l
into the list.Note that in the first part, I've extended your shift function to ask how much to shift, and I've then a list comprehension for
allRotations
.到目前为止给出的答案对于有限列表来说效果很好,但当给出无限列表时最终会出错。 (它们都在列表中调用
length
。)我的解决方案使用
zipWith const
。zipWith const foos bar
乍一看可能与foos
相同(回想一下const xy = x
)。但是,当任一输入列表终止时,从 zipWith 返回的列表也会终止。因此,当 xs 有限时,返回的列表与 xs 的长度相同,正如我们所希望的那样;当 xs 为无限时,返回的列表不会被截断,因此将是无限的,再次如我们所愿。
(在您的特定应用程序中,尝试旋转无限列表可能没有意义。另一方面,它可能没有意义。我提交此答案只是为了完整性。)
The answers given so far work fine for finite lists, but will eventually error out when given an infinite list. (They all call
length
on the list.)My solution uses
zipWith const
instead.zipWith const foos bars
might appear at first glance to be identical tofoos
(recall thatconst x y = x
). But the list returned fromzipWith
terminates when either of the input lists terminates.So when
xs
is finite, the returned list is the same length asxs
, as we want; and whenxs
is infinite, the returned list will not be truncated, so will be infinite, again as we want.(In your particular application it may not make sense to try to rotate an infinite list. On the other hand, it might. I submit this answer for completeness only.)
我更喜欢以下解决方案,使用内置函数
cycle
和tails
:对于您的示例
[1,2,3,4]
函数cycle
生成一个无限列表[1,2,3,4,1,2,3,4,1,2...]
。函数tails
从给定列表生成所有可能的尾部,这里[[1,2,3,4,1,2...],[2,3,4,1, 2,3...],[3,4,1,2,3,4...],...]
。现在我们需要做的就是将“尾部”列表削减到长度 4,并将整个列表削减到长度 4,这是使用take
完成的。引入别名len
是为了避免多次重新计算length xs
。I would prefer the following solutions, using the built-in functions
cycle
andtails
:For your example
[1,2,3,4]
the functioncycle
produces an infinite list[1,2,3,4,1,2,3,4,1,2...]
. The functiontails
generates all possible tails from a given list, here[[1,2,3,4,1,2...],[2,3,4,1,2,3...],[3,4,1,2,3,4...],...]
. Now all we need to do is cutting down the "tails"-lists to length 4, and cutting the overall list to length 4, which is done usingtake
. The aliaslen
was introduced to avoid to recalculatelength xs
several times.我想它会是这样的(我现在没有ghc,所以我无法尝试)
I think it will be something like this (I don't have ghc right now, so I couldn't try it)
我建议:
I suggest: