Terapkan Bogosort


29

Apakah memecahkan Sudoku terlalu sulit? Bahkan versi brute force ? Inilah latihan coding yang sedikit lebih mudah. Saya harap. :-P

Tulis fungsi terpendek untuk mengimplementasikan bogosort. Secara khusus, fungsi Anda harus:

  • Ambil sebuah array (atau bahasa Anda yang setara) sebagai input
  • Periksa apakah elemen-elemennya dalam urutan diurutkan; jika demikian, kembalikan array
  • Jika tidak, kocok elemen, dan mulai lagi

Entri terpendek menang. Dalam kasus seri, fungsi yang mendukung komparator khusus (dan / atau generator nomor pseudorandom) disukai. Ikatan yang tersisa diselesaikan dengan mendukung pengajuan sebelumnya.


Klarifikasi: Anda dapat menggunakan jenis elemen apa pun yang Anda inginkan, asalkan ada beberapa cara untuk memesannya, tentu saja. Juga, pengocokan harus seragam; tak satu pun dari ini "Aku hanya akan cepat-cepat dan menyebutnya terseret" bisnis. :-)


Apa jenis elemennya? int atau string?
Alexandru

@Alexandru: Baik tidak masalah. Anda memilih.
Chris Jester-Young

Menambahkan pembanding khusus akan menambah panjang kode sehingga entri yang menang tidak akan memiliki pembanding khusus. Saya pikir melanggar dasi tidak masuk akal.
Alexandru

1
Ada kemungkinan bahwa algoritma ini dapat gagal saat menggunakan generator acak semu. misalnya ketika panjang daftar melebihi katakanlah 2000, ada 2000! menyatakan untuk daftar yang mungkin melebihi jumlah status antar prng.
gnibbler

2
Ya, kutipan yang relevan dari wikipedia "Namun, jika generator nomor pseudorandom digunakan sebagai pengganti sumber acak, itu mungkin tidak pernah berakhir, karena ini menunjukkan perilaku siklus jangka panjang."
gnibbler

Jawaban:


8

APL (Dyalog), 20

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

Penjelasan

adalah argumen (kanan)
⍵≡⍵[⍋⍵]: Memeriksa apakah diurutkan sama dengan dirinya sendiri
:⍵: Jika ya, lalu kembali
∇⍵[?⍨⍴⍵]: Lain, buat array 1 hingga ⍴⍵(panjang ) secara acak, susun ulang sesuai dengan itu ( ⍵[...]), dan terapkan fungsi itu ( )


Tiba-tiba meninjau kembali masalah ini dan ...

APL (Dyalog), 19

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

Hanya berpikir tentang mengurutkan array di cek membuatnya menjadi tidak berguna (tidak mengatakan bahwa Bogosort bermakna), implementasi yang lebih akurat akan terjadi ∧/2≤/⍵, dan itu terjadi untuk menurunkan jumlah char.


15

Perl 6: 23 karakter

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

1
Apakah ini fungsi dalam perl? Kelihatannya bagus :)
Eelvex

1
Jika Anda tidak tahu, [<=]periksa apakah daftar diurutkan :, [<=] (1, 2, 3,) == (1 <= 2 <= 3) == (1 <= 2) and (2 <= 3)dan .pick(n)pilih n elemen acak dari daftar, dan .pick(*)biarkan Perl memilih semua elemen. use.perl.org/~masak/journal/40459
Ming-Tang

Ini pasti Perl 6. Saya belum pernah melihat pickdigunakan sebelumnya, apalagi [<=]. Di mana dalam dokumentasi itu?
Tn. Llama

@ GigaWatt Ini Perl 6 (bukan Perl 5). []adalah mengurangi operator yang mengambil operator antara tanda kurung. Misalnya, [<=] 1, 2, 3adalah 1 <= 2 <= 3(dan ya, Anda melakukan rentang seperti ini di Perl 6). Dalam hal ini, ini digunakan untuk menentukan apakah elemen sesuai. .pick(*)Metode mengocok daftar ( pick(N)mengambil Nelemen dari daftar). .=memanggil metode, dan menetapkan hasilnya ke variabel. Adapun dokumentasi - well, untuk saat ini hanya spesifikasi Perl 6 yang ada - feather.perl6.nl/syn , tetapi itu ada.
Konrad Borowski

7

APL (22)

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

Pemakaian:

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

