47
\$\begingroup\$

99 bugs in the code

The adaption of "99 bottles of beer on the wall" for computer science where the bugs increase instead of the bottles decreasing is often re-posted around the internet. Example T-Shirt Here.

I think it'll be interesting to see potential recursion and random number generation across a huge variety of languages and finding the most efficient ways to do it.

There's a fair few other challenges to do with 99 bottles of beer but none seem to have an increasing and decreasing number!

Challenge

Your program or function should take no input and then print

99 bugs in the code

99 bugs in the code

Take one down and patch it around

X bugs in the code

(blank line)

Where X is the previous integer minus 1 plus a random integer in the range [-15,5].
You can merge the minus 1 into the random integer, hence allowing the range [-16,4].
Ranges can be exclusive, so minus one plus (-16,6) or (-17,5).

The random integers don't have to be evenly distributed they just have to all be possible.

The program always starts with 99 bugs.

You can ignore the grammatical error of "1 bugs".

The program should stop when the number of bugs is 0 or negative and print

0 bugs in the code

There should never be a negative number of bugs. The ending should look like

Y bugs in the code

Y bugs in the code

Take one down and patch it around

0 bugs in the code

(blank line)

0 bugs in the code

A trailing new line is acceptable.

  • Your code can be a full program or a function.
  • There is no input.
  • The output should be to stdout or returned.
  • Warnings/errors in logs/STDERR are okay as long as STDOUT has the required text. See here for more info.

This is code-golf so the shortest code in bytes wins.

Example Output

Paste bin example output rigged for -11 bugs each time

\$\endgroup\$
  • 1
    \$\begingroup\$ Related: 1 2 (difference: in this challenge the output can be arbitrarily long). \$\endgroup\$ – user202729 May 29 '18 at 14:16
  • 16
    \$\begingroup\$ A more realistic scenario would be if the sign of the random number was flipped! \$\endgroup\$ – Stewie Griffin May 29 '18 at 15:21
  • 9
    \$\begingroup\$ I am disappointed, that the requirements don't include that the program must have a bug once a negative number is encountered, like crashing, overflowing to max int or similar ;). \$\endgroup\$ – allo May 30 '18 at 9:58
  • 3
    \$\begingroup\$ "The random integers don't have to be evenly distributed they just have to all be possible." reminded me of xkcd.com/221 \$\endgroup\$ – Ivo Beckers May 30 '18 at 12:33
  • 2
    \$\begingroup\$ It's a shame 99 has no random number generation. \$\endgroup\$ – Jonathan Allan May 30 '18 at 21:07

46 Answers 46

2
\$\begingroup\$

C (GCC), 138 bytes

i=99;main(v){for(;i-v--;printf("%d bugs in the code\n%s",i*=i>0,v?v+1?i-=rand()%21-4,"\n":"Take one down and patch it around\n":""))v%=3;}

Note: I managed to get it down to 141 bytes by myself (no external help); later I saved three bytes by applying a technique that ErikF used (i*=i>0 instead of i=i<0?0:i). My original solo version:

i=99;main(v){for(;i-v--;printf("%d bugs in the code\n%s",i=i<0?0:i,v?v+1?i-=rand()%21-4,"\n":"Take one down and patch it around\n":""))v%=3;}
\$\endgroup\$
  • \$\begingroup\$ Nice golf! Also, you should provide a way to test the code - for example, a link to tio.run \$\endgroup\$ – user77406 Nov 9 '18 at 20:19
2
\$\begingroup\$

Python 3, 187 bytes

from random import randint as r
p=print;b=99
def l(x): p(x if x > 0 else 0,"bugs in the code.")
while b > 0: l(b);l(b);p("Take one down and patch it around.");b+=r(-16,4);l(b);p("")
l(0)

