Golf ngẫu nhiên trong ngày # 1: Xáo trộn một mảng


35

Giới thiệu về bộ

Tôi sẽ thực hiện một loạt các thử thách golf-golf xoay quanh chủ đề ngẫu nhiên. Về cơ bản, đây sẽ là một sân gôn 9 lỗ , nhưng trải rộng qua nhiều câu hỏi. Bạn có thể tham gia vào bất kỳ thử thách nào như thể đó là một câu hỏi bình thường.

Tuy nhiên, tôi sẽ duy trì bảng xếp hạng trên tất cả các thử thách. Loạt phim sẽ chạy qua 9 thử thách (hiện tại), một bài được đăng mỗi vài ngày. Mỗi người dùng tham gia vào tất cả 9 thử thách đều đủ điều kiện để giành chiến thắng trong toàn bộ chuỗi. Điểm tổng thể của họ là tổng số bài nộp ngắn nhất của họ cho mỗi thử thách (vì vậy nếu bạn trả lời một thử thách hai lần, chỉ có câu trả lời tốt hơn được tính vào điểm số). Nếu bất cứ ai giữ vị trí hàng đầu trên bảng xếp hạng tổng thể này trong 28 ngày, tôi sẽ thưởng cho họ tiền thưởng 500 rep .

Mặc dù tôi có một loạt các ý tưởng được xếp hàng cho loạt bài này, những thách thức trong tương lai vẫn chưa được đặt ra. Nếu bạn có bất kỳ đề xuất nào, xin vui lòng cho tôi biết trên bài đăng hộp cát có liên quan .

Lỗ 1: Xáo trộn một mảng

Nhiệm vụ đầu tiên khá đơn giản: đưa ra một mảng số nguyên không trống, xáo trộn ngẫu nhiên. Có một vài quy tắc mặc dù:

  • Mọi hoán vị có thể phải được trả về với cùng một xác suất (vì vậy việc xáo trộn phải có phân phối đồng đều). Bạn có thể kiểm tra xem thuật toán của bạn có đồng nhất / không thiên vị hay không bằng cách triển khai nó trong JavaScript trên Will it Shuffle , nó sẽ tạo ra một ma trận các thành kiến ​​- kết quả sẽ trông giống như các hàm Fisher-Yates hoặc sắp xếp (thứ tự ngẫu nhiên) của chúng .
  • Bạn không được sử dụng bất kỳ phương thức tích hợp hoặc bên thứ 3 nào để xáo trộn mảng hoặc tạo hoán vị ngẫu nhiên (hoặc liệt kê tất cả các hoán vị). Cụ thể, chức năng ngẫu nhiên tích hợp duy nhất bạn có thể sử dụng là nhận một số ngẫu nhiên duy nhất tại một thời điểm . Bạn có thể giả sử rằng bất kỳ phương pháp số ngẫu nhiên tích hợp nào chạy trong O (1) và hoàn toàn thống nhất trong khoảng thời gian được yêu cầu (theo nghĩa toán học - bạn có thể bỏ qua chi tiết về biểu diễn dấu phẩy động ở đây). Nếu ngôn ngữ của bạn cho phép bạn có được danh sách m số ngẫu nhiên cùng một lúc, bạn có thể sử dụng cơ sở này, miễn là các số m độc lập với nhau và bạn tính nó là O (m).
  • Việc triển khai của bạn không được vượt quá độ phức tạp thời gian của O (N) , trong đó N là kích thước của mảng được xáo trộn. Chẳng hạn, bạn không thể "sắp xếp theo số ngẫu nhiên".
  • Bạn có thể xáo trộn mảng tại chỗ hoặc tạo một mảng mới (trong trường hợp đó mảng cũ có thể được sửa đổi theo cách bạn muốn).

Bạn có thể viết một chương trình đầy đủ hoặc một hàm và nhận đầu vào thông qua STDIN, đối số dòng lệnh, đối số chức năng hoặc lời nhắc và tạo đầu ra thông qua giá trị trả về hoặc bằng cách in ra STDOUT (hoặc thay thế gần nhất). Nếu bạn viết một hàm xáo trộn mảng tại chỗ, bạn không cần phải trả lại khóa đó (với điều kiện ngôn ngữ của bạn cho phép bạn truy cập vào mảng đã sửa đổi sau khi hàm trả về).

Đầu vào và đầu ra có thể ở bất kỳ định dạng chuỗi hoặc danh sách thuận tiện nào, nhưng phải hỗ trợ các số nguyên tùy ý trong phạm vi -2 31 x <2 31 . Về nguyên tắc, mã của bạn sẽ hoạt động cho các mảng có độ dài lên đến 2 31 , mặc dù điều này không nhất thiết phải phù hợp với bộ nhớ của bạn hoặc hoàn thành trong một khoảng thời gian hợp lý. (Tôi chỉ không muốn thấy giới hạn kích thước tùy ý đối với các vòng lặp mã cứng hoặc thứ gì đó.)

Đây là mã golf, vì vậy bài nộp ngắn nhất (tính bằng byte) sẽ thắng.

Bảng xếp hạng

Đoạn mã sau sẽ tạo bảng xếp hạng trong tất cả các thử thách của chuỗi.

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu mọi câu trả lời bằng tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

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

(Ngôn ngữ hiện không được hiển thị, nhưng đoạn mã yêu cầu và phân tích nó và tôi có thể thêm bảng xếp hạng ngôn ngữ trong tương lai.)


7
Tôi thất vọng vì chúng tôi không được phép "thông minh" và sử dụng các chức năng của thư viện ngoài "lấy số ngẫu nhiên" . Chúng ta có muốn xem xét thêm 69 triển khai xáo trộn của Fisher-Yates không? Vui lòng xem xét loại bỏ quy tắc này trong các nhiệm vụ trong tương lai. Ngoài ra, tại sao một giới hạn về độ phức tạp thời gian? Vui lòng xem xét việc thư giãn nó ít nhất là O (n ^ 2); Tôi cũng nghĩ rằng ai đó có thể tìm thấy một triển khai chơi golf đặc biệt nếu bạn cho phép O (n!).
anatolyg

7
@anatolyg Xóa các hạn chế đối với mọi câu trả lời là sortby(random)(lý do hạn chế thời gian) hoặc đơn giản .shuffle()(lý do hạn chế tích hợp), mà tôi nghĩ là kém thông minh hơn nhiều so với việc phải thực hiện Fisher-Yates hoặc một số khác tiếp cận.
Martin Ender

1
Nếu xáo trộn tại chỗ, một hàm có phải trả về mảng không, hoặc nó có đủ để sửa đổi không? Tôi có thể viết một hàm cho shuffle(array)thay vì newArray=shuffle(array)?
Geobits 4/2/2015

1
@Bakuriu Yêu cầu rằng bạn có thể sắp xếp theo thời gian tuyến tính nếu các số được cố định giống như tuyên bố bạn có thể làm bất cứ điều gì trong O (1) nếu kích thước đầu vào được cố định. Ngoài ra, hạn chế có liên quan là các mảng có kích thước cố định, không phải là số nguyên có kích thước cố định - bởi vì kích thước mảng xác định mức độ lớn mà bạn cần các số ngẫu nhiên. Dù sao, giới hạn về độ phức tạp về thời gian dĩ nhiên là đối với thuật toán chung mà bạn triển khai, trong khi đó, các giới hạn về kích thước đầu vào được đặt ra để bạn không phải sử dụng các số nguyên chính xác tùy ý nếu ngôn ngữ của bạn không sử dụng chúng ngoài hộp .
Martin Ender

2
Tại sao giải pháp của Adám lại là 43319 byte khi thực sự là 14?
boboquack

Câu trả lời:


20

APL Dyalog, 25 24 byte

Đầu tiên cho giải pháp 25 ký tự: 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[⍵]

Sau một số biến đổi tương đương ở trên:

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

chúng ta có thể thoát khỏi nhiệm vụ i←và lưu một nhân vật:

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


3
... lí trí. thổi
danwyand 4/2/2015

1
một ngôn ngữ tôi phải đọc từ phải sang trái ?? ồ
Sáng

5
@ Thường như trường hợp với ký hiệu toán học: sin cos ln sqrt x
ngn

4
@ngn khi bạn đặt nó theo cách đó làm cho nhận xét trước đây của tôi trông buồn cười. ha.
Sáng

5
@ronalchn Có mã hóa 8 bit cho APL, như cái này hay cái kia; Tôi nghe nói Dyalog sử dụng một trong số này, như là một thay thế cho Unicode.
anatolyg

12

Mã máy 80386, 44 24 byte

Mã thập phân của mã:

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

Cảm ơn FUZxxl, người đã đề xuất sử dụng rdrandhướng dẫn.

Đây là mã nguồn (có thể được Visual Studio biên dịch):

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

Một triển khai khác của Fisher-Yates. Hầu hết các golf đã đạt được bằng cách thông qua các thông số trong sổ đăng ký.


1
Bạn cũng có thể đã sử dụng rdrandcho shits và cười khúc khích.
FUZxxl

@FUZxxl Tôi hoàn toàn quên mất điều đó! Quá tệ, nó loại bỏ phần thú vị nhất về câu trả lời của tôi ...
anatolyg

9

Java, 88 101

Một shuffle Fisher-Yates cơ bản thực hiện các mẹo. Tôi có cảm giác nó sẽ được sử dụng khá phổ biến ở đây, vì nó nhanh chóng và dễ thực hiện. Có một số vòng lặp / nhiệm vụ nhồi nhét ở đây, nhưng thực sự không có quá nhiều để chơi golf; bản chất nó chỉ ngắn thôi.

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

Với một số ngắt dòng:

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

Điều này xáo trộn tại chỗ, sửa đổi các mảng ban đầu s[]. Chương trình kiểm tra:

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
Không, thách thức nói rằng bạn có thể cho rằng nó " hoàn toàn thống nhất trong phạm vi được yêu cầu ". Phạm vi được yêu cầu Math.random()có kích thước là sức mạnh của hai, vì vậy điều này không đáp ứng được thông số kỹ thuật.
Peter Taylor

1
Diễn giải của @PeterTaylor Jan và Geobits thực sự là cách tôi dự định quy tắc - rằng bạn không phải lo lắng về độ dài chu kỳ thực tế của PRNG của bạn.
Martin Ender

1
@ MartinBüttner độ dài chu kỳ không phải là vấn đề ở đây - được quy định trong quy tắc của bạn. Sự thô cứng của phao là.
John Dvorak

3
@TheBestOne Nó ngắn hơn một byte so với giải pháp python duy nhất hiện được đăng;)
Geobits 3/2/2015

1
Không còn nữa! : D
Sp3000

8

Python 2, 86 byte

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

Đây là một chức năng xáo trộn mảng tại chỗ mà không trả lại nó, bằng cách sử dụng một cách đơn giản thực hiện xáo trộn Fisher-Yates . Lấy số ngẫu nhiên từ Python rất tốn kém ...

Cảm ơn @xnor và @colevk về các mẹo.


Đó là biểu hiện phạm vi trông khá cồng kềnh. Chắc chắn nó ngắn hơn để đếm ngược bằng tay while i:i-=1;...?
xnor

@xnor Vâng đúng vậy - cảm ơn vì điều đó. Tôi tiếp tục quên rằng whilecó xu hướng ngắn hơn so forvới loại điều này ...
Sp3000

1
À ... bây giờ câu trả lời Java của tôi không đánh bại điều này. Tôi đã rất hạnh phúc trong một thời gian rất ngắn :(
Geobits

Bạn có thể lưu thêm 2 byte bằng cách tạo i=len(L)và đặt phần giảm ở đầu vòng lặp while.
colevk 4/2/2015

8

J, 45 44 ký tự

Đây là một trong những khó khăn.

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

Đây là một lời giải thích:

  1. # y: Các kiểm đếm của y, nghĩa là số phần tử trong y.
  2. ?@# y: Một số ngẫu nhiên phân bố đồng đều trong phạm vi từ 1đến (#y)-1.
  3. x { y: Các mục từ y tại chỉ mục x.
  4. (<<<x) { y: Tất cả các mục ngoại trừ mục tại chỉ mục xtrong y.
  5. x , y: y Nối tới x.
  6. x ({ , <^:3@[ { ]) y: Các mục tại chỉ mục xtrong y, sau đó tất cả các mục khác.
  7. (?@# ({ , <^:3@[ { ]) ]) yMột ngẫu nhiên nó từ y, sau đó tất cả các mặt hàng khác.
  8. x {. y: Các xmục đầu tiên được lấy từ y.
  9. x }. y: Các xmục đầu tiên được thả từ y.
  10. x ({. , }.) y: Các xmục đầu tiên được lấy từ y, sau đó các xmục đầu tiên được thả từy
  11. x ({. , (?@# ({ , <^:3@[ { ]) ])@}.) y: Các xmục đầu tiên được lấy từ y, sau đó các xmục đầu tiên được yxử lý như trong số 7.
  12. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.) y: Điều tương tự với thả được kéo vào để lưu một ký tự.
  13. u/ y: u chèn giữa các mục của y.
  14. < y: y đóng hộp .
  15. <"0 y: Mỗi mục của y hộp .
  16. i. y: số nguyên từ 0đến y - 1.
  17. i.@# y: số nguyên từ 0đến (#y) - 1.
  18. (<"0@i.@# , <) y: Số nguyên từ 0để (#y) - 1từng đóng hộp và sau đó ytrong một hộp duy nhất. Điều này là cần thiết bởi vì các mảng trong J là thống nhất. Một hộp ẩn hình dạng của nội dung của nó.
  19. x u&v y: thích (v x) u (v y).
  20. > y: y đã mở , nghĩa là không có hộp của nó.
  21. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&> y cụm từ số 12 được áp dụng cho các đối số chưa được đóng hộp của nó.
  22. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/ ycụm từ số 21 được chèn giữa các mục của y.
  23. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/@(<"0@i.@# , <) ycụm từ số 22 áp dụng cho kết quả của cụm từ số 18, hoặc, hoán vị thống nhất của các mục của y.

1
Tôi chỉ không thể phân biệt tất cả các dấu ngoặc đơn. Và bộ ba quyền anh đó <@<@<@[cũng là một bí ẩn ... Đang chờ giải thích. :)
Randomra

2
Một khi điều này được giải thích, tôi có thể sẽ nâng cao câu trả lời này hơn nhiều ;-)
John Dvorak

@randomra Ở đây bạn đi.
FUZxxl

@JanDvorak Là lời giải thích thỏa mãn?
FUZxxl

Giải thích tuyệt vời! Tôi không biết về tất cả việc sử dụng from( {). Và tôi thực sự thích &>/thủ thuật để thao túng một danh sách. Tôi chắc chắn rằng tôi có thể đã sử dụng nó một vài lần trước đây.
Randomra

5

Bình thường, 25 byte

Kiểm tra nó ở đây.

Một triển khai khác của Fisher-Yates. Về cơ bản giống như giải pháp python @ Sp3000, chỉ trong pyth.

FNrlQ1KONJ@QN XXQN@QKKJ)Q

Cảm ơn @Jakube về thủ thuật hoán đổi

<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

Bạn có thể lưu hai byte bằng cách kết hợp hai phép gán danh sách đó: `XXQN @ QKKJ` thay vì` XQN @ QK XQKJ`.
Jakube

@Jakube cảm ơn vì tiền boa. Tôi biết rằng phải có một cách để trao đổi giá trị trong một danh sách, và điều này thực sự thông minh. Bạn nên thêm nó vào danh sách mẹo.
Maltysen

4

Perl, 68 56 44

Giống như nhiều giải pháp khác, giải pháp này sử dụng thuật toán Fisher-Yates .

Sử dụng nhận xét của nutki , 12 ký tự được lưu bằng cách sử dụng $_thay vì $ivà thực hiện các thao tác trong các chỉ mục mảng.

44:

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

56:

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

Đây là codegolf đầu tiên của tôi.


Không phải là một khởi đầu tồi, tôi không biết rằng bạn có thể sử dụng giá trị @_[...]như thế. Có thể được đánh gôn hơn nữa vào sub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}.
nutki 6/2/2015

3

C, 63 61 60 byte

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

Chỉ cần thực hiện trực tiếp Fischer-Yates sắp xếp mảng đã cho. Biên dịch và liên kết hoàn toàn tốt với trình biên dịch phòng thu trực quan (vs2013, chưa thử nghiệm các phiên bản khác) và Trình biên dịch Intel. Chữ ký chức năng đẹp là s(int array[], int length). Tôi thực sự ấn tượng Tôi đã đánh bại Python và Ruby.

Điều này không giả sử srand()được gọi và rand () được thực hiện đúng, nhưng tôi tin rằng quy tắc này cho phép điều đó:

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

Phiên bản được định dạng chính xác:

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

Tôi nghĩ rằng nó đủ để làm tiêu đề chức năng s(a,m)*a{, nhưng tôi không chắc chắn và cũng không muốn thử nghiệm. Bạn có thể muốn làm một xor-swap, như trong a[i]^=a[m]^=a[i]^=a[m]. Điều này cũng tránh sự cần thiết phải khai báo t.
FUZxxl

@FUZxxl Tôi tin rằng một trao đổi xor gây ra vấn đề nếu i==m.
Geobits 3/2/2015

@Geobits thực sự. Tôi đã bỏ lỡ khả năng đó.
FUZxxl

Tôi chỉ cố gắng tìm ra lý do tại sao nó không hoạt động ... nên nhớ điều đó. Ngoài ra tôi cần s(a,m)int*acho studio hình ảnh và trình biên dịch intel. Đừng cài đặt gcc hoặc clang để kiểm tra, nhưng tôi cho rằng họ cũng sẽ phàn nàn.
bút danh 117

Điều này là khá ấn tượng golf. Sau khi thử rất nhiều sửa đổi mà không tiết kiệm được gì, tôi đã xoay sở để xem cách lưu 2 ký tự. Nếu bạn thay đổi thứ tự hoán đổi để câu lệnh hoán đổi đầu tiên trở thành t=a[i], thì bạn có thể di chuyển i=rand()%m--câu lệnh bên trong dưới dạng chỉ mục mảng.
Runer112

3

Octave, 88 77 byte

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

Tuy nhiên, một triển khai khác của Fisher-Yates ... Sẽ khá đơn giản nếu tôi thêm các trả về và khoảng cách dòng thông thường:

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

Thật không may, các từ khóa "kết thúc" thực sự giết chết điểm golf ở đây. Này, tôi có thể sử dụng "end" thay vì "endfor" và "endfactor"!


1
Chỉ cần FYI, các "byte" là không thực sự cần thiết bởi mã, nó chỉ làm cho chắc chắn có được một dòng tiêu đề, trong đó có chứa một dấu phẩy (để tách các ngôn ngữ) và ít nhất một số sau dấu phẩy, và sau đó chỉ cần chọn cuối cùng số không bị gạch bỏ. Có "byte" trong đó vẫn còn tốt mặc dù. ;)
Martin Ender

1
Bạn có thể tiết kiệm 1 byte bằng cách sử dụng numelthay vì lenght. Như một phần thưởng, chương trình của bạn cũng sẽ hoạt động với các mảng 2 chiều hay còn gọi là ma trận;)
paul.oderso

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

Đó là một lambda dùng int[] và trở về khoảng trống. Nỗ lực đầu tiên của tôi có vẻ không thú vị lắm, vì vậy tôi quyết định để nó thoát ra bằng cách ném một ngoại lệ.

Chương trình kiểm tra:

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
Không phải là gian lận khi sử dụng lambda để phải viết chữ ký hàm, khi bạn phải cung cấp một đại biểu để sử dụng lambda ở bất cứ đâu? Ngoài ra ... bạn không thể bỏ dấu ngoặc đơn xung quanh Math.random()?
Rawling 4/2/2015

1
@Rawling Bạn có thể bỏ phiếu trong câu hỏi meta này . Hiện tại, có 9 phiếu ủng hộ lambdas và 0 phiếu chống. Có, dấu ngoặc đơn có thể được loại bỏ.
frageum

Huh, nếu có một bài viết meta và một sự đồng thuận rất xa thì hãy bắn đi. (Và tận hưởng điểm số golf thấp hơn hai đối với tôi: p)
Rawling

3
Tôi nghĩ, thật không công bằng khi chức năng dừng ngoại lệ trong một trường hợp bình thường, phải không?
Qwertiy 4/2/2015

1
@Qwertiy Với mỗi người của anh ấy ... Bạn nghĩ điều đó không công bằng, tôi nghĩ điều đó thật tuyệt.
feerum 4/2/2015

2

Golflua, 37

Làm thế nào để chạy Golflua?

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

Đầu vào được cung cấp dưới dạng bảng trong biến X. Bảng được xáo trộn tại chỗ.

Ví dụ sử dụng:

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

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}

Đây là một triển khai đơn giản của shuffle Fisher-Yates. Hàm R samplevẽ một mẫu ngẫu nhiên đơn giản có kích thước đã cho từ một vectơ đã cho với xác suất bằng nhau. Ở đây chúng tôi đang vẽ một mẫu ngẫu nhiên có kích thước 1 ở mỗi lần lặp từ các số nguyên i, ..., n. Như đã nêu trong câu hỏi, điều này có thể được coi là O (1), vì vậy trong tất cả việc thực hiện này phải là O (N).


2

Matlab, 67

Cũng thực hiện Fisher-Yates.

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

Tôi nghĩ nó quá tệ Tôi không thể sử dụng randpermchức năng của Matlab . Nhưng sau một vài lần nghịch ngợm, tôi nghĩ rằng tôi có thể nhìn vào nguồn randpermđể xem nó được thực hiện như thế nào và tôi đã rất ngạc nhiên khi thấy rằng chỉ có một dòng: [~,p] = sort(rand(1,n))=)


2

Perl, 44

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

Một perl khác trong 44 ký tự. Ví dụ sử dụng:

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

2

Mathicala, 82 90 83 93 byte

Lưu ý: Biến thể này của Shuffle Fisher-Yates thực sự là giải pháp của Martin Büttner, với một số mã được ghép bởi alephalpha. slà mảng đầu vào. Không có gì lạ mắt, nhưng đôi khi những điều đơn giản lại khó nắm bắt nhất.

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)

Bạn có thể sử dụng Doở đây. Nó ngắn hơn While.
alephalpha

2

Ruby, 57 byte

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

Đầu vào (dưới dạng hàm lambda):

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

Đầu ra:

[2, 1, 4, 3, 5]


2

K, 31 ký tự

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

Không hoàn toàn ngắn như cái tôi đã đưa ra trước đây (đã bị loại) ... oh tốt.

Đó là một shuffle Fisher-Yates cơ bản. Điều này được xây dựng với rất nhiều sự giúp đỡ từ danh sách gửi thư của Kona .


2

JavaScript (ES6), 66

Hàm này xáo trộn các mảng tại chỗ. Nó cũng trả về một mảng sản phẩm phụ KHÔNG phải là đầu ra bị xáo trộn và không được xem xét.

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

2

MATL , 16 byte

XH`HnYr&)XHxvHHn

Hãy thử trực tuyến!

Ngư dân trong MATL. Gần một phần ba chương trình này được dành cho bức thưH , tương ứng với chức năng clipboard trong MATL.

Về cơ bản, Hlưu trữ các mục không sử dụng từ đầu vào, trong khi ngăn xếp theo dõi danh sách được xáo trộn.


2

Japt, 12

rÈiMqZÄ Y}[]

Thử nó!

-10 (khoảng một nửa;) nhờ @Shaggy!

Tôi đã muốn thử một ngôn ngữ chơi gôn và thông dịch viên Japt có tài liệu tốt và cách để thử mọi thứ trong trình duyệt.

Dưới đây là chiến lược tôi đã thực hiện:

  • Giảm seeding đầu vào với một mảng trống
  • Ở mỗi bước, tìm một vị trí ngẫu nhiên để chèn phần tử hiện tại

1
Chào mừng đến với Japt, thật tốt khi có bạn với chúng tôi. Tôi nghĩ rằng điều này làm việc cho 9 byte, sử dụng cùng một phương pháp. Nếu RNG là không thỏa đáng, tuy nhiên, sau đó thử này để thay thế.
Xù xì

@Shaggy - Cảm ơn lời khuyên! :) Tôi đã kết thúc bằng cách sử dụng một phiên bản sửa đổi một chút của giải pháp thứ 2 của bạn. Vì tham số thứ 3 của hàm giảm là một chỉ mục, nên chúng ta đã biết độ dài.
dana

1

Javascript ES6, 69

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

Đó là Fisher Yates.

PS: Có thể được thử nghiệm trong Firefox


@ MartinBüttner, đã xóa nó :)
Qwertiy 4/2/2015


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

Một giải pháp khác của Fisher-Yates lấy cảm hứng từ thuật toán tại https://wiki.haskell.org/Random_shuffle .

s là một hàm có chữ ký: IOArray Int a -> IO [a]


1

CJam - 30

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

Dùng thử tại http://cjam.aditsu.net/

Ví dụ đầu vào: [10 20 30 40 50]
Đầu ra ví dụ: 3020401050(thêm một pở cuối mã để in đẹp)

Nếu mã được phép lấy đầu vào từ ngăn xếp (như hàm), thì 2 ký tự đầu tiên có thể được loại bỏ, giảm kích thước xuống 28.

Giải trình:

Mã này dài hơn tôi mong đợi, do thiếu toán tử "hoán đổi" cho các mảng
(sẽ được thực hiện sau: 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]

Như đã đề cập trong các ý kiến, tôi sợ điều này là không hợp lệ. Ít nhất _là O (N) (bên trong một vòng lặp O (N)). Thật không may, tôi không thấy một cách nào để giải quyết vấn đề đó ở CJam.
Martin Ender

Danh sách được xử lý như các đối tượng bất biến, vì vậy việc sao chép chỉ được thực hiện như sao chép tham chiếu. Đó thực sự là tthứ giết chết nó, vì nó không thể thay đổi danh sách và bây giờ phải tạo một bản sao.
Runer112

@ MartinBüttner Tôi sắp đăng bài tương tự như Runer112; vâng có thể có một vấn đề với t, tôi muốn cải thiện nó trong các phiên bản tương lai ..
aditsu

Vì vậy, mã này tuân theo tinh thần của câu hỏi, nhưng không phải là "chữ cái", do các vấn đề thực thi ngôn ngữ nội bộ.
aditsu

1

JavaScript (ES 6), 61

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

Bạn có thể kiểm tra nó ở đây bằng cách chỉ cần thêm một dòng ghi shuffle = S(chỉ Firefox).


1

SỐ LIỆU, 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

Dự kiến ​​đầu vào là số phân cách không gian. Tôi có thể loại bỏ các tiêu đề và số quan sát khỏi đầu ra nếu bạn muốn, nhưng nếu không thì điều này ngắn hơn.


Cái gì _ntrong cái này?
Martin Ender

_n là số lượng quan sát hiện tại.
đánh dấu


1

SQF, 91 byte

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

1
Điều này là sai lệch (xem "hoán đổi (i <-> ngẫu nhiên)" trên Will It Shuffle), nhưng bạn có thể biến nó thành Fisher-Yates (không thiên vị) bằng cách thay thế %xbằng %i.
Martin Ender

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.