Implementare Bogosort


29

Viene risolvere Sudoku troppo duro? Anche la versione della forza bruta ? Ecco un esercizio di codifica che è un po 'più semplice. Io spero. :-P

Scrivi la funzione più breve per implementare bogosort. In particolare, la tua funzione dovrebbe:

  • Prendi un array (o l'equivalente della tua lingua) come input
  • Verifica se i suoi elementi sono in ordine; in tal caso, restituire l'array
  • In caso contrario, mescola gli elementi e ricomincia

Vince l'ingresso più breve. Nel caso di un pareggio, viene preferita una funzione che supporta un comparatore personalizzato (e / o un generatore di numeri pseudocasuali). Eventuali vincoli rimanenti vengono risolti favorendo l'invio precedente.


Chiarimenti: puoi ovviamente usare qualsiasi tipo di elemento, purché ci sia un modo per ordinarli, ovviamente. Inoltre, il mescolamento deve essere uniforme; niente di tutto questo "lo farò semplicemente e lo chiamerò mischiato". :-)


Quali sono i tipi di elementi? int o stringhe?
Alexandru,

@Alexandru: O va bene. Tu scegli.
Chris Jester-Young,

L'aggiunta di un comparatore personalizzato aumenterà la lunghezza del codice, quindi una voce vincente non avrà un comparatore personalizzato. Penso che rompere la cravatta non abbia senso.
Alexandru,

1
È possibile che questo algoritmo non riesca quando si utilizza il generatore pseudo casuale. ad es. quando la lunghezza della lista supera 2000, ci sono 2000! stati per l'elenco che può superare il numero di stati interali del prng.
Gnibbler,

2
Sì, la citazione pertinente da Wikipedia "Tuttavia, se un generatore di numeri pseudocasuali viene utilizzato al posto di una fonte casuale, potrebbe non terminare mai, poiché mostrano un comportamento ciclico a lungo termine."
Gnibbler,

Risposte:


8

APL (Dyalog), 20

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

Spiegazione

è l'argomento (giusto)
⍵≡⍵[⍋⍵]: Verifica se l' ordinamento è uguale a se stesso
:⍵: Se sì, quindi restituisce
∇⍵[?⍨⍴⍵]: Altrimenti, genera un array da 1 a ⍴⍵(lunghezza di ) in ordine casuale, riordina in base a quello ( ⍵[...]) e applica la funzione ad esso ( )


Improvvisamente rivisitando questo problema e ...

APL (Dyalog), 19

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

Stavo solo pensando di ordinare un array nel controllo, rendendolo in qualche modo inutile (senza dire che Bogosort è significativo), un'implementazione più accurata sarebbe ∧/2≤/⍵, e ciò accadrà a ridurre il conteggio dei caratteri.


15

Perl 6: 23 caratteri

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

1
È una funzione in perl? Sembra carino :)
Eelvex

1
Se non lo sai, [<=]controlla se un elenco è ordinato: [<=] (1, 2, 3,) == (1 <= 2 <= 3) == (1 <= 2) and (2 <= 3)e .pick(n)sceglie n elementi casuali da un elenco e .pick(*)consente a Perl di selezionare tutti gli elementi. use.perl.org/~masak/journal/40459
Ming-Tang

Questo deve essere Perl 6. Non l'ho mai visto pickusato prima, figuriamoci [<=]. Dove sono nella documentazione?
Mr. Llama,

@GigaWatt Questo è Perl 6 (non Perl 5). []è ridurre l'operatore che prende l'operatore tra parentesi quadre. Ad esempio, [<=] 1, 2, 3è 1 <= 2 <= 3(e sì, fai intervalli come questo in Perl 6). In questo caso, viene utilizzato per determinare se gli elementi sono in ordine. .pick(*)Il metodo mescola l'elenco ( pick(N)seleziona gli Nelementi dall'elenco). .=chiama il metodo e assegna il risultato alla variabile. Per quanto riguarda la documentazione - beh, per ora esiste solo la specifica Perl 6 - feather.perl6.nl/syn , ma esiste.
Konrad Borowski il

7

APL (22)

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

Uso:

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

