18
\$\begingroup\$

Create a function in your chosen language that prints out the following:

Old MacDonald had a farm, E-I-E-I-O,
And on that farm he had a cow, E-I-E-I-O,
With a moo moo here and a moo moo there,
Here a moo, there a moo, everywhere a moo moo,
Old MacDonald had a farm, E-I-E-I-O!

Where cow and moo are strings in the function parameters, and as such, can be changed to pig and oink or sheep and baa, for example.

It should take into account capital letters, hyphens, punctuation, spaces and line breaks.

Aim to type the fewest amount of Unicode characters in your code.

\$\endgroup\$
11
  • 1
    \$\begingroup\$ Shouldn't this be kolmogorov-complexity though? \$\endgroup\$
    – mniip
    May 5, 2014 at 9:28
  • 6
    \$\begingroup\$ You say echoes the following. Do you mean the function should print it out or return it? \$\endgroup\$
    – cjfaure
    May 5, 2014 at 9:31
  • 2
    \$\begingroup\$ To make this fair, I think this should have the exact punctuation, spaces and carriage returns in the question. But what do you think about uppercase / lowercase? I thought a single case might be easier and avoid a load of standard applications of base64 or similar. On balance, the only capitals are at the beginning of the line, the word MacDonald and in the E-I-E-I-O, so it may be more interesting to make that exactly per the question too. \$\endgroup\$ May 5, 2014 at 9:45
  • 4
    \$\begingroup\$ Is it acceptable to output a oink or should that be made to be an oink? \$\endgroup\$
    – ClickRick
    May 5, 2014 at 16:06
  • 4
    \$\begingroup\$ @rybo111: Were you aware that the great Donald Knuth wrote an academic paper about this kind of thing? It was actually published in a real journal (admittedly in the April edition). More here including a link to the PDF of the paper: en.wikipedia.org/wiki/The_Complexity_of_Songs \$\endgroup\$ May 6, 2014 at 16:11

24 Answers 24

16
\$\begingroup\$

Javascript ES6 - 204

Aim to type the fewest amount of Unicode characters in your code.

Not the shorter but probably the most obfuscated.

f=(a,b)=>{for(c=[b,a].concat('!,-ADEHIMOWacdefhilmnortvwy \n'.split(o='')),i=62;i;o+=c[e>>10]+c[e/32&31]+c[e&31])e='ⱞᄤ⒇瓤抣瘭㾭癍㚏᫶⦮函࿋Π疽䌐獲樘ྰ㞠戝晐}疽䌐࿈䌐眲Π疽㛏戝癐Π疽伲࿌⒋ფᲉѽ疽䦯䨝抽瘭䦹容㾷碶ᅣᲉᄤྦྷ㜕㞱㗽㾲妴㣗畍⺏'.charCodeAt(--i);alert(o)}

If your browser do not support ES6 :

function f(a,b){for(c=[b,a].concat('!,-ADEHIMOWacdefhilmnortvwy \n'.split(o='')),i=62;i;o+=c[e>>10]+c[e/32&31]+c[e&31])e='ⱞᄤ⒇瓤抣瘭㾭癍㚏᫶⦮函࿋Π疽䌐獲樘ྰ㞠戝晐}疽䌐࿈䌐眲Π疽㛏戝癐Π疽伲࿌⒋ფᲉѽ疽䦯䨝抽瘭䦹容㾷碶ᅣᲉᄤྦྷ㜕㞱㗽㾲妴㣗畍⺏'.charCodeAt(--i);alert(o)}

Copy/Paste that code into your browser console and try f('cow','moo'), f('pig','oink'), f('sheep','baa')

How it works ?

c is an array of 29 letters plus the animal and its sound (let call this our alphabet).
So, all the 31 characters fit in 5 bits (2^5 = 32).
A Unicode character is 16 bits long, so it can encode 3 characters of our alphabet with a padding bit.
The full text with the new lines is 186 characters of our alphabet, it can be encoded with 62 Unicode characters.

For example, Old is encoded like this :

alphabet value         O      l      d
alphabet index         11     20     15
unicode           0  01011  10100  01111  ===> \u2e8f (⺏)

If you have troubles to read some Unicode chars, install Code2000 font

\$\endgroup\$
6
  • 2
    \$\begingroup\$ "cow" and "moo" are supposed to be the function parameters. By getting the caller to pass an array, you're saving characters within the function definition at the expense of adding to the character count of the calling code. This smells like a cheat to me. Taking that approach to the extreme you could define function f(a){alert(a)} (23 characters) and say that it needs to be called like f("Old MacDonald had a ..."). \$\endgroup\$
    – tobyink
    May 6, 2014 at 11:36
  • 1
    \$\begingroup\$ I had passed the strings in two separated parameters but after reading the challenge, I saw no reason to not pass the strings in array format, so I edited my answer. This is not cheating, just saving few chars when it's possible. Let @rybo111 decide if this fits the rule or not. \$\endgroup\$
    – Michael M.
    May 6, 2014 at 11:50
  • 1
    \$\begingroup\$ @tobyink I did use the term 'string' (not array) in the rules, so I suppose you are right. I think 'cheating' is a bit harsh, though! \$\endgroup\$
    – rybo111
    May 6, 2014 at 14:04
  • 2
    \$\begingroup\$ Why does this have so many votes? It's over 200 and not even the shortest javascript solution. \$\endgroup\$ May 6, 2014 at 15:56
  • \$\begingroup\$ Whell thougth and well explained so have my vote too \$\endgroup\$
    – edc65
    Oct 25, 2014 at 13:33
6
\$\begingroup\$

CJam - 142 / GolfScript - 144

{" had| a |farm|68, |68 8|here|Old MacDonald765|, E-I-E-I-O|10,
And on that 5 he7690,
With3 2 and3 t2,
Here4t24everyw23,
10!"'|/~A,{`/\*}/}:F;

Usage: "cow""moo"F
For GolfScript replace '| with "|" and A with 10

Explanation:

The key part is A,{`/\*}/:
A,{...}/ executes the block for each number from 0 to 9 (A=10)
` converts the number to string
/\* does a string replace: if we have on the stack "bar" "foo 1 baz" "1" then / splits the string resulting in ["foo " " baz"], \ swaps this array with the previous item ("bar") and * joins the array resulting in "foo bar baz"

So the code replaces each number in the main string with a string that's previously on the stack. We have the animal and the sound, then " had", " a ", etc and finally ", E-I-E-I-O" and the main string, "10,...!". To avoid using too many quotes, I put all the strings (except the parameters) in one string, then split it and dumped the resulting array ('|/~)

The main string goes through the following transformations:

10,
And on that 5 he7690,
With3 2 and3 t2,
Here4t24everyw23,
10!

replace "0" with ", E-I-E-I-O":

1, E-I-E-I-O,
And on that 5 he769, E-I-E-I-O,
With3 2 and3 t2,
Here4t24everyw23,
1, E-I-E-I-O!

replace "1" with "Old MacDonald765":

Old MacDonald765, E-I-E-I-O,
And on that 5 he769, E-I-E-I-O,
With3 2 and3 t2,
Here4t24everyw23,
Old MacDonald765, E-I-E-I-O!

replace "2" with "here", then "3" with "68 8" etc.

8 corresponds to the sound, and 9 to the animal.

\$\endgroup\$
6
  • \$\begingroup\$ Can you explain this? I don't even know what CJam is \$\endgroup\$
    – Cruncher
    May 5, 2014 at 14:16
  • \$\begingroup\$ @Cruncher CJam is a language I made, sf.net/p/cjam ; I can explain it once I finish golfing it :) \$\endgroup\$ May 5, 2014 at 14:17
  • 1
    \$\begingroup\$ @Cruncher added explanation now \$\endgroup\$ May 5, 2014 at 15:02
  • 9
    \$\begingroup\$ ♬ and on that five he sev'n six nine, ze e e e ro ♬ \$\endgroup\$ May 5, 2014 at 17:26
  • \$\begingroup\$ Can E-I- be a string which is then repeated? :) \$\endgroup\$
    – rybo111
    May 7, 2014 at 20:13
6
\$\begingroup\$

Bash + iconv, 128 Unicode characters

Takes the below pure-bash/ascii function body and reverse-encodes into unicode chars:

m()(c=`iconv -t unicode<<<㵳⁜屡␠ਲ㵨敨敲攊ⰽ⁜ⵅⵉⵅⵉ੏㵯伢摬䴠捡潄慮摬栠摡愠映牡⑭≥攊档␢Ɐ䄊摮漠桴瑡映牡敨栠摡愠␠␱ⱥ圊瑩⑨⁳㈤␠⁨湡⑤⁳㈤琠栤ਬ效敲猤‬⑴⑨ⱳ攠敶祲⑷⑨⁳㈤ਬ漤™ਠ`
eval "${c:2}")

Defines a shell function m. Call as:

$ m pony neigh
Old MacDonald had a farm, E-I-E-I-O,
And on that farm he had a pony, E-I-E-I-O,
With a neigh neigh here and a neigh neigh there,
Here a neigh, there a neigh, everywhere a neigh neigh,
Old MacDonald had a farm, E-I-E-I-O!
$ 

Pure bash, 171 bytes (ascii-only)

I think its worth noting that the original verse (with "cow" and "moo") is only 203 chars.

m()(s=\ a\ $2
h=here
e=,\ E-I-E-I-O
o="Old MacDonald had a farm$e"
echo "$o,
And on that farm he had a $1$e,
With$s $2 $h and$s $2 t$h,
Here$s, t$h$s, everyw$h$s $2,
$o"!)

Defines the shell function m. Call as:

$ m sheep baa
Old MacDonald had a farm, E-I-E-I-O,
And on that farm he had a sheep, E-I-E-I-O,
With a baa baa here and a baa baa there,
Here a baa, there a baa, everywhere a baa baa,
Old MacDonald had a farm, E-I-E-I-O!
$
\$\endgroup\$
5
\$\begingroup\$

C++ (403)

Alright, this is a bit of a long shot, but who doesn't like over-defining?

#define O ", E-I-E-I-O"
#define E O<<","
#define I "Old MacDonald had a farm"
#define H(a) "And on that farm he had a "<<a<<E
#define D(s) s<<" "<<s
#define W(s) "With a "<<D(s)<<" here and a "<<D(s)<<" there,"
#define V(s) "Here a "<<s<<", there a "<<s<<", everywhere a "<<D(s)<<","
#define F I<<O<<"!"
#define N endl
void m(string a, string s){cout<<I<<E<<N<<H(a)<<N<<W(s)<<N<<V(s)<<N<<F<<N;}
\$\endgroup\$
4
  • 2
    \$\begingroup\$ this.eyes.bleeding = true; \$\endgroup\$
    – Proxy
    May 5, 2014 at 23:53
  • \$\begingroup\$ Any defines that could further pack this tighter? \$\endgroup\$ May 6, 2014 at 6:06
  • 1
    \$\begingroup\$ It used to be possible to #define X define and then use #X Y Z. Sadly, those heady IOCCC days are now long past... \$\endgroup\$
    – nneonneo
    May 6, 2014 at 23:49
  • \$\begingroup\$ What about using + instead of <<? Or using char* instead of string? // Only one of these can be used at the same time. \$\endgroup\$
    – Qwertiy
    Oct 25, 2014 at 12:31
3
\$\begingroup\$

Python, 116 Unicode chars

def f(**a):print u'鱸쿳光䷰癌쿉ы㊲匒ሔ툕謒畲尔㵵䅵忘쮇⼱ⅅ伿⒡넣Ⰴ邩ઑ꩕醪徜妮ꊌ㰺⒳Ⰳ鮕꾟ౙ㎧譒ᕒ끒镈롴쀼怪㪢愐腤닔ꋔ狊兔Ⲹ㾗꽡Ȩ똀䝸å'.encode('u16')[2:].decode('zip')%a

StackOverflow is eating my special characters, though, so here's the file in base64:

77u/ZGVmIGYoKiphKTpwcmludCB1J+mxuOy/s+WFieS3sOeZjOy/idGL44qy5YyS4YiU7YiV6KyS55Wy5bCU47W15IW15b+Y7K6H4ryx4oWF5Ly/4pKh64Sj4rCE6YKp4KqR6qmV6Yaq5b6c5aau6oqM47C64pKz4rCD6a6V6r6f4LGZ446n6K2S4ZWS74yS64GS6ZWI7pKA66G07IC85oCq46qi5oSQ6IWk64uU6ouU54uK5YWU4rK4476X6r2hyKjrmIDknbjDpScuZW5jb2RlKCd1MTYnKVsyOl0uZGVjb2RlKCd6aXAnKSVh

The data is packed using zlib, which efficiently codes repeated strings (zlib is good at compressing text in general). To take advantage of the "Unicode characters" rule, the 121-byte zlib chunk is padded and halved to a 61-character Unicode string by interpreting the bytestring as UTF-16.

Call the function as

f(cow='pig', moo='oink')
\$\endgroup\$
5
  • \$\begingroup\$ Nice, but Where cow and moo are strings in the function parameters, and as such, can be changed to pig and oink or sheep and baa, for example. Looks like your output is hardcoded to cow/moo. \$\endgroup\$ May 7, 2014 at 0:05
  • \$\begingroup\$ @DigitalTrauma: My reading comprehension fail! Fixed. \$\endgroup\$
    – nneonneo
    May 7, 2014 at 0:15
  • \$\begingroup\$ thats better :) +1 \$\endgroup\$ May 7, 2014 at 0:23
  • \$\begingroup\$ 115. No need to count the trailing newline. \$\endgroup\$ Oct 27, 2014 at 21:48
  • \$\begingroup\$ @nyuszika7h No, it’s 116. You forgot to count the “UTF-8 BOM” (EF BB BF) at the beginning, which is necessary to let Python 2 accept non-ASCII source. (This isn’t Python 3, which doesn’t have .decode('zip').) \$\endgroup\$ Apr 30, 2016 at 22:02
