此问题中 myAny函数的代码使用foldr.当谓词满足时,它会停止处理无限列表.
我用foldl重写了它:
myAny :: (a -> Bool) -> [a] -> Bool
myAny p list = foldl step False list
where
step acc item = p item || accRun Code Online (Sandbox Code Playgroud)
(请注意,步骤函数的参数已正确反转.)
但是,它不再停止处理无限列表.
我试图在Apocalisp的答案中跟踪函数的执行情况:
myAny even [1..]
foldl step False [1..]
step (foldl step False [2..]) 1
even 1 || (foldl step False [2..])
False || (foldl step False [2..])
foldl step False [2..]
step (foldl step False [3..]) 2
even 2 || (foldl step False [3..])
True || (foldl …Run Code Online (Sandbox Code Playgroud) 普遍认为n个不同符号的列表有n!排列.然而,当符号不明显时,在数学和其他地方最常见的惯例似乎只计算不同的排列.因此,列表的排列[1, 1, 2]通常被认为是
[1, 1, 2], [1, 2, 1], [2, 1, 1].实际上,以下C++代码正好打印出这三个:
int a[] = {1, 1, 2};
do {
cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
} while(next_permutation(a,a+3));
Run Code Online (Sandbox Code Playgroud)
另一方面,Python itertools.permutations似乎打印其他东西:
import itertools
for a in itertools.permutations([1, 1, 2]):
print a
Run Code Online (Sandbox Code Playgroud)
这打印
(1, 1, 2)
(1, 2, 1)
(1, 1, 2)
(1, 2, 1)
(2, 1, 1)
(2, 1, 1)
Run Code Online (Sandbox Code Playgroud)
正如用户Artsiom Rudzenka在一个答案中指出的那样,Python文档说:
元素根据其位置而不是其价值被视为唯一元素.
我的问题:为什么做出这个设计决定?
似乎遵循通常的惯例会给出更有用的结果(事实上它通常正是我想要的)......或者是否存在一些我缺少的Python行为应用?
[或者是一些实施问题?这里的算法next_permutation- 例如在StackOverflow上解释(由我)并在这里显示为O(1)摊销 - 在Python中似乎是高效和可实现的,但是Python做了更有效的事情,因为它不保证基于词典顺序价值?如果是这样,效率的提高是否值得呢?]
我需要迭代地计算排列.方法签名如下:
int[][] permute(int n)
为了n = 3例如,返回值将是:
[[0,1,2],
[0,2,1],
[1,0,2],
[1,2,0],
[2,0,1],
[2,1,0]]
Run Code Online (Sandbox Code Playgroud)
您将如何以最有效的方式迭代地执行此操作?我可以递归地执行此操作,但我有兴趣看到许多替代方法来迭代地执行此操作.
要求:生成集合的所有可能组合的算法,无需重复,或递归调用函数以返回结果.
大多数,如果不是所有的答案都在JavaScript中的Permutations提供?从循环或其他函数中递归调用函数以返回结果.
循环内的递归函数调用示例
function p(a, b, res) {
var b = b || [], res = res || [], len = a.length;
if (!len)
res.push(b)
else
for (var i = 0; i < len
// recursive call to `p` here
; p(a.slice(0, i).concat(a.slice(i + 1, len)), b.concat(a[i]), res)
, i++
);
return res
}
p(["a", "b", "c"]);
Run Code Online (Sandbox Code Playgroud)
当前的问题试图在线性过程中创建给定的排列,依赖于先前的排列.
例如,给定一个数组
var arr = ["a", "b", "c"];
Run Code Online (Sandbox Code Playgroud)
确定可能的排列总数
for (var len = 1, i = k …Run Code Online (Sandbox Code Playgroud) 我正在研究一个涉及解决中国邮递员问题的课程.我们的任务只要求我们编写一个程序来解决它的硬编码图,但我试图在我自己的一般情况下解决它.
给我带来麻烦的部分是为奇数顶点生成配对分区.
例如,如果我在图中有以下标记的奇数顶点:
1 2 3 4 5 6
Run Code Online (Sandbox Code Playgroud)
我需要找到我可以用这些顶点做出的所有可能的配对/分区.
我发现我会i给出分配:
n = num of odd verticies
k = n / 2
i = ((2k)(2k-1)(2k-2)...(k+1))/2^n
Run Code Online (Sandbox Code Playgroud)
因此,考虑到上面的6个奇数顶点,我们将知道我们需要生成i = 15分区.
15个部分看起来像:
1 2 3 4 5 6
1 2 3 5 4 6
1 2 3 6 4 5
...
1 6 ...
Run Code Online (Sandbox Code Playgroud)
然后,对于每个分区,我取每对,找到它们之间的最短距离,并为该分区求和.选择其对之间具有最小总距离的分区,然后我将奇数顶点之间的最短路径(在所选分区中找到)之间的所有边加倍.
这些代表邮递员必须走两次的边缘.
起初我以为我已经制定了适当的算法来生成这些分区:
从按升序排序的所有奇数顶点开始
12 34 56选择当前具有最大顶点的对后面的对
12 [34] 56将此对中的第二个数字增加1.将所选对的左侧所有内容保持相同,并使所选对中右侧的所有数字与集合中的其余数字一致,按递增顺序排序.
12 35 46重复
但是,这是有缺陷的.例如,我意识到当我到达最后并且选择对位于最左侧位置(即)时:
[16] .. ..
我计算出来的算法在这种情况下会停止,而不会生成其余开始的对[16],因为它的左边没有对可以改变.
所以,它又回到了绘图板.
之前有没有研究过这个问题的人是否有任何提示可以帮助我指出正确的方向来生成这些分区?
出于特殊的原因,我决定寻找一种算法,该算法产生1 ... n之间k个整数的所有可能选择,其中k整数中的顺序无关紧要(n选择k thingy).
从完全相同的原因,这是没有理由的,我也用C#实现了它.我的问题是:
你在我的算法或代码中看到任何错误吗?而且,更重要的是,你能建议一个更好的算法吗?
请注意算法而不是代码本身.这不是我写过的最漂亮的代码,虽然可以告诉你是否看到了错误.
编辑: Alogirthm解释 -
码:
public class AllPossibleCombination
{
int n, k;
int[] indices;
List<int[]> combinations = null;
public AllPossibleCombination(int n_, int k_)
{
if (n_ <= 0)
{
throw new ArgumentException("n_ must be in N+");
}
if (k_ <= 0)
{
throw new ArgumentException("k_ must be in N+");
}
if (k_ …Run Code Online (Sandbox Code Playgroud) 我想知道是否有关于在Lisp中使用标签的标准做法.我一直在讨论第一个答案中描述的算法的Lisp实现这里懒惰地生成排列 我当前版本使用标签来突破部分功能.
(defun next-permutation (pmute)
(declare (vector pmute))
(let ((len (length pmute)))
(if (> len 2)
(labels ((get-pivot ()
(do ((pivot (1- len) (1- pivot)))
((or (= pivot 0)
(< (aref pmute (1- pivot))
(aref pmute pivot)))
pivot)))
(get-swap (pivot)
(let ((swp (1- len)))
(loop for i from (1- len) downto pivot do
(if (or (and (> (aref pmute i)
(aref pmute (1- pivot)))
(< (aref pmute i) (aref pmute swp)))
(< (aref pmute swp) (aref pmute (1- pivot)))) …Run Code Online (Sandbox Code Playgroud) 功能:
给定列表lst返回列表的内容的所有排列,其长度为k,如果未提供,则默认为列表的长度.
(defun permute (lst &optional (k (length lst)))
(if (= k 1)
(mapcar #'list lst)
(loop for item in lst nconcing
(mapcar (lambda (x) (cons item x))
(permute (remove-if (lambda (x) (eq x item)) lst)
(1- k))))))
Run Code Online (Sandbox Code Playgroud)
问题:我在连接到sbcl的emacs中使用SLIME,我还没有做太多的自定义.该功能在较小的输入上工作正常,例如lst ='(1 2 3 4 5 6 7 8)k = 3,这在实践中主要用于它.但是,当我连续两次使用大输入调用它时,第二个调用永远不会返回,而sbcl甚至不会显示在顶部.这些是REPL的结果:
CL-USER> (time (nth (1- 1000000) (permute '(0 1 2 3 4 5 6 7 8 9))))
Evaluation took:
12.263 seconds of real time
12.166150 seconds of total run time (10.705372 user, …Run Code Online (Sandbox Code Playgroud) 我有一个很大的元素列表,我想以随机顺序迭代.但是,我无法修改列表,我也不想创建它的副本,因为1)它很大,2)可以预期迭代会提前取消.
List<T> data = ...;
Iterator<T> shuffled = shuffle(data);
while (shuffled.hasNext()) {
T t = shuffled.next();
if (System.console().readLine("Do you want %s?", t).startsWith("y")) {
return t;
}
}
System.out.println("That's all");
return t;
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个算法,上面的代码将运行O(n)(并且最好只需要O(log n)空格),因此缓存之前生成的元素不是一个选项.我不在乎算法是否有偏差(只要它不明显).
(我在我的问题中使用伪Java,但如果你愿意,你可以使用其他语言)
这是我到目前为止最好的.
Iterator<T> shuffle(final List<T> data) {
int p = data.size();
while ((data.size() % p) == 0) p = randomPrime();
return new Iterator<T>() {
final int prime = p;
int n = 0, i = 0;
public boolean hasNext() { return i < …Run Code Online (Sandbox Code Playgroud) 我有一个N项目列表,我想知道如何循环列表以获得每个组合.没有双打,所以我需要得到全部N!排序.额外的内存没有问题,我正在考虑最简单的算法,但我遇到了麻烦.
algorithm ×7
permutation ×5
common-lisp ×2
lisp ×2
math ×2
c# ×1
c++ ×1
coding-style ×1
combinators ×1
f# ×1
factorial ×1
fold ×1
haskell ×1
javascript ×1
python ×1
recursion ×1
sbcl ×1
shuffle ×1
slime ×1