22
\$\begingroup\$

Your bird has been itching for some exercise and is sick of being stuck in static positions all the time. Write a program that will show a randomly dancing ascii bird, updating every 100ms*n or 200ms*n depending on the dance move. The bird always begins with the dance move <(")>.

The program should accept one input which is a number to multiply the sleep interval by (n >= 0 && n <= 50).

100ms Moves

^(")v
v(")^
^(")^
v(")v

200ms Moves

(>")>
<(")>
<("<)

Extra Details

  • Randomness doesn't have to be uniform but each dance move should have a reasonable chance of occuring (at least 1 in 60 seems fair, it's OK if the same move occurs twice in a row)
  • There should only be one bird displayed at a time, not multiple birds
  • Trailing whitespace is allowed (but other trailing characters are not)
  • A bird should be displayed before the sleep

Example in Python 3

import random, time, sys

birds = """(>")>
<(")>
<("<)
^(")v
v(")^
^(")^
v(")v"""
birds = birds.split()

interval = int(input("Sleep for 100ms*"))
selection = -1

while True:
    if selection == -1:
        selection = 1
    else:
        selection = random.randint(0, len(birds)-1)
    sys.stdout.write('\r'+birds[selection])
    if selection > 2:
        time.sleep(0.1*interval)
    else:
        time.sleep(0.2*interval)

Winning

\$\endgroup\$
12
  • \$\begingroup\$ Are the bird's eyes a double quote or two single quotes? \$\endgroup\$
    – Pavel
    Dec 31, 2016 at 23:05
  • \$\begingroup\$ @Pavel, double quote \$\endgroup\$ Dec 31, 2016 at 23:05
  • 6
    \$\begingroup\$ Well, today I learned you don't have to escape quote marks in multi line strings in python. \$\endgroup\$
    – Pavel
    Dec 31, 2016 at 23:25
  • \$\begingroup\$ If my language can't modify outputs, can I just output a new bird every 100/200 ms? \$\endgroup\$
    – devRicher
    Jan 1, 2017 at 0:11
  • 1
    \$\begingroup\$ Using Ideone, the Lua \r escape seems to act just like a \n. Neither can I use os.execute("cls") there. @redstarcoder \$\endgroup\$
    – devRicher
    Jan 1, 2017 at 0:17

9 Answers 9

6
\$\begingroup\$

Matlab, 125 117 bytes

Unfortunately this cannot be displayed in TIO as there is no "streaming" of the output. Here's a gif for an input of 1 instead:

t=input('')*.1;a='^(")vv(")^^(")^v(")v(>")><(")><("<)';while 1;n=randi(7);clc;disp(a(n*5-4:n*5));pause(t+t*(n>4));end

Thanks @LuisMendo for -8 bytes!

\$\endgroup\$
0
5
\$\begingroup\$

*><>, 103 101 bytes

<vD[3'(")'
1x<.5
S\:43_C43CdooI:o@:o@:o@Do
R!"^"x"v">
>:2* _"><"92.
x '>)">('u.02S*2:oooooodO<'<("<)'

Try it here! (write in n on the initial stack or you'll get an error)

I decided to take a stab at my challenge since there were no sub 100 bytes answers. Place n on the stack and away you go! This reuses the (") characters to save some bytes.

Explanation

Initialisation

<vD[3'(")'

Here we store (") for later usage.

<           move the IP left
   [3'(")'  push '(")' to a new stack
  D         move back down to a clean stack
 v          move the IP down into "dance chooser"

Dance chooser

1x<.5
 \

This is frequently executed to select which type of dance we're going to generate.

 x         generate a 100ms dance or a 200ms dance
1  .5      jump to "200ms dance"
 \         mirror IP into "100ms dance"

There's a v above the x and a < to the right of it too. These make the x get re-executed if it tries to move the IP in the wrong direction.

Generate 100ms dance

S\:1*43_C43CdooI:o@:o@:o@Do

Here we generate and output one of the 100ms dance moves.

 \                         mirror the IP right
  :                        copy n
   43 C43C                 call "generate '^' or 'v'" twice
     _                     ignored mirror
          do               output a carriage return
            o              output the first hand of the bird
             I:o@:o@:o@D   select, copy, and output '(")'
                        o  output the second hand of the bird
S                          sleep for previous n*100ms
 \                         mirror IP back to "dance chooser"

43C - Generate "^" or "v"

R!"^"x"v">

This is a simple function that generates "^" or "v" then returns. It works similarly to the dance chooser where it has instructions around x to ensure the IP only moves left or right.

     x      generate "^" or "v"
R!"^"    >  push "^" to stack and return
R     "v"   push "v" to stack and return

Generate 200ms dance

This is another that begins with x. It'll be separated into two sections: <(")> and another (>")> and <("<), because they're two distinct sections and x is the only thing they share.

<(")>

>:2* _"><"b2.

This basically does the beginning of the generate 100ms dance routine, but populates the bird hands as >< instead of a random ^v combo. It multiplies n by two this time as well. This makes it all setup to utilise the generate 100ms dance routine to output the entire bird and wait 200ms instead.

>              move IP right
 :2*           copy n and do n*2
     _         ignored mirror
      "><"     push "><" to stack
          b2.  jump to "output carriage return" in "generate 100ms dance"

(>")> and <("<)

x '>)">('u.02S*2:oooooodO<'<("<)'

This little explanation is about the (>")> and <("<) generation, though the x can send the IP outside of it (explained below).

x                                  move to "choose dance", generate (>")>, <("<), or <(")> (previous routine)  
  '>)">('                          push '(>")>' to the stack
                          '<("<)'  push '<("<)' to the stack
         u              O<         ensure inner code block is always executed with IP moving left
                      od           output carriage return
                 ooooo             output bird
             S*2:                  sleep for n*200ms
          .02                      jump to "dance chooser"
\$\endgroup\$
0
3
\$\begingroup\$

MATL, 53 bytes

xXx`'./U;HbG#3@@!{uu'F'v^<>(")'Za7e 7YrY)D5M3>QG*&XxT

Moves are uniformly random.

Below is a sample run withn = 2. Or try it at MATL Online! (The interpreter is experimental. If it doesn't run initially try pressing "Run" again or refreshing the page).

enter image description here

Explanation

x                   % Take input n and delete it
Xx                  % Clear screen
`                   % Do...while
  './U;HbG#3@@!{uu' %   Push this (compressed) string
  F                 %   Specify source alphabet for decompression
  'v^<>(")'         %   Push target alphabet
  Za                %   Base conversion (decompress)
  7e                %   Reshape as a 7-row char matrix. Each row is a move
  7Yr               %   Push random integer from 1 to 7
  Y)                %   Select that row from the char matrix
  D                 %   Display it
  5M                %   Push the integer again
  3>                %   Does it exceed 3? Gives false (0) or true (1)
  Q                 %   Add 1
  G*                %   Multiply by n
  &Xx               %   Pause that many tenths of a second and clear screen
  T                 %   Push true
                    % End (implicit). Since top of the stack is true, this causes
                    % and infinite loop
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6) + HTML5: 118 116 + 8 = 124 bytes

Javascript: 119 bytes

f=n=>{a.innerHTML='(>")>0<(")>0<("<)0^(")v0v(")^0^(")^0v(")v'.split(0)[r=+new Date%7],setTimeout(f,(1+(r<3))*100*n,n)}

I'm using the milliseconds since epoch to generate a random-ish number. Theoretically, this would always generate the same (set of) number(s), but a test on my PC gave me a pretty random outcome (most numbers appeared more or less equally). Also using the fact that html elements with an id get added to the global window object in JavaScript, so document.getElementById() is not needed.

HTML: 8 bytes

<b id=a>

I'm omitting the quotes here and I'm not closing the b tag. It's not valid html, but all browsers automatically close the tag anyway. I made it bold because b is a one-character HTML element and because my bird's dance deserves being noticed.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ When f re-calls itself, it doesn't pass n again. For me at least this seems to only honour n the first time, after which it's zero (or undefined). Also sometimes the output is undefined. Should it be r%7? \$\endgroup\$
    – Chris M
    Jan 1, 2017 at 11:50
  • \$\begingroup\$ You're right, I forgot to pass n. It should indeed be %7. I miscounted the amount of bird poses. Thanks for the correction, it's fixed now. \$\endgroup\$
    – Luke
    Jan 1, 2017 at 12:30
  • \$\begingroup\$ Sorry I keep increasing your byte counts! Cool golfing, I like the random function and zero splitting \$\endgroup\$
    – Chris M
    Jan 1, 2017 at 15:30
  • \$\begingroup\$ Thanks. I found a 4B improvement while editing my answer, which meant I ended up saving 2B, so it's all right. The zero splitting used to save bytes in ES5 and earlier, but you can omit the parentheses with template strings since ES6, so it's not as useful anymore. It is a remainder from a different approach (where I used a template string as first argument for the setInterval). \$\endgroup\$
    – Luke
    Jan 1, 2017 at 17:36
2
\$\begingroup\$

PowerShell, 124 117 bytes

(Thanks TimmyD)

for(){(-split'^(")v v(")^ ^(")^ v(")v (>")> <(")> <("<)')[($i=0..6|random)];sleep -m((100,200)[$i-gt3]*$args[0]);cls}

Try it online! (Not that it will work in TIO...)

\$\endgroup\$
3
  • \$\begingroup\$ You can eliminate $b and use a pseudo-ternary to get down to 117 -- for(){(-split'^(")v v(")^ ^(")^ v(")v (>")> <(")> <("<)')[($i=0..6|random)];sleep -m((100,200)[$i-gt3]*$args[0]);cls} ... I think shorter is possible; I'm still poking at it. \$\endgroup\$ Jan 3, 2017 at 17:26
  • \$\begingroup\$ You just keep bailing me out @TimmyD (thanks)! I think those changes are significant enough to warrant your own answer; it doesn't leave much of anything unique in my code :) \$\endgroup\$
    – briantist
    Jan 3, 2017 at 17:29
  • \$\begingroup\$ No, they're just minor tweaks on your code. The overall logic is the exact same. Have at it. \$\endgroup\$ Jan 3, 2017 at 17:30
2
\$\begingroup\$

Noodel, noncompeting 67 bytes

ʠƘṣḳƑðẉḤż’ṀỴ(EḞ4ĊḌṀY%¤ĠẸG^ḞðxỌð
ḊḢðḞ’ṀḌcṀḌcİ8c¬ððɲḷṛḋʠṡʠạÇƥƥạƥḋʠ⁺µḍ

This challenge was very difficult for Noodel because it does not have any smart arithmetic or comparative based operators. But after doing this challenge, I think Noodel is ready for its first release.

Try it:)

How It Works

                                                                     # Note: The input is immediately pushed onto the stack.
ʠ                                                                    # Moves the pointer for the top of the stack down one.
 ƘṣḳƑðẉḤż’ṀỴ(EḞ4ĊḌṀY%¤ĠẸG^ḞðxỌð                                      # Creates a string based off of the key "ƘṣḳƑðẉḤż" and the compressed text "ṀỴ(EḞ4ĊḌṀY%¤ĠẸG^ḞðxỌð" to create "^(")vðv(")^ð^(")^ðv(")vð(>")>ð<(")>ð<("<)" which then gets split by the null character "ð" to create an array of strings which gets pushed to the stack.
                               \n                                    # A new line to separate the literals.
                                 ḊḢðḞ’ṀḌcṀḌcİ8c¬ðð                   # Creates a string based off of the key "ḊḢðḞ" and the compressed text "ṀḌcṀḌcİ8c¬ðð" to create "100ð100ð100ð100ð200ð200ð200" which then gets split the same way as before.
                                                  ɲ                  # Turns each element in the array into a number creating the array of delays.
                                                   ḷ                 # Loops the rest of the code unconditionally.
                                                    ṛ                # Generates a random number from 0 to the length-1 of the array on top of the stack.
                                                     ḋ               # Duplicates the random number.
                                                      ʠ              # Moves the stack pointer down to save one of the random numbers for later.
                                                       ṡ             # Swap the array with the random number such that the array is on top again.
                                                        ʠ            # Moves the stack pointer down such that the random number is on top.
                                                         ạ           # Uses the random number to access the bird array which is now after the random number and pushes the element onto the stack.
                                                          Ç          # Clears the screen and pops the bird and pushes it to the screen.
                                                           ƥƥ        # Moves the stack pointer up two times such that the random number is the top.
                                                             ạ       # Use the random number to access the array with delays and pushes that item onto the stack.
                                                              ƥ      # Moves the stack pointer up in order to have the input on top.
                                                               ḋ     # Duplicates the users input.
                                                                ʠ    # Moves the stack pointer back down in order to have the user input on top followed by the random item from the delay array.
                                                                 ⁺µ  # This command pops two numbers off and multiplies them and pushes the result back on.
                                                                   ḍ # Pops off of the stack and uses that as a delay in milliseconds.

64 bytes

Here is a version that works as a code snippet.

ʠƘṣḳƑðẉḤż’ṀỴ(EḞ4ĊḌṀY%¤ĠẸG^ḞðxỌð EAð¶’Ṁ|ṢĿ<h4¶¬ȥḷṛḋʠṡʠạÇƥƥạƥḋʠ⁺µḍ

<div id="noodel" code="ʠƘṣḳƑðẉḤż’ṀỴ(EḞ4ĊḌṀY%¤ĠẸG^ḞðxỌð EAð¶’Ṁ|ṢĿ<h4¶¬ȥḷṛḋʠṡʠạÇƥƥạƥḋʠ⁺µḍ" input="2" cols="5" rows="3"></div>

<script src="https://tkellehe.github.io/noodel/release/noodel-1.1.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>

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

Python, 157 bytes

import time,random;n,m=5,int(input())
while 1:print('(>")><(")><("<)^(")vv(")^^(")^v(")v'[n:n+5]);time.sleep((.1+(n<15)/10)*m);n=(n+random.randint(1,6)*5)%35

I also tried to do it without the chicken ascii art, but that was way longer.

import time,random;n,m=5,int(input())
while 1:
  print(['^v'[n%2]+'(")'+'v^'[0<n<3],''.join(map(chr,[40+20*(n>4),62-22*(n>4),34,41+19*(n>5),62-21*(n>5)]))][n>3])
  time.sleep((.1+(n>3)/10)*m);n=(n+random.randint(1,6))%7
\$\endgroup\$
1
\$\begingroup\$

Ruby, 97+1 = 98 bytes

+1 byte from the -n flag.

a=1;loop{puts %w{^(")v <(")> v(")^ (>")> ^(")^ <("<) v(")v}[a];sleep$_.to_i*0.1*(1+a%2);a=rand 7}
\$\endgroup\$
1
\$\begingroup\$

Clojure, 185 178 bytes

+18 bytes because it wasn't starting with <(")>.

-7 bytes by inlining birds, and getting rid of the let.

#(loop[m nil r(or m 1)](print"\r"((clojure.string/split"(>\")> <(\")> <(\"<) ^(\")v v(\")^ ^(\")^ v(\")v"#" ")r))(flush)(Thread/sleep(*(if(> r 2)100 200)%))(recur 1(rand-int 7)))

Just splits the birds on spaces, picks a random index from 0-6, displays the chosen bird, then if the chosen index is greater than 2, it waits for 100ms, else 200ms.

Clojure really needs a string split method in the core.

Ungolfed:

(defn dancing-bird [n]
  (loop [m nil]
    (let [birds (clojure.string/split "(>\")> <(\")> <(\"<) ^(\")v v(\")^ ^(\")^ v(\")v" #" ")
          rand-i (or m 1)]
      (print "\r" (birds rand-i))
      (flush)
      (Thread/sleep (* (if (> r 2) 100 200) n))
      (recur (rand-int 7)))))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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