Penjelasan:

  • ⍋⍵: mengembalikan indeks item dalam urutan, jadi ⍋30 10 20beri2 1 3
  • (⍳X←⍴⍵)≡⍋⍵:⍵Menyimpan panjang daftar input dalam X. Jika rentang [1..X]sama dengan urutan indeks yang diurutkan, daftar diurutkan, jadi kembalikan.
  • ⋄∇⍵[X?X]: jika ini tidak terjadi, kambuh dengan array yang dikocok.

7

Ruby - 33 karakter

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

1 char less:g=proc{|l|0until l.sort==l.shuffle!}
AShelly

@ Ashelly, versimu tidak berfungsi. Versi saya (kurang lebih 5 karakter) f=->l{l.sort!=l.shuffle!?redo:l}(Ruby 1.9)
Hauleth

dapat seseorang tolong jelaskan kepada saya mengapa redobekerja dengan proctetapi tidak dalam metode klasik dengan def...end? Saya pikir redohanya bekerja dengan loop?
Patrick Oscity

1
Ok sudahlah, saya menemukan sesuatu di buku 'The Ruby Programming Language': " redo[...] mentransfer kontrol kembali ke awal proc atau lambda". Sederhananya seperti itu.
Patrick Oscity

6

Mathematica , 40 37

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

Dengan spasi putih:

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

Jika Anda mengabaikan kesalahan, Anda dapat menyimpan tiga byte dengan#//.l_/;Sort@l!=l:>RandomSample@l&
Martin Ender

13sh byte di Mthmca.
Michael Stern

5

J - 34 27

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

misalnya:

f 5 4 1 3 2
1 2 3 4 5

f 'hello'
ehllo

Bagian {~? ~ @ # Mengocok input:

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

3

Python 61

Urutkan di tempat.

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

Fungsi Anda tidak mengembalikan array pada kesuksesan.
hallvabo

Urutkan di tempat. Array yang diteruskan dimodifikasi.
Alexandru

Pertanyaannya memang mengatakan bahwa fungsi seharusnya mengembalikan array - meskipun jika secara teknis tidak diperlukan untuk mendapatkan hasilnya.
Jonathan M Davis

1
from random import*bisa menghemat char.
ugoren

1
Ini mungkin tidak selalu berhasil: (dari dokumentasi modul python acak): "Perhatikan bahwa untuk len yang bahkan lebih kecil (x), jumlah total permutasi x lebih besar daripada periode kebanyakan generator bilangan acak; ini menyiratkan bahwa sebagian besar permutasi dari urutan panjang tidak akan pernah bisa dihasilkan. "
Matt

3

Python 94

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

Jawaban python lainnya menggunakan random.shuffle (). Dokumentasi modul python random menyatakan:

Perhatikan bahwa untuk len (x) yang bahkan agak kecil, jumlah total permutasi x lebih besar dari periode kebanyakan generator bilangan acak; ini menyiratkan bahwa sebagian besar permutasi dari urutan panjang tidak pernah dapat dihasilkan.


Sebaliknya, lakukan lambda; Saya pikir itu akan lebih pendek. Perhatikan juga bahwa Anda dapat melakukan return[x...sebaliknya return [x.... Sama dengan permutations(a) if- bisa jadi permutations(a)if.
0WJYxW9FMN

lambda a: [x for x in __import__("itertools").permutations(a) if x==tuple(sorted(a))][0]adalah 88 byte
terkenal 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 karakter)

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

Mengurutkan bilangan bulat dalam meningkatkan urutan numerik. Perhatikan bahwa solusi rekursif, seperti

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

akan gagal karena stack overflow bahkan untuk input kecil (katakanlah N> 5), karena Python tidak melakukan optimasi panggilan-ekor.


2

D tanpa pembanding khusus: 59 Karakter

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

Lebih Jelas:

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

    return r;
}

D dengan pembanding khusus: 69 Karakter

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

Lebih Jelas:

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)

Di Scala, kita dapat memeriksa apakah kompiler melakukan optimasi panggilan-ekor:

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

dan ya, benar. Namun, untuk Daftar singkat 100 nilai:

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

butuh hampir 4 bulan untuk menyelesaikannya. ;)


2

C # (184 karakter)

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();}

Ini tidak benar-benar baik untuk melakukan ini dalam C #. Anda harus mendukung obat generik untuk mendukung tipe nilai dan referensi. Tidak ada fungsi atau fungsi array shuffle untuk memeriksa apakah ada sesuatu yang diurutkan.

Adakah yang punya tips untuk membuat ini lebih baik?

Edit Versi yang hanya memilah int (134 karakter):

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 / BASH 65

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

