21
\$\begingroup\$

The game of Chinese checkers is played on a board with spaces in the shape of a six-pointed star:

Board image

Image from Wikipedia

We can create an ASCII-art representation of this board, using . for empty spots and the letters GYORPB for the six colored starting locations:

            G
           G G
          G G G
         G G G G
B B B B . . . . . Y Y Y Y
 B B B . . . . . . Y Y Y
  B B . . . . . . . Y Y
   B . . . . . . . . Y
    . . . . . . . . .
   P . . . . . . . . O
  P P . . . . . . . O O
 P P P . . . . . . O O O
P P P P . . . . . O O O O
         R R R R
          R R R
           R R
            R

To make it more interesting, we can also change the size. We'll measure the size of a board by the side length of its triangular starting locations: the board above is size 4.

Since it's really a pain to type all that by hand, let's write a program (or function) to do it!

Details

Your code should take a positive integer representing the size of the board, via STDIN, ARGV, or function argument. Output the checkerboard pattern to STDOUT (you may alternately return it as a string if your submission is a function).

Output must either

  • have no trailing spaces at all, or
  • have exactly enough trailing spaces to fill out the pattern to a perfect rectangle of width 6 * N + 1.

Output may optionally have a trailing newline. No other extra (leading, trailing) whitespace is permitted.

Examples

Size 1:

   G
B . . Y
 . . .
P . . O
   R

Size 2:

      G
     G G
B B . . . Y Y
 B . . . . Y
  . . . . .
 P . . . . O
P P . . . O O
     R R
      R

Size 4:

            G
           G G
          G G G
         G G G G
B B B B . . . . . Y Y Y Y
 B B B . . . . . . Y Y Y
  B B . . . . . . . Y Y
   B . . . . . . . . Y
    . . . . . . . . .
   P . . . . . . . . O
  P P . . . . . . . O O
 P P P . . . . . . O O O
P P P P . . . . . O O O O
         R R R R
          R R R
           R R
            R

Scoring

This is : the shortest code in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ Can the output have empty lines of spaces before and after? \$\endgroup\$ – xnor May 30 '15 at 6:04
  • \$\begingroup\$ I'm going to say no. \$\endgroup\$ – DLosc May 30 '15 at 6:29
  • \$\begingroup\$ You mentioned trailing spaces, but what about leading spaces? Does the image need to be flush left, or can it have an equal amount of leading spaces on each line? \$\endgroup\$ – Sp3000 May 30 '15 at 6:35
  • \$\begingroup\$ Flush left, as shown in the sample output. \$\endgroup\$ – DLosc May 30 '15 at 6:39
  • \$\begingroup\$ Can there be spaces beyond the right edge but still forming a rectangle? \$\endgroup\$ – xnor May 30 '15 at 6:42
2
\$\begingroup\$

Ruby, 141 127

Returns a rectangular string

->n{(-2*n..2*n).map{|i|j=i.abs
k=j>n ?0:j 
(([i>0??P:?B]*k+[j>n ?i>0??R:?G:?.]*(2*n+1-j)+[i>0??O:?Y]*k)*" ").center(6*n+1)}*$/}

Ungolfed in test program

f=->n{
  (-2*n..2*n).map{|i|                    #Iterate rows from -2*n to 2*n
    j=i.abs                              #Absolute value of i
    k=j>n ?0:j                           #Value of j up to n: for PBYO
    (                                    #An array of characters forming one line
      ([i>0??P:?B]*k+                    #B or P * (k=j or 0 as appropriate)
       [j>n ?i>0??R:?G:?.]*(2*n+1-j)+    #R,G or . * (2*n+1-j) to form centre diamond
       [i>0??O:?Y]*k                     #O or Y * (k=j or 0 as appropriate)
      )*" "                              #Concatenate the array of characters into a string separated by spaces.
    ).center(6*n+1)                      #pad the string to the full width of the image, adding spaces as necessary.
  }*$/                                   #Concatenate the array of lines into a string separated by newlines.
}

puts f[gets.to_i]
\$\endgroup\$
8
\$\begingroup\$

Python 2, 140 bytes

n=input()
for k in range(4*n+1):x=abs(k-2*n);y=2*n-x;p,q,r=" BP G..R YO "[(k-~k)/(n-~n)::4];print(" "*y+" ".join(p*x+q*-~y+r*x)+" "*y)[n:-n]

Not great, but here's my initial bid.

The whitespace rules added a lot of bytes. For comparison, here's a 120 byte Python 3 program which is only correct visually, and doesn't follow the whitespace rules:

def f(n):
 for k in range(4*n+1):x=abs(k-2*n);y=2*n-x;p,q,r=" BP G..R YO "[(k-~k)//(n-~n)::4];print(" "*y,*p*x+q*-~y+r*x)

And here's my slightly longer recursive 149 byte Python 3 attempt:

def f(n,k=0):x=2*n-k;s=" ".join(["B"*x+"."*-~k+"Y"*x,"G"*-~k][k<n]).center(6*n+1);print(s);k<n*2and[f(n,k+1),print(s.translate({71:82,66:80,89:79}))]
\$\endgroup\$
7
\$\begingroup\$

Python 2, 152

n=input();x=N=2*n
while~N<x:s='';y=n*3;exec"a=x+y;q=[0,a>N,x-y>N,-x>n,-a>N,y-x>N,x>n,1];s+=' BYROPG.'[q.index(sum(q)<~a%2*3)];y-=1;"*(y-~y);print s;x-=1

This is, in retrospect, the wrong approach for Python, but I'm posting it here in case someone can make use of it. Rather than explaining this mess of code, I'll try to say the idea behind it.

The idea is to use triangular coordinates, in which the triangular lattice corresponds to integer triples (a,b,c) with a+b+c=0.

enter image description here

(Here, the lattice points are drawn as hexagons.)

We can convert Cartesian coordinates to triangular ones as

a = (x+y)/2
b = (x-y)/2
c = -x

noting that x and y must have the same parity, or otherwise it's off-checkerboard and we should print a space.

In triangular coordinates, the bounding lines of the six-sided star have equations: a==n, b==n, c==n, a==-n, b==-n, c==-n.

So, we can determine what region we're in by which of [a,b,c,-a,-b,-c] are greater than n.

  • If none are, we're in the center and print a dot.
  • If exactly one is, we're in one of the six outer triangles, and print the letter corresponding to the index.
  • If two or more are, we're outside the board, and print a space.

The bounding rectangle requires that we do this for x in the closed interval [-2*n,2*n] and y in the closed interval [-3*n,3*n].

\$\endgroup\$
  • \$\begingroup\$ The code does not work for me. \$\endgroup\$ – BadAtGeometry Mar 31 at 5:16
  • \$\begingroup\$ @BadAtGeometry It works for me. \$\endgroup\$ – xnor Apr 6 at 5:48
  • \$\begingroup\$ What version are you using? \$\endgroup\$ – BadAtGeometry Apr 6 at 20:55
  • \$\begingroup\$ @BadAtGeometry TIO is using 2.7.15. What happens when you run it? \$\endgroup\$ – xnor Apr 6 at 21:11
7
\$\begingroup\$

Retina, 234 bytes

.
P
.+
iP$0$0x$0j$0x$0Px$0kqw
P(?=P*xP*j)
s
P(?=P*j)
R
P(?=P*xP*k)
c
P(?=P*k)
O
x

+`i(s+R+)R
is$1#$1R
+`(s*)P(P*c*)(O*)O(?=k)
$0#s$1$2c$3
j|k
#
s

+`([^#]+#)q(.*)
q$1$2$1
R(?=.*w)
G
P(?=.*w)
B
O(?=.*w)
Y
w[^#]*#|q|i

\w
$0 
c
.
 #
#

Takes input in unary.

Each line should go to its own file and # should be changed to newline in the file. This is impractical but you can run the code as is as one file with the -s flag, keeping the # markers and maybe changing them to newlines in the output for readability if you wish.

The code has minimal regex-complexity. The main steps in the generation are the followings:

  • Create the last G line and the first B.Y line (delimited by markers ijk and actual used letetrs are RPO).
  • Duplicate the topmost G line with a plus space, minus a G until there is only one G.
  • Duplicate the bottom B.Y line with a plus space and dot, minus a B and Y until there are no B and Y left.
  • Copy all the lines in reverse order after the current string (with the help of the marker q). We keep a marker (w) in the middle.
  • We change the letters RPO to GBY if they are before the marker.
  • Add the missing in-between spaces.

The results after each of the above points (delimited by ='s) for the input 1111 (unary 4):

1111
==============================
isssssssssRRRRjPPPPcccccOOOOkqw
==============================
issssssssssssR
sssssssssssRR
ssssssssssRRR
sssssssssRRRRjPPPPcccccOOOOkqw
==============================
issssssssssssR
sssssssssssRR
ssssssssssRRR
sssssssssRRRRjPPPPcccccOOOO
sPPPccccccOOO
ssPPcccccccOO
sssPccccccccO
ssssccccccccckqw
==============================
qi            R
           RR
          RRR
         RRRR
PPPPcccccOOOO
 PPPccccccOOO
  PPcccccccOO
   PccccccccO
    ccccccccc
w    ccccccccc
   PccccccccO
  PPcccccccOO
 PPPccccccOOO
PPPPcccccOOOO
         RRRR
          RRR
           RR
i            R
==============================
qi            G
           GG
          GGG
         GGGG
BBBBcccccYYYY
 BBBccccccYYY
  BBcccccccYY
   BccccccccY
    ccccccccc
w    ccccccccc
   PccccccccO
  PPcccccccOO
 PPPccccccOOO
PPPPcccccOOOO
         RRRR
          RRR
           RR
i            R
==============================
            G
           G G
          G G G
         G G G G
B B B B . . . . . Y Y Y Y
 B B B . . . . . . Y Y Y
  B B . . . . . . . Y Y
   B . . . . . . . . Y
    . . . . . . . . .
   P . . . . . . . . O
  P P . . . . . . . O O
 P P P . . . . . . O O O
P P P P . . . . . O O O O
         R R R R
          R R R
           R R
            R
\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6) 228

Construction line by line. Incredibly long compared to @Sp3000 that does the same.

Using template string to save 3 more bytes for newlines. All newlines are significant and counted.

f=w=>(i=>{r=(n,s=b=' ')=>s.repeat(n),l=c=>(c='GBYPOR'[c])+r(i,b+c),t=n=>r(w*3-i)+l(n)+`
`,s=n=>r(w-1-i)+l(n)+b+r(w+w-i,'. ')+l(n+1)+`
`;for(o='',q=r(w)+r(w+w,'. ')+`.
`;++i<w;o+=t(0))q+=s(3);for(;i--;o+=s(1))q+=t(5)})(-1)||o+q

// LESS GOLFED

u=w=>{
  r =(n,s=b=' ') => s.repeat(n),
  l = c => (c='GBYPOR'[c])+r(i, b+c),
  t = n => r(w*3-i) + l(n) + '\n',
  s = n => r(w-1-i) + l(n) + b + r(w+w-i,'. ') + l(n+1) + '\n',
  o = '',
  q = r(w) + r(w+w,'. ') + '.\n';
  for(i=0; i<w; i++)
    o += t(0), q += s(3);  
  for(;i--;)
    o += s(1), q += t(5);
  return o+q
}  

go=()=> O.innerHTML=f(I.value|0)

go()
<input id=I value=5><button onclick='go()'>-></button><br>
<pre id=O></pre>

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.