Make An ASCII Poker Chip Stack Arrangement

20

Poker has etiquette in how you arrange your chips, often enforced in tournaments - your chips may not be "hidden" from your opponents by being behind others, mostly to not hide some large denomination chip(s).


The Challenge

We are going to be playing poker in ASCII, so we need to write a function or program that will draw our ASCII chip stack arrangement given its total value, n.

Input
- A positive integer, n (up to 2**32-1 should be handled)

Output
- An ASCII representation of the stack arrangement as defined below.
This may contain white-space to the right of each line such that no line is longer than one more character than the length used by printable characters in the longest (bottom) line;
This may contain a single trailing new line; and
The characters representing chips may be in lowercase if you prefer.

The stack arrangement will:

  • Contain the fewest chips possible, given the denominations (see below);
  • Will have equal valued chips in "stacks" (columns);
  • Be ordered such that the shorter stacks are to the right of taller stacks; and
  • Be ordered such that stacks with greater denomination chips will be to the right of equal sized stacks of lower denominations (representing that they are visible to our opponent(s) on the right)

The chips themselves are to be represented as individual characters identifying their colour:

    White : 1    = W
      Red : 5    = R
    Green : 25   = G
    Black : 100  = B
   Yellow : 500  = Y
     Pink : 1K   = P
   Orange : 5K   = O
     Cyan : 25K  = C
  Magenta : 100K = M
Aqua-blue : 500K = A
 Lavender : 1M   = L
   Indigo : 5M   = I
Turquoise : 25M  = T
   Violet : 100M = V
   Silver : 500M = S

Example

For n = 276,352 the smallest number of chips would be:

2 * 100K + 3 * 25K + 1 * 1K + 3 * 100 + 2 * 25 + 2 * 1
    MM         CCC       P        BBB       GG       WW

The single P must go on the far right,
then the three stacks of size 2 must go next,
- but the MM must go furthest to the right followed by the GG and then the WW since 100K > 25 > 1 then the two stacks of size 3 go on the left,
- but the CCC must go to the right of the BBB since 25K > 100

Now we must place these chips into actual stacks, to make our output:

BC
BCWGM
BCWGMP

Test Cases

Input:
1

Output:
W


Input:
9378278

Output:
L
LWGPCM
LWGPCMB
LWGPCMBI


Input:
22222222

Output:
ROI
ROI
ROIWBPML
ROIWBPML


Input:
1342185143

Output:
WRCIV
WRCIVOLS
WRCIVOLSGBMT


Input:
2147483647

Output:
RMIS
RMISPC
RMISPCWL
RMISPCWLGBYOTV


Input:
4294967295

Output:
S
S
S
S
SRML
SRMLGOIT
SRMLGOITBPCV
SRMLGOITBPCVA

This is , so shortest code in bytes wins. No loopholes, yada yada, you know the drill.

Jonathan Allan

Posted 2016-09-21T19:48:05.343

Reputation: 67 804

Wow, this looks fun, I may try a Julia answer when i get home. – Magic Octopus Urn – 2016-09-21T20:39:53.773

Did you mean 2**31-1, or is your intent to be larger than most signed int types? – Linus – 2016-09-21T21:54:22.217

@Linus hmm, I made it unsigned; I did actually specifically ask if the input range was OK in the sandbox and no one responded. As you can see 2**32-1 is a test case, but I'm willing to lower it. (Interesting fact: PokerStars has a 25B chip in their image folder.) – Jonathan Allan – 2016-09-21T21:58:54.723

Answers

5

Pyth, 56 55 52 bytes

The code contains some unprintables, so here's a reversible xxd hexdump.

00000000: 3d48 516a 5f2e 745f 2023 6c44 2a56 2e22  =HQj_.t_ #lD*V."
00000010: 4159 261c 0c24 2087 0c86 1e22 6d68 412e  AY&..$ ...."mhA.
00000020: 4448 645f 2e75 2a4e 5950 2a33 6a37 3733  DHd_.u*NYP*3j773
00000030: 3620 362f                                6 6/

Try it online. Test suite.

Pro tip: to golf 1 in the end of a program accepting a nonzero number in Q, just add /. /QQ, which in Python would be Q // Q, is 1 for nonzero Q.

Without compression and unprintables (55 bytes):

=HQj_.t_ #lD*V"SVTILAMCOPYBGRW"mhA.DHd_.u*NYP*3j7736 6/

PurkkaKoodari

Posted 2016-09-21T19:48:05.343

Reputation: 16 699

6

JavaScript (ES6), 185 177 ... 171 bytes

f=(a,s='')=>(a=(a[0]?a:[...(m='25455')+m+m].map((m,i)=>(a-=(k=a/(v/=m)|0)*v,k*16+i),v=1E9).sort((a,b)=>b-a)).map(n=>n>15&&(s+='SVTILAMCOPYBGRW'[n&15],n-16)),s&&f(a)+`
`+s)

Formatted and commented