So it turns out that dealing with IO/Random in Haskell is a nightmare, so changed the solution to Python. First attempt, not too great :( But at least it's working.

\$\endgroup\$
2
\$\begingroup\$

javascript: 142

i=99
t=` bugs in the code
`;s='';while(i){s+=i+t+i+t+`Take one down and patch it around
`;i+=4-Math.random()*20|0;i=i<0?0:i;s+=i+t+`
`}s+=i+t;

Try it online

\$\endgroup\$
2
\$\begingroup\$

Bash, 182 178 151 149 bytes

i=99;b=" bugs in the code";a(){ echo $i$b;};while((i>0));do a;a;echo Take one down and patch it around;i=$[i-$RANDOM%21+4];((i<0))&&i=0;a;echo;done;a

Try it online!

Ungolfed

i=99;                             # Var i as current number of bugs
b=" bugs in the code";            # b to shortcut our string

a() {                             # Define function 'a'
    echo $i$b;                    # to shortcut displaying or number of bugs
};

while((i>0)); do                  # Repeat as long as var i is greater than 0
    a;a                           # Execute 'a' twice
    echo Take one down and...     # Display some bugs taken down
    i=                            # Assign the following value to $i:
      $[i-$RANDOM%21+4]           # i minus a random value between -4 and 16
                                  #     $RANDOM is a bash builtin function to generate a
                                  #     pseudorandom value between 0 and 32767 inclusive.
                                  #     I have applied a modulo 21 to get 21 possible
                                  #     values. We take advantage of the allowed uneven
                                  #     distribution.

    ((i<0))                       # Perform the expression i < 0
           &&                     # and assign 0 to i only if the previous
             i=0                  # command completed successfully

    a                             # Execute 'a'
    echo                          # Display a blank line
done
a                                 # Execute 'a'

Thanks to muru and Sam Dean for their improvements, they saved me 31 bytes.

\$\endgroup\$
  • \$\begingroup\$ can't you remove the " -e" after the first echo? \$\endgroup\$ – Sam Dean May 31 '18 at 14:52
  • \$\begingroup\$ removed the " -e" and a whitespace "; i" Try it online! \$\endgroup\$ – Sam Dean May 31 '18 at 14:53
  • \$\begingroup\$ You can replace if [[ $i -lt 0 ]];then i=0;fi with ((i<0))&&i=0, [[ $i -gt 0 ]] with ((i>0)), i=$((i-$RANDOM%21+4)) with i=$[i-RANDOM%21+4] to get 152 bytes \$\endgroup\$ – muru Jun 1 '18 at 6:33
  • \$\begingroup\$ @muru Thanks, I'll add it. \$\endgroup\$ – MC Emperor Jun 1 '18 at 7:39
2
\$\begingroup\$

Python 3, 199 191 171 bytes

-8 bytes thanks to @Stephen
-20 bytes thanks to @Jo King

import random
x=99
l="bugs in the code\n"
p=print
while x>0:p(f"{x} {l}"*2+"Take one down and patch it around");x=max(0,x+random.choice(range(-16,5)));p(f"{x} {l}")
p(0,l)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ 191 bytes by putting the while body on one line and using import random and random.choice \$\endgroup\$ – Stephen Nov 9 '18 at 16:03
  • \$\begingroup\$ Assign print to a variable, join the prints, and actually moving the while loop to one line. 171 bytes \$\endgroup\$ – Jo King Nov 10 '18 at 1:21
2
\$\begingroup\$

SAS 153 146 145 bytes

data;a=99;b='bugs in the code';do while(a>0);put a b/a b;put'Take one down and patch it around';a=max(a+int(ranuni(0)*20-16),0);put a b/;end;run;

The original version is Joe's answer, thanks him.

\$\endgroup\$
  • 3
    \$\begingroup\$ You have to specify the language and the length in bytes (since it is code golf). Also, you have to at least try to golf it, e.g. remove unnecessary spaces or newlines. \$\endgroup\$ – Bubbler Nov 26 '18 at 4:53
  • \$\begingroup\$ @Bubbler Sorry, it is just a variant version by Joe: SAS, 210 Bytes. And I will try to golf it only if I know better how to edit my answer. \$\endgroup\$ – whymath Nov 26 '18 at 5:15
  • \$\begingroup\$ @whymath Edit by pressing the edit button. Also, if this is a small improvement in another user's answer, submit it as a comment instead, which you can do after obtaining a small amount of reputation from upvotes. \$\endgroup\$ – lirtosiast Nov 26 '18 at 5:51
  • \$\begingroup\$ Thanks, @lirtosiast .kind of difficult cause I am not so good at this operation. By the way, why some answers' title also have a link? I mean, the name of the language. \$\endgroup\$ – whymath Nov 26 '18 at 10:25
  • \$\begingroup\$ @JonathanFrech okay, I already handled this. \$\endgroup\$ – whymath Nov 26 '18 at 10:30
1
\$\begingroup\$

Python 3, 144 bytes

from pylab import*
s='bugs in the code\n'
X=99
while X>0:i=randint(-16,5);print(X,s,X,s,'\ntake one down and patch it around',max(X+i,0),s);X+=i
\$\endgroup\$
  • \$\begingroup\$ Formatting is incorrect - the leading spaces may be ok if you ask, but this misses some new lines and does not print the final extra "0 bugs in the code" as required. \$\endgroup\$ – Jonathan Allan May 30 '18 at 22:32
1
\$\begingroup\$

Red, 166 163 bytes

b: 99 forever[if b > 1[print[b t:{bugs in the code}s:"^/"b t
s{Take one down and patch it around}]if
0 > b: b + 4 - random 20[prin[0 t s s 0 t]break]print[b t s]]]

Try it online!

More readable:

b: 99
t: {bugs in the code}
s: "^/" 
forever [
    if b > 1 [
        print [ b t s b t s {Take one down and patch it around} ]
        if 0 > b: b + 4 - random 20 [
            prin [ 0 t s s 0 t ]
            break
        ]
        print [ b t s ]
    ]
]
\$\endgroup\$
1
\$\begingroup\$

Japt, 124 123 121 120 116 110 107 bytes

U=U||99P=` Þï  e ¬¸`OpU+POpU+P  Op`Take e ܵ, p®  ÂÐ` U=Mr0-15,5 +U-1U=Uc  (U>0 ?(OpU+P+R ,ßU  :Oo0+P

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I'm guessing I need some headers/footers for it to work in TIO? Try it online! \$\endgroup\$ – Sam Dean May 30 '18 at 9:10
  • \$\begingroup\$ Fixed Try it online! \$\endgroup\$ – Logern May 30 '18 at 12:54
  • \$\begingroup\$ @SamDean it looks like there are non-printing characters in the compressed string that aren't getting copied, it works in the TIO I posted. Here is the difference: diffchecker.com/MATxOdMv \$\endgroup\$ – Logern May 30 '18 at 13:00
  • \$\begingroup\$ Strings looking good now! You do need to change that "," for " and" though! "Take one down and patch it around" \$\endgroup\$ – Sam Dean May 31 '18 at 8:28
  • \$\begingroup\$ Oh, didn't notice there was another Japt solution when I posted mine. Can see quite a few potential savings here but I'm on my phone so they'll have to wait 'til the morning. Welcome to PPCG, and Japt :) \$\endgroup\$ – Shaggy May 31 '18 at 22:56
1
\$\begingroup\$

.COM opcode, 137 bytes

0000h: BE 63 00 E8 3B 00 85 F6 75 01 C3 E8 33 00 B2 61
0010h: CD 21 0F C7 F0 F7 26 87 01 01 D6 83 EE 10 73 02
0020h: 31 F6 E8 1C 00 B2 5E CD 21 EB D8 99 F7 36 85 01
0030h: 85 C0 74 05 52 E8 F3 FF 5A B4 02 80 CA 30 CD 21
0040h: C3 89 F0 E8 E5 FF B4 09 BA 4D 01 EB F1 20 62 75
0050h: 67 73 20 69 6E 20 74 68 65 20 63 6F 64 65 0D 0A
0060h: 24 54 61 6B 65 20 6F 6E 65 20 64 6F 77 6E 20 61
0070h: 6E 64 20 70 61 74 63 68 20 69 74 20 61 72 6F 75
0080h: 6E 64 0D 0A 24 0A 00 15 00                     

        org 100h

        mov si, 99
lp:     call put2
        test si, si
        jnz @f
            ret
        @@:
        call put2
        mov dl, str2 - 256
        int 33
        rdrand ax
        ;mov ax, 65536*14/21+1
        mul [twentyone]
        add si, dx
        sub si, 16
        ;lea si, [esi+edx-16]
        jnc @f
            xor si, si
        @@:
        call put2
        mov dl, str2 - 256 - 3
        int 33
        jmp lp

put1:   cwd
        div [ten]
        test ax, ax
        jz @f
            push dx
            call put1
            pop dx
        @@:
        mov ah, 2
        or dl, 48
int33:  int 33
        ret

put2:   mov ax, si
        call put1
        mov ah, 9
        mov dx, str1
        jmp int33

str1:   db ' bugs in the code', 13, 10, '$'
str2:   db 'Take one down and patch it around', 13, 10, '$'
ten     dw 10
twentyone dw 21
\$\endgroup\$
  • \$\begingroup\$ p.s. with upper 60000+, if not consider it running up so high (in 250) can save some bytes \$\endgroup\$ – l4m2 May 30 '18 at 16:47
1
\$\begingroup\$

Ruby, 128 bytes

N=99
def f;puts"#{N} bugs in the code"end
(f;f
puts"Take one down and patch it around"
N-=[N,15-rand(21)].min
f
puts)while 0<N
f

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Japt -R, 83 79 75 73 bytes

Includes a trailing newline

#c
` Þï  e ¬¸
`
@§T}a@Np[UVUV`ìǦÓnÓlp®äNh
`qʸTwU±Gn#ö¹V]¬ÃpViT

Test it


Explanation

#c                                         :99
\n                                         :Assign to variable U
`...`                                      :The compressed string " bugs in the code\n"
\n                                         :Assign to variable V
        [UVUV                  V]          :Build an array with U as the 1st & 3rd elements,
                                           : V as the 2nd, 4th & 7th
                                           : and the following as the 5th & 6th:
             `...`                         :  The compressed string "Takeloneldownlandlpatchlitlaround\n"
                  qÊ                       :   Split on "l"
                    ¸                      :   Join with spaces
                      w       ¹            :  Maximum of
                     T                     :   0 and
                           #               :    21
                             ö             :    Random number in the range [0,21)
                          n                :    Subtract
                         G                 :    16
                       U±                  :    Add to U
                                 ¬         :Join to a string
      Np                                   :Push to N, initially an empty array
@  }a@                            Ã        :Repeat until
 §T                                        :  U is less than or equal to 0
                                   p       :Push
                                    ViT    :  V prepended with 0
                                           :Implicitly join with newlines and output
\$\endgroup\$
1
\$\begingroup\$

BLZ 2.6, 155 bytes

b=99
while b>0
n={text.newline}
s=" bugs in the code"+n
p=(x->print(99+s+99+s+"Take one down and patch it around"+n+b+s))
p()
b=b+random(-16,5)
end
b=0
p()

Reminds me that I need to make "\n" a newline so I can save some of those characters from {text.newline}

\$\endgroup\$
  • \$\begingroup\$ anyway we can test that? also can you remove the space before "5" in the random function? \$\endgroup\$ – Sam Dean Jun 6 '18 at 10:15
  • 1
    \$\begingroup\$ @SamDean Good call on the space, down to 155 bytes. You can test it by installing blz if you want. There's a guide here github.com/blazingkin/blz-ospl/wiki/Installation You'd also have to checkout the v2.6 branch \$\endgroup\$ – blazingkin Jun 6 '18 at 18:44
1
\$\begingroup\$

C# (.NET Core), 175 bytes

var s="";var r=new Random();for(int p=99;p>0;){var d=" bugs in the code\n";s+=p+d+p+d+"Take one down and patch it around\n";p+=r.Next(-17,5);s+=(p>0?p:0)+d+"\n";}return s;

Try it online!

C# uses a class for randomizing. Without the "Random" object, the response would be around 148 bytes. Using a for loop instead of a while loop removes one byte. using "new Random.Next()" will not work, since creating multiple Random objects within a loop wont make the Randomizer actually random.

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG. \$\endgroup\$ – Muhammad Salman Jun 5 '18 at 22:46
  • \$\begingroup\$ You need to add that final "0 bugs in the code" but nice answer! \$\endgroup\$ – Sam Dean Jun 6 '18 at 10:13
1
\$\begingroup\$

Clojure, 192 188 bytes

#(loop[b 99](def s"bugs in the code")(printf"%s %s\n%s %s\nTake one down and patch it around\n"b s b s)(def n(max(+ b(rand-int 21)-16)0))(println n s"\n")(if(= n 0)(println n s)(recur n)))

Try it online!

Explanation

#(loop [b 99] ; Initialize a loop with b=99
  (def s "bugs in the code") ; Define a variable s that equals "bugs in the code"
  (printf "%s %s\n%s %s\nTake one down and patch it around\n" b s b s) ; Prints 
    ;    "99 bugs in the code
    ;     99 bugs in the code
    ;     Take one down and patch it around" with the correct formatting.
  (def n (max (+ b (rand-int 21) -16) 0)) ; Let n = max(b+<some random number between -16 and 4 inclusive>, 0) This prevents negative numbers by replacing them with 0
  (println n s "\n") ; Prints "<n> bugs in the code" followed by an extra newline
  (if (= n 0) ; If n equals 0
    (println n s) ; Prints "<n> bugs in the code"
    (recur n))) ; Otherwise run the loop again with b=n
\$\endgroup\$
1
\$\begingroup\$

Dart, 173 169 bytes

import'dart:math';f({n=99,m=' bugs in the code\n'}){while(n>0){print('$n$m$n$m\Take one down and patch it around');n=n+Random().nextInt(20)-16;n=n<0?0:n;print('$n$m');}}

Try it online!

Almost competing with other Java-like languages for once

\$\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.