g | x | w | all
Bytes Lang Time Link
105V vim210412T155953ZRazetime
085PowerShell180816T014058ZVeskah
038Dyalog APL180815T174825Zmousetra
023Stax180820T152359Zrecursiv
106Haskell180817T120831ZMax Yekh
101Haskell180814T183715Zovs
130R180814T165417ZdigEmAll
184Java JDK 10180815T224617ZOlivier
026Canvas180814T120916Zdzaima
02305AB1E180814T141958ZMagic Oc
153Red180815T074814ZGalen Iv
028Jelly180814T205142ZJonathan
031Jelly180814T181224ZMr. Xcod
030Charcoal180814T204850ZNeil
081Python 2180814T130000Zovs
100JavaScript ES6180814T124359ZArnauld
108Python 2180814T122619ZRod
131Python 2180814T120202ZTFeld

V (vim), 105 bytes

"aDiaibgyor<esc>0vg_y$@ap0l@alhd$:s/a/ v/g
qqYP0xjYP!!rev
gJkhq2@a@qylpp02ld$0VG:center<c-r>=2*(<c-r>a+ceil(1+<c-r>a/7))

Try it online!

There's many possible saves here, but for now I'm just happy I got it working.

PowerShell, 108 98 89 85 bytes

param($x)($x+=$x/7-replace'\..*')..0|%{' '*$_+-join(" vibgyor"*$x)[$x..$_+$_+$_..$x]}

Try it online!

This one feels pretty alright now. Banker's rounding is still the devil and I figured out how to make a non-dumb join. I tried monkeying with $ofs to not much success. Speaking of, the results without joins look pretty good, a bit melty:

         vvv
        v     v
       v   rrr   v
      v   r ooo r   v
     v   r o yyy o r   v
    v   r o y ggg y o r   v
   v   r o y g bbb g y o r   v
  v   r o y g b iii b g y o r   v
 v   r o y g b i vvv i b g y o r   v
v   r o y g b i v     v i b g y o r   v

Dyalog APL, 41 39 38 bytes

↑{⌽(⌽,⊃,A↑⊢)⍵↑A⍴' vibgyor'}¨-⍳A←⌈⎕×8÷7

Try it online!

A similar approach to others: A←⌈⎕×8÷7 finds the height of the rainbow (also the width of the longest 'half row' to the left/right of the centre) and assigns it to A for later use, while ¨-⍳ iterates through the values 1..A, negating them to select on the correct side when used with .

A⍴' vibgyor' generates a 'half row' and ⍵↑ selects the correct length substring. (⌽,⊃,A↑⊢) generates the full row in reverse (which takes fewer characters to do), starting with a reversed half row (), then the centre character taken from the beginning of the half row string () and finally a right padded version of the half row (A↑⊢). The final reverses the row into the correct orientation and turns the vector of rows into a 2D array.

Edit: -2 thanks to dzaima

Edit: -1 thanks to ngn

Stax, 23 bytes

⌡G'5h!M╩EV[Ez ▼>≈<S⌡⌡0`

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

" vibgyor"  string literal
,8*7/^      input * 8 / 7 + 1
:m          repeat literal to that length
|]          get all prefixes
Mr          rectangularize, transpose array of arrays, then reverse
            this is the same as rotating counter-clockwise
m           map over each row with the rest of the program, then implicitly output
            the stack starts with just the row itself
  _h        push the first character of the row
  _r        push the reversed row
  L         wrap the entire stack in a single array

Run this one

Haskell, 106 113 bytes

I can't yet comment other posts (namely this) so I have to post the solution as a separate answer.

Golfed away 7 bytes by ovs

p x=reverse x++x!!0:x
u m|n<-m+div(m-1)7=[(' '<$[z..n])++p(drop(n-z)$take(n+1)$cycle" vibgyor")|z<-[0..n]]

Try it online!

(Old version, 113 bytes)