(a, s = '') => (                           // a = bankroll OR array of chip stacks
  a = (                                    // s = string of chip initials for this iteration
    a[0] ?                                 // if 'a' already is an array:
      a                                    // use it as-is
    :                                      // else, 'a' is the bankroll:
      [...(m = '25455') + m + m]           // for each 'm' in [ 2, 5, 4, 5, 5, ... ] (x3)
      .map((m, i) =>                       // v = current chip value = previous value / m
        (                                  // k = floor(a / v) = number of these chips
          a -= (k = a / (v /= m) | 0) * v, // update remaining bankroll: a = a - k * v
          k * 16 + i                       // saved in array: chip index in bits 0-3
        ),                                 // and number of chips in bits 4+
        v = 1E9                            // initial chip value = 1 billion
      )                                    // (1B / 2 -> 500M, 500M / 5 -> 100M, etc.)
      .sort((a, b) => b - a)               // sort the chip stacks
  )                                        //
  .map(n =>                                // for each chip stack:
    n > 15 &&                              // if there's at least one remaining chip of
    (                                      // this kind:
      s += 'SVTILAMCOPYBGRW'[n & 15],      // append its initial to the string
      n - 16                               // decrement the number of chips in this stack
    )                                      //
  ),                                       // process recursive call if there was at least
  s && f(a) + '\n' + s                     // one non-empty chip stack (the next lines are
)                                          // appended at the beginning of the final string)

Demo

let f=(a,s='')=>(a=(a[0]?a:[...(m='25455')+m+m].map((m,i)=>(a-=(k=a/(v/=m)|0)*v,k*16+i),v=1E9).sort((a,b)=>b-a)).map(n=>n>15&&(s+='SVTILAMCOPYBGRW'[n&15],n-16)),s&&f(a)+`
`+s)

function update() {
  document.getElementById('o').innerHTML = f(+document.getElementById('i').value);
}
update();
<input id="i" value="1342185143" oninput="update()"><pre id="o"></pre>

Arnauld

Posted 2016-09-21T19:48:05.343

Reputation: 111 334

5

Ruby, 181 177 bytes

->n{*a=5*10**8
14.times{|i|a<<a[-1]/[5,4,5,5,2][i%5]}
a=a.zip("SVTILAMCOPYBGRW".chars).map{|v,c|[-(n/v),v,c,n%=v]}.sort
l=-a[0][0]
(1..l).map{|i|a.map{|d|l-i<-d[0]?d[2]:""}*""}}

Tests on Ideone.

m-chrzan

Posted 2016-09-21T19:48:05.343

Reputation: 1 390

4

Python 2.7, 282 248 238 bytes

c=input();L=[]
for i in range(15):m=[5,1,25,5,1][i%5]*10**int("886665533322000"[i]);L+=[[c/m,i,"SVTILAMCOPYBGRW"[i]]];c%=m
L.sort();S=[]
while L[~1][0]:
 s=""
 for X in L[::-1]:
  if X[0]>0:X[0]-=1;s+=X[2]
 S+=[s]
for s in S[::-1]:print s

Explanation:
Fill list L with elements [quanity, chip_order, chip_character] indicating the quantity of each type of chip , where chip_order ensures chips of equal quantity get sorted in reverse order (higher value chips first). Take chips from L in reverse to build strings for each line. Print lines in reverse to get smallest lines on top.

Thanks to Blue for some of the improvements.

Linus

Posted 2016-09-21T19:48:05.343

Reputation: 1 948

Great answer! However, there are a couple things you can do to golf it more. First, you can put multiple statements on one line by separating them by semicolons (but not statements that require indents after). Second, if you only use a variable once (like X, Y and S in the first for loop), you can just substitute the raw value to save some bytes. For more tips, check out http://codegolf.stackexchange.com/questions/54/tips-for-golfing-in-python

– Blue – 2016-09-22T00:03:38.913

Also, regular input will get you the integer w/o having to convert, and X[0]>0 can be shortened to X[0] – Blue – 2016-09-22T00:07:51.813

@Blue, thanks I hate python's input. I'll check the tips and see if I can come up with anything else. – Linus – 2016-09-22T00:17:01.497

3

Mathematica, 440 bytes

n=Input[]
c=Characters["SVTILAMCOPYBGRW"]
l=Reap[Do[n=n-#[[-i]]*Sow[Floor[n/#[[-i]]]]&@FoldList[Times,1,{5,5,4,5,2,5,5,4,5,2,5,5,4,5}],{i,1,15}]][[2,1]]
StringJoin@@((StringJoin[#,"\n"])&/@StringJoin/@Reverse/@((PadRight[#,Max[l],""]&/@Sort[Table[If[l[[n]]>0,Table[c[[n]],l[[n]]],Nothing],{n,1,15}],If[Length[#1]==Length[#2],Position[c,#1[[1]]][[1,1]]<Position[c,#2[[1]]][[1,1]],Length[#1]<Length[#2]]&])[[All,#]]&/@Range[Max[l]])//Reverse)

The ASCI-representation and right order swallows most of the code.

*Only works with Version11 and higher (use of Nothing)*

Julien Kluge

Posted 2016-09-21T19:48:05.343

Reputation: 283

1Is there really no free Mathematica?! – Jonathan Allan – 2016-09-21T21:43:23.837

3

You can currently use it online at: https://develop.open.wolframcloud.com/app/

– Julien Kluge – 2016-09-21T22:45:18.787

0

PHP, 274 Bytes

$t=$argv[1];$n=[500,100,25,5,1];$c=YBGRWAMCOPSVTIL;foreach($n as$k=>$v)for($i=0;$i<3;)$r[$v*10**($i*3)]=$c[$k+$i++*5];krsort($r);foreach($r as$v=>$k)$t-=($x[$v]=floor($t/$v))*$v;ksort($x);arsort($x);for($y=max($x);$y;$y--){foreach($x as$k=>$v)if($v>=$y)echo$r[$k];echo"\n";}

Jörg Hülsermann

Posted 2016-09-21T19:48:05.343

Reputation: 13 026