So, last week I posted a challenge to play Duck, Duck, Goose. This lead to a number of Minnesotans commenting about their regional 'Gray duck' variation.

So here's the rules:

Using this list of colours:


Write a program to follow these rules:

  1. Select one of these colours, and prepend it to the word 'duck' and print the result to a new line.
  2. If the colour was not 'Gray', repeat step 1.
  3. If the colour was 'Gray', end your program.

Rules which must be followed:

  • The program should not consistently print the same number of lines.
  • It can begin on 'Gray duck', but should not do consistently.
  • There should be exactly one duck on each line and no empty lines are output.
  • There should be at least one space between a colour and a duck.
  • White space before and after the significant output does not matter.
  • The case of the output doesn't matter.
  • Colours can be repeated.
  • The output doesn't have to contain every colour every time, but it must be possible that your code will output every colour.
  • No colours outside the above array can be included.
  • Either grey or gray are acceptable in your answer.
  • Colours should not consistently be in the same order.
  • Aim for the shortest program. Smallest number of bytes wins.

Example output:

Green duck
Orange duck
Yellow duck
Indigo duck
Yellow duck 
Gray duck

Thanks to @Mike Hill for first alerting me to this variation.

  • \$\begingroup\$ Any rules on the distribution on outcomes? Because I could generate valid outputs by picking from non-grey colours a random number of times, followed by printing Grey once (so I wouldn't have to pick from all of them and check whether I've picked Grey). \$\endgroup\$ – Martin Ender Mar 19 '18 at 10:10
  • \$\begingroup\$ @MartinEnder That's fine. "Colours should not consistently be in the same order." matters, but there's nothing to stop you picking grey separately at the end. \$\endgroup\$ – AJFaraday Mar 19 '18 at 10:12
  • 3
    \$\begingroup\$ Is the alternative spelling "gray" allowed? \$\endgroup\$ – 12Me21 Mar 19 '18 at 12:09
  • \$\begingroup\$ @12Me21 Curious, tho. Is there a technical reason for that? Or just an aesthetic one? \$\endgroup\$ – AJFaraday Mar 19 '18 at 12:10
  • 2
    \$\begingroup\$ In my not-so-humble opinion, you are missing one extremely important duck color. Blue is close, but not precise enough. \$\endgroup\$ – cobaltduck Mar 20 '18 at 23:29

51 Answers 51


T-SQL, 211 178 bytes

SELECT c+' Duck'FROM(SELECT TOP(CAST(RAND()*9AS INT))c FROM(VALUES('Red'),('Orange'),('Yellow'),('Green'),('Blue'),('Indigo'),('Violet'))v(c)ORDER BY NEWID()UNION SELECT'Grey'c)q


  • 1
    \$\begingroup\$ Nice work, I couldn't figure out how to make TOP vary like that. You can save 2 bytes by removing the spaces after ' Duck' and after RAND()*9. \$\endgroup\$ – BradC Mar 20 '18 at 16:44
  • 1
    \$\begingroup\$ Also, looks like its sorting the other colors by name, you could keep the randomness (and save bytes) by removing the outer sort entirely, and simply changing the order of your UNION: ...FROM(SELECT TOP...ORDER BY NEWID()UNION SELECT'Grey'c)q \$\endgroup\$ – BradC Mar 20 '18 at 16:46
  • \$\begingroup\$ @BradC: Good advices, thanks! Although UNION without ORDER BY does not guarantee ordering, it's probable that the order will be correct, because for few rows it's unlikely to get a parallel execution plan. \$\endgroup\$ – Razvan Socol Mar 20 '18 at 18:17
  • \$\begingroup\$ Yep, seems unlikely in this small dataset. This answer suggests that a UNION ALL is more likely to not change the order, but doesn't link to any sources. \$\endgroup\$ – BradC Mar 20 '18 at 18:34

x86_64 machine code, 120 bytes.

I got inspired by the 6502 machine code and implemented the same in x86_64 machine code.

0x603000: 0x47    0x72    0x61    0x79    0x20    0x00    0x00    0x00
0x603008: 0x52    0x65    0x64    0x20    0x00    0x00    0x00    0x00
0x603010: 0x4f    0x72    0x61    0x6e    0x67    0x65    0x20    0x00
0x603018: 0x59    0x65    0x6c    0x6c    0x6f    0x77    0x20    0x00
0x603020: 0x47    0x72    0x65    0x65    0x6e    0x20    0x00    0x00
0x603028: 0x42    0x6c    0x75    0x65    0x20    0x00    0x00    0x00
0x603030: 0x49    0x6e    0x64    0x69    0x67    0x6f    0x20    0x00
0x603038: 0x56    0x69    0x6f    0x6c    0x65    0x74    0x20    0x00
0x603040: 0x64    0x75    0x63    0x6b    0x0a    0x00    0x0f    0x31
0x603048: 0xc1    0xe8    0x03    0x33    0xdb    0x83    0xc3    0x07
0x603050: 0x23    0xd8    0x8b    0xfb    0xc1    0xe7    0x03    0x48
0x603058: 0x81    0xc7    0x00    0x30    0x60    0x00    0xe8    0x73
0x603060: 0xd5    0xdf    0xff    0x48    0xc7    0xc7    0x40    0x30
0x603068: 0x60    0x00    0xe8    0x67    0xd5    0xdf    0xff    0x85
0x603070: 0xdb    0x0f    0x85    0xcf    0xff    0xff    0xff    0xc3