Haskell, 114 110 101 bytes

Thanks to [nimi][1] for -4 13 bytes!

f n=""#(n+1+div n 7)
w#0=[]
w#n|x<-cycle"r vibgyo"!!n=((' '<$[2..n])++reverse w++x:x:x:w):(x:w)#(n-1)

Try it online!

R, 130 bytes

function(n,k=n%/%7*8+1+n%%7,a=el(strsplit(' vibgyor'/k,'')))for(i in k:1)cat(d<-' '/(i-1),a[c(k:i,i,i:k)],d,sep='','
')
"/"=strrep

Try it online!

Java (JDK 10), 184 bytes

n->{int h=n+n/7,i=h+1,w=i*2+1,j,k=0;var o=new char[i][w];for(;i-->0;o[i][w/2]=o[i][w/2+1])for(j=w/2;j-->0;)o[i][j]=o[i][w+~j]=i<h?j<1?32:o[i+1][j-1]:" vibgyor".charAt(k++%8);return o;}

Try it online!

Prints an extra leading and trailing space for each multiple of 7.

Explanation

n->{                             // IntFunction
 int h=n+n/7,                    //  Declare that height = n + n/7
     i=h+1,                      //          that index  = h + 1
     w=i*2+1,                    //          that width  = (h+1)*2+1
     j,                          //          j
     k=0;                        //          that k      = 0
 var o=new char[i][w];           //  Declare a 2D char array
 for(;                           //  Loop
   i-->0;                        //    Until i is 0
   o[i][w/2]=o[i][w/2+1]         //    After each run, copy the middle letter.
 )
  for(j=w/2;                     //   Loop on j = w/2
   j-->0;                        //     Until j = 0
  )                              //
   o[i][j]                       //    copy letters to the left side,
    =o[i][w+~j]                  //      and the right side
    =i<h                         //      if it's not the last line
     ?j<1                        //        if it's the first (and last) character
      ?32                        //          set it to a space.
      :o[i+1][j-1]               //          else set it to the previous character on the next line.
     :" vibgyor".charAt(k++%8);  //      else assign the next letter.
 return o;                       //  return everything
}

Credits

Canvas, 29 28 26 bytes

7÷U+{ <ibgyor@¹×/n}⇵K2*∔─↶

Try it here!

Explanation:

7÷U+                          ceil(input/7) + input
    {             }         for n in 1..the above
      <ibgyor@                in the string " <ibgyor", pick the nth character
              ¹×              repeat n times
                /             create a diagonal of that
                 n            and overlap the top 2 stack items (the 1st time around this does nothing, leaving an item for the next iterations)
                   ⇵        reverse the result vertically
                    K       take off the last line (e.g. " <ibgyor <ib")
                     2*     repeat that vertically twice
                       ∔    and append that back to the diagonals
                        ─   palindromize vertically
                         ↶  and rotate 90° anti-clockwise. This rotates "<" to "v"

25 24 22 bytes after fixing that mold should cycle if the wanted length is bigger than the inputs length and fixing for like the 10th time

05AB1E, 32 31 23 bytes

.•VvÈ©•¹∍¬„ v:Rηε¬ý}.c

Try it online!

-1 thanks to Kevin Cruijssen and -8 thanks to Adnan


Explanation (Stack example w/ input of 3):

.•VvÈ©•                  # Push 'aibgyor'           | ['aibgyor']
       ¹∍                # Extend to input length.  | ['aib']
         ¬               # Push head.               | ['aib','a']
          „ v:           # Replace with ' v'.       | [' vib']
              R          # Reverse.                 | ['biv ']
               η         # Prefixes.                | ['b', 'bi', 'biv', 'biv ']
                ε   }    # For each....             | []
                 ¬ý     # Bifurcate, join by head. | ['b','b']       ->    ['bbb']
                                                    | ['bi','ib']     ->   ['biiib']
                                                    | ['biv','vib']   ->  ['bivvvib']
                                                    | ['biv ',' vib'] -> ['biv   vib']
                     .c # Center the result.        | Expected output.