Hmm, bisakah saya mendapatkan pengecualian khusus untuk mengembalikan aturan array karena fungsi bash hanya dapat benar-benar mengembalikan byte yang tidak ditandai?
kojiro

2

C ++ 11, 150 karakter

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

Hanya .. dibuat untuk bersenang-senang.


1
std :: random_shuffle tidak seragam. Dalam klarifikasi dinyatakan: "Juga, pengocokan harus seragam"
STDQ

Oke ... saya tidak tahu itu tidak seragam.

Itu bergantung pada rand () yang tidak seragam - lihat open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3924.pdf . Sepertinya tidak banyak orang yang mengikuti jadi saya kira itu bukan masalah besar.
STDQ

Jadi jika saya menggunakan yang sepenuhnya acak seperti menggunakan srand (waktu (0)) maka apakah itu dihitung?

Masalahnya adalah bahwa rand tidak dijamin memiliki kualitas angka acak yang baik apalagi keseragaman, beberapa menghasilkan bit orde rendah acak. Saya kira itu tidak penting pada akhirnya. Saya hanya mendapat 8 byte lagi menggunakan distributor seragam dengan std :: shuffle dan sebagainya, cukup bagus untuk saya.
STDQ

2

Python - 61 karakter

Rekursif

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

Fungsi Anda mengembalikan Benar atau Salah, bukan array.
hallvabo

2
Perhatikan juga bahwa solusi rekursif akan gagal bahkan untuk input kecil.
hallvabo

1
@hallvabo: Saya sebenarnya ingin menulis solusi ekor-rekursif dalam Skema, yang tentu saja tidak akan menguras tumpukan Anda.
Chris Jester-Young

@hallvabo, Alexandru sudah melakukan solusi Python yang jelas, jadi saya hanya akan mencari sesuatu yang berbeda di sini. Tentu saja solusi rekursif hanya untuk bersenang-senang dan bukan lawan yang serius
gnibbler

from random import*mungkin lebih pendek.
0WJYxW9FMN

2

PowerShell , 85 82 56 55 52 byte

-26 byte berkat saran mazzy
-1 byte terima kasih kepada AdmBorkBork
-3 byte berkat mazzy

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

Cobalah online!

PowerShell memang memiliki perbandingan array yang relatif murah dengan melemparkannya ke string dan membandingkannya.


2
Pindahkan paraminisialisasi Anda ke inisialisasi Anda foruntuk menyimpan byte -for($l=$args;
AdmBorkBork

1
bagus. -nemelemparkan operator kanan ke jenis skalar dari operator kiri. jadi, Anda dapat menyimpan beberapa byte: Cobalah secara online!
mazzy

1

Javascript 291 karakter

min

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}

batalkan

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;
}

Saya merasa saya sudah mengatakan ini sebelumnya, tetapi Anda dapat menghapus semua varitu. Jadikan semuanya global tersirat, ini hanya tentang membuat kode sesingkat mungkin.
gcampbell

1

Matlab, 59 byte

Pendekatan yang relatif lurus ke depan:

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

1

J, 22 byte

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

Ini adalah monad rekursif, diam-diam menggunakan agenda. Begini cara kerjanya:

Biarkan ymenjadi daftar kami. Pertama, kata kerja di sebelah kanan agenda adalah -:/:~. Kata kerja ini dengan anggun disediakan oleh Leaky Nun . Cocok dengan ( -:) terlepas dari apakah input diurutkan ( /:~) menggunakan hook monadic atau tidak . ( (f g) y = y f (g y)) Ini mengembalikan satu atau nol sesuai. Sisi kiri agenda adalah gerund dari dua kata kerja: di sebelah kanan adalah kata kerja identitas ], dan di sebelah kiri adalah tempat terjadinya rekursi. Yang ditunjuk oleh agenda baik identitas kata kerja pada posisi 1jika daftar yang diurutkan, dan semakin lama kerja di posisi 0jika daftar tidak diurutkan.