Spiegazione:

  • ⍋⍵: restituisce gli indici degli articoli in ordine, quindi ⍋30 10 202 1 3
  • (⍳X←⍴⍵)≡⍋⍵:⍵Memorizza la lunghezza dell'elenco di input in X. Se l'intervallo [1..X]è uguale all'ordine dell'indice ordinato, l'elenco viene ordinato, quindi restituiscilo.
  • ⋄∇⍵[X?X]: in caso contrario, ricorrere con matrice mescolata.

7

Rubino - 33 caratteri

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

1 carattere in meno:g=proc{|l|0until l.sort==l.shuffle!}
AShelly,

@Shelly, la tua versione non funziona. La mia versione (5 caratteri in meno) f=->l{l.sort!=l.shuffle!?redo:l}(Ruby 1.9)
Hauleth

qualcuno può spiegarmi perché redofunziona con un procmetodo classico ma non con def...end? Ho pensato redoche funziona solo con i loop?
Patrick Oscity,

1
Ok, non importa, ho trovato qualcosa nel libro "The Ruby Programming Language": " redo[...] trasferisce il controllo all'inizio del proc o lambda". È semplicemente così.
Patrick Oscity,

6

Mathematica , 40 37

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

Con spazi bianchi:

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

Se si ignorano gli errori, è possibile salvare tre byte con#//.l_/;Sort@l!=l:>RandomSample@l&
Martin Ender,

13sh byte in Mthmca.
Michael Stern,

5

J - 34 27

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

per esempio:

f 5 4 1 3 2
1 2 3 4 5

f 'hello'
ehllo

La parte {~? ~ @ # Mescola l'input:

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

3

Python 61

Ordina sul posto.

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

La tua funzione non restituisce l'array in caso di successo.
hallvabo,

Ordina sul posto. L'array passato viene modificato.
Alexandru,

La domanda dice che la funzione dovrebbe restituire l'array, anche se non è tecnicamente necessario per ottenere il risultato.
Jonathan M Davis,

1
from random import*può salvare un carattere.
ugoren,

1
Questo potrebbe non funzionare sempre: (dalla documentazione del modulo casuale di Python): "Nota che anche per una len piuttosto piccola (x), il numero totale di permutazioni di x è maggiore del periodo della maggior parte dei generatori di numeri casuali; ciò implica che la maggior parte delle permutazioni di una lunga sequenza non può mai essere generata. "
Matt,

3

Python 94

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

Altre risposte a Python usano random.shuffle (). La documentazione del modulo casuale di Python afferma:

Si noti che anche per len piuttosto piccola (x), il numero totale di permutazioni di x è maggiore del periodo della maggior parte dei generatori di numeri casuali; questo implica che la maggior parte delle permutazioni di una lunga sequenza non può mai essere generata.


Fai invece una lambda; Penso che sarebbe più breve. Nota anche che puoi fare return[x...al contrario di return [x.... Lo stesso con permutations(a) if- potrebbe essere permutations(a)if.
0WJYxL9FMN,

lambda a: [x for x in __import__("itertools").permutations(a) if x==tuple(sorted(a))][0]è di 88 byte
famoso 1622 il

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 caratteri)

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

Ordina i numeri interi in ordine numerico crescente. Si noti che le soluzioni ricorsive, come

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

fallirà a causa di un overflow dello stack anche per input piccoli (diciamo N> 5), perché Python non esegue l'ottimizzazione della coda.


2

D senza comparatore personalizzato: 59 caratteri

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

Più leggibilmente:

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

    return r;
}

D con comparatore personalizzato: 69 caratteri

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

Più leggibilmente:

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)

In Scala, possiamo verificare se il compilatore ha fatto un'ottimizzazione di coda:

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

e sì, lo ha fatto. Tuttavia, per un breve elenco di 100 valori:

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

ci sono voluti quasi 4 mesi per il completamento. ;)


2

C # (184 caratteri)

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

Non è davvero bello farlo in C #. Devi supportare generici per supportare sia il valore che i tipi di riferimento. Non esiste alcuna funzione di array shuffle o funzione per verificare se qualcosa è stato ordinato.

