Xuất ra một sàn được xáo trộn bằng cách sử dụng đầu vào ngẫu nhiên


9

Đầu ra đầu vào:

Input : Một thống nhất ngẫu nhiên, dài vô hạn, chuỗi '0 và' 1 của, lấy từ stdin. Chuỗi được coi là thực sự ngẫu nhiên, không giả ngẫu nhiên. Điều thống nhất là mỗi nhân vật đều có khả năng là '0' hoặc '1' như nhau.

Cẩn thận! Đầu vào dài vô hạn, vì vậy bạn không thể lưu trữ tất cả trong bộ nhớ bằng cách sử dụng hàm như raw_input () trong python. Nếu tôi không nhầm, golfscript sẽ thất bại với đầu vào vô hạn, vì nó đẩy toàn bộ đầu vào lên ngăn xếp trước khi chạy.

Đầu ra : Một sàn chuẩn xáo trộn ngẫu nhiên đồng đều, không có joker. Đó là thống nhất trong đó tất cả các thứ tự đều có khả năng như nhau.

Mỗi thẻ trong đầu ra là thứ hạng, A, 2-9, T, J, Q hoặc K được ghép nối với nó phù hợp, c, d, h hoặc s. Ví dụ, 10 spades làTs

Các thẻ của bộ bài nên được phân cách bằng khoảng trắng.

Bạn không được sử dụng các thư viện hoặc hàm ngẫu nhiên tích hợp vì chúng không thực sự ngẫu nhiên, chỉ giả ngẫu nhiên.

Ví dụ đầu vào

Bạn có thể sử dụng tập lệnh python sau đây để nhập dữ liệu vào chương trình của mình:

import sys, random
try:
    while True:
        sys.stdout.write(str(random.randint(0,1)))
except IOError:
    pass

Nếu bạn lưu tập lệnh dưới dạng rand.py, hãy kiểm tra chương trình của bạn với python rand.py | your_program

Trong python 3, nó chạy như mong đợi, nhưng trong python 2.7 tôi nhận được thông báo lỗi sau đầu ra của chương trình, nhưng chỉ sau khi mọi thứ đã xong, vì vậy hãy bỏ qua thông báo lỗi.

Ví dụ đầu ra:

Đây là cách bộ bài nên được in nếu nó được xáo trộn thành một thứ tự được sắp xếp:

Ac 2c 3c 4c 5c 6c 7c 8c 9c Tc Jc Qc Kc Ad 2d 3d 4d 5d 6d 7d 8d 9d Td Jd Qd Kd Ah 2h 3h 4h 5h 6h 7h 8h 9h Th Jh Qh Kh As 2s 3s 4s 5s 6s 7s 8s 9s Ts Js Qs Ks

Ghi điểm:

Đây là một mã golf. Mã ngắn nhất sẽ thắng.

Chương trình ví dụ:

Đây là một giải pháp python 2.7, không chơi gôn.

import sys
def next():
    return int(sys.stdin.read(1))==1
def roll(n):
    if n==1:
        return 0
    if n%2==0:
        r=roll(n/2)
        if next():
            r+=n/2
        return r
    else:
        r=n
        while(r==n):
            r=roll(n+1)
        return r
deck = [rank+suit for suit in 'cdhs' for rank in 'A23456789TJQK']
while len(deck)>0:
    print deck.pop(roll(len(deck))),

3
"Nếu tôi không nhầm, golfscript sẽ thất bại với đầu vào vô hạn, vì nó đẩy toàn bộ đầu vào lên ngăn xếp trước khi chạy." Chà, đó là một cách để đưa nó ra khỏi hoạt động.
dmckee --- ex-moderator mèo con

Tôi hơi bối rối, tha thứ cho tôi. Đầu vào phải làm gì với xáo trộn bộ bài thực tế? Có lẽ tôi chỉ cần làm rõ một chút.
jdstankosky

1
Bạn không thể sử dụng các hàm giả ngẫu nhiên trong mã của mình, vì vậy bạn cần sử dụng đầu vào (mà chúng tôi giả sử là thực sự ngẫu nhiên) để tạo ngẫu nhiên. Ví dụ: trong python bạn có thể sử dụng (sys.stdin.read (1) == '1') để lấy boolean ngẫu nhiên, nhưng bạn không thể sử dụng (Random.randint (0,1) == 1), bởi vì nó chỉ là giả ngẫu nhiên.
tông_box

