25
\$\begingroup\$

Buzzby Berkeley Robot Hokey Pokey

Task

Write a program or function to produce an ASCII art animation depicting a line of robots dancing to the lyrics of the Hokey Pokey (or Cokey, if you prefer) in the style of a Busby Berkeley number!

Example Output

enter image description here

Input

Accepts three arguments (assumed to be valid):

N = number of robots in the line (Min=6)

B = duration of one "beat" in milliseconds (Min=10)

D = delay in ms between successive robots (Min=0)

(In the example output above: N=8, B=380, C=75)

Specifications

  1. N robots are shown in a row upon a stage.

  2. One line of text from "the verse" is shown at a time beneath the stage (centred to within 1 character, and enclosed in quotation marks.)

  3. The robots perform the actions for each line as it is shown until the verse has been repeated 5 times.

  4. An action is performed by depicting a robot using a set of ASCII characters and waiting a specified duration before performing the next action. The duration of an action is measured in "beats". The duration of 1 beat is a number of milliseconds, B.

  5. The first robot starts performing the actions for each line of verse immediately when the line's text is displayed.

  6. Each subsequent robot delays starting its actions until a specific time (D) after the robot to its right (your left!) begins its actions.

  7. Robots' depictions vary by the ASCII characters which represent a robot's "antenna", of which there are 5 possible types, distributed randomly every time the program is run.

  8. Each type of antenna must be used by at least one robot, but the same type must not appear on any robots separated by fewer than 3 other robots. The amounts of any two types of antennae may differ by no more than 1 (e.g. 1xType_4 and 3xType_5's is illegal since 3-1>1 )

Verse and Actions

The whole verse is repeated 5 times, 1 line at a time...

Line  Text                            Action/Beats, 
----  -----------------------------   ------------------------------------
1     You put your ? in               ??/4
2     You take your ? out             AA/4
3     You put your ? in               ??/4
4     And you shake it all about      AA/1, ??/1, AA/1, ??/1
5     You do the Hokey Pokey and...   
      ...you turn yourself around     AA/1, H[1-7]/1
6     That's what it's all about!     AA/4, ZZ/4

For each repetition (R) of the verse, substitute ? and ??...

R   ?=           ??=
--  -----------  ---
1.  right foot   RF 
2.  left foot    LF
3.  right hand   RH
4.  left hand    LH
5.  whole self   WS

Actions and ASCII patterns

Each labelled action is represented by 5 lines of 8 ASCII symbols.
The representation of each action is as follows...

1 |   12     12        12    12        12     12      12   
2 |  ['']   ['']      ['']  ['']      ['']   ['']   \[*-] 
3 | └[__]┘ └[__]┘    └[__]┘┌[__]┘    └[__]┐ ┌[__]┐   [__]\ 
4 |   ||     /<        >\    <\        />    /  \     /|
5 |--------------------------------------------------------
  |\__AA__/\__RF__/\__LF__/\__RH__/\__LH__/\__WS__/\__ZZ__/ 

1 |   12     12_     34_      34      _34     _12     12    
2 |  ['']    [" ]    [ _]    [__]    [_ ]    [ "]    ['']
3 | >[__]<   [_<]    [<.]   <[..]>   [.>]    [>_]   <[__]>
4 |   ||      |\      ||      /|      ||      |\      ||
5 |--------------------------------------------------------
  |\__H1__/\__H2__/\__H3__/\__H4__/\__H5__/\__H6__/\__H7__/

In row 1, replace "1-4" with corresponding symbol for each antenna type...

1 | 1234 1234 1234 1234 1234 
  | \/\/ |┌┐| )||( |||| ┐/\┌ <-- Symbols 1-4 for...
  | 1    2    3    4    5    <-- ...antenna types 1-5

Output

The entire scene must be rendered at least once immediately whenever the content of the scene changes in any way. (I.e. assuming the delay between robots' actions is > 0, the output may be rendered no less than N times per action.)

Ideally, for an animation the console or equivalent output area is cleared before each update is rendered. To provide for languages unable to clear the console, output may also be rendered in a continuous stream, subject to the same requirement described above.

Scoring

Winners are the shortest programs in each language, as well as the shortest overall.

Exception 1 Because clearing the console each render is preferable though not required, bytes used exclusively for this luxurious purpose do not count towards the total bytes. This includes commands to clear the console, and padding output with blank lines to scroll the console contents out of view.

Exception 2 CSS or effectively similar means used exclusively for the purpose of styling the output beyond the minimum requirements do not count towards the total bytes. E.g. *{color:blue;text-align:center;} counts as only 32-10=22 bytes since color:blue; doesn't serve to satisfy any specification, whereas centred text is specified.

Meta

Inspired by (showing my age) the TRS-80 Dancing Demon, Android Nim, and of course Busby Berkeley (and no, I'm not that old).

\$\endgroup\$
  • \$\begingroup\$ Great... last thing I need before I am already tired is a challenge to grab my attention. Are the tags on the top necessary? \$\endgroup\$ – Matt May 30 '17 at 0:53
  • \$\begingroup\$ @Matt, well the whole challenge isn't strictly "necessary", but I've removed the duplicate tags. ;-) \$\endgroup\$ – Bumpy May 30 '17 at 0:56
  • \$\begingroup\$ I've removed the maximum limit for input parameter 'D'. It was "D < B/N" to make sure each robot down the line had at least started the action while the first robot was still performing it (to avoid too much chaos), but by error, my own example broke that rule, and it seems to look okay anyway so I've removed the max delay limit. Apologies for that late change. \$\endgroup\$ – Bumpy May 30 '17 at 12:57
  • \$\begingroup\$ I've updated the section on scoring CSS and the like. \$\endgroup\$ – Bumpy Jun 1 '17 at 12:21
  • 3
    \$\begingroup\$ That is the most adorable thing I've ever seen. \$\endgroup\$ – Wossname Jun 6 '17 at 21:13
13
\$\begingroup\$

Ladies and Gentlemen, please welcome our lovely

Full Frontend-Stack Dance Group, 1,320 1,378 1,425 1,495 bytes

JavaScript: 1,195 bytes | CSS: 103 bytes | HTML: 22 bytes


This is a cute challenge. It also has lots of special cases. Oh boy, so many special cases. And those antennas …

It will run forever and restart after all actions (left foot, right foot etc.) are completed.

You can try it on jsFiddle or by using the code snippet thingy below:

t=setTimeout
c=l=a=i=0
_=(x,y,z)=>{if(!i)for(;++i<=x;q=~~(Math.random()*10))s.append(document.createElement('pre'))
for(i=l=0,c=a+1;i<33;)(i=>{t($=>{if(4==i){c=0
l=1}if(8==i){c=a+1
l=0}if(12==i|14==i){c=0
l=2}if(13==i|15==i)c=a+1
if(16==i){c=0
l=3}if(16<i&24>i)c=i-10
if(24==i){c=0
l=4}if(28==i)c=6
if(31<i){a=++a%5
_(x,y,z)}for(j=0;j<x;)(j=>{t($=>s.childNodes[j][h]=(-1<[1,3,8,9].indexOf(c)?'  ':2==c||4==c?'    ' :'   ')+(11==c||12==c?'_':'')+['\\/\\/','|┌┐|',')||(','||||','┐/\\┌'][(q+j)%4].substring($=8<c&12>c?2:0,$+2)+(8==c||9==c?'_':'')+'\n'+[`  ['']			   
 └[__]┘ 
   ||`,` ['']  
└[__]┘  
  /<`,`   ['']
  └[__]┘
    >\\`,` ['']
┌[__]┘
  <\\`,`   ['']
  └[__]┐
    />`,`  ['']
 ┌[__]┐
  /  \\`,` \\[*-]
  [__]\\
   <\\`,`  ['']
 >[__]<
   ||`,`  [" ]
  [_<]
   |\\`,`  [ _]
  [<.]
   ||`,`  [__]
 <[..]>
   /|`,`  [_ ]
  [.>]
   ||`,`  [ "]
  [>_]
   |\\`,`  ['']
 <[__]>
   ||`][c]+'\n-------',j*z)})(j++)
p[h='innerText']='"'+["You put your $ in","You take your $ out","And you shake it all about","You do the Hokey Pokey and you turn yourself around","That's what it's all about!"][l].replace('$',['right foot','left foot','right hand','left hand','whole self'][a])+'"'},i*y)})(i++)}

// let's dance (not included in the byte count – as if it would make any difference)
_(8, 400, 50)
*{text-align:center}x pre{display:inline-block;width:55px;text-align:left}pre{line-height:16px;margin:0
<x id=s></x><pre id=p>


Tested in Chrome and Firefox on macOS, Windows 10 and Ubuntu


Edits

  • Saved 70 bytes by removing the extra container to hold the antennas. Thanks to Bumpy. Also found some more whitespaces, removed the now unnecessary caching of createElement and removed the long access to .firstChild.
  • Saved 47 bytes – just realized that I actually don't need to call getElementById. This also makes the caching of document unnecessary.
  • Saved 4 bytes by replacing || and && with bitwise & and |. Thanks to TheLethalCoder.
  • Saved 54 bytes by simplifying lots of small things and by optimizing the CSS.
\$\endgroup\$
  • \$\begingroup\$ Bravo!!! The Full Frontend-Stack Dance Group's a hit!! Apologies for the amount of special cases; I chose the antennae combinations specifically to frustrate, but the rest of the symbols were all in service of the animation - I didn't plan it to be SO fiddly. Now, I feel churlish criticising such a brilliant performance, but I think the underscores/antenna are slightly out of whack when they turn around (1 character too far to the left, possibly?) But whatever - it's great! Thanks for taking up my challenge! \$\endgroup\$ – Bumpy Jun 1 '17 at 0:59
  • \$\begingroup\$ @Bumpy Thanks. You're right, I mixed up some magic numbers. The antennas are now perfectly in order. I also managed to get the same line-height for all figures. Really a fun challenge. \$\endgroup\$ – insertusernamehere Jun 1 '17 at 9:27
  • 1
    \$\begingroup\$ Fiddling with dancing robots at 2 o'clock you say? Wonderful, bwahaha! \$\endgroup\$ – Bumpy Jun 1 '17 at 11:56
  • 1
    \$\begingroup\$ || and && to | and &? \$\endgroup\$ – TheLethalCoder Jun 8 '17 at 13:00
  • 1
    \$\begingroup\$ @TheLethalCoder Absolutely. Your suggestion is already in the source and reflected in the edits. Thanks a lot. \$\endgroup\$ – insertusernamehere Jun 13 '17 at 9:18
5
\$\begingroup\$

C#, 1188 1376 1382 bytes after exceptions

Compacted:

namespace System.Threading{using S=String;void H(int n,int b,int d){Console.CursorVisible=false;int t,u=0,v=5,w,x,y,z;S[]i=",That's what it's all about!,,You do the Hokey Pokey and you turn yourself around,And you shake it all about,,You take? out,You put? in".Split(',');i[0]=i[1];i[2]=i[3];i[5]=i[7];for(b=b<d*n?0:b-d*n;v-->0;)for(w=32;w-->0;Thread.Sleep(b))for(t=u,z=0;z++<n;Thread.Sleep(d)){S s="",r=i[w/4].Replace("?"," your "+(v<1?"whole self":(v%2<1?"right ":"left ")+(v/3<1?"hand":"foot")));u="88880000765432109090999900009999"[w];u=u>56?9+v:u-48;for(y=4;y-->0;s+="\n")for(x=0;x<n;x++)s+=S.Format(@"{0}{0}   |\   {0}   /|   {0}   |\   {0}   /|{4} /  \{4}  />{4}<\{4}{4}>\{4}/<{4} └{1}┘  >{1}<   [_<]{4}[<.]   <[..]>   [.>]{4}[>_]   <{1}>   {1}\  ┌{1}┐   └{1}┐┌{1}┘{4}└{1}┘└{1}┘   {2}  {2}   ["" ]{4}[ _]{4}{1}{4}[_ ]{4}[ ""]   {2}  \[*-]   {2}   {2}{2}{4}{2}{2}  {3}{3}  12_{4} 34_{4}  34{4}  _34{4} _12  {3}{3}{3} {3} 12{4} {3} 12{4}", "   ||   ","[__]"," [''] ","   12   ","    ").Substring(y*14+(x<z?u:t)<<3,8).Replace("12",@"\/|┌)|||┐/".Substring(x%5*2,2)).Replace("34",@"\/┐||(||\┌".Substring(x%5*2,2));Console.Clear();Console.Write(s+new S('-',n*8)+"\n"+new S(' ',n*4-r.Length/2)+r);}}}

Slightly nicer formatting and wrapped in an executable program:

namespace System.Threading{
    using S=String;

    //** Not counted towards score: execution wrapper
    class P{
        static void Main(S[]a){
            new P().H(int.Parse(a[0]),int.Parse(a[1]),int.Parse(a[2]));
        }
    //** End not counted towards score

        void H(int n,int b,int d){
            Console.CursorVisible=false;  // Not counted under exception 2
            int t,u=0,v=5,w,x,y,z;
            S[]i=",That's what it's all about!,,You do the Hokey Pokey and you turn yourself around,And you shake it all about,,You take? out,You put? in".Split(',');
            i[0]=i[1];
            i[2]=i[3];
            i[5]=i[7];
            for(b=b<d*n?0:b-d*n;v-->0;)
                for(w=32;w-->0;Thread.Sleep(b))
                    for(t=u,z=0;z++<n;Thread.Sleep(d)){
                        S s="",r=i[w/4].Replace("?"," your "+(v<1?"whole self":(v%2<1?"right ":"left ")+(v/3<1?"hand":"foot")));
                        u="88880000765432109090999900009999"[w];
                        u=u>56?9+v:u-48;
                        for(y=4;y-->0;s+="\n")
                            for(x=0;x<n;x++)
                                s+=S.Format(@"{0}{0}   |\   {0}   /|   {0}   |\   {0}   /|{4} /  \{4}  />{4}<\{4}{4}>\{4}/<{4} └{1}┘  >{1}<   [_<]{4}[<.]   <[..]>   [.>]{4}[>_]   <{1}>   {1}\  ┌{1}┐   └{1}┐┌{1}┘{4}└{1}┘└{1}┘   {2}  {2}   ["" ]{4}[ _]{4}{1}{4}[_ ]{4}[ ""]   {2}  \[*-]   {2}   {2}{2}{4}{2}{2}  {3}{3}  12_{4} 34_{4}  34{4}  _34{4} _12  {3}{3}{3} {3} 12{4} {3} 12{4}", "   ||   ","[__]"," [''] ","   12   ","    ").Substring(y*14+(x<z?u:t)<<3,8).Replace("12",@"\/|┌)|||┐/".Substring(x%5*2,2)).Replace("34",@"\/┐||(||\┌".Substring(x%5*2,2));
                        Console.Clear(); // Not counted under exception 1
                        Console.Write(s+new S('-',n*8)+"\n"+new S(' ',n*4-r.Length/2)+r);
                    }
        }
    } // Not counted towards score: end class
}

Try it online!

  1. Visit this link: tutorialspoint.com
  2. In the Default Term tab at the bottom of the screen, type:
    mono main.exe 8 400 40

Edit 1

Replaced string.Format(i,j) with i.Replace("?",j) saving 6 bytes overall.

Edit 2

Complete revamp with suggestions from the comments.

\$\endgroup\$
  • \$\begingroup\$ Yay! Is there an easy way to run it online somewhere? \$\endgroup\$ – Bumpy Jun 9 '17 at 12:46
  • \$\begingroup\$ @Bumpy, added a link in the answer! \$\endgroup\$ – Hand-E-Food Jun 10 '17 at 13:20
  • 1
    \$\begingroup\$ @insertusernamehere By compiling to a anonymous function and some minor golfing I've got it to under 1300. \$\endgroup\$ – TheLethalCoder Jun 13 '17 at 9:43
  • 1
    \$\begingroup\$ @insertusernamehere, done! Your turn! :-D \$\endgroup\$ – Hand-E-Food Jun 13 '17 at 14:11
  • 1
    \$\begingroup\$ @TheLethalCoder, thanks for that! I got rid of c for a small saving. I knew I'd forgotten a better way than new string(c,n). However, now that I've aliased S=String, new S(c,n) is shorter still. \$\endgroup\$ – Hand-E-Food Jun 13 '17 at 14:14
0
\$\begingroup\$

JavaScript, 948 bytes

Probably poor form to answer your own question, but anyway...

Tried all sorts of ways to compress the text, but most ended up longer than the original with the key+algorithm included. I'm certain there's still a more optimal way to compress it all down, but I have to draw the line somewhere.

Interestingly, the search yielded one or two ideas for some other challenges which I might refine and post later.

<pre id=O/>

f=(N,B,D)=>{Q=c=>(K={},k='~',[...c].map(v=>v<k?K[k=v]='':K[k]+=K[v]||v),K[k])
x=``,A=`//,||,)||(,,/`.split(',').sort(new Date)
r=new Array(N).fill(0),t=i=v=0,n=`\n`,T=setTimeout
C=_=>(w=Q(`ouhand t t's ake Y y all abtokey righlefwhole fooself ,${v+1},,1yr ${x[v*2]+x[v*2+1]}puintt,,Ashi,do the HPaturn yrarnd,,7,8,90123,Twi!,,6,`).split(',')[i++])<'A'?(r.map((_,m)=>T((a,b)=>R(r[N-a]=b),m*D,m,w)),i>22?(v++,i=0):0,v<3?T(C,B*(i<7||i>21?4:1)):0):C(t=w),R=_=>{for(o='',m=4;m--;o+=n){for(w=N;w--;)o+=Q(`┌┐└┘\\/||/${A[w%5]}   [__] [''] ||] _ __ _  [*-][" ][ _][_ ][ "] ┐ ┐><[_<] [<.]<[..]>[.>] [>_]<> /<></>/ //`).substr(r[w]*8+(3-m)*112,8)}
O.innerHTML=o+'-'.repeat(N*8)+' '.repeat(((N*8)-t.length)/2)+t}
C()}

(NB: Contains some characters in the range 1-31 whose representations are a bit odd when posted here)

Watch the full psychedelic dance cycle on CodePen!

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