2
\$\begingroup\$

Python, 217

You can't really golf this much. I just took out the blatant front-end repetition and...

m,f="Old MacDonald had a farm, E-I-E-I-O",lambda x,y:m+",\nAnd on that farm he had a %s, E-I-E-I-O,\nWith a %shere and a %sthere,\nHere a %s, there a %s, everywhere a %s %s,\n%s!"%((x,)+((y+' ')*2,)*2+(y,)*4+(m,))

Javascript, 241 - JSCrush cheat

Made this with JSCrush...not really a real answer, it'd just be interesting to see if anybody can beat this in a mainstream language. (EDIT: uh)

_='var f=function(c,a){var b=a "+a;return"Anon that he hadcWith  and tHere  t   everyw!"};OlMacDonalhaa a "+, O,\\nhere+"b farm a, d E-I-';for(Y in $=' ')with(_.split($[Y]))_=join(pop());eval(_)
\$\endgroup\$
2
\$\begingroup\$

Java, 246

void f(String[] a){String o="Old MacDonald had a farm",e=", E-I-E-I-O",x=" a "+a[1],s=x+" "+a[1];System.out.print(o+e+",\nAnd on that farm he had a "+a[0]+e+",\nWith"+s+" here and"+s+" there,\nHere"+x+", there"+x+", everywhere"+s+",\n"+o+e+"!");}

Usage: f(new String[]{"cow","moo"});

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

Java - 262 258

void m(String...s){String b=s[1],c=b+" "+b,d="E-I-E-I-O",e="Old MacDonald had a farm, "+d;System.out.print(e+",\n"+"And on that farm he had a "+s[0]+", "+d+",\nWith a "+c+" here and a "+c+" there,\nHere a "+b+", there a "+b+", everywhere a "+c+",\n"+e+"!");}

Further optimization is definitely possible.

\$\endgroup\$
2
  • \$\begingroup\$ You could use printf \$\endgroup\$ May 5, 2014 at 13:51
  • \$\begingroup\$ Trevin Avery suggested this edit: Java - 243 - void String...a){String c=" a "+a[1],d=c+" "+a[1],e=", E-I-E-I-O",f="Old MacDonald had a farm"+e;System.out.print(f+",\nAnd on that farm he had a "+a[0]+e+",\nWith"+d+" here and"+d+" there,\nHere"+c+", there"+c+"', everywhere"+d+",\n"+f+"!");} Further optimization is definitely possible \$\endgroup\$
    – Justin
    May 5, 2014 at 15:28
2
\$\begingroup\$

Perl 5 (UTF-8) - 131 characters, 313 bytes

The script below needs to be saved as UTF-8 with no BOM.

use utf8;use Encode;eval encode ucs2,'獵戠晻③㴤∮灯瀻⑥㴢Ⱐ䔭䤭䔭䤭伢㬤漽≏汤⁍慣䑯湡汤⁨慤⁡⁦慲洤攢㬤ⰽ≥牥⁡∻獡礢⑯Ⰺ䅮搠潮⁴桡琠晡牭⁨攠桡搠愠䁟⑥Ⰺ坩瑨⁡③③⁨␬湤⁡③③⁴桥牥Ⰺ䠤Ⱔ戬⁴栤Ⱔ戬⁥癥特睨␬③③Ⰺ⑯™紱';

