Günün Rastgele Golfü # 1: Diziyi Karıştır


35

Seriler Hakkında

Rasgeleğin teması etrafında dönen bir dizi kod-golf mücadelesi yapacağım. Bu, temel olarak 9 Delikli Golf Sahası olacak , ancak birkaç soruya dağıttı. Herhangi bir mücadeleye, normal bir soru olmuş gibi bireysel olarak katılabilirsiniz.

Bununla birlikte, tüm zorluklarda lider tablosu koruyacağım. Dizi, birkaç günde bir yayınlanan 9'un üzerinde mücadele verecek (şimdilik). 9 yarışmaya katılan her kullanıcı , tüm seriyi kazanmaya hak kazanıyor. Genel puanları, her meydan okuma için en kısa gönderimlerinin toplamıdır (bu nedenle, iki kez bir mücadeleye cevap verirseniz, sadece puan için daha iyi bir cevap sayılır). Birisi bu genel liderlik tablosunda 28 gün boyunca en üst sırada yer alırsa onlara 500 temsilcilik ödül vereceğim .

Dizi için sıraya giren bir sürü fikrim olmasına rağmen, gelecekteki zorluklar henüz kesin olarak belirlenmedi. Herhangi bir öneriniz varsa, lütfen bana bildirin ilgili sanal alan gönderisini .

Delik 1: Bir Diziyi Karıştır

İlk görev oldukça basittir: boş olmayan bir tamsayı dizisi verildiğinde, rasgele karıştırın. Yine de birkaç kural var:

  • Her olası permütasyon aynı olasılıkta döndürülmelidir (bu nedenle, karışık dağılım düzgün bir dağılıma sahip olmalıdır). Algoritmanızın düzgün / tarafsız olup olmadığını, önyargı matrisini üretecek olan Shuffle Will Will Shuffle'daki JavaScript'te uygulayarak kontrol edebilirsiniz - sonuç, yerleşik Fisher-Yates veya sıralama (rastgele sıra) kadar düzgün görünmelidir .
  • Diziyi karıştırmak veya rastgele bir permütasyon oluşturmak için (veya tüm permütasyonları numaralandırmak) herhangi bir yerleşik veya 3. taraf yöntemini kullanmamalısınız. Özellikle, kullanabileceğiniz tek dahili rastgele işlev bir kerede tek bir rasgele sayı elde etmektir . Sen olabilecek herhangi O (1) 'de rasgele sayı yöntemi çalışır dahili ve istenen aralık boyunca tek düze bir olduğunu varsayalım (matematiksel anlamda - Burada kayan nokta gösterimi ayrıntılarını göz ardı edebilirler). Diliniz bir kerede m rastgele sayılar listesi elde etmenize izin veriyorsa , bu özelliği kullanabilirsiniz. m sayısının birbirinden bağımsız olması ve O (m) olarak sayınız.
  • Sizin uygulaması aşmamalıdır O (N) zaman karmaşıklığı , N karıştırılacak dizinin büyüklüğüdür. Örneğin, "rasgele sayılarla sıralayabilirsiniz".
  • Diziyi yerinde dağıtabilirsiniz veya yeni bir dizi oluşturabilirsiniz (bu durumda eski dizi istediğiniz gibi değiştirilebilir).

Tam bir program veya bir işlev yazabilir ve STDIN, komut satırı argümanı, işlev argümanı veya komut istemi üzerinden girdi alabilir ve geri dönüş değeri üzerinden veya STDOUT'a (veya en yakın alternatife) yazdırarak çıktı üretebilirsiniz. Diziyi yerinde kaydıran bir işlev yazarsanız, onu elbette döndürmeniz gerekmez (işlev döndükten sonra dilinizin değiştirilmiş diziye erişmenize izin vermesi şartıyla).

Giriş ve çıkış, herhangi bir uygun liste veya dize biçiminde olabilir, ancak -2 31 ≤ x <2 31 aralığında rasgele tamsayıları desteklemesi gerekir . Prensip olarak, kodunuz 2 31'e kadar olan diziler için çalışmalıdır , bunun için mutlaka belleğinize sığması veya makul bir süre içinde tamamlaması gerekmez. (Sabit kod döngülerine veya başka şeylere rasgele boyut sınırları görmek istemiyorum.)