Or the disassembly:

   0x603046:  rdtsc  
   0x603048:  shr    eax,0x3
   0x60304b:  xor    ebx,ebx
   0x60304d:  add    ebx,0x7
   0x603050:  and    ebx,eax
   0x603052:  mov    edi,ebx
   0x603054:  shl    edi,0x3
   0x603057:  add    rdi,0x603000
   0x60305e:  call   0x4005d6 <printf>
   0x603063:  mov    rdi,0x603040
   0x60306a:  call   0x4005d6 <printf>
   0x60306f:  test   ebx,ebx
   0x603071:  jne    0x603046
   0x603077:  ret     

The first 70 bytes is a string table that looks like:


There is certainly room for optimizations and it might not be the shortest implementation in terms of bytes but it probably competes for least amount of bytes executed :)


Japt, 54 53 52 bytes

Could probably be shorter but my tool for finding the optimal permutation of the string to compress is crapping out on this, for some reason.

_èSiy}a@P±` Ýõ
`i`gÎ9h½uehéHÃÎÁe⸩ºÄgohgyËB`qh ö

Test it

1 byte saved thanks to Oliver

  • \$\begingroup\$ 52 bytes \$\endgroup\$ – Oliver Mar 19 '18 at 15:30
  • \$\begingroup\$ Thanks, @Oliver. Did you brute force that? \$\endgroup\$ – Shaggy Mar 19 '18 at 18:10
  • \$\begingroup\$ Your tool only works with six items, so I excluded red and grey (shortest length), ran it through your tool, then added red and grey to the final list. \$\endgroup\$ – Oliver Mar 19 '18 at 19:22

APL (Dyalog Unicode), 86 bytes

{×⍵:∇r⊣⎕←'Grey' 'Red' 'Orange' 'Yellow' 'Green' 'Blue' 'Indigo' 'Violet'[r←?8]'duck'}1

Try it online!

Assumes ⎕IO←0.


Red, 96 91 bytes

until[n: random 8 print[pick[Red Orange Yellow Green Blue Indigo Violet Grey]n"duck"]n = 8]

Try it online!


APL+WIN, 106 bytes

⊃('red' 'orange' 'yellow' 'green' 'blue' 'indigo' 'violet' 'grey')[(↑(m=8)/⍳⍴m)↑m←1+8|n←1E3?1E3],¨⊂' duck'

Generates a vector of random integers between 1 and 8 and takes the series up to and including the first occurance of an 8 as indices into the colour vector and then concatenates the duck.


SOGL V0.12, 40 39 38 bytes

]"sω2a⁄Ξ┌┼0⁾    a║EΣ?GΘƨ+}‘θJ;7ψ:≥w⁽OX@oo

Try it Here!


Pyth, 72 bytes(SBCS)

K" Duck"#=kOc." y9Fª¹Ú¹«·.Û»õx¾jL[`ýõ?;ß¼<|9ü"\ +kKIqk"Gray"B

Try it online!

Python 3 translation:
import random
K=" Duck"
while True:
    k=random.choice("Red Orange Yellow Green Blue Indigo Violet Gray".split())
    if k=="Gray":
  • \$\begingroup\$ 65 bytes: Try it here \$\endgroup\$ – user48543 Mar 19 '18 at 18:17

Perl 6/Rakudo 78 bytes

say $_=<Grey Red Orange Yellow Green Blue Indigo Violet>.roll~" duck"until /y/

Stealing directly from Dom Hastings' Perl 5 answer

Perl 6 wins slightly with .roll


PHP, 166, 148, 142 98 Bytes

Down to 98 bytes thanks to Shaggy and Titus.

I tried a recursive solution.

