实施Bogosort


29

解决数独太辛苦?甚至是蛮力版本?这是一个编码练习,要容易一些。我希望。:-P

编写最短的函数来实现bogosort。具体来说,您的功能应:

  • 以数组(或您的语言的等效形式)作为输入
  • 检查其元素是否按顺序排列;如果是这样,返回数组
  • 如果不是,请重新排列元素,然后重新开始

入围时间最短者获胜。在平局的情况下,支持自定义比较器(和/或伪随机数生成器)的函数会受到青睐。通过支持较早的提交,可以解决任何剩余的联系。


说明:当然,您可以使用所需的任何元素类型,只要可以通过某种方式订购它们即可。而且,改组必须是统一的;这与“我将快速排序并改组”无关。:-)


元素类型是什么?整数还是字符串?
亚历山德鲁

@Alexandru:都可以。你选。
克里斯·杰斯特·杨

添加自定义比较器将增加代码长度,因此获胜作品将没有自定义比较器。我认为打破平局没有任何意义。
亚历山德鲁

1
使用伪随机生成器时,此算法可能会失败。例如,当列表的长度超过2000时,就是2000!列表的状态可能超出prng的内部状态数。
gnibbler'2

2
是的,来自维基百科的相关引文“但是,如果使用伪随机数生成器代替随机源,则它可能永远不会终止,因为它们表现出长期的循环行为。”
gnibbler'2

Answers:


8

APL(Dyalog),20

{⍵≡⍵[⍋⍵]:⍵⋄∇⍵[?⍨⍴⍵]}

说明

是(正确的)参数
⍵≡⍵[⍋⍵]:检查排序是否等于自身
:⍵:如果是,则返回
∇⍵[?⍨⍴⍵]:否则,以随机顺序生成1到⍴⍵(长度为)的数组,根据该(⍵[...])重新排序,并将函数应用于该(


突然重温这个问题并...

APL(Dyalog),19岁

{∧/2≤/⍵:⍵⋄∇⍵[?⍨⍴⍵]}

只是考虑对检查中的数组进行排序使其毫无意义(并不是说Bogosort是有意义的),因此将是一种更准确的实现∧/2≤/⍵,并且恰好降低了字符数。


15

Perl 6:23个字符

@s.=pick(*)until[<=] @s

1
这是Perl中的功能吗?看起来不错:)
Eelvex

1
如果您不知道,请[<=]检查列表是否已排序:[<=] (1, 2, 3,) == (1 <= 2 <= 3) == (1 <= 2) and (2 <= 3),然后.pick(n)从列表中选择n个随机元素,然后.pick(*)让Perl选择所有元素。use.perl.org/~masak/journal/40459
Ming-Tang

必须是Perl6。我以前从未见过pick使用过,更不用说了[<=]。这些在文档中的哪里?
拉玛先生先生2013年

@GigaWatt这是Perl 6(不是Perl 5)。[]是归约运算符,它将运算符放在方括号之间。例如,[<=] 1, 2, 3is 1 <= 2 <= 3(是的,您在Perl 6中执行了这样的范围)。在这种情况下,它用于确定元素是否有序。.pick(*)方法会随机播放列表(从列表中pick(N)选择N元素)。.=调用方法,并将结果分配给变量。至于文档-好吧,目前仅存在Perl 6规范-feather.perl6.nl/syn,但是它存在。
Konrad Borowski14年

7

APL(22)

{(⍳X←⍴⍵)≡⍋⍵:⍵⋄∇⍵[X?X]}

用法:

    {(⍳X←⍴⍵)≡⍋⍵:⍵⋄∇⍵[X?X]} 3 2 1
1 2 3

说明:

  • ⍋⍵:按排序顺序返回项目的索引,因此⍋30 10 20给出2 1 3
  • (⍳X←⍴⍵)≡⍋⍵:⍵将输入列表的长度存储在X中。如果range [1..X]等于排序的索引顺序,则对列表进行排序,因此将其返回。
  • ⋄∇⍵[X?X]:如果不是这种情况,请使用随机数组递归。