Bu kod golf, yani en kısa gönderme (bayt cinsinden) kazanır.

Liderler Sıralaması

Aşağıdaki kod parçası, dizinin tüm zorluklarına karşı bir liderlik tablosu oluşturacaktır.

Yanıtlarınızın göründüğünden emin olmak için, lütfen aşağıdaki Markdown şablonunu kullanarak her bir başlığa başlıkla başlayın:

# Language Name, N bytes

Gönderinizin Nbüyüklüğü nerede ? Puanınızı artırmak varsa, olabilir onları içinden vurarak, başlığa eski hesapları tutmak. Örneğin:

# Ruby, <s>104</s> <s>101</s> 96 bytes

(Dil şu anda gösterilmiyor, ancak snippet bunu gerektiriyor ve ayrıştırıyor ve gelecekte bir dilin lider tahtası ekleyebilirim.)


7
"Zeki" olmamızın ve "rastgele bir sayı almanın" dışında kütüphane işlevlerini kullanmamıza izin verilmediği için hayal kırıklığına uğradım . Fisher-Yates karıştırmasının 69 uygulamasına bir daha bakmak ister miyiz? Lütfen gelecekteki görevlerde bu kuralı kaldırmayı düşünün. Ayrıca, neden zaman karmaşıklığı konusunda bir sınır? Lütfen en az O (n ^ 2) ile dinlenmeyi düşünün; Ayrıca, O'ya (n!) İzin verirseniz, birisinin özellikle golf oyunu bulabileceğini düşünüyorum.
anatolyg

7
@anatolyg Kısıtlamaları kaldırmak, her cevap için sortby(random)(zaman kısıtlamasının nedeni) ya da basitçe .shuffle()(yerleşik kısıtlamaların nedeni), Fisher-Yates ya da diğerlerinden biraz daha zeki olduğunu düşünüyorum. yaklaşım.
Martin Ender

1
Karıştırma yerine koyulursa, bir işlev diziyi döndürmek zorunda mıdır, yoksa değiştirilmesi yeterli mi? shuffle(array)Bunun yerine bir fonksiyon yazabilir miyim newArray=shuffle(array)?
Geobits

1
@Bakuriu Rakamlar sabitse doğrusal zamanda sıralayabileceğinizi iddia etmek, giriş boyutları sabitse O (1) 'de herhangi bir şey yapabileceğinizi iddia etmek gibi bir şeydir. Ayrıca, ilgili kısıtlama sabit boyutlu tamsayılar değil sabit boyutlu dizilerdir - çünkü dizi büyüklüğü rastgele sayılarınızın ne kadar büyük olması gerektiğini belirler. Her neyse, zaman karmaşıklığına ilişkin sınırlama elbette uyguladığınız genel algoritma için geçerlidir; oysa giriş boyutlarındaki sınırlar vardır, böylece diliniz bunları kutudan çıkarmazsa isteğe bağlı tamsayıları kullanmak zorunda kalmazsınız. .
Martin Ender,

2
Adám'ın çözümü neden 14 yaşındayken 43319 bayt olarak geliyor?
boboquack

Yanıtlar:


20

Dyalog APL, 25 24 bayt

İlk 25 karakterli çözüm için: i{⊃a[⍺⍵]←a[⍵⍺]}¨?i←⌽⍳⍴a←⎕

                      a←⎕ ⍝ evaluated input, assign to "a"
                     ⍴a   ⍝ length
                    ⍳⍴a   ⍝ 1 2 .. length
                   ⌽⍳⍴a   ⍝ length .. 2 1
                 i←       ⍝ assign to "i"
                ?i        ⍝ random choices: (1..length)(1..length-1)..(1 2)(1)
i{            }¨?i        ⍝ for each index ⍺ and corresponding random choice ⍵
   a[⍺⍵]←a[⍵⍺]            ⍝ swap a[⍺] and a[⍵]
        ←                 ⍝ in Dyalog, assignment returns its right-hand side
  ⊃                       ⍝ first element, i.e. a[⍵]
                          ⍝ the result from {} is an array of all those a[⍵]

Yukarıdakilerde bazı denklik dönüşümlerinden sonra:

i {}¨ ?i  ←→  i {}¨∘? i   ⍝ because A f∘g B ←→ A f g B
          ←→  {}¨∘?⍨ i    ⍝ because f⍨ B ←→ B f B

Görevden kurtulabilir i←ve bir karakter kaydedebiliriz:

{⊃a[⍺⍵]←a[⍵⍺]}¨∘?⍨⌽⍳⍴a←⎕


3
... zihin. şişmiş.
danwyand

1
sola doğru okumak zorunda olduğum bir dil ?? Vaov!
Aydınlık

5
@Luminous sık sık olduğu gibi matematiksel gösterimde de geçerlidir: günah cos ln sqrt x
ngn

4
Bu şekilde koyduğunuzda @ngn önceki yorumumu güldürülebilir gösteriyor. Ha.
Aydınlık

5
@ronalchn gibi APL 8 bit kodlama vardır , bu bir ya da bu diğer on; Ben duydum Dyalog Unicode alternatif olarak, bunlardan biri kullanır.
anatolyg

12

80386 makine kodu, 44 24 bayt

Kodun Hexdump:

60 8b fa 0f c7 f0 33 d2 f7 f1 49 8b 04 8f 87 04
97 89 04 8f 75 ed 61 c3

FUZxxl'e teşekkür etmeyi önerdi. rdrandTalimatları .

İşte kaynak kod (Visual Studio tarafından derlenebilir):

__declspec(naked) void __fastcall shuffle(unsigned size, int array[])
{
    // fastcall convention:
    // ecx = size
    // edx = array
    _asm
    {
        pushad;             // save registers
        mov edi, edx;       // edi now points to the array

    myloop:
        rdrand eax;         // get a random number
        xor edx, edx;
        div ecx;            // edx = random index in the array

        dec ecx;            // count down
        mov eax, [edi + 4 * ecx];   // swap elements
        xchg eax, [edi + 4 * edx];  // swap elements
        mov [edi + 4 * ecx], eax;   // swap elements
        jnz myloop;

        popad;              // restore registers
        ret;
    }
}

Yine bir başka Fisher-Yates uygulaması. Golf oynamaların çoğu, kayıtlardaki parametreler geçirilerek sağlandı.


1
Ayrıca kullanılmış olabilir rdrandshits ve espri olsun diye.
FUZxxl,

@ FUZxxl Bu konuda tamamen unuttum! Ne yazık ki
cevabımdaki

9

Java, 88 101

Temel bir Fisher-Yates karışıklığı işe yarıyor. Uygulaması hızlı ve kolay olduğu için burada oldukça yaygın bir şekilde kullanıldığı hissine kapılıyorum. Burada tıkanmış bazı döngüler / ödevler var, ama golf oynamak için çok fazla değil ; doğası gereği sadece kısa.

void t(int[]s){for(int i=s.length,t,x;i>0;t=s[x*=Math.random()],s[x]=s[i],s[i]=t)x=i--;}

Bazı satır sonları ile:

void t(int[]s){
    for(int i=s.length,t,x;
        i>0;
        t=s[x*=Math.random()],
        s[x]=s[i],
        s[i]=t
    )
        x=i--;
}

Bu, orijinal diziyi değiştirerek yerine geçer s[]. Test programı:

public class Shuffle {
    public static void main(String[] args) {
        int[] a = {1,2,3,4,5,6,7,8,9};
        new Shuffle().t(a);
        for(int b:a)
            System.out.print(b+" ");
    }
    void t(int[]s){for(int i=s.length,t,x;i>0;t=s[x*=Math.random()],s[x]=s[i],s[i]=t)x=i--;}
}

1
Hayır, zorluk, " istenen aralıkta tamamen tekdüze olduğunu" varsayabileceğinizi belirtir . İstenilen aralık, Math.random()iki güç olan bir boyuta sahiptir, bu nedenle bu özellik karşılanmaz.
Peter Taylor

1
Bunu - @PeterTaylor Jan'ın ve Geobits' yorumların ben kuralı amaçlanan ne kadar ciddi ciddi olmayan sizin PRNG gerçek çevrim-uzunluğu hakkında endişe var.
Martin Ender

1
@ MartinBüttner döngü uzunluğu burada sorun değil - bu sizin kuralınız tarafından kapsanmaktadır. Yüzenlerin kaba olması.
John Dvorak

3
@ TheBestOne Sadece şu anda yayınlanan python çözümünden bir bayt daha kısa ;)
Geobits

1
Artık değil! : D
Sp3000

8

Python 2,86 bayt

from random import*
def S(L):i=len(L);exec"i-=1;j=randint(0,i);L[i],L[j]=L[j],L[i];"*i

Bu, Fisher-Yates karışıklığının basit bir uygulamasını kullanarak diziyi yerine geri döndürmeden değiştiren bir işlevdir . Python'dan rastgele sayılar almak pahalı ...

İpuçları için @xnor ve @colevk'a teşekkürler.


Bu aralık ifadesi oldukça hantal görünüyor. Elbette ki manuel olarak geri saymak daha mı kısa while i:i-=1;...?
xnor

@xnor Evet öyle - bunun için teşekkürler. Bunun böyle bir şeyden whiledaha kısa olma eğiliminde olduğunu unutmaya devam ediyorum for...
Sp3000