function f(){echo[grey,red,orange,yellow,green,blue,indigo,violet][$n=rand()&7]." duck 


function f(){
  //a line break goes here, thats why it skips a line after duck
  //saves one byte over \n
        ." duck

For real it does not need much, the function will stop when $n == false or as php asumes $n == 0 as a false then it leaves the method.

Try it online

Don't really know how to "golf code", but i found this forum really, really fascinating.

  • \$\begingroup\$ the php tag was missing :D \$\endgroup\$ – Francisco Hahn Mar 19 '18 at 13:35
  • 1
    \$\begingroup\$ Welcome to PPCG! I think I see a few potential savings but I'll let those more proficient in PHP steer you better. @AJFaraday, you're missing the first line. \$\endgroup\$ – Shaggy Mar 19 '18 at 13:39
  • \$\begingroup\$ @Shaggy I didn't, if you take a look at the edit history, it initially didn't have the php tag. \$\endgroup\$ – AJFaraday Mar 19 '18 at 13:40
  • \$\begingroup\$ Replace ' Duck'.PHP_EOL with " Duck\n" to save a few bytes, for starters. \$\endgroup\$ – Shaggy Mar 19 '18 at 13:44
  • \$\begingroup\$ Do i need to set something else on tio.run?, if i do that the output is "Violet Duck\nGreen Duck\nRed Duck\nGray Duck\n" \$\endgroup\$ – Francisco Hahn Mar 19 '18 at 13:45

Python 3, 127 bytes

from random import *;x=''

Try it online!

  • \$\begingroup\$ FYI a very standard Python tip is to use from module import* and then just thing rather than module.thing here it will save 1 byte -- exceptions are when module is length four of less (e.g. import os;os.wait(1)) or there are multiple imports being made, when choices between modules should be made and as may come into play. \$\endgroup\$ – Jonathan Allan Mar 20 '18 at 8:23
  • \$\begingroup\$ You could swap x!='Grey to 'Grey'!=x to save one (the space). You could use no arguments for split() to save 3 (splits on spaces). You could use the allowance of any casing of output to go from 'Grey'!=x to something like 'a'<x to save four more... All in all my tips will save you 9 bytes Try It Online! - it doesn't get you under other Python answers but good things for future golfing IMO anyway :) \$\endgroup\$ – Jonathan Allan Mar 20 '18 at 8:32

Python 3, 124 bytes

import random
while b>0:b=random.randint(0,7);print('Gray Red Orange Yellow Green Blue Indigo Violet'.split()[b],'duck')

Try it online!

I almost always accompany my posts with explanations, but this one seems simple enough that I feel confident going without one...


SmileBASIC, 134 116 bytes

DIM C$[8]C=RND(8)COPY C$,@L@L?C$[C];" duck

Swift, 161 143 bytes

import Foundation;var x=9;while x>0{x=time(nil)%7;print(["Grey","Red","Orange","Yellow","Green","Blue","Indigo","Violet"][x]+" duck");sleep(1)}

Thanks to @cleblanc, whom I got the idea of the shorter code from.


import Foundation                   //we need Foundation for time

var x = 9

while x > 0 {
    x = time(nil)%7
           "Violet"][x] + " duck") //subscripting color array, appending "duck"

Try it online!


F#, 171 bytes

let r=System.Random()
let mutable i=r.Next(8)
while i<>7 do
 printfn"%s duck"["Red";"Orange";"Yellow";"Green";"Blue";"Indigo";"Violet"].[i]
printf"Grey duck"

Try it online!

That flipping "mutable" keyword! I thought that F#'s lack of a do/while loop (it only has while/do) would hurt me, but on retrospect it worked out, since "Grey duck" is always printed without a line separator (printfn versus printf), so there's no trailing empty line.


Visual Basic for Applications, 110 102 bytes

Edit: saved eight more bytes by using split() instead of array()

while rnd>.3:?split("Red,Orange,Yellow,Green,Blue,Indigo,Violet",",")(rnd*6)+" duck":wend:?"Gray duck"

Type in the immediate window.


TI-BASIC, 80 bytes

Repeat not(I

Bash + Coreutils, 100 Bytes

B=`shuf -en1 Red Orange Yellow Green Blue Indigo Violet Gray`;echo $B duck;[[ $B = Gray ]]||bash $0
  • \$\begingroup\$ Welcome to the site! I think you have a little bit of unneeded whitespace in this answer. But I'm not an expert in Bash. Does [[$B=Gray]]||bash $0 at the end work? \$\endgroup\$ – DJMcMayhem Mar 23 '18 at 22:12

C (gcc), 138 133 123 122 bytes

Saved a byte thanks to @ceilingcat

*c[]={"Grey","Red","Orange","Yellow","Green","Blue","Violet"};main(i){for(;printf("%s duck\n",c[i=time(sleep(1))%6])*i;);}

Try it online!


ink, 78 87 bytes

-(e){RANDOM(0,1):{~Red|Orange|Yellow|Green|Blue|Indigo|Violet} duck|Gray duck->END}

Try it online!


-(e){RANDOM(0,1):{~Red|Orange|Yellow|Green|Blue|Indigo|Violet} duck|Gray duck->END}  // With a 50% chance of each, either pick a colour that hasn't been picked already (unless all others have also been picked) and print it followed by "duck", or print "Gray duck" and terminate.
->e   // if we haven't terminated we get here and go back to the line above

+9 bytes: Apparently shuffles in ink will not repeat an option until all options have been visited. This means the previous version of my program was not valid, since it would always encounter "gray" before it could encounter any other colour for the second time, and thus broke the "Colours can be repeated" rule. The new answer will print each non-gray colour once until all have been printed, then shuffle again and restart - except every time it's about to pick a colour there's a 50% chance it instead prints gray and terminates.


C (gcc), 104 bytes

f(n){for(;printf("%.6s duck\n","Gray\0 OrangeYellowIndigoVioletGreen\0Blue\0 Red"+(n=time(0)%7)*6),n;);}

Try it online!


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.