Qualcuno ha qualche consiglio per renderlo migliore?

Modifica versione che ordina solo int (134 caratteri):

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, posso ottenere un'eccezione speciale per restituire la regola dell'array poiché le funzioni bash possono restituire letteralmente solo un byte senza segno?
Kojiro,

2

C ++ 11, 150 caratteri

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

Solo ... fatto per divertimento.


1
std :: random_shuffle non è uniforme. Nei chiarimenti si afferma: "Inoltre, il mescolamento deve essere uniforme"
STDQ

Ok ... non sapevo che non fosse uniforme.

Si basa su rand () che non è uniforme - vedi open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3924.pdf . Non molte altre persone sembrano seguire, quindi immagino non sia un grosso problema.
STDQ,

Quindi se ne uso uno completamente casuale come usare srand (time (0)), allora conta?

Il problema è che non è garantito che il rand abbia una buona qualità di numeri casuali per non parlare dell'uniformità, alcuni producono bit non casuali di ordine inferiore. Immagino che alla fine non sia importante. Ho ottenuto solo altri 8 byte usando un distributore uniforme con std :: shuffle e così via, abbastanza buono per me.
STDQ,

2

Python - 61 caratteri

Ricorsivo

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

La tua funzione restituisce True o False, non l'array.
hallvabo,

2
Si noti inoltre che le soluzioni ricorsive sono destinate al fallimento anche per input di piccole dimensioni.
hallvabo,

1
@hallvabo: In realtà voglio scrivere una soluzione ricorsiva di coda in Scheme, che ovviamente non esaurirà il tuo stack.
Chris Jester-Young,

@hallvabo, Alexandru aveva già fatto l'ovvia soluzione Python, quindi stavo solo cercando qualcosa di diverso qui. Naturalmente la soluzione ricorsiva è solo per divertimento e non un serio contendente
gnibbler

from random import*potrebbe essere più breve.
0WJYxL9FMN,

2

PowerShell , 85 82 56 55 52 byte

-26 byte grazie ai suggerimenti di mazzy
-1 byte grazie ad AdmBorkBork
-3 byte grazie a mazzy

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

Provalo online!

PowerShell ha un confronto di array relativamente economico lanciandoli in stringhe e confrontandolo.


2
Sposta la tua paraminizializzazione nella tua forinizializzazione per salvare un byte -for($l=$args;
AdmBorkBork

1
simpatico. -nelancia l'operatore destro su un tipo scalare dell'operatore sinistro. quindi, puoi risparmiare qualche byte: provalo online!
mazzy

1

Javascript 291 caratteri

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}

un-min

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

Ho la sensazione di averlo detto prima, ma puoi rimuovere tutti vari messaggi. Rendili tutti impliciti a livello globale, si tratta solo di rendere il codice il più breve possibile.
gcampbell,

1

Matlab, 59 byte

Approccio relativamente diretto:

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

1

J, 22 byte

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

Questa è una monade ricorsiva e tacita che usa un ordine del giorno. Ecco come funziona:

Lascia che ysia la nostra lista. Innanzitutto, il verbo a destra dell'agenda è -:/:~. Questo è un verbo gentilmente fornito da Leaky Nun . Corrisponde a ( -:) indipendentemente dal fatto che l'input sia ordinato o meno ( /:~) usando un hook monadico. ( (f g) y = y f (g y)) Questo restituisce uno o uno zero di conseguenza. Il lato sinistro dell'agenda è un gerundio di due verbi: a destra è il verbo di identità ], e a sinistra è dove si svolge la ricorsione. L'agenda seleziona il verbo di identità in posizione 1se l'elenco è ordinato e il verbo più lungo in posizione 0se l'elenco non è ordinato.