1
Awww ... şimdi Java cevabım bunu atmıyor. Çok kısa bir süre için çok mutlu oldum :(
Geobits

Bu i=len(L)sürenin başlangıcında azaltma işlemini yaparak ve koyarak başka bir 2 bayt kaydedebilirsiniz .
colevk

8

J, 45 44 karakter

Bu çok zordu.

<@({.,?@#@}.({,<^:3@[{])}.)&>/@(<"0@i.@#,<)

İşte bir açıklama:

  1. # y: Tally arasında yolduğu, eleman sayısı y.
  2. ?@# y: Rastgele bir sayı eşit ila dağılmış 1için(#y)-1 .
  3. x { y: Öğe gelen y indeksinde x.
  4. (<<<x) { y: Dizindeki öğenin hariç tüm öğeler xde y.
  5. x , y: y Ekteki için x.
  6. x ({ , <^:3@[ { ]) y: Dizinindeki öğe xiçinde y, o zaman tüm diğer öğeler.
  7. (?@# ({ , <^:3@[ { ]) ]) yBir rastgele y, sonra diğer tüm öğeler.
  8. x {. y: İlk xürün alındığı dan y.
  9. x }. y: İlk xürün düştü dan y.
  10. x ({. , }.) y: İlk xürün alındığı gelen y, daha sonra ilk xürün düştü dany
  11. x ({. , (?@# ({ , <^:3@[ { ]) ])@}.) y: İlk xürün alındığı dan ysonra ilk xöğey sayısı 7 de olduğu gibi işlendi.
  12. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.) y: Damla ile aynı şey bir karakter kaydetmek için içeri çekti.
  13. u/ y: öğeleri u arasına yerleştirilmişy .
  14. < y: y kutulu .
  15. <"0 y: Her y kutulu ürün .
  16. i. y: Tamsayılar gelen 0etmek y - 1.
  17. i.@# y: Tamsayılar gelen 0etmek(#y) - 1.
  18. (<"0@i.@# , <) y: Tamsayılar 0için (#y) - 1her bir kutu ve daha sonray tek bir kutuda. Bu gereklidir, çünkü J'deki diziler tek tiptir. Bir kutu içeriğinin şeklini gizler.
  19. x u&v y: sevmek (v x) u (v y) .
  20. > y: y açıldı , yani, kutusuz.
  21. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&> y 12 numaralı cümle, kutusuz argümanlarına uygulanır.
  22. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/ y21 arasındaki cümle, öğelerin arasına ekleniry .
  23. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/@(<"0@i.@# , <) y22 numaralı cümle 18 numaralı cümlenin sonucuna veya cetvellerin üniform bir permütasyonuna uygulanır y.

1
Tüm parantezleri ayırt edemiyorum. Ve bu üçlü boks <@<@<@[da bir gizemdir ... Açıklama bekliyorum. :)
randomra

2
Bu bir kez açıklandığında, bu cevabı yükseltmek için çok daha muhtemel olabilirim ;-)
John Dvorak

@randomra İşte gidiyoruz.
FUZxxl

@JanDvorak Açıklama tatmin edici mi?
FUZxxl

Harika bir açıklama! from( {) ' Nin tüm kutulu kullanımlarını bilmiyordum . Ve gerçekten &>/bir listeyi değiştirme hilesini seviyorum . Eminim daha önce birkaç kez kullanabilirdim.
randomra

5

Pyth, 25 bayt

Burada test et.

Yine bir başka Fisher-Yates uygulaması. Temelde @ Sp3000 python çözeltisi ile aynıdır, sadece pyth.

FNrlQ1KONJ@QN XXQN@QKKJ)Q

Takas numarası için @Jakube'e teşekkürler

<implicit>    Q=input()
FNrlQ1        For N in len(Q) to 1, only goes len Q-1 because how range implemented in pyth
 KON          K = random int 0-N
 J@QN         J=Q[N]
 <space>      Suppress print
 XXQN@QKKJ    Swap K and J
)             End for
Q             Print Q

Bu iki liste atamasını birleştirerek iki bayttan tasarruf edebilirsiniz: `XQN @ QK XQKJ` yerine` XXQN @ QKKJ`.
Jakube

@Jakube bahşiş için teşekkürler. Bir listedeki değerleri değiştirmenin bir yolu olduğunu biliyordum ve bu gerçekten zekice. İpuçları listesine eklemelisin.
Maltysen

4

Perl, 68 56 44

Diğer birçok çözüm gibi, bu Fisher-Yates algoritmasını kullanır.

Kullanılması Nutki bireyin yorumunu, 12 karakter kullanılarak kaydedilir $_yerine $ive dizi indeksleri işlemleri gerçekleştirmektir.

44:

sub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}

56:

sub f{$i=@_;$j=int(rand$i),@_[$i,$j]=@_[$j,$i]while$i--}

Bu benim ilk kodlayıcım.


Fena bir başlangıç ​​değil, böyle bir değer @_[...]olarak kullanabileceğinizi bilmiyordum . Daha da içine golf edilebilir sub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}.
nutki

3

C, 63 61 60 bayt

i,t;s(a,m)int*a;{for(;m;a[m]=t)t=a[i=rand()%m--],a[i]=a[m];}

Verilen diziyi uygulayan Fischer-Yates'ün sadece dürüst bir uygulaması. Görsel stüdyo derleyicisiyle (vs2013, diğer sürümleri test etmedi) ve Intel Derleyicisiyle mükemmel şekilde derler ve bağlantılar oluşturur. Güzel görünümlü fonksiyon imza s(int array[], int length). Yasal olarak etkilendim, Python ve Ruby'yi yendim.

Bu srand(), çağrıldığını ve rand () 'nin doğru uygulandığını varsayar , ancak bu kuralın buna izin verdiğine inanıyorum:

You may assume that any built-in random number method runs in O(1) and is perfectly uniform over the requested interval

Güzel formatlanmış versiyon:

index, temp;
shuffle(array, length) int* array;  {
    for(;length; array[index] = temp)
        index = rand() % length--,
        temp = array[length],
        array[length] = array[index];
}

İşlev başlığının yapılmasının yeterli olduğunu düşünüyorum s(a,m)*a{, ancak emin değilim ve ya da test etmek istemiyorum. xorİçinde olduğu gibi, bir takas yapmak isteyebilirsiniz a[i]^=a[m]^=a[i]^=a[m]. Bu ayrıca beyan etme ihtiyacını da ortadan kaldırır t.
FUZxxl

@ FUZxxl Ben xor takas eğer sorunlara neden olduğuna inanıyorum i==m.
Geobits,

@Geobitler gerçekten. Bu olasılığı kaçırdım.
FUZxxl

Sadece neden işe yaramadığını anlamaya çalışıyordum ... bunu hatırlaması gerekiyordu. Ayrıca s(a,m)int*agörsel stüdyoya ve intel compiler'e ihtiyacım var. Test etmek için gcc veya clang yüklü değil, ancak şikayet edeceklerini de farz ediyorum.
takma

Bu oldukça etkileyici bir golf. Hiçbir şey kaydetmeyen birçok değişiklik denedikten sonra 2 karakter kaydetmenin bir yolunu görmeyi başardım. Takas sırasını ilk takas ifadesi t=a[i]olacak şekilde değiştirirseniz, i=rand()%m--ifadeyi dizi dizini olarak içine taşıyabilirsiniz .
Runer112

3

Octave, 88 77 bayt

function s=r(s)for(i=length(s):-1:1)t=s(x=randi(i));s(x)=s(i);s(i)=t;end;end

Yine bir başka Fisher-Yates uygulaması ... Eğer normal satır iadeleri ve aralıkları eklersem çok basit olmalı:

function s=r(s)
  for(i=length(s):-1:1) # Counting down from i to 1
    t=s(x=randi(i));    # randi is builtin number generator for an int from 0 to i
    s(x)=s(i);
    s(i)=t;
  end
end

"Son" anahtar kelimeler maalesef buradaki golf puanını gerçekten öldürüyor. Hey, "endfor" ve "endfunction" yerine "end" kullanabilirim!


1
Bilginize, "bayt" gerçekten kod tarafından gerekli değildir, sadece emin orada yapar edilir daha sonra virgülden sonra virgül (dili ayırmak için) ve en az bir dizi içerir ve bir başlık, sadece geçen seçer çarpılamamış sayı. Orada "bayt" olması hala güzel. ;)
Martin Ender

1
Bunun numelyerine 1 byte tasarruf edebilirsiniz lenght. Bonus olarak programınız 2-D dizileri aka matrislerle de çalışacak;)
paul.oderso 17:16

2

Java 8, 77

(x)->{for(int i=x.length,j,t;;t=x[j*=Math.random()],x[j]=x[i],x[i]=t)j=i--;};

Bu bir lambda alarak int[] geri veren bir kuzu. İlk denemem pek ilginç görünmedi, bu yüzden istisna atarak çıkmaya karar verdim.

Test programı:

interface shuff {
    void shuff(int[] x);
}
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        shuff s = (x)->{for(int i=x.length,j,t;;t=x[j*=Math.random()],x[j]=x[i],x[i]=t)j=i--;};
        int[] x = {3, 9, 2, 93, 32, 39, 4, 5, 5, 5, 6, 0};
        try {
            s.shuff(x);
        } catch(ArrayIndexOutOfBoundsException _) {}
        for(int a:x) System.out.println(a);
    }
}

1
Lambda'yı herhangi bir yerde kullanmak için bir delege sağlamanız gerektiğinde, bir fonksiyon imzası yazmak zorunda kalmak için bir lambda kullanmak hile yapmak değil midir? Ayrıca ... parantezleri etrafa bırakamaz mısın Math.random()?
Rawling, 14

1
@Rawling Bu meta soruda oy kullanabilirsiniz . Şu anda, lambranda lehine 9 oy ve 0 aleyhte oy var. Evet, parantezler kaldırılabilir.
feersum

Huh, eğer bir meta yayını ve çok uzak bir fikir birliği varsa, o zaman ateş et. (Ve bana iki düşük golf puanının tadını çıkarın: p)
Rawling

3
Bence, normal bir durumda fonksiyonun istisna ile durması haksızlık değil mi?
Qwertiy

1
@Qwertiy Her birinin kendi için ... Sizce haksızlık olduğunu düşünüyorum, bence harika.
feersum

2

Golflua, 37

Golflua nasıl çalıştırılır?

~@i=1,#X`r=M.r(i)X[i],X[r]=X[r],X[i]$

Giriş, X değişkeninde bir tablo olarak sağlanır. Tablo yerine karıştırılır.

Örnek kullanım:

> X={0,-45,8,11,2}
> ~@i=1,#X`r=M.r(i)X[i],X[r]=X[r],X[i]$
> w(T.u(X))
-45 0 8 11 2

2

R, 79 bayt

f=function(x){n=length(x);for(i in 1:n){j=sample(i:n,1);x[c(i,j)]=x[c(j,i)]};x}

Bu, Fisher-Yates karışıklığının basit bir uygulamasıdır. R fonksiyonu sampleverilen bir vektörden eşit olasılıkla verilen basit bir rasgele örneklem çizer. Burada tamsayılar gelen her tekrarda büyüklüğü 1 rastgele bir örneğini çekiyorlar i, ..., n. Soruda belirtildiği gibi, bunun O (1) olduğu varsayılabilir, bu nedenle tüm bu uygulamalarda O (N) olması gerekir.


2

Matlab, 67

Ayrıca Fisher-Yates’i de uygulamak.

a=input('');n=numel(a);for i=1:n;k=randi(i);a([i,k])=a([k,i]);end;a

Çok kötü olduğunu düşündüm, Matlab'ın randpermişlevini kullanamam . Ancak bazı hilkat garibesi olduktan sonra, randpermnasıl yapıldığını görmek için kaynağa bakabileceğimi düşündüm ve sadece bir satır olduğunu görmek beni şaşırttı: [~,p] = sort(rand(1,n))=)


2

Perl, 44

sub f{($_[$x],$_)=($_,$_[$x=rand++$i])for@_}

44 karakterden başka bir perl. Örnek kullanım:

@x=(1..9);f(@x);print@x

2

Mathematica, 82 90 83 93 bayt

Not: Fisher-Yates karışıklığındaki bu değişiklik, aslında Martin Büttner’ın çözümü, bazı kodlar da alephalpha’yla aynı. sgiriş dizisidir. Hiçbir şey fantezi-smancy, ama bazen basit şeyler en zor.

f@s_:=(a=s;m=Length@a;Do[t=a[[r=RandomInteger@{1,m-1}]];a[[r]]=a[[m]]; a[[m]]=t,{n,1,m-1}];a)

DoBurada kullanabilirsiniz . Bundan daha kısa While.
alephalpha

2

Ruby, 57 bayt

->a{a.size.times{|i|j=rand(i+1);a[i],a[j]=a[j],a[i]};p a}

Giriş (lambda işlevi olarak):

f.([1,2,3,4,5])

Çıktı:

[2, 1, 4, 3, 5]


2

K, 31 karakter

f:{{l[i:x,1?x]:l@|i}'|!#l::x;l}

Daha önce koyduğum kadar kısa değil (ki diskalifiye edildi).

Temel bir Fisher-Yates karıştırması. Bu Kona posta listesinden birçok yardımla yapıldı .


2

JavaScript (ES6), 66

Bu işlev diziyi yerinde karıştırır. Ayrıca, karıştırılmış çıktı DEĞİLDİR ve dikkate alınmaması gereken bir yan ürün dizisi döndürür.

F=a=>a.map((v,i)=>a[a[i]=a[j=0|i+Math.random()*(a.length-i)],j]=v)

2

MATL , 16 bayt

XH`HnYr&)XHxvHHn

Çevrimiçi deneyin!

MATL'de Fisher-Yates. Bu programın neredeyse üçte biri H, MATL'deki pano işlevine karşılık gelen mektuba ayrılmıştır .

Temel olarak, Hkullanılmayan öğeleri girişten kaydeder, yığın karıştırılmış listeyi izler.


2

12 yaşında

rÈiMqZÄ Y}[]

Dene!

@Shaggy sayesinde -10 (yaklaşık yarısı;)!

Bir golf dili denemek istiyordum ve Japt tercümanının iyi belgeleri ve tarayıcıda bir şeyler denemek için bir yolu vardı.

Aldığım strateji aşağıda:

  • Boş bir dizi ile tohum ekimini azalt
  • Her adımda, geçerli öğeyi yerleştirmek için rastgele bir yuva bulun

1
Japt’e hoş geldin, yanımızda olman güzel. Bence bu aynı yöntemi kullanarak, 9 bayt için çalışır. Eğer RNG tatmin edici değilse, bunun yerine bunu deneyin .
Shaggy

@Shaggy - Tavsiyeler için teşekkürler! :) 2. çözümünüzün biraz değiştirilmiş bir versiyonunu kullandım. Azaltma işlevinin 3. parametresi bir dizin olduğundan, zaten uzunluğu biliyoruz.
Dana

1

Javascript ES6, 69

a=>{m=a.length;while(m)[a[m],a[i]]=[a[i=~~(Math.random()*m--)],a[m]]}

Fisher-Yates.

Not: Firefox'ta test edilebilir


@ MartinBüttner, kaldırıldı :)
Qwertiy


1

Haskell, 170

import System.Random
import Data.Array.IO
s a=do(_,n)<-getBounds a;sequence$map(\i->do j<-randomRIO(i,n);p<-a%i;q<-a%j;writeArray a j p;return q)[1..n]where(%)=readArray

Https://wiki.haskell.org/Random_shuffle adresindeki algoritmadan ilham alan başka bir Fisher-Yates çözümü .

s imzası olan bir işlevdir: IOArray Int a -> IO [a]


1

CJam - 30

q~_,,W%{_I=I)mr:J2$=@I@tJ@t}fI

Http://cjam.aditsu.net/ adresinde deneyin

Örnek girdi: [10 20 30 40 50]
Örnek çıktı: 3020401050( pgüzel baskı için kodun sonuna ekleyin )

Kodun girişi yığından almasına izin verilirse (bir işlev gibi), ilk 2 karakter kaldırılabilir, böylece boyut 28'e düşer.

Açıklama:

Kod, diziler için bir "takas" işlecinin olmamasından dolayı umduğumdan daha uzun
(daha sonra uygulanacak: p)

q~            read and evaluate the input (let's call the array "A")
_,,           make an array [0 1 2 ... N-1] where N is the size of A
W%            reverse the array, obtaining [N-1 ... 2 1 0]
{…}fI         for I in this array
    _I=       push A[I]
    I)mr:J    push a random number from 0 to I (inclusive) and store it in J
              stack: A, A[I], J
    2$=       get A[J]
    @I@t      set A[I] = A[J]
              stack: former A[I], A
    J@t       set A[J] = former A[I]

Yorumlarda belirtildiği gibi, korkarım bu geçersiz. En azından _O (N) (bir O (N) döngüsünün içinde) var. Maalesef, CJam’da bunun için uğraşmanın bir yolunu görmüyorum.
Martin Ender

Listeler, değişmez nesneler gibi işlenir, bu nedenle çoğaltma yalnızca başvuruyu çoğaltma olarak uygulanır. Bu aslında tonu öldürüyor, çünkü listeyi değiştiremiyor ve şimdi de bir kopya oluşturmalı.
Runer112

@ MartinBüttner Runer112 ile aynı şeyi göndermek üzereydim; evet bir sorun olabilir t, gelecekteki sürümlerinde geliştirmek istiyorum ..
aditsu

Bu nedenle, bu kod, iç dilin uygulama sorunları nedeniyle, sorunun ruhunu izler ancak “mektup” u izlemez.
aditsu

1

JavaScript (ES 6), 61

S=a=>(a.map((c,i)=>(a[i]=a[j=Math.random()*++i|0],a[j]=c)),a)

Bunu test edebilirsiniz burada sadece diyen bir satır ekleyerek shuffle = S(Yalnızca Firefox).


1

STATA, 161

di _r(s)
set ob wordcount($s)
token $s
g a=0
foreach x in $s{
gl j=floor(runiform()*_n)+1
replace a=`$j' if word($s,_n)=`x'
replace a=`x' if word($s,_n)=`$j'
}
l

Girdiyi boşlukla ayrılmış sayılar olarak bekler. İsterseniz başlıkları ve gözlem numaralarını çıkarabilirim, ancak aksi takdirde bu daha kısa olur.


Bunda ne var _n?
Martin Ender

_n mevcut gözlemin numarasıdır.
işaretler


1

SQF, 91 bayt

params["i"];{n=floor random count i;i set[_forEachIndex,i select n];i set[n,_x]}forEach i;i

1
Bu önyargılıdır (Will It Shuffle'daki "takas (ben <-> rastgele)"), ancak %xile değiştirerek Fisher-Yates'e (tarafsız) dönüştürebilirsiniz %i.
Martin Ender,

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.