Câu trả lời:


7

Ruby, 89 87 ký tự

l=*0..51;l.map{l-=[i=l[gets(6).to_i 2]||redo];$><<'A23456789TJQK'[i/4]+'cdhs'[i%4]+' '}

Chỉnh sửa: phiên bản trước

l=*0..51;(l-=[i=l[gets(6).to_i 2]];i&&$><<'A23456789TJQK'[i/4]+'cdhs'[i%4]+' ')while l[0]

3

Con trăn 122

import sys
D=[R+S for S in'cdhs'for R in'A23456789TJQK']
while(D):
    x=int(sys.stdin.read(6),2)
    if x<len(D):print D.pop(x)

Giải trình:

Thẻ không sử dụng được lưu trữ trong D. Điều này chỉ đơn giản là lấy chỉ số ngẫu nhiên hợp lệ tiếp theo từ luồng đầu vào và bật phần tử đó từ D.

Trừ khi tôi đang thiếu một cái gì đó, không nên có sự thiên vị. Kịch bản sẽ đưa ra bất kỳ chỉ số không hợp lệ> len(D), nhưng điều này không dẫn đến sai lệch cho các số thấp hơn bởi vì mỗi cửa sổ bật lên liên tiếp sẽ làm giảm chỉ số của từng yếu tố trong quá khứ so với i.


Vì vậy, bạn loại bỏ hầu hết các đầu vào ngẫu nhiên (vô hạn)? Tức là bạn ngừng xáo trộn một khi bạn không có thẻ "không sử dụng"?
Leigh

3

Perl, 80 ký tự

Đây là một triển khai khác không bị sai lệch và ngắn hơn hai ký tự:

$/=1x9;$_=A23456789TJQK;s/./$&s$&c$&d$&h/g;%h=map{<>.$_,"$_ "}/../g;say values%h

thực hiện cũ (82 ký tự):

$/=1x9;$_=A23456789TJQK;s/./$&s$&c$&d$&h/g;say map/..$/&&$&.$",sort map<>.$_,/../g

mô tả thực hiện cũ:

# set input record separator (how internal readline() delimits lines) to "11111111"
$/ = 1x9; 

# constructs a string representation of all 52 cards: "AsAc(...)KdKh"
$_ = A23456789TJQK; s/./$&s$&c$&d$&h/g;

# for each pair of characters (each card) in the string $_
foreach $card (/../g)
{
    # read from STDIN until $/ is found (this may NEVER occur!), which
    # results in a random string of 1s and 0s
    $weight = <>; 

    # append the card identifier onto the random string
    $card = $weight . $card;

    # add this new card identifier to a new list
    push @cards, $card;
}

# sort the cards with their random string prefix
sort @cards;

# for each card in the "randomly sorted" list
foreach $card (@cards)
{
    # capture the final two characters from the card (the rank and suit), 
    # and append a space onto them
    $card =~ /..$/;  
    $card = $card . $";

    print $card;
}

Chỉ tò mò: bất cứ ai cũng có thể chỉ ra rằng phương pháp này tạo ra mỗi bộ bài có xác suất giống nhau?
Howard

2
Nếu tôi đang đọc đúng (IANAPH), nó sẽ gán 'trọng số' ngẫu nhiên cho mỗi thẻ, sau đó sắp xếp theo trọng lượng. Khi hai thẻ được gán cùng trọng số, chúng sẽ được để lại theo thứ tự sort, dẫn đến sai lệch đối với thứ tự chữ cái.
gian hàng

bạn nói đúng, @boothby. sắp xếp không để lại giải pháp này với sự thiên vị trong trường hợp nhiều thẻ có cùng "trọng lượng". cũng không thể đảm bảo rằng giải pháp này sẽ tạo ra kết quả. Tôi sẽ thêm một mô tả về cách thức hoạt động của nó để ai đó thông minh hơn tôi có thể phân tích nó
vào