Red, 153 bytes

func[n][r: take/last/part append/dup copy"""roygbiv "n l: 9 * n + 8 / 8
repeat i l[print rejoin[t: pad/left take/part copy r i l last t reverse copy t]]]

Try it online!

Slightly more readable:

f: func[ n ] [
    r: copy ""
    append/dup r "roygbiv " n
    r: take/last/part r l: 9 * n + 8 / 8
    repeat i l [
        print rejoin [ t: pad/left take/part copy r i l
                       last t 
                       reverse copy t ]
    ]
]

Jelly, 28 bytes

:7+‘“ vibgyor”ṁµṫJZz⁶U;"⁸ŒBṚ

A monadic link accepting an integer which yields a list of lists of characters.

Try it online! (footer joins with newline characters)

Or see the test-suite.

How?

:7+‘“ vibgyor”ṁµṫJZz⁶U;"⁸ŒBṚ - Link: integer
:7                           - integer divide by seven (number of full rainbows)
   ‘                         - increment (the input integer)
  +                          - add (gets the number bands)
    “ vibgyor”               - list of characters = " vibgyor"
              ṁ              - mould like the result above (as a range)
               µ             - start a new monadic chain
                 J           - range of length
                ṫ            - tail (vectorises) (gets the suffixes)
                  Z          - transpose
                   z⁶        - transpose with filler space character
                             -   (together these pad with spaces to the right)
                     U       - reverse each
                             -   (now we have the left side of the rainbow upside down)
                        ⁸    - chain's left argument, as right argument of...
                       "     -   zip with:
                      ;      -     concatenation
                             -   (adds the central character)
                         ŒB  - bounce (vectorises at depth 1)
                             -   (reflects each row like [1,2,3,4] -> [1,2,3,4,3,2,1])
                           Ṛ - reverse (turn the rainbow up the right way)

Jelly, 31 bytes

:7+‘µ“ vibgyor”ṁṚ,Ṛjṛ/ƲƤṭ"ḶṚ⁶ẋƲ

Try it online!

Check out a test suite!

ಠ_ಠ This is overly complicated because Jelly doesn't have a centralize function...

Charcoal, 30 bytes

↶≔… vibgyor⁺²÷×⁸⊖N⁷θθ⸿Eθ✂θκ‖O←

Try it online! Link is to verbose version of code. Explanation:

Change the drawing direction to upwards.

≔… vibgyor⁺²÷×⁸⊖N⁷θ

Calculate the height of the rainbow and repeat the literal string to that length.

θ⸿

Print the central line of the rainbow.

Eθ✂θκ

Print the right half of the rainbow by taking successive slices and printing each on its own "line".

‖O←

Reflect to complete the rainbow.

Python 2, 84 82 81 bytes

-2 bytes thanks to ElPedro.

n=input();n+=n/7;w=''
while-~n:w+=" vibgyor"[n%8];print' '*n+w+w[-1]+w[::-1];n-=1

Try it online!

JavaScript (ES6), 100 bytes

Returns an array of strings.

f=(n,a=[i='   '])=>++i<n+n/7?f(n,[c=' vibgyor'[i&7],...a].map(s=>c+s+c)):a.map(s=>' '.repeat(--i)+s)

Try it online!

Python 2, 108 bytes

n=input()-1
n+=n/7+2
o=[]
for s in(' vibgyor'*n)[:n]:o=[s+l+s for l in[s]+o]
for l in o:print l.center(n-~n)

Try it online!

Python 2, 132 131 bytes

def f(n):
 t=n+n/7;s=('vibgyor '*n)[:t];r=[s[~i:]+t*' 'for i in range(t)]
 for l in zip(*r+3*[' '+s]+r[::-1])[::-1]:print''.join(l)

Try it online!


Saved: