Geben Sie ein gemischtes Deck mit zufälliger Eingabe aus

9

Input-Output:

Eingabe : Eine gleichmäßig zufällige, unendlich lange Folge von '0' und '1', entnommen aus stdin. Es wird angenommen, dass die Zeichenfolge wirklich zufällig und nicht pseudozufällig ist. Es ist insofern einheitlich, als jedes Zeichen gleich wahrscheinlich eine '0' oder '1' ist.

Vorsichtig! Die Eingabe ist unendlich lang, sodass Sie nicht alles mit einer Funktion wie raw_input () in Python im Speicher speichern können. Wenn ich mich nicht irre, schlägt Golfscript mit unendlicher Eingabe fehl, da es die gesamte Eingabe vor dem Ausführen auf den Stapel schiebt.

Ausgabe : Ein gleichmäßig zufällig gemischtes Standarddeck ohne Joker. Es ist insofern einheitlich, als alle Bestellungen gleich wahrscheinlich sind.

Jede Karte in der Ausgabe hat den Rang A, 2-9, T, J, Q oder K, der mit der Farbe c, d, h oder s verknüpft ist. Zum Beispiel ist die 10 PikTs

Die Karten des Decks sollten durch Leerzeichen getrennt sein.

Sie dürfen keine integrierten Zufallsbibliotheken oder Funktionen verwenden, da diese nicht wirklich zufällig sind, sondern nur pseudozufällig.

Beispiel Eingabe

Sie können das folgende Python-Skript verwenden, um Eingaben in Ihr Programm zu leiten:

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

Wenn Sie das Skript als rand.py speichern, testen Sie Ihr Programm mit python rand.py | your_program

In Python 3 läuft es wie erwartet, aber in Python 2.7 wird nach der Ausgabe meines Programms eine Fehlermeldung angezeigt, jedoch erst, nachdem alles erledigt ist. Ignorieren Sie einfach die Fehlermeldung.

Beispielausgabe:

So sollte das Deck gedruckt werden, wenn es zufällig in eine sortierte Reihenfolge gemischt wird:

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

Wertung:

Dies ist ein Code Golf. Der kürzeste Code gewinnt.

Beispielprogramm:

Hier ist eine Python 2.7-Lösung, die nicht Golf spielt.

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))),
Pappschachtel
quelle
3
"Wenn ich mich nicht irre, schlägt Golfscript mit unendlicher Eingabe fehl, da es die gesamte Eingabe vor dem Ausführen auf den Stapel schiebt." Nun, das ist eine Möglichkeit, es aus dem Rennen zu nehmen.
dmckee --- Ex-Moderator Kätzchen
Ich bin ein bisschen verwirrt, vergib mir. Was hat die Eingabe mit dem tatsächlichen Mischen des Decks zu tun? Vielleicht brauche ich nur eine kleine Klarstellung.
jdstankosky
1
Sie können keine Pseudozufallsfunktionen in Ihrem Code verwenden, daher müssen Sie die Eingabe (von der wir annehmen, dass sie wirklich zufällig ist) verwenden, um Zufälligkeit zu generieren. In Python können Sie beispielsweise (sys.stdin.read (1) == '1') verwenden, um einen zufälligen Booleschen Wert zu erhalten, aber Sie können (random.randint (0,1) == 1) nicht verwenden, weil es ist nur pseudozufällig.
cardboard_box

Antworten:

7

Ruby, 89 87 Zeichen

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

Bearbeiten: vorherige Version

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

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

Erläuterung:

Nicht verwendete Karten werden in D gespeichert. Dadurch wird einfach der nächste gültige Zufallsindex aus dem Eingabestream abgerufen und dieses Element aus D entfernt.

Wenn mir nichts fehlt, sollte es keine Voreingenommenheit geben. Das Skript wirft alle ungültigen Indizes aus> len(D), dies führt jedoch nicht zu einer Verzerrung für niedrigere Zahlen, da jedes aufeinanderfolgende Pop den Index jedes vergangenen Elements als i reduziert.

Scleaver
quelle
Sie verwerfen also den größten Teil der (unendlichen) zufälligen Eingabe? Dh du hörst auf zu mischen, wenn du keine "unbenutzten" Karten hast?
Leigh
3

Perl, 80 Zeichen

