g | x | w | all
Bytes Lang Time Link
683tinylisp240817T205716ZAndrew B
nanScala 3240818T031015Z138 Aspe
127Ruby160905T014124ZLevel Ri
228JavaScript ES6150530T151227Zedc65
140Python 2150530T090056ZSp3000
234Retina150530T114326Zrandomra
152Python 2150530T080010Zxnor

tinylisp, 760 683 bytes


(d R(q((n A)(i n(J A(L(R(s n 1)A)()))(
(d L(q((A B)(i A(L(t A)(c(h A)B))B
(d K(q((A B)(i A(K(t A)(L(h A)B))B
(d J(q(args(K args(
(d P(q((A B)(s A(s 0 B
(d X(q((n B x)(i n(X(s n 1)B(L(J(R(s B n)(q(32)))(R n(q(32 80)))(R(P B(s B n))(q(32 46)))(q(46))(R n(q(79 32)))(q(10))x)()))x
(d W(q((n B x)(i n(W(s n 1)B(L(J(R(s n 1)(q(32)))(R(s(P B 1)n)(q(32 66)))(R(P n(s B 1))(q(32 46)))(q(46))(R(P(s B n)1)(q(89 32)))(q(10))x)()))x
(d Y(q((n B x)(i n(Y(s n 1)B(L(J(R(P B B)(q(32)))(R(s n 1)(q(32)))(R(P(s B n)1)(q(82 32)))(i(e n B)()(q(10)))x)()))x
(d Z(q((n B x)(i n(Z(s n 1)B(L(J(R(P B B)(q(32)))(R(s B n)(q(32)))(R n(q(71 32)))(q (10))x)()))x
(d k(q((n)(string(Z n n(W(P n 1)n(X n n(Y n n(

Try it online!

Partially ungolfed version:


(d R
(q
((n A)
 (i
 (e n 0)
 ()
 (J A (L (R (s n 1) A) ()) ))
)))

(d L(q
((A B)
  (i
    (e A ())
    B
    (L (t A) (c (h A) B))
  )
)))

(d K(q
((A B)
  (i
    (e A ())
    B
    (K (t A) (L (h A) B))
  )  
)))

(d J(q
(args
  (K args ())  
)))

(d P(q(
  (A B)
  (s A (s 0 B))
)))

(d X
(q 
((n B x)
  (i
    (e n 0)
    x
    (X (s n 1) B
      (L (J
        (R (s B n) (q(32)))
        (R n (q(32 80)))
        (R (P B (s B n) ) (q(32 46)))
        (q(46)) 
        (R n (q(79 32)))
        (q(10))
        x
      ) ())
    )
  )
)))   


(d W
(q 
((n B x)
  (i
    (e n 0)
    x
    (W (s n 1) B
      (L (J
        (R (s n 1) (q(32)))
        (R (s (P B 1) n) (q(32 66)))
        (R (P n (s B 1)) (q(32 46)))
        (q(46)) 
        (R (P (s B n) 1) (q(89 32)))
        (q(10))
        x
      ) ())
    )
  )
)))   

(d Y
(q
((n B x)
  (i
    (e n 0)
    x
    (Y (s n 1) B
      (L (J 
        (R (P B B) (q(32)))  
        (R (s n 1) (q(32))) 
        (R (P (s B n) 1) (q (82 32))) 
        (i (e n B) () (q (10)))
        x 
      ) ())
    )
  ) 
)))

(d Z
(q
((n B x)
  (i
    (e n 0)
    x
    (Z (s n 1) B
      (L (J 
        (R (P B B) (q(32)))  
        (R (s B n) (q(32))) 
        (R n (q (71 32))) 
        (q (10))
        x 
      ) ())
    )
  ) 
)))

(d k
(q
((n)
(string (Z n n (W (P n 1) n (X n n (Y n n ()))) )    ) 
)))


Try it online!

Approach

For this challenge, I broke the board into 4 sections, and wrote a function for each section - that's the functions Z W X & Y. I also wrote some helper functions for joining together strings of chars.

Perhaps there is a golfing opportunity still - the two halves of the board are sufficiently similar that I may be able to achieve the same result with 2 functions instead of 4, adding a parameter that tells me if I'm drawing the upper or lower section.

Scala 3, 263 251 bytes

Saved 12 bytes thanks to @DLosc


Golfed version. Attempt This Online!

n=>(-2*n to 2*n).map{i=>
val j=math.abs(i)
val k=if(j>n)0 else j
val l=(Array.fill(k)(if(i>0)'P'else'B')++Array.fill(2*n+1-j)(if(j>n){if(i>0)'R'else'G'}else'.')++Array.fill(k)(if(i>0)'O' else'Y')).mkString(" ")
" "*((6*n+1-l.size)/2)+l}.mkString("\n")

Ungolfed version. Attempt This Online!

object Main {
  def f(n: Int): String = {
    val result = (-2 * n to 2 * n).map { i =>
      val j = math.abs(i)
      val k = if (j > n) 0 else j

      val line = (
        Array.fill(k)(if (i > 0) 'P' else 'B') ++  // B or P repeated k times
        Array.fill(2 * n + 1 - j)(if (j > n) { if (i > 0) 'R' else 'G' } else '.') ++ // R, G, or . repeated (2*n + 1 - j) times
        Array.fill(k)(if (i > 0) 'O' else 'Y')    // O or Y repeated k times
      ).mkString(" ")

      line.center(6 * n + 1) // Center the line within a width of 6*n + 1 characters
    }

    result.mkString("\n") // Join all the lines with newline characters
  }

  implicit class StringOps(str: String) {
    def center(width: Int): String = {
      val padding = (width - str.length) / 2
      " " * padding + str + " " * padding
    }
  }

  def main(args: Array[String]): Unit = {
    println(f(3))
  }
}

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]

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>

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}))]

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:

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

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.

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].