Code Golf: Diamond Blackjack
The challenge
The shortest code by character count to output a best-case blackjack hand from the list of number-cards given.
Input is a list of numbers from 1 to 10 (inclusive) separated by space.
Output will be the best blackjack hand formed from that list of cards - the closest available combo to reach 21 by the sum of all card values without surpassing it. Cards can be removed but not added.
If a case where removing two or more cards in favor of one card to accomplish the same result (removing 5 or 4,1 to gain 21) removing the least cards is required.
If the equal amount of cards is to be removed (removing 1,4 or 3,2) the group with the minimum of the minimum will be removed (in the previous example, 1,4 will be removed as min(min(3,2), min(1,4))
belongs to that pair). In the case of duplicate cards, the first encounter should be removed.
Output will be formed as diamond cards, with input order preserved:
__________ __________ | || | | || /\ | | || \/ | | /\ || | | \/ || | | || /\ | | || \/ | |__________||__________| __________ __________ | || | | /\ || /\ /\ | | \/ || \/ \/ | | /\ || | | \/ || | | /\ || /\ /\ | | \/ || \/ \/ | |__________||__________| __________ __________ | |开发者_Go百科| | | /\ /\ || /\ /\ | | \/ \/ || \/ \/ | | /\ || /\ /\ | | \/ || \/ \/ | | /\ /\ || /\ /\ | | \/ \/ || \/ \/ | |__________||__________| __________ __________ | || | | /\ /\ || /\ /\ | | \/ /\ \/ || \/ /\ \/ | | /\ \/ /\ || /\ \/ /\ | | \/ \/ || \/ /\ \/ | | /\ /\ || /\ \/ /\ | | \/ \/ || \/ \/ | |__________||__________| __________ __________ | /\ /\ || /\ /\ | | \/ \/ || \/ /\ \/ | | /\ /\ || /\ \/ /\ | | \/ /\ \/ || \/ \/ | | /\ \/ /\ || /\ /\ | | \/ \/ || \/ /\ \/ | | /\ /\ || /\ \/ /\ | |_\/____\/_||_\/____\/_|
Test cases
Input:
1 5 7 8
Output:
__________ __________ __________ __________
| || || || |
| || /\ /\ || /\ /\ || /\ /\ |
| || \/ \/ || \/ /\ \/ || \/ /\ \/ |
| /\ || /\ || /\ \/ /\ || /\ \/ /\ |
| \/ || \/ || \/ \/ || \/ /\ \/ |
| || /\ /\ || /\ /\ || /\ \/ /\ |
| || \/ \/ || \/ \/ || \/ \/ |
|__________||__________||__________||__________|
Input:
10 3 4 2 6
Output:
__________ __________ __________ __________
| /\ /\ || || || |
| \/ /\ \/ || /\ || /\ || /\ /\ |
| /\ \/ /\ || \/ || \/ || \/ \/ |
| \/ \/ || /\ || || /\ /\ |
| /\ /\ || \/ || || \/ \/ |
| \/ /\ \/ || /\ || /\ || /\ /\ |
| /\ \/ /\ || \/ || \/ || \/ \/ |
|_\/____\/_||__________||__________||__________|
Input
5 10 5 2 3
Output:
__________ __________ __________ __________
| /\ /\ || || || |
| \/ /\ \/ || /\ /\ || /\ || /\ |
| /\ \/ /\ || \/ \/ || \/ || \/ |
| \/ \/ || /\ || || /\ |
| /\ /\ || \/ || || \/ |
| \/ /\ \/ || /\ /\ || /\ || /\ |
| /\ \/ /\ || \/ \/ || \/ || \/ |
|_\/____\/_||__________||__________||__________|
Code count includes input/output (i.e full program).
J, 303 characters
4(1!:2)~,&(10{a.)"1>,.&.>/4 :'''/\/\''(x(<@:+)"1]4 2$1|.4#0 1)}y'&.>/@((<>1 7 1#1&|.@(2 10&#)&.>' _';'| ';'|_'),~>)"0(>({~[:(i.[:>./[*22&>)+/@>)(#:@i.@(2&^)@#<@#"1 _])".1!:1]3){a:,(((1$7);(a 0 _1;7),(a 0 2 _3 _1;7),((a=:,&.>/\)0 2 6 8 _3 _1;4;_5)){&.><,{(2+i.5);2 5 8),(4 5;k);<2 5;6 5;k=:,{2 8;~>:+:i.4
$ echo -n 1 5 7 8 | jconsole test.ijs __________ __________ __________ __________ | || || || | | || /\ /\ || /\ /\ || /\ /\ | | || \/ \/ || \/ /\ \/ || \/ /\ \/ | | /\ || /\ || /\ \/ /\ || /\ \/ /\ | | \/ || \/ || \/ \/ || \/ /\ \/ | | || /\ /\ || /\ /\ || /\ \/ /\ | | || \/ \/ || \/ \/ || \/ \/ | |__________||__________||__________||__________| $ echo -n 10 3 4 2 6 | jconsole test.ijs __________ __________ __________ __________ | /\ /\ || || || | | \/ /\ \/ || /\ || /\ || /\ /\ | | /\ \/ /\ || \/ || \/ || \/ \/ | | \/ \/ || /\ || || /\ /\ | | /\ /\ || \/ || || \/ \/ | | \/ /\ \/ || /\ || /\ || /\ /\ | | /\ \/ /\ || \/ || \/ || \/ \/ | |_\/____\/_||__________||__________||__________| $ echo -n 5 10 5 2 3 | jconsole test.ijs __________ __________ __________ __________ | /\ /\ || || || | | \/ /\ \/ || /\ /\ || /\ || /\ | | /\ \/ /\ || \/ \/ || \/ || \/ | | \/ \/ || /\ || || /\ | | /\ /\ || \/ || || \/ | | \/ /\ \/ || /\ /\ || /\ || /\ | | /\ \/ /\ || \/ \/ || \/ || \/ | |_\/____\/_||__________||__________||__________|
The core, finding the best hand, is actually really easy. Generate the power set of the cards given, and select the one with the highest value less than 22.
({~[:(i.[:>./[*22&>)+/@>)(#:@i.@(2&^)@#<@#"1 _])
Then we start with a blank card
<>1 7 1#1&|.@(2 10&#)&.>' _';'| ';'|_'
and layer on diamonds in the appropriate places.
'/\/\'(x(<@:+)"1]4 2$1|.4#0 1)}y
The rest of the program is dominated by the table of what diamonds go where.
Golfscript - 228 Characters
' ':x/{~}%:h;9,{:r;h,2\?,{:m;h,,{2\?m&},{h\=}%}%1>{:j[{+}*.22<\j,j$j]}$)\;{:c;[x]3,{4\?' \//\__'2/[11'?'*8'@'*'bb@BBbbbbbQY@AAQQQYYbfH@H@HbffYQD@D@DQQYfb@``bbbbfQY@PPQQQQQbf'8'?'*]']]'+10r*c+=@/3&=}%[x]++' _'1/7r&!=*}%'|':x;n}%
$ echo 10 9 8 7 6 5 | ../golfscript.rb black.gs __________ __________ __________ | || || | | /\ /\ || /\ /\ || /\ /\ | | \/ /\ \/ || \/ /\ \/ || \/ \/ | | /\ \/ /\ || /\ \/ /\ || /\ /\ | | \/ /\ \/ || \/ \/ || \/ \/ | | /\ \/ /\ || /\ /\ || /\ /\ | | \/ \/ || \/ \/ || \/ \/ | |__________||__________||__________|
231 Characters
' ':x/{~}%:h,2\?,{:m;h,,{2\?m&},{h\=}%}%1>{:j[{+}*.22<\j,j$j]}$-1=:h;9,{:r;h{:c;[x]3,{4\?' \//\__'2/11'?'*8'@'*'bb@BBbbbbbQY@AAQQQYYbfH@H@HbffYQD@D@DQQYfb@``bbbbfQY@PPQQQQQbf'8'?'*']]'++++10r*c+=@/3&=}%[x]++' _'1/7r&!=*}%'|':x;n}%
how it works
# parse input into a list
' ':x/{~}%:h
# create the powerset
,2\?,{:m;h,,{2\?m&},
# map the powerset onto the cards
{h\=}%}%
# trim the empty set from the powerset
1>
# sort the hands. most preferred hand will be last
{:j[{+}*.22<\j,j$j]}$
# take the preferred hand from the end of the list
-1=:h;
# for r in 0..8
9,{:r
...more to follow
Python - 365 Characters
h=map(int,raw_input().split());H=len(h);R=range
for r in R(9):x=["| "[1>r]];print"".join("_ "[0<r<8].join(x+[" \//\__"[ord(('?'*11+'@'*8+'bb@BBbbbbbQY@AAQQQYYbfH@H@HbffYQD@D@DQQYfb@``bbbbfQY@PPQQQQQbf????????]]')[r*10+c])*2>>i&6:][:2]for i in 0,2,4]+x)for c in max([[h[b]for b in R(H)if n&1<<b]for n in R(1<<H)],key=lambda c:(sum(c)<22,sum(c),len(c),sorted(c),c)))
$ echo 2 4 8 1 8 3| python blackjack.py __________ __________ __________ __________ | || || || | | /\ || /\ /\ || /\ /\ || /\ | | \/ || \/ /\ \/ || \/ /\ \/ || \/ | | || /\ \/ /\ || /\ \/ /\ || /\ | | || \/ /\ \/ || \/ /\ \/ || \/ | | /\ || /\ \/ /\ || /\ \/ /\ || /\ | | \/ || \/ \/ || \/ \/ || \/ | |__________||__________||__________||__________| $ echo 1 4 5 4 7 4 8| python blackjack.py __________ __________ __________ __________ __________ | || || || || | | || /\ /\ || /\ /\ || /\ /\ || /\ /\ | | || \/ \/ || \/ \/ || \/ /\ \/ || \/ \/ | | /\ || /\ || || /\ \/ /\ || | | \/ || \/ || || \/ \/ || | | || /\ /\ || /\ /\ || /\ /\ || /\ /\ | | || \/ \/ || \/ \/ || \/ \/ || \/ \/ | |__________||__________||__________||__________||__________|
369 Characters
h=map(int,raw_input().split());H=len(h);R=range;j=[]
for n in R(1<<H):c=[h[b]for b in R(H)if n&1<<b];j+=[(sum(c)<22,sum(c),len(c),sorted(c),c)]
for r in R(9):x=["| "[1>r]];print"".join("_ "[0<r<8].join(x+[" \//\__"[ord(('?'*11+'@'*8+'bb@BBbbbbbQY@AAQQQYYbfH@H@HbffYQD@D@DQQYfb@``bbbbfQY@PPQQQQQbf????????]]')[r*10+c])*2>>i&6:][:2]for i in 0,2,4]+x)for c in max(j)[-1])
377 Characters
h=map(int,raw_input().split());H=len(h);R=range;j=[]
for n in R(1<<H):c=[h[b]for b in R(H)if n&1<<b];j+=[(sum(c),len(c),sorted(c),c)]*(sum(c)<22)
T="@@@HD@@?@BA@@`P?@BAHD`P?@bQ@@bQ?@bQHDbQ?@bQbQbQ?@bYfQbQ?@bYfYfQ?bQbYfQb]bYfQbYf]"
for r in R(9):x=["| "[1>r]];print"".join("_ "[0<r<8].join(x+[" \//\__"[ord(('?'+T[c*8-8:])[r])*2>>i&6:][:2]for i in 0,2,4]+x)for c in max(j)[-1])
408 characters
h=map(int,raw_input().split());H=len(h);R=range;j=[]
for n in R(1<<H):c=[h[b]for b in R(H)if n&1<<b];j+=[(sum(c),len(c),sorted(c),c)]*(sum(c)<22)
T="@@@DH@@ @AB@@P` @ABDHP` @Qb@@Qb @QbDHQb @QbQbQb @QfYbQb @QfYfYb QbQfYbQn QfYbQfYn".split();U="\x3f"
for r in R(9):s="_ "[0<r<8];x=["| "[1>r]];print"".join(s.join(x+[(" ","/\\","\/","__")[ord((U+T[c-1]+U)[r])>>i&3]for i in 0,2,4]+x)for c in sorted(j)[-1][-1])
Perl
Blatantly stolen from gnibbler's Python solution; turns out to be three characters shorter, at 362 -- if input is given on the command line.
sub p{(local$z=pop)?(@z=&p,map[@$_,$z],@z):[]}
for(p@ARGV){$t=0;$t+=$_ for@$_;($s,@c)=($t,@$_)if$t>=$s&&$t<22}
for$r(0..8){$x=$r?'|':$";for$c(@c){print+join$r*($r<8)?$":'_',$x,
map(join('',((split//,' \//\__')[ord((('?')x11,('@')x8,split//,
'bb@BBbbbbbQY@AAQQQYYbfH@H@HbffYQD@D@DQQYfb@``bbbbfQY@PPQQQQQbf????????]]'
)[$r*10+$c])*2>>$_&6..7])[0,1]),0,2,4),$x}print$/}
To read from stdin, replace @ARGV
by @F
and use perl -an
; using traditional Perl golf scoring, that counts as 362.
And, of course, gnibbler's other other Python trick can be copied too.
$ perl -pechomp <<'END' \ > >'bb@BBbbbbbQY@AAQQQYYbfH@H@HbffYQD@D@DQQYfb@``bbbbfQY@PPQQQQQbf????????]]' > sub p{(local$z=pop)?(@z=&p,map[@$_,$z],@z):[]} > for(p@F){$t=0;$t+=$_ for@$_;($s,@c)=($t,@$_)if$t>=$s&&$t<22} > for$r(0..8){$x=$r?'|':$";for$c(@c){print+join$r*($r<8)?$":'_',$x, > map(join('',((split//,' \//\__')[ord((('?')x11,('@')x8,split//,$0) > [$r*10+$c])*2>>$_&6..7])[0,1]),0,2,4),$x}print$/} > END $ wc -c <bb* 287 $ echo 10 5 2 9 3 | perl -an bb* __________ __________ __________ | /\ /\ || || /\ /\ | | \/ /\ \/ || /\ || \/ \/ | | /\ \/ /\ || \/ || /\ /\ | | \/ \/ || || \/ /\ \/ | | /\ /\ || || /\ \/ /\ | | \/ /\ \/ || /\ || \/ \/ | | /\ \/ /\ || \/ || /\ /\ | |_\/____\/_||__________||_\/____\/_|
Lua, 895
OK, correct now. Can even score 1 as ace.
t=table p=ipairs j=arg x={}r={}o={}b=0 function f()local e,s,n,m=0,0,{}for i,v in p(j)do s=s+v e=e+(v+0==1 and 1 or 0)n[i]=v end t.sort(n)for i,v in p(n)do if o[i]and v~=o[i]then m=v>o[i]break end end while e>0 and s<12 do s=s+10 e=e-1 end if s<=21 and s>b or(s==b and(#j>#r or(#j==#r and m)))then b=s for i=1,#r>#j and #r or #j do r[i]=j[i]o[i]=j[i]end t.sort(o)end if s>0 then for i=1,#j do t.insert(x,t.remove(j,i))f()t.insert(j,i,table.remove(x))end end end f()t={" __________ ","| |","|__________|","| /\\ |","| /\\ |","| /\\ |","| /\\ /\\ |","| \\/ /\\ \\/ |","|_\\/____\\/_|"}c={"12224D223","125E226F3","125E4D6F3","127G227G3","127G4D7G3","127G7G7G3","1278HG7G3","1278H8HG3","17G78HG79","178HG78H9"}for i=1,9 do for j,x in p(r)do v=c[tonumber(x)]:sub(i,i):byte()io.write(v<64 and t[v-48]or(t[v-64]:gsub("[/\\]",{["/"]="\\",["\\"]="/"})))end io.write("\n")end
Sample output:
>lua card.lua 8 9 10 7
__________ __________
| /\ /\ || /\ /\ |
| \/ \/ || \/ /\ \/ |
| /\ /\ || /\ \/ /\ |
| \/ /\ \/ || \/ \/ |
| /\ \/ /\ || /\ /\ |
| \/ \/ || \/ /\ \/ |
| /\ /\ || /\ \/ /\ |
|_\/____\/_||_\/____\/_|
>lua card.lua 1 4 5 4 7 4 8
__________ __________ __________ __________ __________
| || || || || |
| || /\ /\ || /\ /\ || /\ /\ || /\ /\ |
| || \/ \/ || \/ \/ || \/ /\ \/ || \/ \/ |
| /\ || /\ || || /\ \/ /\ || |
| \/ || \/ || || \/ \/ || |
| || /\ /\ || /\ /\ || /\ /\ || /\ /\ |
| || \/ \/ || \/ \/ || \/ \/ || \/ \/ |
|__________||__________||__________||__________||__________|
>lua card.lua 1 9 5 5
__________ __________ __________
| || || |
| || /\ /\ || /\ /\ |
| || \/ \/ || \/ \/ |
| /\ || /\ || /\ |
| \/ || \/ || \/ |
| || /\ /\ || /\ /\ |
| || \/ \/ || \/ \/ |
|__________||__________||__________|
Python - 298 Characters
simply rename the script like this
mv blackjack.py '???????????@@@@@@@@bb@BBbbbbbQY@AAQQQYYbfH@H@HbffYQD@D@DQQYfb@``bbbbfQY@PPQQQQQbf????????]].py'
Here is the script
import sys
h=map(int,raw_input().split());H=len(h);R=range
for r in R(9):x=["| "[1>r]];print"".join("_ "[0<r<8].join(x+[" \//\__"[ord(sys.argv[0][r*10+c])*2>>i&6:][:2]for i in 0,2,4]+x)for c in max([[h[b]for b in R(H)if n&1<<b]for n in R(1<<H)],key=lambda c:(sum(c)<22,sum(c),len(c),sorted(c),c)))
and a sample run
$ echo 1 2 3 4 5 | python '???????????@@@@@@@@bb@BBbbbbbQY@AAQQQYYbfH@H@HbffYQD@D@DQQYfb@``bbbbfQY@PPQQQQQbf????????]].py'
__________ __________ __________ __________ __________ | || || || || | | || /\ || /\ || /\ /\ || /\ /\ | | || \/ || \/ || \/ \/ || \/ \/ | | /\ || || /\ || || /\ | | \/ || || \/ || || \/ | | || /\ || /\ || /\ /\ || /\ /\ | | || \/ || \/ || \/ \/ || \/ \/ | |__________||__________||__________||__________||__________|
Python, 632 characters
from itertools import*
o=sum;q=range;r=filter
l=map(int,raw_input().split())
s=r(lambda x:o(x)<22,chain.from_iterable(imap(combinations,repeat(l),q(len(l)+1))))
s=r(lambda x:o(x)==max(map(o,s)),s)
t=max(([(min(x),x)for x in s if len(x)==max(map(len,s))]))[1]
a=" __________ "
b="| |"
c="| /\ /\ |";e=c[::-1]
d="| /\ |";l=d[::-1]
g="| \/ |";k=g[::-1]
i="| /\ |";j=i[::-1]
h="| /\ \/ /\ |";f=h[::-1]
n="|_\/____\/_|"
m="|__________|"
y="aaaaaaaaaabbbbbbbbccbddcccccefbggeeeffchibibichhfejbjbjeefhcbkkcccchefblleeeeechmmmmmmmmnn"
for x in q(9):
print''.join([globals()[y[x*10:(x+1)*10][v-1]]for v in t])
Sample output:
10 5 7 4 1 1 __________ __________ __________ __________ __________ | /\ /\ || || || || | | \/ /\ \/ || /\ /\ || /\ /\ || || | | /\ \/ /\ || \/ \/ || \/ \/ || || | | \/ \/ || /\ || || /\ || /\ | | /\ /\ || \/ || || \/ || \/ | | \/ /\ \/ || /\ /\ || /\ /\ || || | | /\ \/ /\ || \/ \/ || \/ \/ || || | |_\/____\/_||__________||__________||__________||__________|
Haskell minimally tested 721 characters
Updated Haskell version, now supposedly works for all cases but it could probably do with more testing.
import Data.List --17
--shorteners
m=map --6
r=reverse --10
l=length --9
u=True --7
g=minimum --10
--printing of the cards
p=foldl1(zipWith(++)).m d --26
a=[" __________ ","| |","| /\\ /\\ |",r(a!!2),"| /\\ |",r(a!!4),"| \\/ |",r(a!!6),"| /\\ |",r(a!!8),"| /\\ \\/ /\\ |",r(a!!10),"|_\\/____\\/_|","|__________|"] --190
j(Just x)=x --12
d(n+1)=m(j.(flip$lookup)(zip"abcedlgkijhfnm"a).("aaaaaaaaaabbbbbbbbccbddcccccefbggeeeffchibibichhfejbjbjeefhcbkkcccchefblleeeeechmmmmmmmmnn"!!).(+n))[0,10..80] --160
-- interaction and pipeline
main=interact$unlines.p.f.m read.words --39
f x=head.filter((<22).sum).r.sortBy(o x)$x:z x --47
-- generate all possible hands (power set)
z[]=[] --7
z(x:s)=s:m(x:)(z s)++z s --25
-- sorting logic
c f a b=compare(f a)$f b --25
o x a b|l a==l b=s x a b|u=c l a b --35
s o a b|g a==g b=t o a b|u=c g a b --35
t o a b|all(`elem`b)a=c(n o)a b|u=GT --37
n t=m(j.(`elemIndex`t)) --24
Haskell version not finished yet 622 characters
it won't win any beauty contests, could also be improved I'm sure, and doesn't exactly follow the spec (still working on the min(min(3,2), min(1,4))
issue as well as the duplicate filtering (the o
function needs more cases)). Despite it's incompleteness it does pass all the test cases given.
Each line is commented (--
) with the number of characters on it, including the new line.
import Data.List --17
p=foldl1(zipWith(++)).m d --26
r=reverse --10
a=[" __________ ","| |","| /\\ /\\ |",r(a!!2),"| /\\ |",r(a!!4),"| \\/ |",r(a!!6),"| /\\ |",r(a!!8),"| /\\ \\/ /\\ |",r(a!!10),"|_\\/____\\/_|","|__________|"] --190
j(Just x)=x --12
d(n+1)=m(j.(flip$lookup)(zip"abcedlgkijhfnm"a).("aaaaaaaaaabbbbbbbbccbddcccccefbggeeeffchibibichhfejbjbjeefhcbkkcccchefblleeeeechmmmmmmmmnn"!!).(+n))[0,10..80] --160
m=map --6
main=interact$unlines.p.snd.f.m read.words --43
f x=head.filter((<22).fst).m(\x->(sum x,x))$r$sortBy o$x:z x --61
c f a b=compare(f a)$f b --25
z[]=[] --7
z(x:s)=s:m(x:)(z s)++z s --25
l=length --9
o a b|l a==l b=GT|True=c l a b --31
Perl, 410 char
Don't know how much more improvement is possible, but maybe this would be easier to port to GolfScript than gnibbler's algorithm:
sub R{for(@_){substr$q[$_],$B+$z,2,'/\\';substr$q[$_+1],$B+$z,2,'\/';
if($B==2){$B=8;R(8-$_);$B=2}}}
for$i(1..1<<(@p=@ARGV)){$s=$n=0;$i&1<<$n++&&($s+=21*$_+1)for@p;
$q=$s,$N=$i if$s<462&&$q<$s}
@q=($/)x9;for$p(grep$N&1<<$_,0..@p){
s/$/| |/for@q;
$B=5;($P=$p[$p])&1&&R(4-($P==7));$P-8||R 5,3;$P>9&&R 6,2;
$B=2;if($P>8){R 1,3,5,7}else{R 2if$P>1;R 6if$P>3;R 4if$P>5}$z+=12}
$q[0]=~y/| / _/;$q[-1]=~y/ /_/;print@q
精彩评论