Hier ist eine weitere Implementierung, die nicht unter der Verzerrung leidet und zwei Zeichen kürzer ist:

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

alte Implementierung (82 Zeichen):

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

alte Implementierungsbeschreibung:

# 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;
}
ardnew
quelle
Nur neugierig: Kann jemand zeigen, dass dieser Ansatz jedes Kartenspiel mit der gleichen Wahrscheinlichkeit erzeugt?
Howard
2
Wenn ich dieses Recht lese (IANAPH), weist es jeder Karte zufällige 'Gewichte' zu und sortiert dann nach Gewicht. Wenn zwei Karten das gleiche Gewicht zugewiesen bekommen, werden sie in der richtigen Reihenfolge belassen sort, was zu einer Tendenz zur alphabetischen Reihenfolge führt.
Stand
Sie haben Recht, @boothby. Die Sortierung hinterlässt bei dieser Lösung eine Verzerrung für den Fall, dass mehrere Karten das gleiche "Gewicht" haben. Es kann auch nicht garantiert werden, dass diese Lösung jemals zu einem Ergebnis führen wird. Ich werde eine Beschreibung hinzufügen, wie es funktioniert, damit jemand, der klüger als ich ist, es analysieren kann
zwar
Es ist vollkommen in Ordnung, wenn einige Eingaben dazu führen, dass das Programm niemals beendet wird, solange sich die Wahrscheinlichkeit, dass das Programm beendet wird, 1 nähert, wenn sich die Zeit unendlich nähert. Das Beispielprogramm wird niemals bei einer Eingabe aller Einsen beendet. Ich bin mir ziemlich sicher, dass es tatsächlich unmöglich ist, eine einheitliche Zufälligkeit zu erzielen, wenn Sie wissen, dass Ihr Programm nach einer bestimmten Anzahl gelesener Bits beendet wird.
cardboard_box
1
Wie kann man eine einheitliche Zufallszahl zwischen 1 und 3 mit einer endlichen Anzahl von Bits auswählen? Sie müssen dies gegen Ende des Fisher-Yates-Shuffle tun, und Fakultät (52) ist durch 3 teilbar, sodass das gleiche Problem besteht.
cardboard_box
3

C, 197 178 161 Zeichen

BEARBEITEN : Verwenden einer neuen Zufallsfunktion, die viel kürzer ist - liest eine 4-stellige Ganzzahl sund verwendet s%64. Jede 6-stellige Dezimalzahl, die nur aus 0 und 1 besteht, %64führt zu einem eindeutigen Ergebnis, sodass die Zufälligkeit gut ist.
Dieser Ansatz verbraucht viel mehr zufällige Bits, ist jedoch erheblich kürzer.

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

Die grundlegende Logik ist einfach: Initialisieren Sie ein Array von 52 Zoll mit 0..51, mischen Sie (ersetzen Sie das Element x zufällig durch ein anderes aus dem Bereich 0..x), drucken Sie es formatiert (n / 4 = Rang, n% 4 = Farbe). .
Eine Schleife, die 104 Mal ausgeführt wird, führt die Initialisierung (erste 52 Läufe), das Mischen und Drucken (die letzten 52 Läufe) durch.
Eine Zufallszahl wird durch Ziehen von nZufallsbits erzeugt , bis 1<<nmindestens das gewünschte Maximum erreicht ist. Wenn das Ergebnis mehr als das Maximum ist, versuchen Sie es erneut.

ugoren
quelle
Das s>7?"ATJQK"[s-8]:s+50ist länger als das Einfache "A23456789TJQK"[s]. Zweitens können Sie t/4und t%4anstelle von t%13und verwenden t/13.
Howard
Sie müssen tbei der Ausgabe nicht immer noch in das Array zurückkehren
l4m2
3

Unix Shell ~ 350

Dies ist weder kurz noch hübsch, noch ist es effizient, aber ich habe mich gefragt, wie schwierig es wäre, dies mit Standard-Unix-Shell-Dienstprogrammen zu tun.

Diese Antwort zerlegt die unendliche Binärzeichenfolge in 6 Bitlängen und wählt nur diejenigen aus, die im richtigen Bereich (1-52) liegen. Hier wird die unendliche Binärzeichenfolge durch urandom und xxd simuliert:

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

Das Hacken und Auswählen erfolgt mit Fold, Sed und BC:

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

Dies erzeugt Linien wie:

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

Welches kann in bc gerichtet werden.

Aus diesem Zahlenstrom wird die Reihenfolge des Decks wie folgt ausgewählt (ich verwende zsh, aber die meisten modernen Shells sollten daran anpassbar sein):

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

Die zufällige Zahlenfolge muss nun in Kartennamen geändert werden. Die Kartennamenfolge kann einfach mit GNU parallel generiert werden:

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

Kombinieren Sie die Ausgabe der letzten beiden Befehle mit Einfügen und Sortieren der Zahlen:

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

Das Ganze als ein monströser Einzeiler (nur in zsh getestet):

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

Bearbeiten - Bash-Version hinzugefügt

Hier ist eine Version, die in Bash funktioniert. Ich habe die In-Shell entfernt { }und die Array-Indizes basieren auf Null. Die Array-Leere wird mit einer etwas effizienteren Parametererweiterung überprüft und auch im obigen Beispiel übernommen.

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
Thor
quelle
2

K & R c - 275

  • v3 Indizieren Sie direkt in die Zeichenfolgenliterale
  • v2 Vorschlag von luser droog in den Kommentaren, Zeichenfolgen zu verwenden und verbleibende charLiterale durch intLiterale zu ersetzen

Golf:

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

Ziemlich brutale Gewalt hier. Ich habe gerade neun Bits von der Eingabe gelesen, um eine minimale RNG-Ausgabe zu bilden, und die übliche Reduzierung des Moduls am Ende vorgenommen, wenn die nicht verwendeten Werte am Ende reduziert werden, um eine gleichmäßige Ausgabe für eine Auswahlmischung zu erhalten.

Diese Version ohne Golf unterscheidet sich darin, dass die Eingabe /dev/urandomeher vom als vom beschriebenen Eingabeformat stammt.

#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(' ');
  }
}
dmckee --- Ex-Moderator Kätzchen
quelle
+1 Ich muss noch viel lernen. Übrigens, warum nicht "TJQKA"und "cdhs"?
luser droog
Oh. Richtig. ints. Ich verstehe es. Könnte sich trotzdem lohnen, alle Satzzeichen zu speichern. Könnte sogar das charAus getcharund putcharmit einem verrückten pastösen Makro
berücksichtigen
1
Makro - Ersetzungen brauchen viel zu gewinnen , weil sie mit anfangen #define N und enden mit einem Newline , dass zählt als ein Zeichen und das ist 11, plus die Bit Sie ersetzen. Es gibt sicherlich noch ein paar Zeichen, wenn einige oder alle Zeichenliterale durch int-Literale ersetzt werden, aber hier ist es spät ... vielleicht mache ich es ein anderes Mal.
dmckee --- Ex-Moderator Kätzchen
@luserdroog Clearer jetzt geleitet. Natürlich sind Zeichenfolgen besser - obwohl Sie den Typ angeben müssen -, da Zeichen nur kurze Ganzzahlen sind. Außerdem kann ich sie kombinieren und die ASCII-Ersetzungen erhalten eine Reihe von Strichen auf einmal.
dmckee --- Ex-Moderator Kätzchen
0

PHP, 158 Zeichen

Es wurden Zeilenumbrüche hinzugefügt, um zu verhindern, dass der Codeblock Bildlaufleisten erhält. Sie können sicher entfernt werden.

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

Bevor ich aufgefordert werde, ein hinzuzufügen <?php, lassen Sie es wissen, dass Sie PHP ohne dieses Tag ganz einfach aufrufen können, indem Sie:cat golf.php | php -a

Entgolf und kommentiert:

// 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)
);

Es gibt zwei erwartete Fehler, die sich nicht auf die Ausgabe des Programms auswirken.

Der erste Grund $aist, dass nicht initialisiert wird, aber NULL in 0 konvertiert wird und das Programm fortgesetzt wird.

Der zweite Grund ist, dass der Zeichenstrom von irgendwoher eine neue Zeile zu bekommen scheint, auch wenn er nicht bereitgestellt wird (gutes altes PHP), und das ist ein undefinierter Index im Array. Es ist das letzte Zeichen der Eingabe und hat keinen Einfluss auf die Ausgabe.

Leigh
quelle