Sẽ hoàn toàn ổn nếu một số đầu vào khiến chương trình không bao giờ kết thúc, miễn là xác suất chương trình chấm dứt tiếp cận 1 khi thời gian đến vô cùng. Chương trình ví dụ không bao giờ chấm dứt trên đầu vào của tất cả '1'. Tôi khá chắc chắn rằng thực sự không thể có được sự ngẫu nhiên thống nhất trong khi biết chương trình của bạn chấm dứt sau một số bit nhất định được đọc.
tông_box

1
Làm thế nào bạn có thể chọn một số ngẫu nhiên thống nhất giữa 1 và 3 với số bit hữu hạn? Bạn sẽ cần phải làm điều đó ở gần cuối của shuffle Fisher-Yates và giai thừa (52) chia hết cho 3 để nó có cùng một vấn đề.
tông_box

3

C, 197 178 161 ký tự

EDIT : Sử dụng một hàm ngẫu nhiên mới, ngắn hơn nhiều - đọc số nguyên 4 chữ số svà sử dụng s%64. Mỗi số thập phân gồm 6 chữ số chỉ gồm 0 và 1, được lấy %64kết quả trong một kết quả duy nhất, do đó tính ngẫu nhiên là tốt.
Cách tiếp cận này tiêu thụ nhiều bit ngẫu nhiên hơn, nhưng ngắn hơn đáng kể.

B[52],t,s,i=104;
r(){scanf("%6d",&s);s%=64;s>i&&r();}
main(){
    for(;i--;)B[i%52]=i<52
        ?r(),t=B[s],B[s]=B[i],printf("%c%c\n","23456789ATJQK"[t/4],"cdhs"[t%4]),t
        :i-52;
}

Logic cơ bản rất đơn giản - khởi tạo một mảng gồm 52 ints bằng 0..51, xáo trộn (thay thế ngẫu nhiên phần tử x bằng một phần tử khác từ phạm vi 0..x), in định dạng (n / 4 = xếp hạng, n% 4 = phù hợp) .
Một vòng lặp, chạy 104 lần, thực hiện khởi tạo (52 lần chạy đầu tiên), xáo trộn và in (52 lần chạy cuối cùng).
Một số ngẫu nhiên được tạo bằng cách kéo ncác bit ngẫu nhiên, cho đến khi 1<<nít nhất là mức tối đa mong muốn. Nếu kết quả là nhiều hơn mức tối đa - thử lại.


Điều này phức tạp s>7?"ATJQK"[s-8]:s+50dài hơn đơn giản "A23456789TJQK"[s]. Thứ hai bạn có thể sử dụng t/4t%4thay vì t%13t/13.
Howard

Không cần phải đặt tlại vào mảng khi xuất
l4m2

3

vỏ unix ~ 350

Điều này không phải là ngắn hay đẹp, cũng không hiệu quả, tuy nhiên tôi đã tự hỏi làm thế nào khó khăn để làm điều này với các tiện ích vỏ unix tiêu chuẩn.

Câu trả lời này chọn chuỗi nhị phân vô hạn thành 6 bit độ dài và chỉ chọn những chuỗi nằm trong phạm vi chính xác (1-52), ở đây chuỗi nhị phân vô hạn được mô phỏng bởi urandom và xxd:

</dev/urandom xxd -b | cut -d' ' -f2-7 | tr -d ' \n'

Việc cắt và lựa chọn được thực hiện với nếp gấp, sed và bc:

random_source | {echo ibase=2; cat | fold -w6 | sed -r 's/^/if(/; s/([^\(]+)$/\1 <= 110100 \&\& \1 > 0) \1/'}

Điều này tạo ra các dòng như:

if(101010 <= 110100 && 101010 > 0) 101010

Mà có thể được hướng vào bc.

Từ luồng số này, chuỗi của bộ bài được chọn như thế này (Tôi đang sử dụng zsh, nhưng hầu hết các shell hiện đại nên thích ứng với điều này):

deck=({1..52})
seq_of_numbers | while read n; do 
  if [[ -n $deck[n] ]]; then 
    echo $n; deck[n]=""
    [[ $deck[*] =~ "^ *$" ]] && break
  fi
done

Chuỗi số ngẫu nhiên bây giờ cần phải được thay đổi thành tên thẻ. Trình tự tên thẻ được tạo dễ dàng với GNU song song:

parallel echo '{2}{1}' ::: c d s h ::: A {2..9} T J Q K

Kết hợp đầu ra từ hai lệnh cuối cùng với dán và sắp xếp trên các số:

paste random_deck card_names | sort -n | cut -f2 | tr '\n' ' '

Toàn bộ điều như một lớp lót quái dị (chỉ được thử nghiệm trong zsh):

paste \
  <(deck=({1..52}); \
    </dev/urandom xxd -b | cut -d' ' -f2-7 | tr -d ' \n' |
      {echo ibase=2; fold -w6 | sed -r 's/^/if(/; s/([^\(]+)$/\1 <= 110100 \&\& \1 > 0) \1/'} | 
      bc | 
      while read n; do 
        if [[ -n $deck[n] ]]; then 
          echo $n; deck[n]=""
          [[ -z ${${deck[*]}%% *} ]] && break
        fi
      done) \
  <(parallel echo '{2}{1}' ::: c d s h ::: A {2..9} T J Q K) | 
sort -n | cut -f2 | tr '\n' ' '

Chỉnh sửa - thêm phiên bản bash

Đây là một phiên bản hoạt động trong bash. Tôi đã loại bỏ các { }chỉ mục trong shell và mảng là zero. Độ trống của mảng được kiểm tra với việc mở rộng tham số, hiệu quả hơn một chút và cũng được áp dụng trong ví dụ trên.

paste \
  <(deck=($(seq 52)); \
    </dev/urandom xxd -b | cut -d' ' -f2-7 | tr -d ' \n' | 
      (echo ibase=2; fold -w6 | sed -r 's/^/if(/; s/([^\(]+)$/\1 <= 110100 \&\& \1 > 0) \1/') | 
        bc | 
        while read n; do 
          if [[ -n ${deck[n-1]} ]]; then 
            echo $n
            deck[n-1]=""
            [[ -z ${deck[*]%% *} ]] && break
          fi
        done \
  ) \
  <(parallel echo '{2}{1}' ::: c d s h ::: A {2..9} T J Q K) | 
sort -n | cut -f2 | tr '\n' ' '; echo

2

K & R c - 275

  • Chỉ số v3 vào chuỗi ký tự trực tiếp
  • v2 Gợi ý từ luser droog trong các bình luận để sử dụng chuỗi và thay thế các charchữ còn lại bằng intchữ

Chơi gôn

#define F for(i=52;--i;)
#define P putchar 
M=1<<9-1,i,j,k,t,v,s,a[52];r(){t=0,j=9;while(--j)t=t<<1|(getchar()==49);
return t;}main(){F a[i]=i;F{k=i+1;do{j=r();}while(j>M/k*k-1);j%=i;t=a[i];
a[i]=a[j];a[j]=t;}F{s=a[i]&3;v=a[i]>>2;P(v>7?"TJQKA"[v-8]:v+50);
P("cdhs"[s]);P(32);}}

Khá nhiều lực lượng vũ phu ở đây. Tôi chỉ đọc chín bit từ đầu vào để tạo ra đầu ra RNG tối thiểu và thực hiện việc giảm mô đun vẽ lại thông thường-nếu-không-sử dụng-giá trị-ở-đầu-cuối để có được đầu ra đồng nhất để tạo ra sự xáo trộn lựa chọn.

Phiên bản không chơi gôn này khác ở chỗ nó lấy đầu vào /dev/urandomthay vì từ định dạng đầu vào được mô tả.

#include <stdio.h>
M=1<<8-1, /* RANDMAX */
  i, j, k, /* counters */
  t, /* temporary for swapping, and accumulating */
  a[52]; /* the deck */
r(){ /* limited, low precision rand() that depends on a random stream
    of '0' and '1' from stdin */
  t=0,j=9;
  while(--j)t=t<<1|(getchar()&1);
  return t;
}
main(){
  for(i=52;--i;)a[i]=i;  /* initialize the deck */
  for(i=52;--i;){
    /*  printf("shuffling %d...\n",i); */
    k=i+1;
    do { /* draw *unifromly* with a a-unifrom generator */
      j=r(); 
      /* printf("\t j=0x%o\n",j); */
    }while(j>M/k*k-1); /* discard values we can't mod into evently */
    j%=i;
    t=a[i];a[i]=a[j];a[j]=t; /* swap */
  }
  for(i=52;--i;){ /* output the deck */
    j=a[i]&3;
    k=a[i]>>2;
    putchar(k>7?"TJQKA"[k-8]:k+'2');
    putchar("cdhs"[j]);
    putchar(' ');
  }
}