$:@({~?~@#)panggilan $:(kata kerja terpanjang yang ada di dalamnya) di atas hasil {~?~@#on y. Ini mengocok daftar, seperti yang ?~@#mengambil permutasi dari panjang y, menjadi indeks diurutkan secara acak y. {~, dalam hook monadik, mengembalikan daftar dari yindeks mana yang merupakan arg yang tepat. Daftar acak ini kemudian dipanggil kembali dengan agenda, dan diulang sampai diurutkan.


1

C ++ 14, 158 byte

#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

Jelly , 6 byte, tantangan tanggal kiriman bahasa

ẊŒ¿’$¿

Cobalah online!

Penjelasan

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

Œ¿memberikan nomor untuk setiap permutasi daftar; 1 diurutkan, 2 memiliki dua elemen terakhir yang dipertukarkan, dll., Hingga faktorial panjang daftar (yang merupakan daftar dalam urutan terbalik). Jadi untuk daftar yang diurutkan, ini memiliki nilai 1, dan kita dapat mengurangi menggunakan untuk menghasilkan tes "tidak diurutkan" yang dapat digunakan sebagai Boolean dalam kondisi loop sementara. Ini $menyebabkan kondisi tersebut diurai sebagai sebuah grup.


1

C ++, 166 byte

Ah.

#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;}

Ini harus bekerja pada semua wadah STL yang memiliki begin()dan end().

Tidak Terkumpul:

#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 byte

∈&ṣ≤₁

Cobalah online!

Ketika saya pertama kali melihat jawaban Brachylog ais523 (yang bertentangan dengan jawaban Jelly-nya, karena jika saya tidak salah, user62131 juga adalah dia), saya bertanya-tanya, bagaimana jika itu digunakan untuk melacak mundur alih-alih rekursi? Jadi pada awalnya, saya mencoba ṣ≤₁. Ternyata, karena memilih sesuatu secara acak tidak menghasilkan banyak output sebanyak itu hanya menghasilkan satu output secara tidak pasti, predikat shuffle tidak dapat dilacak ke belakang, jadi menjalankan itu hanya akan gagal kecuali Anda cukup beruntung untuk mengocoknya dengan benar pada percobaan pertama. Setelah itu, saya mencoba pṣ≤₁, yang bekerja sebagian besar waktu, tetapi karena daftar yang panjang memiliki banyak permutasi, itu kadang-kadang masih gagal secara acak. Setelah mengabaikan tujuan mencapai pengurangan panjang, saya akhirnya menemukan ini:

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

(Demonstrasi keacakan)

Meskipun sebenarnya bisa sedikit lebih pendek jika kita mengambil beberapa kebebasan dengan I / O ...

Brachylog , 4 byte

⊆ṣ≤₁

Cobalah online!

Agar output berguna, input tidak boleh mengandung elemen duplikat, karena selain mengurutkan input, predikat bogosort ini menambahkan sejumlah acak elemen duplikat dan nol. (Secara hipotetis, itu bisa menambah apa saja, tapi sepertinya tidak.) Biasanya saya tidak akan repot-repot menyebutkan sesuatu yang jauh dari berfungsi dengan benar, tetapi saya merasa itu adalah semangat tantangan.

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

1

Perl 6 , 28 byte

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

Cobalah online!

Blok kode anonim yang mengacak daftar sampai diurutkan. Perhatikan bahwa ia mengurutkan daftar setidaknya sekali, yang diizinkan. Dan tidak, itu {.pick(*)}tidak bisa diganti*.pick(*)


1

Pyth , 11 byte

Wn=Q.SQSQ;Q

Cukup senang dengan ini, mungkin bisa bermain golf sedikit lebih

Penjelasan


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

Cobalah online!


Anda dapat menyingkat =Q.SQmenjadi =.SQ-1 byte (bekerja dengan operator lain juga, seperti =QhQ-> =hQ)
ar4093

1

Japt , 11 9 byte

_eZñ}a@öx

Cobalah

_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 byte

≤₁|ṣ↰

Cobalah online!

Pengiriman fungsi. (TIO link menggunakan argumen baris perintah yang secara otomatis membungkus fungsi menjadi program lengkap.)

Penjelasan

≤₁|ṣ↰
≤₁      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 (bahasa yang dikompilasi oleh Brachylog) adalah ekor-rekursif, sehingga fungsi ini akhirnya dikompilasi menjadi loop ketat.


0

C (203 karakter, tanpa loop input: hanya fungsi)

#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);}

Ini sama dengan yang berikut, di mana kita juga membaca array dari stdin dan menulis array yang diurutkan. Karena Q meminta fungsi dan bukan keseluruhan program ...

C (296 karakter)

#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]);}}

Kompilasi dapat memberikan peringatan (deklarasi implisit). Batas ukuran array hardencoded dari 999 elemen. Rapuh.

jika tidak perlu pra-periksa apakah array diurutkan, itu bisa dilakukan pada 284.

C (251 karakter, dulu 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]);}}

(menggunakan global bukan fungsi args).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.