7

Ruby-33个字符

g=->l{l.shuffle!!=l.sort ?redo:l}

少1个字符:g=proc{|l|0until l.sort==l.shuffle!}
AShelly 2012年

@AShelly,您的版本不起作用。我的版本(少5个字符)f=->l{l.sort!=l.shuffle!?redo:l}(Ruby 1.9)
Hauleth 2012年

有人可以向我解释为什么redo使用a proc而不是经典方法def...end吗?我以为redo只适用于循环?
Patrick Oscity 2012年

1
好的,没关系,我在“ Ruby编程语言”书中找到了一些东西:“ redo[…]将控制权转移回proc或lambda的开头。” 就是这样。
Patrick Oscity 2012年

6

数学40 37

NestWhile[RandomSample,#,Sort@#!=#&]&

带空格:

NestWhile[RandomSample, #, Sort@# != # &] &

如果您忽略错误,则可以使用#//.l_/;Sort@l!=l:>RandomSample@l&
Martin Ender

Mthmca中的13sh字节。
Michael Stern

5

J- 34 27

f=:({~?~@#)^:(1-(-:/:~))^:_

例如:

f 5 4 1 3 2
1 2 3 4 5

f 'hello'
ehllo

{~~ @#部分打乱输入:

({~ ?~@#) 1 9 8 4
4 8 9 1
({~ ?~@#) 'abcd'
bdca

3

Python 61

排序到位。

import random
def f(l):
 while l!=sorted(l):random.shuffle(l)

您的函数不会在成功时返回数组。
hallvabo,2011年

排序到位。传递的数组被修改。
亚历山德鲁

问题确实表明该函数虽然应该返回数组,即使从技术上讲不是必须要获得结果的。
乔纳森·M·戴维斯

1
from random import*可以保存一个字符。
ugoren

1
这可能并不总是有效:(来自python随机模块文档):“请注意,即使len(x)很小,x的排列总数也比大多数随机数生成器的周期大;这意味着x的大多数排列永远不会产生长序列。”
马特

3

Python 94

from itertools import*
def f(a):return [x for x in permutations(a) if x==tuple(sorted(a))][0]

其他python答案使用random.shuffle()。python random模块的文档指出:

请注意,即使len(x)很小,x的排列总数也比大多数随机数生成器的周期大。这意味着长序列的大多数排列永远不会生成。


代之以lambda;我认为它会更短。另请注意,您可以执行return[x...而不是return [x...。与permutations(a) if- 相同-可能是permutations(a)if
0WJYxW9FMN

lambda a: [x for x in __import__("itertools").permutations(a) if x==tuple(sorted(a))][0]是88个字节
著名1622

3

K,31 25

{while[~x~x@<x;x:x@(-#x)?#x];x}

{x@(-#x)?#x}/[{~x~x@<x};]

k){x@(-#x)?#x}/[{~x~x@<x};] 3 9 5 6 7 9 1
`s#1 3 5 6 7 9 9

k){x@(-#x)?#x}/[{~x~x@<x};] "ascsasd"
`s#"aacdsss"

2

Python(69个字符)

from random import*
def f(a):
 while a>sorted(a):shuffle(a)
 return a

以递增数字顺序对整数排序。请注意,递归解决方案

from random import*;f=lambda a:a>sorted(a)and(shuffle(a)or f(a))or a

由于即使很小的输入(例如N> 5)的堆栈溢出也会失败,因为Python不会进行尾部调用优化。


2

D,不带自定义比较器:59个字符

R f(R)(R r){while(!isSorted(r))r.randomShuffle();return r;}

更清晰:

R f(R)(R r)
{
    while(!r.isSorted)
        r.randomShuffle();

    return r;
}

带自定义比较器的D:69个字符

R f(alias p,R)(R r){while(!isSorted!p(r))r.randomShuffle();return r;}

更清晰:

R f(alias p, R)(R r)
{
    while(!isSorted!p(r))
        r.randomShuffle();

    return r;
}

2

Scala 73:

def s(l:Seq[Int]):Seq[Int]=if(l==l.sorted)l else s(util.Random.shuffle l)

在Scala中,我们可以检查编译器是否进行了尾部调用优化:

@annotation.tailrec
def s(l:Seq[Int]):Seq[Int]=if(l==l.sorted)l else s(util.Random shuffle l)

是的,它做到了。但是,对于100个值的简短列表:

val rList = (1 to 100).map(x=>r.nextInt (500))
s(rList) 

花了将近4个月的时间才能完成。;)


2

C#(184个字符)

T[]S<T>(T[]i)where T:IComparable<T>{T l=default(T);while(!i.All(e=>{var r=e.CompareTo(l)>=0;l=e;return r;})){i=i.OrderBy(a=>Guid.NewGuid()).ToArray();l=default(T);}return i.ToArray();}

用C#做到这一点并不是很好。您必须支持泛型以支持值和引用类型。没有数组随机播放功能或检查某项是否已排序的功能。

有人有任何技巧可以使它变得更好吗?

编辑版本仅对int进行排序(134个字符):

int[]S(int[]i){var l=0;while(!i.All(e=>{var r=e>=l;l=e;return r;})){i=i.OrderBy(a=>Guid.NewGuid()).ToArray();l=0;}return i.ToArray();}

2

GNU /重击65

b(){ IFS=$'\n';echo "$*"|sort -C&&echo "$*"||b $(shuf -e "$@");}

嗯,由于bash函数只能从字面上返回一个无符号字节,我是否可以得到一个特殊的异常来返回数组规则?
2013年

2

C ++ 11,150个字符

#include<deque>
#include<algorithm>
void B(std::deque &A){while(!std::is_sorted(A.begin(),A.end())std::random_shuffle(myvector.begin(),myvector.end());}

只是..取笑。


1
std :: random_shuffle不一致。在说明中指出:“此外,改组必须统一”
STDQ

好吧...我不知道那不是统一的。

它依赖于不统一的rand()-请参阅open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3924.pdf。似乎没有多少其他人关注,所以我想这没什么大不了的。
STDQ

所以,如果我使用像srand(time(0))这样的完全随机变量,那算不算?

问题是不能保证兰德具有良好的随机数质量,更不用说均匀性了,有些会产生非随机的低阶位。我想这最后也没有关系。使用带有std :: shuffle等的统一分发器,我再只有8个字节,对我来说足够好了。
STDQ

2

Python-61个字符

递归的

from random import*;f=lambda l:l==sorted(l)or shuffle(l)>f(l)

您的函数返回True或False,而不是数组。
hallvabo

2
还要注意,即使对于少量输入,递归解决方案注定也会失​​败。
hallvabo 2011年

1
@hallvabo:实际上,我实际上想在Scheme中编写一个尾递归解决方案,这当然不会耗尽您的堆栈。
克里斯·杰斯特·杨

@ hallvabo,Alexandru已经完成了显而易见的Python解决方案,所以我只是在这里做一些不同的事情。当然,递归解决方案只是出于娱乐目的,而不是一个
有力的

from random import*可能会更短。
0WJYxW9FMN

2

PowerShell85 82 56 55 52字节

-26个字节,感谢mazzy的建议
--1个字节,感谢AdmBorkBork
-3个字节,感谢mazzy

for($l=$args;"$l"-ne($l|sort)){$l=$l|sort{random}}$l

在线尝试!

通过将它们转换为字符串并进行比较,PowerShell确实具有相对便宜的数组比较。


2
param初始化移到for初始化中以保存一个字节for($l=$args;
AdmBorkBork

1
很好 -ne将右运算符转换为左运算符的标量类型。因此,您可以节省一些字节:在线尝试!
mazzy

1

Javascript 291个字符

function f(e){var t=[].concat(e).sort();t.e=function(e){var n=true;t.forEach(function(t,r){if(t!=e[r])n=false});return n};while(!t.e(e.sort(function(){return Math.floor(Math.random()*2)?1:-1}))){console.log(e)}return e}

最小

function f(a) {
var b = [].concat(a).sort();
b.e = function (z) {
    var l = true;
    b.forEach(function (v, i) {
        if (v != z[i]) l = false;
    });
    return l
};
while (!b.e(a.sort(function () {
    return Math.floor(Math.random() * 2) ? 1 : -1;
}))) {
    console.log(a);
}
return a;
}

我之前已经说过,但是您可以删除所有vars。只需使它们成为所有隐式全局变量,就可以使代码尽可能短。
gcampbell '16

1

Matlab,59个字节

相对简单的方法:

x=input('');while~issorted(x);x=x(randperm(numel(x)));end;x

1

J,22个字节

$:@({~?~@#)`]@.(-:/:~)

这是使用议程的递归默认默纳德。运作方式如下:

y我们的List。首先,议程右侧的动词是-:/:~。这个动词由Leaky Nun慷慨地提供。-:是否/:~使用单子钩对输入进行排序()匹配()。((f g) y = y f (g y))相应地返回一或零。议程的左侧是两个动词的动名词:右侧是恒等动词],而左侧是递归发生的地方。议程选择无论是在位置上的身份动词1如果列表排序,动词较长的位置0,如果列表排序。

$:@({~?~@#)$:{~?~@#on 的结果上方调用(包含它的最长动词)y。这会随机排列索引为,对列表进行改编,并?~@#采用长度的排列y方式y{~在单子钩子中,返回列表,y其索引为正确的arg。然后,此混编的列表将再次与议程一起调用,并重复进行直到分类。


1

C ++ 14,158个字节

#include <algorithm>
#include <random>
[](int*a,int s){std::random_device r;for(std::knuth_b g(r());!std::is_sorted(a,a+s);std::shuffle(a,a+s,g));return a;};

1

果冻,6个字节,语言发布日期挑战

ẊŒ¿’$¿

在线尝试!

说明

ẊŒ¿’$¿
     ¿  While
 Œ¿’$     the input is not in its earliest possible permutation (i.e. sorted)
Ẋ       shuffle it

Œ¿为列表的每个排列分配一个数字;1被排序,2被交换了最后两个元素,依此类推,直到列表长度的阶乘(这是相反顺序的列表)。因此,对于一个已排序的列表,它的值为1,我们可以使用递减该值,以产生一个“未排序”的测试,该测试在while循环条件下可用作布尔值。的$是使状态解析为一组。


1

C ++,166字节

#import<algorithm>
#import<random>
#define r b.begin(),b.end()
template<class v>
v f(v b){auto a=std::mt19937();while(!std::is_sorted(r))std::shuffle(r,a);return b;}

这应该在所有具有begin()end()

取消高尔夫:

#include <algorithm>
#include <random>
template <class v>
v f(v b) {
    auto a = std::mt19937();
    while (!std::is_sorted(b.begin(),b.end()))
        std::shuffle(b.begin(),b.end(),a);

    return b;
}


1

Brachylog,5个字节

∈&ṣ≤₁

在线尝试!

当我第一次看到ais523的Brachylog答案(与他的Jelly答案相对,因为如果我没记错的话user62131也是他),我想知道它是否使用回溯而不是递归?所以起初,我尝试过ṣ≤₁。事实证明,由于随机选择某事物不会产生太多输出,而只是不确定地产生一个输出,因此不能将shuffle谓词回溯到原来的状态,因此除非您有幸将其正确洗掉,否则运行将失败第一次尝试。之后,我尝试了pṣ≤₁大部分时间都起作用的方法,但是由于有限的长列表具有有限的排列,因此有时仍然会随机失败。放弃了减少长度的目标之后,我终于想到了:

         The input
∈        is an element of
         an unused implicit variable,
 &       and the input
  ṣ      shuffled randomly
   ≤₁    which is increasing
         is the output.

(随机性的证明)

虽然如果我们对I / O采取一些自由措施的话,实际上可能会更短一些。

Brachylog,4个字节

⊆ṣ≤₁

在线尝试!

为了使输出有用,输入中不得包含任何重复元素,因为此bogosort谓词除了对输入进行排序外,还会添加随机数量的重复元素和零。(从理论上讲,它可以添加任何内容,但实际上并没有。)通常,我不会不提任何无法正常工作的内容,但我觉得这是挑战的精神。

⊆        An ordered superset of the input
 ṣ       shuffled randomly
  ≤₁     which is increasing
         is the output.

1

Perl 6,28个字节

{({.pick(*)}...~.sort).tail}

在线尝试!

匿名代码块,将列表随机排序直到排序。请注意,它至少对列表排序一次,这是允许的。不,{.pick(*)}不能用*.pick(*)


1

Pyth,11个字节

Wn=Q.SQSQ;Q

对此很满意,也许可以再打些高尔夫球

说明


Wn=Q.SQSQ;Q
W    While
  =Q.SQ    Variable Q (input variable) shuffled 
 n  Does not equal
       SQ    Variable Q sorted
             ;  Do nothing (loop ends)
              Q    And output variable Q

在线尝试!


您可以缩短=Q.SQ=.SQ-1个字节(也可以与其他运算符一起使用,例如=QhQ-> =hQ
ar4093

1

Japt11个 9 字节

_eZñ}a@öx

试试吧

_eZñ}a@öx     :Implicit input of array U
_             :Function taking an array as argument via parameter Z
 e            :  Test Z for equality with
  Zñ          :  Z sorted
    }         :End function
     a        :Repeat and return the first result that returns true
      @       :Run this function each time and pass the result to the first function
       öx     :  Random permutation of U

1

Brachylog(v2),5个字节

≤₁|ṣ↰

在线尝试!

功能提交。(TIO链接使用命令行参数,该参数自动将功能包装到完整程序中。)

说明

≤₁|ṣ↰
≤₁      Assert that {the input} is (nonstrictly) sorted in ascending order
  |     Output it
  |     Exception handler: if an assertion fails:
   ṣ      Randomly shuffle {the input}
    ↰     and run this function recursively on it, {outputting its output}

Prolog(Brachylog编译成的语言)是尾递归的,因此该函数最终被编译成紧密循环。


0

C(203个字符,无输入循环:仅函数)

#include <stdio.h>
#define P (int*a,int n){
#define F for(i=0;i<n;i++){
int i,j,v;s P F if(a[i]>a[i+1])return 0;}return 1;}void h P F v=a[i];a[i]=a[j=rand()%n];a[j]=v;}}void b P while(!s(a,n-1))h(a,n);}

这与以下内容相同,我们也从stdin中读取数组并写出排序后的数组。由于Q要求功能而不是整个程序...

C(296个字符)

#include <stdio.h>
#define P (int*a,int n){
#define F for(i=0;i<n;i++){
int i,j,n,v,x[999];s P F if(a[i]>a[i+1])return 0;}return 1;}void h P F j=rand()%n;v=a[i];a[i]=a[j];a[j]=v;}}void b P while(!s(a,n-1))h(a,n);}main(){while(scanf("%d",&v)==1)x[n++]=v;if(!s(x,n))b(x,n);F printf("%d\n",x[i]);}}

编译可能会发出警告(隐式声明)。Hardencoded数组的大小限制为999个元素。脆弱。

如果不需要预先检查数组是否已排序,则可以在284中完成。

C(251个字元,当时为284)

#include <stdio.h>
#define F for(i=0;i<n;i++){
int i,j,n,v,a[999];s(int n){F if(a[i]>a[i+1])return 0;}return 1;}void h(){F v=a[i];a[i]=a[j=rand()%n];a[j]=v;}}void b(){while(!s(n-1))h();}main(){while(scanf("%d",&a[n++])>0);b();F printf("%d\n",a[i]);}}

(使用全局变量而不是函数args)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.