+1 Tôi có nhiều thứ để học. BTW, tại sao không "TJQKA""cdhs"?
luser droog

Oh. Đúng. intS. Tôi hiểu rồi. Có thể vẫn còn giá trị để lưu tất cả các dấu câu. Thậm chí có thể tạo ra yếu tố bên charngoài getcharputcharvới một macro pasty điên rồ ...
kẻ lừa đảo rủ rê

1
Sự thay thế vĩ mô cần phải đạt được rất nhiều bởi vì chúng phải bắt đầu #define N và kết thúc bằng một dòng mới được tính là một ký tự và đó là 11, cộng với bit bạn đang thay thế. Chắc chắn có thêm một vài nhân vật trong việc thay thế một số hoặc tất cả các ký tự chữ bằng ký tự int, nhưng đã muộn ở đây ... có lẽ tôi sẽ làm điều đó vào lúc khác.
dmckee --- ex-moderator mèo con

@luserdroog Clearer đứng đầu bây giờ. Tất nhiên các chuỗi là tốt hơn - mặc dù bạn phải chỉ định loại - bởi vì các ký tự chỉ là số nguyên ngắn. Ngoài ra, tôi có thể kết hợp chúng và những người thay thế ASCII có được một loạt các nét trong một lần.
dmckee --- ex-moderator mèo con

0

PHP, 158 ký tự

Các dòng mới đã được thêm vào để ngăn chặn khối mã đạt được thanh cuộn, chúng có thể được gỡ bỏ một cách an toàn.

for($i=52,$x='shdcKQJT98765432A';$i--;$c[]=$x[4+$i%13].$x[$i/13]);
while(ord($i=fgetc(STDIN)))$c[$i]^=$c[$a]^=$c[$i]^=$c[$a=2+($a+++$i)%50];
die(join(' ',$c));

Trước khi tôi được yêu cầu thêm a <?php, hãy biết rằng bạn có thể gọi PHP mà không cần thẻ này khá dễ dàng, bằng cách sử dụng:cat golf.php | php -a

De-golfed và nhận xét:

// Abuse of the for construct to save a bit of space, and to make things more obscure looking in general.
for (
    // Card suit and number are reversed because we're using a decrementor to count
    // down from 52, instead of up to 52
    $i = 52,
    $x = 'shdcKQJT98765432A';
    // Condition AND per-loop decrement
    $i--;
    // Add a new element to the array comprising of $i mod 13 + 4 (to skip suit ids)
    // followed by simply $i divided by 13 to pick a suit id.
    $c[] =
        $x[4 + $i % 13] .
        $x[$i / 13]
);

while(

    // Assignment inside the condition, a single character from input.
    ord($i = fgetc(STDIN))
)
    // In-place swap. Shorter than using a single letter temporary variable.
    // This is the pseudo-random shuffle.
    $c[$i] ^=
    $c[$a] ^=
    $c[$i] ^=
    $c[
        // We use the input (0 or 1) to identify one of two swap locations at the
        // start of the array. The input is also added to an accumulator (to make
        // the increments "random") that represents a swap destination.
        $a = 2 + ($a++ + $i) % 50
    ];

// Dramatic way of doing "echo" in the same space.
die(
    join(' ', $c)
);

Có hai lỗi dự kiến, không ảnh hưởng đến đầu ra của chương trình.

Đầu tiên là vì $akhông được khởi tạo, nhưng NULL được chuyển đổi thành 0 và chương trình tiếp tục.

Thứ hai là bởi vì dòng ký tự dường như nhận được một dòng mới từ một nơi nào đó, ngay cả khi nó không được cung cấp (PHP tốt) và đó là một chỉ mục không xác định trong mảng. Đây là ký tự cuối cùng của đầu vào và không ảnh hưởng đến đầu ra.

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.