15
\$\begingroup\$

"Y.M.C.A." is a popular disco song by the Village People that has a well-known dance. Write the shortest program to output the capital letters "Y", "M", "C", and "A" synchronized to the song's chorus.

Generally, one letter goes on each line sent to standard output. This primarily is to simplify programs subject to the output buffering of the C standard library (printing a newline flushes the output buffer), so you may omit any or all of these newlines if such omission would make your program shorter.

Your program, which is started at the same time as the music, must output the letter "Y" within 0.125 s of each of these times after starting (in seconds; I determined these from the music video posted on YouTube).

 45.766   49.611   60.889
 64.661  109.816  113.591
124.810  128.687  173.830
177.620  188.950  192.724
204.013  207.739  219.057

The letters "M", "C", and "A" respectively come 0.930 s, 1.395 s, and 1.628 s after each "Y". For testing purposes, these relative times are converted into absolute times by adding them to the time of the preceding "Y".

I have written a test program and corresponding example program in C that assume a newline follows each letter (although this is not a rule of competition). It is written for Linux and will not work on Windows without using Cygwin. If you cannot test your submission using the test program, at least check your submission against the YouTube video.

If your submission requires a special command-line option to behave properly, that command-line option counts when calculating your score. However, any interpreter startup time does not count against you, and the test program can be modified to accommodate that if necessary.

Although I doubt one exists, I must say that using a programming language function or library designed specifically for this task is prohibited.

\$\endgroup\$

5 Answers 5

4
\$\begingroup\$

Ruby 180 135 124 118 108 104

[458,k=22,*[97,k,435,k]*2,*[98,k]*2,98].flat_map{|e|[e,9,5,2]}.zip(%w(Y M C A)*15){|a,b|sleep a/1e1;p b}
\$\endgroup\$
11
  • \$\begingroup\$ I just realized there is nothing in the rules prohibiting double quotes around each letter. However, the submission seems to work perfectly :) \$\endgroup\$ Jul 22, 2012 at 6:19
  • 1
    \$\begingroup\$ The second part of codegolf.stackexchange.com/questions/6695/… is relevant to you too. \$\endgroup\$
    – JPvdMerwe
    Jul 22, 2012 at 6:42
  • \$\begingroup\$ @JPvdMerwe Thanks a lot! You'e right. Dropping two decimals does not have any significant effect. Also, after I did that I noticed that if I tweak the values ±0.1 there are some patterns that allow the array to be constructed in less chars. \$\endgroup\$ Jul 22, 2012 at 11:40
  • \$\begingroup\$ Could you do %w(Y M C A)*15 instead of 'Y M C A'.split*15 to generate the letters? Also that each could probably be a map even though you don't need the output. Oh, and you can write 10.0 as 1e1! \$\endgroup\$ Jul 22, 2012 at 22:42
  • \$\begingroup\$ @chron Thanks! I thought there was nothing much I could do to golf this code even more, but I was obviously wrong. :-) \$\endgroup\$ Jul 23, 2012 at 6:43
3
\$\begingroup\$

C, 161 154 chars

#define P(d,x)w(d);puts(#x);
w(n){usleep(n<<16);}
y(d){P(d,Y)P(14,M)P(7,C)P(3,A)}
b(){y(664);y(35);y(147);y(35);}
main(){b(b(b(w(34))));y(148);y(33);y(148);}

The tester passes, but only if fflush(stdout); is added after each puts. Since the question clearly states that fflush is not required, I take it as a problem in the tester.

Logic:
w sleeps, the time is given in units of 16.384 65.536 ms. This resolution allows accurate enough timing and small constants (I should perhaps try 100ms).
P waits a while and prints a character.
y prints a YMCA sequence, after an initial delay.
b prints 4 YMCA sequences - this 4*YMCA happens 3 times, with similar enough timing.
main prints the 3*4*YMCA sequences, plus the remaining 3.

\$\endgroup\$
2
  • \$\begingroup\$ "a problem in the tester" - You're right, as apparently pipes are not "interactive" devices :( I will make it use a PTY (which should be more realistic) instead of a pipe as soon as I get the time to. \$\endgroup\$ Jul 23, 2012 at 17:53
  • \$\begingroup\$ OK, I changed the tester to use a PTY, and your program passes the test. I also found out about a utility called stdbuf that uses some LD_PRELOAD trick to override the default buffering behavior of the C standard I/O library. \$\endgroup\$ Jul 26, 2012 at 21:00
0
\$\begingroup\$

Python2.6 (82)(214)(219)(196)(185)(152)

Fixed. Ran against the video & seems accurate. Saved quiet a few characters by reducing the precision from 3 to 2 in most of the cases(thanks for the tip @JPvdMerwe).

The only problem is that the tester shows a huge discrepancy in the timings. It starts out of sync & tries to come back into sync. In the two test cases it was more than 175 seconds out of sync at the beginning and came back to within 0.342 and 0.451 seconds of being back in sync.

import time;s=time.sleep
for t in[45.8,2.1,9.5,2,43.4,2,9.5,2.1,43.4,2,9.6,2,9.5,2,9.6]*15:
 i=0;s(t)
 while i<4:s([.1,.9,.5,.2][i]);print'YMCA'[i];i+=1
\$\endgroup\$
13
  • \$\begingroup\$ Can you make it run at each of the fifteen times listed above? It also seems that on my machine, you will need to include the -u command line option in the count. \$\endgroup\$ Jul 21, 2012 at 15:22
  • \$\begingroup\$ @PleaseStand done, now it runs 15 times. I don't know about adding -u, don't need it on mine. I have Python2.6, if that helps \$\endgroup\$
    – elssar
    Jul 21, 2012 at 15:42
  • \$\begingroup\$ To clarify, your program should print the first "Y" after approximately 45.766 s, and -u is necessary for the tester program (which uses a pipe), not for output directly to a terminal. \$\endgroup\$ Jul 21, 2012 at 15:50
  • \$\begingroup\$ @PleaseStand Yeah, I was wondering about the timing. Was gonna ask you, but you already answered before I had a chance. And about the tester program, is it a requirement that the program runs on your tester as it is, or will you accept submissions that need to be modified to run on the tester, but run fine standalone? \$\endgroup\$
    – elssar
    Jul 21, 2012 at 16:27
  • \$\begingroup\$ Humm, I can pass my code to the tester without having to use any options \$\endgroup\$
    – elssar
    Jul 21, 2012 at 16:55
0
\$\begingroup\$

Mathematica, 157

p=Print[Pause@#;#2]&

(#~p~"Y";.93~p~"M";.465~p~"C";.233~p~"A")&/@{45.766,2.217,9.65,2.144,43.527,2.147,9.591,2.249,43.515,2.162,9.702,2.146,9.661,2.098,9.69}

I watched the entire video to confirm the timing. Y M C A.... Y M C A...

It could be shorter with less precision, but then I'd have to watch the video again to confirm that it was not off by more than .125 at the end. lol

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

JavaScript (Node.js), 206 bytes

s=async t=>await new Promise(r=>setTimeout(r,t*1e3));(async _=>{for(t of[45.8,2.1,9.5,2,43.4,2,9.5,2.1,43.4,2,9.6,2,9.5,2,9.6])for(i=0,await s(t);i<4;)await s([.1,.9,.5,.2][i])||console.log('YMCA'[i++])})()

Try it online!

i tried out the tester program and it was within about half a second for each cue but not 0.125. i think the startup time just needs to be factored in and some of the deltas may need to be adjusted to account for accumulated rounding errors.

i'm curious if there may be a shorter solution without using >ES5 await, and a shorter way to print to STDOUT.

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