$:@({~?~@#)chiama $:(il verbo più lungo in cui è contenuto) in cima al risultato di {~?~@#on y. Questo mescola l'elenco, così come ?~@#le permutazioni della lunghezza di y, essendo indici di casuali ordinati y. {~, in un gancio monadico, restituisce un elenco dai ycui indici sono l'arg giusto. Questo elenco casuale viene quindi richiamato nuovamente con l'agenda e si ripete fino a quando non viene ordinato.


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

Gelatina , 6 byte, sfida postdatati in lingua

ẊŒ¿’$¿

Provalo online!

Spiegazione

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

Œ¿assegna un numero a ciascuna permutazione di un elenco; 1 è ordinato, 2 ha gli ultimi due elementi scambiati, ecc., Fino al fattoriale della lunghezza della lista (che è la lista in ordine inverso). Quindi, per un elenco ordinato, questo ha il valore 1 e possiamo decrementarlo usando per produrre un test "non ordinato" che può essere utilizzato come booleano in una condizione del ciclo while. L' $è quello di provocare la condizione analizzare come un gruppo.


1

C ++, 166 byte

Meh.

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

Questo dovrebbe funzionare su tutti i contenitori STL che hanno begin()e end().

Ungolfed:

#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

∈&ṣ≤₁

Provalo online!

Quando ho visto per la prima volta la risposta di Brachylog di ais523 (al contrario della sua risposta di Jelly, perché se non sbaglio l'utente62131 era anche lui), mi chiedevo, cosa sarebbe successo se avesse usato il backtracking invece della ricorsione? Quindi all'inizio ho provato ṣ≤₁. Si scopre, dal momento che la scelta di qualcosa a caso non produce più output tanto quanto produce solo un output in modo non deterministico, il predicato shuffle non può essere retrocesso a, quindi l'esecuzione che fallirà semplicemente a meno che tu non sia abbastanza fortunato da mescolarlo correttamente al primo tentativo. Dopodiché, ho provato pṣ≤₁, che ha funzionato per la maggior parte del tempo, ma dato che un elenco finitamente lungo ha fin troppe permutazioni, a volte falliva ancora a caso. Dopo aver abbandonato l'obiettivo di raggiungere la riduzione della lunghezza, ho finalmente trovato questo:

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

(Dimostrazione di casualità)

Anche se in realtà può essere un po 'più breve se ci prendiamo alcune libertà con l'I / O ...

Brachylog , 4 byte

⊆ṣ≤₁

Provalo online!

Affinché l'output sia utile, l'input non deve contenere elementi duplicati, poiché oltre a ordinare l'input, questo predicato bogosort aggiunge un numero casuale di elementi duplicati e zero. (Ipoteticamente, potrebbe aggiungere qualcosa, ma non è così.) Normalmente non mi preoccuperei di menzionare qualcosa di così lontano dal corretto funzionamento, ma sento che è nello spirito della sfida.

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

1

Perl 6 , 28 byte

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

Provalo online!

Blocco di codice anonimo che mescola l'elenco fino a quando non viene ordinato. Si noti che ordina l'elenco almeno una volta, il che è consentito. E no, {.pick(*)}non può essere sostituito*.pick(*)


1

Pyth , 11 byte

Wn=Q.SQSQ;Q

Abbastanza soddisfatto di ciò, probabilmente può essere giocato a golf un po 'di più

Spiegazione


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

Provalo online!


Puoi accorciare =Q.SQa =.SQ-1 byte (funziona anche con altri operatori, come =QhQ-> =hQ)
ar4093

1

Japt , 11 9 byte

_eZñ}a@öx

Provalo

_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

≤₁|ṣ↰

Provalo online!

Invio di funzioni. (Il collegamento TIO utilizza un argomento della riga di comando che avvolge automaticamente una funzione in un programma completo.)

Spiegazione

≤₁|ṣ↰
≤₁      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 (il linguaggio in cui Brachylog compila) è ricorsivo di coda, quindi questa funzione finisce per essere compilata in un ciclo stretto.


0

C (203 caratteri, nessun loop di input: solo la funzione)

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

È uguale al seguente, in cui leggiamo anche l'array da stdin e scriviamo l'array ordinato. Dal momento che il Q ha richiesto la funzione e non un intero programma ...

C (296 caratteri)

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

La compilazione può dare un avvertimento (dichiarazioni implicite). Limite della dimensione dell'array con codifica fissa di 999 elementi. Fragile.

se non è necessario verificare preventivamente se la matrice è ordinata, può essere eseguita in 284.

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

(usando globals invece di args di funzione).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.