There's never really been a definitive ASCII-cards challenge AFAIK. So, using the following deck of ASCII cards:
.------..------..------..------..------..------..------..------..------..------..------..------..------.
|2.--. ||3.--. ||4.--. ||5.--. ||6.--. ||7.--. ||8.--. ||9.--. ||T.--. ||J.--. ||Q.--. ||K.--. ||A.--. |
| (\/) || (\/) || (\/) || (\/) || (\/) || (\/) || (\/) || (\/) || (\/) || (\/) || (\/) || (\/) || (\/) |
| :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: |
| '--'2|| '--'3|| '--'4|| '--'5|| '--'6|| '--'7|| '--'8|| '--'9|| '--'T|| '--'J|| '--'Q|| '--'K|| '--'A|
'------''------''------''------''------''------''------''------''------''------''------''------''------'
.------..------..------..------..------..------..------..------..------..------..------..------..------.
|2.--. ||3.--. ||4.--. ||5.--. ||6.--. ||7.--. ||8.--. ||9.--. ||T.--. ||J.--. ||Q.--. ||K.--. ||A.--. |
| :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: |
| :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: || :\/: |
| '--'2|| '--'3|| '--'4|| '--'5|| '--'6|| '--'7|| '--'8|| '--'9|| '--'T|| '--'J|| '--'Q|| '--'K|| '--'A|
'------''------''------''------''------''------''------''------''------''------''------''------'
.------..------..------..------..------..------..------..------..------..------..------..------..------.
|2.--. ||3.--. ||4.--. ||5.--. ||6.--. ||7.--. ||8.--. ||9.--. ||T.--. ||J.--. ||Q.--. ||K.--. ||A.--. |
| :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: || :/\: |
| (__) || (__) || (__) || (__) || (__) || (__) || (__) || (__) || (__) || (__) || (__) || (__) || (__) |
| '--'2|| '--'3|| '--'4|| '--'5|| '--'6|| '--'7|| '--'8|| '--'9|| '--'T|| '--'J|| '--'Q|| '--'K|| '--'A|
'------''------''------''------''------''------''------''------''------''------''------''------''------'
.------..------..------..------..------..------..------..------..------..------..------..------..------.
|2.--. ||3.--. ||4.--. ||5.--. ||6.--. ||7.--. ||8.--. ||9.--. ||T.--. ||J.--. ||Q.--. ||K.--. ||A.--. |
| :(): || :(): || :(): || :(): || :(): || :(): || :(): || :(): || :(): || :(): || :(): || :(): || :(): |
| ()() || ()() || ()() || ()() || ()() || ()() || ()() || ()() || ()() || ()() || ()() || ()() || ()() |
| '--'2|| '--'3|| '--'4|| '--'5|| '--'6|| '--'7|| '--'8|| '--'9|| '--'T|| '--'J|| '--'Q|| '--'K|| '--'A|
'------''------''------''------''------''------''------''------''------''------''------''------''------'
Take two integers, p and q as input; where p is the number of players and q is the number of cards each player gets.
- Randomly shuffle the deck of cards (this is ambiguous, but means that all cards must be equally likely to appear anywhere once).
- Deal 1 round of cards per player, outputting
qrows ofpcards each row.
Rules:
- The results should be uniformly random, each card should be equally likely to appear anywhere.
- It is guaranteed that
0 < p*q <= 52 and p < 10, you may have undefined behavior for scenarios where this is not met. - You should output
qrows of cards withpcards per row. - Each column should be separated by
|(a pipe char surrounded by spaces); if you choose a different char than this, explain why. Surrounding spaces here are NOT optional. - Each row must have 1 or more newlines inbetween them, more than one is acceptable, 0 is not (1 newline meaning the newline there by default).
- Each row should be labeled with the player who owns it in the format "Player N" (0 or 1-indexed is fine).
- No one card may appear more than once.
Tis for Ten.
Examples:
Function(p=1,q=1):
Player 1 # Can also be 0.
.------.
|2.--. |
| (\/) |
| :\/: |
| '--'2|
'------'
Function(p=2,q=1):
Player 1 | Player 2 # Can also be "Player 0 | Player 1"
.------. | .------.
|2.--. | | |T.--. |
| (\/) | | | (\/) |
| :\/: | | | :\/: |
| '--'2| | | '--'T|
'------' | '------'
Function(p=2,q=2):
Player 1 | Player 2 # Can also be "Player 0 | Player 1"
.------. | .------.
|J.--. | | |3.--. |
| (\/) | | | :/\: |
| :\/: | | | :\/: |
| '--'J| | | '--'3|
'------' | '------'
.------. | .------.
|8.--. | | |6.--. |
| :(): | | | :/\: |
| ()() | | | (__) |
| '--'8| | | '--'6|
'------' | '------'
Artistic credit to a font on: http://patorjk.com/software/taag
10 Answers 10
Charcoal, (削除) 142 (削除ここまで) (削除) 133 (削除ここまで) 125 bytes
×ばつ6θ| »Player IιFθ«↙↓.↓4←'←6↑'↑4.P6↓≔‽52εWNoυε≔‽52ε⊞υε≔§"w↘τ[5PkxτG"εδδ.--.¶✂"{➙aETê;s∨Hμ=⎚↑Z〜SÀd〜⌀Tê"%ε4φ4'--'δ↘
Try it online! Link is to verbose version of code. Edit: Saved 9 bytes by improving my random sampling code. Saved a further 8 bytes by improving my suit printing code. Explanation:
Nθ
Read the number of cards into q.
FN«
Loop over each player.
×ばつ6θ| »
If this is not the first player, print the vertical line between the previous and this player.
Player Iι
Print the player number.
Fθ«
Loop over each card.
↙↓.↓4←'←6↑'↑4.P6↓
Print the card's edge.
≔‽52εWNoυε≔‽52ε⊞υε
Pick a card index that hasn't already been picked, and add it to the list of picked card indices.
≔§"w↘τ[5PkxτG"εδδ
Choose and print the card's rank by cyclically indexing into a string of valid card ranks (2-9, T, J, Q, K, A).
.--.¶
Print the top of the suit.
✂"{➙aETê;s∨Hμ=⎚↑Z〜SÀd〜⌀Tê"%ε4φ4
Print the middle of the suit by slicing into a string. The slice begins at the card index modulo 4 and takes every 4th character until the string runs out (or the f=1000th character is reached). Since 4 and 13 are coprime this ensures that all 52 cards are possible.
'--'δ↘
Print the bottom of the suit and a copy of the rank, and then move to a point that conveniently is not too far away from either the copy of the rank, the start of the next card, or the start of the dividing line for the next player.
-
\$\begingroup\$ When I saw this in the sandbox it was a k-c challenge to print the deck, which took me 102 bytes: Try it online! Link is to verbose version of code. \$\endgroup\$Neil– Neil2017年12月19日 00:49:13 +00:00Commented Dec 19, 2017 at 0:49
Python 2, 357 bytes
from random import*
p,q=input()
A,V=':/\:',':\/:'
c=sample([(""".------.
|%s.--. |
| %s |
| %s |
| '--'%s|
'------'"""%(n,s,t,n)).split('\n')for s,t in('(\/)',V),(A,V),(A,'(__)'),(':():','()()')for n in'123456789TJQKA'],p*q)
print' | '.join('Player '+`i`for i in range(p))
for i in range(0,p*q,p):print'\n'.join(map(' | '.join,zip(c[i:i+p][0],c[i:i+p][1])))
I have no friggin' idea.
Jelly, 126 bytes
×ばつṁẹHY»;6¤ṫ5W;
2r9;"TJQKA"
"¡ẏ%TZ=ẹaɦAY’ṃ"(\/)_:"s4s2
"E¬ƭḊHẈḢ"ðİ"|e*Ḳ?BḤ’ṃ". -|1¶'"żÐ€¢FỴ$€p2£j/€Ẋ
¢ssḢμṣ€"1Zj€" | "Yμ€ÑY
JavaScript (ES6), (削除) 328 (削除ここまで) ... 312 bytes
Takes input in currying syntax (p)(q). Players are 0-indexed.
p=>g=(q,i=p*q*6,d=[...Array(52).keys(a=`:\\/:,(__),()(),(\\/),:/\\:,:():, | ,
,.3.,|0.--. |,| 1 |,| 2 |,| '--'0|,'3',Player 4`.split`,`)].sort(_=>Math.random()-.5))=>i--+p?g(q,i,d)+a[i%p?6:7]+a[i<0?14:i/p%6|8].replace(/\d/,c=>['TJQKA'[j=x>>2]||j-3,a['3454'[x&=3]],a[x%3],'------',p+i][c],x=d[i%p+p*(i/p/6|0)]):''
Demo
let f =
p=>g=(q,i=p*q*6,d=[...Array(52).keys(a=`:\\/:,(__),()(),(\\/),:/\\:,:():, | ,
,.3.,|0.--. |,| 1 |,| 2 |,| '--'0|,'3',Player 4`.split`,`)].sort(_=>Math.random()-.5))=>i--+p?g(q,i,d)+a[i%p?6:7]+a[i<0?14:i/p%6|8].replace(/\d/,c=>['TJQKA'[j=x>>2]||j-3,a['3454'[x&=3]],a[x%3],'------',p+i][c],x=d[i%p+p*(i/p/6|0)]):''
;(update = _ => O.innerText = f(+P.value)(+Q.value))()
<label>Players <input id=P type=number value=1 onchange="update()"/></label> <label>Cards <input id=Q type=number value=1 onchange="update()"/></label> <button onclick="update()">Deal</button><pre id=O style="font-size:10px"></pre>
How?
This is a recursive function, building the output from bottom to top. During the main part in which the cards are drawn, i is initialized to p*q*6 and decremented until it reaches 0. We then draw the header by further decrementing i until it reaches -p.
The ASCII art is split into small pieces stored into the array a[]. The table below describes the content of a[], which makes the rest of the code easier to understand.
Index | Content | Description
-------+------------+------------------------------------------------
0 | ":\\/:" | bottom of 'diamonds' and 'hearts'
1 | "(__)" | bottom of 'spades'
2 | "()()" | bottom of 'clubs'
3 | "(\\/)" | top of 'hearts'
4 | ":/\\:" | top of 'diamonds' and 'spades'
5 | ":():" | top of 'clubs'
6 | " | " | player separator
7 | "\n" | line-feed
8 | ".3." | card row #1, "3" --> "------"
9 | "|0.--. |" | card row #2, "0" --> symbol of card value
10 | "| 1 |" | card row #3, "1" --> top of color ASCII art
11 | "| 2 |" | card row #4, "2" --> bottom of color ASCII art
12 | "| '--'0|" | card row #5, "0" --> symbol of card value
13 | "'3'" | card row #6, "3" --> "------"
14 | "Player 4" | header, "4" --> player ID
Formatted and commented
p => g = ( // p = number of players
q, // q = number of cards
i = p * q * 6, // i = counter
d = [...Array(52).keys( // d = deck
a = `:\\/:,(__),...`.split`,` // a = ASCII art pieces (truncated, see above)
)].sort(_ => Math.random() - .5) // shuffle the deck
) => //
i-- + p ? // if i is greater than -p:
g(q, i, d) + // do a recursive call and append ...
a[i % p ? 6 : 7] + // separator or line-feed
a[i < 0 ? 14 : i / p % 6 | 8] // header or card row
.replace(/\d/, c => [ // where digits are replaced with:
'TJQKA'[j = x >> 2] || j - 3, // 0: symbol of card value
a['3454'[x &= 3]], // 1: top of color ASCII art
a[x % 3], // 2: bottom of color ASCII art
'------', // 3: horizontal border
p + i // 4: player ID
][c], //
x = d[i % p + p * (i / p / 6 | 0)] // x = current card with: bits 0-1 = color
) // bits 2-5 = value
: // else:
'' // stop recursion
Python 2, (削除) 382 (削除ここまで) (削除) 358 (削除ここまで) (削除) 346 (削除ここまで) (削除) 338 (削除ここまで) 332 bytes
from random import*
p,n=input()
d=zip([0,1,2,3]*13,'23456789TJQKA'*4)
shuffle(d)
C=""".------.
|%s.--. |
| %s |
| %s |
| '--'%s|
'------'"""
print' | '.join('Player '+`i`for i in range(p))
exec"for l in zip(*[(C%(v,'(:::\/(//\)\):::'[s::4],':((:\_)\/_(/:)):'[s::4],v)).split('\\n')for s,v in d[:p]]):print' | '.join(l)\nd=d[p:]\n"*n
SOGL V0.12, 106 bytes
E(03⁄8║(Ηe─t¦4»\2ドル‘8n{"1<ω1⁄8┘‘4n╬¡;4n33žASUjk"TJQKA"+{a;22žF75ž}}'#δNo{ψ⌡≤οc+C}c_.∫:"▓1⁄8▲さんかくŗ‘Κ(e{≤+};H?;lƧ |Γ∙┼;┼
Card generating:
...‘ push "(\/):\/::/\::\/::/\:(__):():()()" - the suits
8n split to line lengths of 8 - individual suits
{ for each suit
"...‘ push ".---| .-| " - a quarter of a suit
4n split to line lengths of 4 - [".---", "| .-", "| "]
έ quad palindromize - empty card
; get the suit on top
4n split to line lengths of 4
33ž insert in the card at [3; 3]
A save on variable A - card template
SU push "1234567890"
jk remove the first and last digits
"TJQKA"+ append "TJQKA"
{ } for each number - "23456789TJQKA"
a load the template
;22ž at [2; 2] insert the current number
F75ž at [7; 5] insert the current number
Shuffling:
'# push 52
δ lower range - [0, 1, ..., 50, 51]
No reverse - [51, 50, ..., 1, 0]
{ } for each, pushing the current item
ψ get a random number from 0 to ToS (inclusive)
⌡ that many times
≤ put the first item of the stack on the top
οc+C prepend that to the variable C, predefined with an empty array
Dealing:
c_ push Cs contents on the stack - the stack is now a mess of cards
.∫ repeat input times - each player - pushing the current player number
: duplicate the number
"..‘ push "player "
Κ prepend "player " to the number
( uppercase the 1st letter
e{ } repeat 2nd input times
≤ put the first stack item on the top
+ append it to "Player X" vertically (making an array)
; get the other copy of the player number
H? if POP-1 (aka if it's not 1)
; swap the top 2 items - the current collumn and all the previous ones (by then they've been joined together)
l get its (vertical) length
Ƨ | push " |"
Γ palindromize - [" | "]
∙ multiply " | " vertically that length times
┼ append it horizontally (to the previous collumns)
;┼ append the current collumn
Ruby, 262 bytes
->p,q{a=[*0..51].shuffle
puts ["Player %d"]*p*(d=" | ")%[*1..p],(1..q*6).map{|i|(["'------'
.------.
|%X.--. |
| %s |
| %s |
| '--'%X|".split($/)[i%6]]*p*d%a[i/6*p,p].map{|j|["(\\/):()::/\\:"[u=j%4*4-4,4],":\\/:()():\\/:(__)"[u,4],j/4][i%3]}).tr("01BC","TJQK")}}
Harder to follow, but shorter!
Ruby, 279 bytes
->p,q{puts [*1..p].map{|k|"Player #{k}"}*" | "
a=[*0..51].shuffle
(q*6).times{|i|puts [".------.
|%s.--. |
| %s |
| %s |
| '--'%s|
'------'".split($/)[i%6]]*p*" | "%a[i/6*p,p].map{|j|[":\\/:()():\\/:(__)"[u=j%4*4-4,4],("%X"%(j/4)).tr("01BC","TJQK"),"(\\/):()::/\\:"[u,4]][i%3]}}}
Builds a format for each row, then uses the % operator like sprintf to populate it.
The fact that the card value appears on every 3rd row is handy. Card values are presented in hexadecimal with the digits 01BC substituted to TJQK.
Saved 4 bytes from the suit symbols by considering that the top of diamonds and spades are the same but added 2 back on for the -4 at the end of j%4*4-4 Suit codes are -4 0 4 or 8 where [-4,4] means 4 characters starting the 4th last character in the string.
Could probably save a few more bytes. Having to repeat code for the player identifications is ugly.
PHP, 509 bytes
<?$hu='(\/}';$hv=$dv=':\/:';$du=$su=':/\:';$sv='(__)';$cu=':():';$cv='()()';$q="------";$t=$argv[1];foreach([h,d,s,c]as$a)foreach([2,3,4,5,6,7,8,9,T,J,Q,K,A]as$b)$c[]=[$b,$a];shuffle($c);$h=$a=0;for(;$a<$t;$a++)$e[]="Player $a";$f[]=join(" | ",$e);for($g=$argv[2];$g--;){$p=$i=$k=$l=$m=$r=[];$j=$h+$t;for(;$h<$j;$h++){$n=$c[$h][0];$o=$c[$h][1];$p[]=".$q.";$i[]="|$n.--. |";$k[]="| ${$o.u} |";$l[]="| ${$o.v} |";$m[]="| '--'$n|";$r[]="'$q'";}foreach([p,i,k,l,m,r]as$b)$f[]=join(" | ",${$b});}echo join('
',$f);
This is my first attempt at code golf, so it can probably be improved a lot. I figured I had to start somewhere. :)
Java (OpenJDK 8), (削除) 784 (削除ここまで) (削除) 835 (削除ここまで) (削除) 843 (削除ここまで) (削除) 826 (削除ここまで) (削除) 815 (削除ここまで) (削除) 781 (削除ここまで) 775 bytes
String k(String s){return s.replaceAll("...$","\n");}
p->q->{int c=0,l=0,s[]=new int[p*q],i=0,j,t,b;java.util.List e=new java.util.Stack();String v="TJQK",o="",n[]=new String[p*q],x=o;for(;i<p;o+="Player "+i+++" | ",x+=v);o=k(o);for(i=0;i<q;i++){o=k(o+x.replace(v,".------. | "));for(j=0;j<p;j++){do{t=(int)(Math.random()*13)+1;b=(int)(Math.random()*4);}while(e.contains(t+""+v.charAt(b)));e.add(t+""+v.charAt(b));s[c]=b;n[c]=t<2?"A":t<10?""+t:""+v.charAt(t-10);o+="|2.--. | | ".replace("2",n[c++]);}o=k(o);for(j=0;j<p;j++,l++)o+="| "+(s[l]<1?"(\\/)":s[l]<3?":/\\:":":():")+" | | ";o=k(o);for(j=0;j<p;j++)o+="| "+(s[i*p+j]<2?":\\/:":s[i*p+j]<3?"(__)":"()()")+" | | ";o=k(o);for(j=0;j<p;)o+="| '--'2| | ".replace("2",n[i*p+j++]);o=k(k(o)+x.replace(v,"'------' | "));}return o;}
Why the downvote, it complies with the spec
-
\$\begingroup\$ Also, you should create alternate methods instead of creating
Function<String,String>: the latter is very, very costly. Both at creation and when used. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年10月26日 11:42:07 +00:00Commented Oct 26, 2017 at 11:42 -
\$\begingroup\$ I'm assuming the downvote was for the original bugged answer, but the current seems correct, so I've upvoted to neutralize it. Some small things to golf: parenthesis can be removed at
n[c]=t<2?"A":t<10?""+t:""+"TJQK".charAt(t-10);for(j=0;j<p;j++){o+=...;l++;}can befor(j=0;j<p;l++,j++)o+=...;; you canreturn o;instead ofSystem.out.print(o);by using a secondFunctioninstead ofConsumer;,y=p*qcan be removed and you can usep*qtwo times directly instead ofy. There is without doubt a lot more to golf, but I don't have time to look into that right now.. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年10月26日 13:48:24 +00:00Commented Oct 26, 2017 at 13:48 -
1\$\begingroup\$ @KevinCruijssen Actually, no. I downvoted after the first edit for "no effort in golfing" beyond removing spaces and using 1-char variable names. My guess is that Roberto Graham should entirely re-read Tips for golfing in Java. The point is that it indeed complies to the spec of the challenge, but not to the spec of the code-golf tag. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年10月26日 14:50:19 +00:00Commented Oct 26, 2017 at 14:50
-
\$\begingroup\$ How I know it can be golfed further? I was around 400 bytes when I gave up after seeing this answer, and I estimated around 50 more bytes the rest to finish it. 450 bytes vs. 850, there's barely any golf involved. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2017年10月26日 14:55:53 +00:00Commented Oct 26, 2017 at 14:55
-
\$\begingroup\$
s[l]<2?":/\\:":s[l]<3?":/\\:"can bes[l]<3?":/\\:"ands[i*p+j]<1?":\\/:":s[i*p+j]<2?":\\/:"can bes[i*p+j]<2?":\\/:". @OlivierGrégoire And I'm aware it can most likely be almost halved, so I understand the downvote. But this is mostly a lack of experience, and indeed not reading all the tips multiple times. Some of the things in the answer I've done in the past as well, and this isn't a particular easy challenge for Java. Btw, if you have a 400-450 byte answer, why don't you post it as a separated answer then (if significantly different enough)? You'd have my upvote. ;) \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2017年10月26日 15:13:33 +00:00Commented Oct 26, 2017 at 15:13
Python 3, 332 Bytes
from random import*
P=lambda x:print(*x,sep=' | ')
R=range
def f(p,c):
P(f"Player {i}"for i in R(p))
d=[f".------.,|{n}.--. |,| {a[:4]} |,| {a[4:]} |,| '--'{n}|,'------'".split(",")for a,n in sample([*zip(r':/\:(__) (\/):\/: :/\::\/: :():()()'.split()*13,'A23456789TJQK'*4)],p*c)]
for i in R(c):
for t in zip(*d[i::c]):
P(t)
Explore related questions
See similar questions with these tags.
Each row must have 1 or more newlines inbetween them, more than one is acceptable, 0 is not....But your test cases don't have newlines between cards..? \$\endgroup\$