Usage: f("cow", "moo");.

Perl needs to have been run with the -M5.010 flag to enable Perl 5.10 features. (This is allowed.)

I quite like the symmetry of the character count (131) and byte count (313). It's very yin and yang.

Perl 5 (ASCII) - 181 characters, 181 bytes

sub f{$b=$".pop;$e=", E-I-E-I-O";$o="Old MacDonald had a farm$e";$,="ere a";say"$o,
And on that farm he had a @_$e,
With a$b$b h$,nd a$b$b there,
H$,$b, th$,$b, everywh$,$b$b,
$o!"}

Usage: f("cow", "moo");.

Again, perl needs to have been run with the -M5.010 flag to enable Perl 5.10 features.

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

CJam (non-ASCII) - 77 chars

"啝裢樃濿䶹讄團챤鋚䖧雿ꆪꆵ䷶텸紎腕Խꍰ搓᩟童䚯⤭刧损⬛豳Ẍ퍾퓱郦퉰怈䡞௳閶蚇⡾쇛蕟猲禼࿆艹蹚㞿䛴麅鞑椢⧨餎쏡첦휽嬴힡ݷ녣㯂鐸㭕"56e3b127b:c~

Usage: "cow""moo"F

The string is my other CJam solution converted from base 127 to base 56000.
A UTF-8 locale might be required.

By the way, now you can try this online at http://cjam.aditsu.net/

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

JavaScript: 152 chars / ES6: 149 chars

Here's a JS function called "z" that does the job in 214 chars. (don't execute it!)

function z(a,b){c=' a '+b;d=c+' '+b;e=', E-I-E-I-O';f='Old MacDonald had a farm'+e;return(f+',\nAnd on that farm he had a '+a+e+',\nWith'+d+' here and'+d+' there,\nHere'+c+', there'+c+', everywhere'+d+',\n'+f+'!')}

I "packed" it in unicode chars using a technique created by @subzey and I for 140byt.es).

eval(unescape(escape('𩡵𫡣𭁩𫱮𘁺𚁡𛁢𚑻𨰽𙰠𨐠𙰫𨠻𩀽𨰫𙰠𙰫𨠻𩐽𙰬𘁅𛑉𛑅𛑉𛑏𙰻𩠽𙱏𫁤𘁍𨑣𡁯𫡡𫁤𘁨𨑤𘁡𘁦𨑲𫐧𚱥𞱲𩑴𭑲𫠨𩠫𙰬𧁮𠑮𩀠𫱮𘁴𪁡𭀠𩡡𬡭𘁨𩐠𪁡𩀠𨐠𙰫𨐫𩐫𙰬𧁮𥱩𭁨𙰫𩀫𙰠𪁥𬡥𘁡𫡤𙰫𩀫𙰠𭁨𩑲𩐬𧁮𢁥𬡥𙰫𨰫𙰬𘁴𪁥𬡥𙰫𨰫𙰬𘁥𭡥𬡹𭱨𩑲𩐧𚱤𚰧𛁜𫠧𚱦𚰧𘐧𚑽').replace(/uD./g,'')))

execute that last snippet, then call z("cow","moo"), and you'll get this string:

Old MacDonald had a farm, E-I-E-I-O,
And on that farm he had a cow, E-I-E-I-O
With a moo moo here and a moo moo there,
Here a moo, there a moo, everywhere a moo moo,
Old MacDonald had a farm, E-I-E-I-O!"

More info here: http://xem.github.io/golfing/en.html#compress

ES6 version:

eval(unescape(escape('𮠽𚁡𛁢𚐽🡻𨰽𙰠𨐠𙰫𨠻𩀽𨰫𙰠𙰫𨠻𩐽𙰬𘁅𛑉𛑅𛑉𛑏𙰻𩠽𙱏𫁤𘁍𨑣𡁯𫡡𫁤𘁨𨑤𘁡𘁦𨑲𫐧𚱥𞱲𩑴𭑲𫠨𩠫𙰬𧁮𠑮𩀠𫱮𘁴𪁡𭀠𩡡𬡭𘁨𩐠𪁡𩀠𨐠𙰫𨐫𩐫𙰬𧁮𥱩𭁨𙰫𩀫𙰠𪁥𬡥𘁡𫡤𙰫𩀫𙰠𭁨𩑲𩐬𧁮𢁥𬡥𙰫𨰫𙰬𘁴𪁥𬡥𙰫𨰫𙰬𘁥𭡥𬡹𭱨𩑲𩐧𚱤𚰧𛁜𫠧𚱦𚰧𘐧𚑽').replace(/uD./g,'')))
\$\endgroup\$
3
  • \$\begingroup\$ I think you didn't copy-paste things correctly, your code seems to have over 250 chars -- oops, maybe not, but my text editor is behaving strangely, I'll investigate. \$\endgroup\$ May 6, 2014 at 16:52
  • \$\begingroup\$ Oh, most of your characters are from some astral planes (that's probably why they get counted as 2 characters here)... and unallocated too. This is stretching the rules a bit :) \$\endgroup\$ May 6, 2014 at 16:59
  • \$\begingroup\$ Well, I don't think this is cheating: those symbols are unicode chars, and shouldn't count as 2 chars. Also, Twitter counts each of them as 1 char. If you copy the ES6 version in a tweet, it says it's too long by 9 chars. So, 149 it is :) \$\endgroup\$
    – xem
    May 6, 2014 at 17:31
2
\$\begingroup\$

C# - 339 Bytes

void x(string c, string d){var a="Old MacDonald had a farm";var b=", E-I-E-I-O";var f=" a ";var g=" there";Debug.WriteLine(a+b+",");Debug.WriteLine("And on that farm he had"+f+c+b+",");Debug.WriteLine("With"+f+d+" "+d+" here and"+f+d+" "+d+g+",");Debug.WriteLine("Here"+f+d+","+g+f+d+", everywhere"+f+d+" "+d+",");Debug.WriteLine(a+b+"!");

Usage: x("cow","moo");

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

Rebol, 206 202

f: func[a b][print reword{$o$e,
And on that farm he had a $a$e,
With a $b $b here and a $b $b there,
Here a $b, there a $b, everywhere a $b $b,
$o$e!}[e", E-I-E-I-O"o"Old MacDonald had a farm"a a b b]]

Usage: f "cow" "moo"

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

Delphi XE3 (272 252)

procedure k(a,s:string);const o='Old MacDonald had a farm';e=', E-I-E-I-O';n=','#13#10;begin s:=' '+s;write(o+e+n+'And on that farm he had a '+a+e+n+'With a'+s+s+' here and a'+s+s+' there'+n+'Here a'+s+', there a'+s+' every where a'+s+s+n+o+e+'!');end;

Ungolfed

procedure k(a,s:string);
const
  o='Old MacDonald had a farm';
  e=', E-I-E-I-O';
  n=','#13#10;
begin
  s:=' '+s;
  write(o+e+n+'And on that farm he had a '+a+e+n+'With a'+s+s+' here and a'+s+s+' there'+n+'Here a'+s+', there a'+s+' every where a'+s+s+n+o+e+'!');
end;
\$\endgroup\$
1
\$\begingroup\$

Lua 237

function f(a,b)c=b.." "..b;d="Old MacDonald had a farm, E-I-E-I-O"print(d..",\nAnd on that farm he had a "..a..", E-I-E-I-O,\nWith a "..c.." here and a "..c.." there,\nHere a "..b..", there a "..b..", everywhere a "..c..",\n"..d.."!")end

By defining c=b.." "..b, I can save a dozen characters. By defining d as I do, I save 23 characters. I do not see how I can shorten this anymore. This is called via f("<animal>","<sound>").

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

Java 8(411)

String m(String...m){LinkedHashMap<String,String>n=new LinkedHashMap<>();n.put("/","( * #, -");n.put("#","farm");n.put("-","E-I-E-I-O");n.put("+","here");n.put("*","had a");n.put("(","Old MacDonald");n.put("|"," a )");n.put(")","moo");n.put("moo",m[1]);n.put("cow",m[0]);m[0]="/,\nAnd on that # he * cow, -,\nWith|) + and|) t+,\nHere|, t+|, everyw+|),\n/!";n.forEach((k,v)->m[0]=m[0].replace(k,v));return m[0];}

Abusing of lambda, putted the replaces in a LinkedhashMap to keep em in a defined order then used a foreach lambda to replace key with value in main String. parameters are added as last 2 replacements in the map. that varargs argument is to shave off some bytes in the method header

Ungolfed version:

String m(String... m)
{
    LinkedHashMap<String, String> n = new LinkedHashMap<>();
    n.put("/", "( * #, -");
    n.put("#", "farm");
    n.put("-", "E-I-E-I-O");
    n.put("+", "here");
    n.put("*", "had a");
    n.put("(", "Old MacDonald");
    n.put("|", " a )");
    n.put(")", "moo");
    n.put("moo", m[1]);
    n.put("cow", m[0]);
    m[0] = "/,\nAnd on that # he * cow, -,\nWith|) + and|) t+,\nHere|, t+|, everyw+|),\n/!";
    n.forEach((k, v) -> m[0] = m[0].replace(k, v));
    return m[0];
}
\$\endgroup\$
1
\$\begingroup\$

JavaScript 220

function f(a,b){c=' a '+b;d=c+' '+b;e=', E-I-E-I-O';f='Old MacDonald had a farm'+e;console.log(f+',\nAnd on that farm he had a '+a+e+',\nWith'+d+' here and'+d+' there,\nHere'+c+', there'+c+', everywhere'+d+',\n'+f+'!');}

Called by

f('cow', 'moo');
\$\endgroup\$
1
\$\begingroup\$

Pure C, 298 bytes, no unicode

In my function I take a single argument, which is actually a bunch of char*'s packed together. Each string is null terminated, and there's an extra null terminator at the end. This allows me to check strlen(a) at the end of each loop, rather than keeping a counter variable.

mcdonald.c:

m(char*a){while(strlen(a)){printf("Old MacDonald had a farm, E-I-E-I-O\nAnd on that farm he had a %s, E-I-E-I-O,\nWith a ",a);a+=strlen(a)+1;printf("%s %s here and a %s %s there,\nHere a %s, there a %s, everywhere a %s %s,\nOld MacDonald had a farm, E-I-E-I-O!\n",a,a,a,a,a,a,a,a);a+=strlen(a)+1;}}

main.c:

int m(char *v);
int main(int argc, char **argv) {
    m("cow\0moo\0programmer\0meh\0\0");
    return 0;
}

Output:

clang main.c mcdonald.c && ./a.out
Old MacDonald had a farm, E-I-E-I-O
And on that farm he had a cow, E-I-E-I-O,
With a moo moo here and a moo moo there,
Here a moo, there a moo, everywhere a moo moo,
Old MacDonald had a farm, E-I-E-I-O!
Old MacDonald had a farm, E-I-E-I-O
And on that farm he had a programmer, E-I-E-I-O,
With a meh meh here and a meh meh there,
Here a meh, there a meh, everywhere a meh meh,
Old MacDonald had a farm, E-I-E-I-O!
\$\endgroup\$
1
1
\$\begingroup\$

Cobra - 203

def f(a,b)
    d=" a [b] "+b
    e=", E-I-E-I-O"
    m="Old MacDonald had a farm[e]"
    print "[m],\nAnd on that farm he had a [a][e],\nWith[d] here and[d] there,\nHere a [b], there a [b], everywhere[d],\n[m]!"

Even for a language with little-to-no multi-lining, and strict indentation rules, Cobra still does pretty well.

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

C: 224 bytes

By using the printf precision specifier, we can use the same string as both the printf format string and as two of the parameters.

o(char*x,char*y){char*f="Old MacDonald had a farm, E-I-E-I-O,\nAnd on that farm he had a %s%.13sWith a %s %s here and a %s %s there,\nHere a %s, there a %s, everywhere a %s %s,\n%.35s!\n";printf(f,x,f+24,y,y,y,y,y,y,y,y,f);}

With white space and the string split into lines:

o(char* x, char* y)
{
    char* f=
        "Old MacDonald had a farm, E-I-E-I-O,\n"
        "And on that farm he had a %s%.13s"
        "With a %s %s here and a %s %s there,\n"
        "Here a %s, there a %s, everywhere a %s %s,\n"
        "%.35s!\n";

    printf(f,x,f+24,y,y,y,y,y,y,y,y,f);
}
\$\endgroup\$
1
1
\$\begingroup\$

PHP - 272 characters, 272 bytes

function m($q,$w){for($e="@&And on that farm he had^<%&With *h# and*th#&H(th(everywh#^> >&@!",$r=1;;$e=$r){$r=str_replace(["@","#","^","%","<",">","&","*","("],["Old MacDonald had^farm%","ere"," a ",", E-I-E-I-O",$q,$w,",\n","^> > ","#^>, "],$e);if($e==$r)break;}echo $e;}

Usage: m("cow", "moo");, m("fox", "Hatee-hatee-hatee-ho");

Parameters with @#%^<>&*( crash the output.

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

Haskell (282 and still somewhat readable :))

wc -c oldmacdonald.hs
     282 oldmacdonald.hs

The file:

main=mapM putStrLn[s"cow""moo",s"pig""oink",s"sheep""baa"]
s c m=o#",\nAnd on that farm he had"#b c#e#let n=m#" "#m in",\nWith"#b n#" here and"#b n#" there,\nHere"#b m#", there"#b m#", everywhere"#b n#",\n"#o#"!\n"
o="Old MacDonald had a farm"#e
e=", E-I-E-I-O"
b=(" a "#)
(#)=(++)
\$\endgroup\$
1
  • \$\begingroup\$ It's 281, you don't usually count the trailing newline, unless it's a C preprocessor macro or something else that requires newline termination. In most cases, you can just subtract 1 from the byte count returned by wc -c, but I prefer using mothereff.in/byte-counter and making sure there's no empty line at the end unless required for the program to work. \$\endgroup\$ Oct 27, 2014 at 21:47
1
\$\begingroup\$

ES6, 2 solutions of 179 186 chars without any unicode

f=(a,b)=>alert("325And on that farm he had a025With a11 h4nd a11 th45H41, th41, everywh411532!".replace(/\d/g,x=>[" "+a," "+b,", E-I-E-I-O","Old MacDonald had a farm","ere a",",\n"][x]))

And the second:

f=(a,b)=>alert("3625And on7at6 he ha8025With a11 h4n811745H41,741, everywh4115362!".replace(/\d/g,x=>(` ${a}0 ${b}0, E-I-E-I-O0Old MacDonald had a0ere a0,\n0 farm0 th0d a`).split(0)[x]))

I've added alert call (+7 chars).

\$\endgroup\$
1
  • \$\begingroup\$ I think, it's the shortest solution from non-unicoded ones for now. \$\endgroup\$
    – Qwertiy
    Oct 25, 2014 at 13:25
1
\$\begingroup\$

JavaScript (E6) 140 chars

Char counter: https://mothereff.in/byte-counter, 140 chars, 425 bytes in UTF-8

eval(unescape(escape('𩠽𚁡𛁢𚐽🡡𫁥𬡴𚀧𜀱𜠵𠑮𩀠𫱮𘀶𨑴𜐳𩐳𨑤𝰠𞐲𝑗𪐶𘁡𞀸𜰴𝱮𩀠𨐸𞀠𝠴𝑈𝀷𞀬𘀶𝀷𞀬𘁥𭡥𬡹𭱨𝀷𞀸𝐰𜐲𘐧𛡲𩑰𫁡𨱥𚀯𧁤𛱧𛁣🐾𚀧𣱬𩀠𣑡𨱄𫱮𨑬𩀠𪁡𩀠𨐰𘁦𨑲𫐰𛀠𡐭𢐭𡐭𢐭𣰰𘁨𜁥𬡥𜀬𧁮𜁴𪀰𘁡𜀠𙰫𨠫𜀫𨐩𛡳𬁬𪑴𚀰𚑛𨱝𚐩𒠠').replace(/uD./g,'')))

Original ASCII code 188 bytes

f=(a,b)=>alert('0125And on 6at13e3ad7 925Wi6 a88347nd a88 645H478, 6478, everywh47885012!'.replace(/\d/g,c=>('Old MacDonald had a0 farm0, E-I-E-I-O0 h0ere0,\n0th0 a0 '+b+0+a).split(0)[c]))

Compressed with http://xem.github.io/obfuscatweet/

Test in FireFox/FireBug console

f('mosquito','zzz')

Output

Old MacDonald had a farm, E-I-E-I-O,
And on that farm he had a mosquito, E-I-E-I-O,
With a zzz zzz here and a zzz zzz there,
Here a zzz, there a zzz, everywhere a zzz zzz,
Old MacDonald had a farm, E-I-E-I-O!
\$\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.