Jump to content

  • Log In with Google      Sign In   
  • Create Account

99 Bottles Of Beer Challenge With Least Amount Of Characters ?

  • You cannot reply to this topic
97 replies to this topic

#41 swiftcoder   Senior Moderators   -  Reputation: 10446

Like
1Likes
Like

Posted 06 July 2013 - 06:46 PM


What? Wait... what? Can somebody translate that for me, because some things I didn't see yet in C# (or I saw but didn't have the need to use hence forgot it).

It's mostly some very clever applications of string formatting.

 

That said, Mike clearly knows way more fun facts about string formatting than I do :)


Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


Sponsor:

#42 Mike.Popoloski   Crossbones+   -  Reputation: 2931

Like
0Likes
Like

Posted 06 July 2013 - 06:56 PM

 


What? Wait... what? Can somebody translate that for me, because some things I didn't see yet in C# (or I saw but didn't have the need to use hence forgot it).

It's mostly some very clever applications of string formatting.

 

That said, Mike clearly knows way more fun facts about string formatting than I do smile.png

 

 

Oh, the things you learn by trawling through the MSDN documentation at random :)   So many bits of the BCL are completely unknown to most people.


Mike Popoloski | Journal | SlimDX

#43 Cornstalks   Crossbones+   -  Reputation: 6991

Like
5Likes
Like

Posted 06 July 2013 - 06:59 PM

Also, I see your 300+ C# entry and raise you 250 (even beats some of the other languages)  biggrin.png

string f="{0:#;;",e=".\n",o="s;s;''} of beer",w=" on the wall",n="o more} bottle",x=n+"{1:"+o;
for(int a=99;a>=0;)System.Console.WriteLine(f+'N'+x+w+", "+f+'n'+x+e+
"{1:Take one down and pass it around;Go to the store and buy some more}, {1:#;99;n"+n+"{2:"+o+w+e,a,a-1,--a-1);
It doesn't require the conditional operator either, which is nifty.

You can cut out a few characters so it becomes (the change is with a-1,--a-1):

string f="{0:#;;",e=".\n",o="s;s;''} of beer",w=" on the wall",n="o more} bottle",x=n+"{1:"+o;for(int a=99;a>=0;)System.Console.WriteLine(f+'N'+x+w+", "+f+'n'+x+e+"{1:Take one down and pass it around;Go to the store and buy some more}, {1:#;99;n"+n+"{2:"+o+w+e,a,--a,a-1);
248 characters! I made it one line because... well... I guess that's less whitespace, if you're going to count whitespace (it's 315 characters to get a compilable version, including whitespace, and 286 characters of non-whitespace).
 

What? Wait... what? Can somebody translate that for me, because some things I didn't see yet in C# (or I saw but didn't have the need to use hence forgot it).

It's some black magic I wasn't familiar with before, but here's what it expands to:
 
for (int a = 99; a >= 0;)
    System.Console.WriteLine("{0:#;;No more} bottle{1:s;s;''} of beer on the wall, {0:#;;no more} bottle{1:s;s;''} of beer.\n" +
			     "{1:Take one down and pass it around;Go to the store and buy some more}, {1:#;99;no more} bottle{2:s;s;''} of beer on the wall.\n", a, a - 1, --a - 1);
Here's what each formatting specifier means:
  • "{0:#;;No more}"
    • For argument 0 (a), print the number if it's non-zero, or "No more" if it's zero.
  • "{1:s;s;''}"
    • For argument 1 (a - 1), print "s" if it's positive or negative, or nothing ('') if it's zero. 
  • "{0:#;;no more}"
    • For argument 0 (a), print the number if it's non-zero, or "no more" if it's zero.
  • "{1:Take one down and pass it around;Go to the store and buy some more}"
    • For argument 1 (a - 1), print "Take one down and pass it around" if it's zero or greater, otherwise print "Go to the store and buy some more" if it's negative.
  • "{1:#;99;no more}"
    • For argument 1 (a - 1), print the number if it's positive, 99 if it's negative, and "no more" if it's zero.
  • "{2:s;s;''}"
    • For argument 2 (--a - 1), print "s" if it's positive or negative, or nothing ('') if it's zero.
See Custom Numeric Format Strings, especially the part that talks about semicolons "Section Separator" (which says it basically acts kinda like a ternary operator).
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#44 Aurioch   Crossbones+   -  Reputation: 1304

Like
0Likes
Like

Posted 06 July 2013 - 07:27 PM

Thanks for thorough explanation. I'm still stunned at that "black magic", and I believe I won't ever have to use that kind of formatting XD



#45 SiCrane   Moderators   -  Reputation: 9676

Like
0Likes
Like

Posted 06 July 2013 - 07:38 PM

It's actually pretty common in business applications. Sometimes people want negatives done with parenthesis around them, or instead of displaying a 0, a single dash. For rich text formatting it's also common to also specify color as part of these, so you can have something like negatives also be red. 



#46 jperalta   Members   -  Reputation: 356

Like
2Likes
Like

Posted 06 July 2013 - 08:24 PM

n=:<'no more'
a=:(n,~<1)0}(>:(;"0)+)i.99
b=:<'bottles of beer'
o=:<'on the wall'
t=:<'take one down, pass it around'
c=:(99#b),"0~{."1 a
(|.c,"1 o,"1 c,"1 t,"1(}."1 a),"1 b,o),o,~b,~n,b,o,n,b,'go to the store and buy some more';99
 
201 non-whitespace, 230 whitespace characters in J. I could probably get it shorter but I've already forgotten how it works.


#47 dmatter   Crossbones+   -  Reputation: 3300

Like
2Likes
Like

Posted 07 July 2013 - 05:57 AM

I've got a Python3 solution of 160 non-whitespace characters or 162 if you count whitespace:

 

import urllib.request,re
print(re.sub('<br/?> ?','\n',re.sub('</p>\n?<p>','\n\n',urllib.request.urlopen('http://goo.gl/PEeK').read().decode('utf-8')[3592:-1028])))

 

Requires an internet connection wink.png



#48 rip-off   Moderators   -  Reputation: 8764

Like
4Likes
Like

Posted 07 July 2013 - 06:14 AM

This was my best attempt, without looking at any of the others: 232/261* characters in Ruby
 
def b(i,c)"#{i==0? "#{c==1? ?N:?n}o more":i} bottle#{i==1?'':?s} of beer"end
def w(i,c)b(i,c)+" on the wall"end
99.downto(0){|i|puts "#{w(i,1)}, #{b(i,0)}.\n#{i>0? "Take one down and pass it around, #{w(i-1,0)}":"Go to the store and buy some more, #{w(99,0)}"}."}
It might be a mild case of delirium, but I think I can still almost read it!

[edit: * 261 total characters, the "non whitespace" site tells me 232]

Edited by rip-off, 07 July 2013 - 06:21 AM.


#49 rip-off   Moderators   -  Reputation: 8764

Like
5Likes
Like

Posted 07 July 2013 - 07:00 AM

Having looked up some more uncommon Ruby syntax, I can reduce that to:

def b i,c;"#{i==0?"#{c==1??N:?n}o more":i} bottle#{?s if i!=1} of beer"end
def w i,c=0;b(i,c)+" on the wall"end
99.downto(0){|i|puts"#{w i,1}, #{b i,0}.\n#{i>0? "Take one down and pass it around, #{w i-1}":"Go to the store and buy some more, #{w 99}"}."}

This is 252 total, 218 non whitespace.



#50 Code Fox   Members   -  Reputation: 1811

Like
0Likes
Like

Posted 07 July 2013 - 08:12 AM

You blew my 250 non white space code right out of the water ( Ruby ) !!

Right now I am seeing if I can abuse Python 2.7 into submission, but I see it's going to be tough to get under 218


Does Anyone Actually Read This ?
 


#51 swiftcoder   Senior Moderators   -  Reputation: 10446

Like
1Likes
Like

Posted 07 July 2013 - 08:57 AM


Right now I am seeing if I can abuse Python 2.7 into submission, but I see it's going to be tough to get under 218

I finally brought my Python down to 250, but I'm running into entropy limits here - the majority of my overhead is in language keywords.

 

I'm probably going to have to go to a regexp to drop this any further... 

 

Edit: down to 243, by dint of tuple-as-conditional tricks.


Edited by swiftcoder, 07 July 2013 - 09:10 AM.

Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#52 Code Fox   Members   -  Reputation: 1811

Like
0Likes
Like

Posted 07 July 2013 - 09:23 AM

Wow - I'm only down to 284 with Python ... I need to learn more "magic" tricks. Ruby I am down to 243.

i = 99
m = ", "
n = "."
r = " of beer"
a = " on the wall"
b = " bottles" + r
c = b + a
d = b + n
e = "\n"
f = c + m
g = c + n
h = "Take one down and pass it around, "
o ="1 bottle" + r
k = ""
j = ""
p = "o more"
q = "n" + p
while i != 2:
    j = str(i)
    k = str(i-1)
    print  j + f + j + d + e + h + k + g
    i -=1
print k + f + k + d + e + h + o + n + e + o + a + m + o + n + e + h + q + g + e + "N" + p + f + q + d + e + "Go to the store and buy some more, 99" + g








Edited by Shippou, 07 July 2013 - 09:32 AM.

Does Anyone Actually Read This ?
 


#53 dmatter   Crossbones+   -  Reputation: 3300

Like
2Likes
Like

Posted 07 July 2013 - 10:05 AM

Thought I would have another go, this time without any cheating. I have a Python3 solution down to 222 non-whitespace characters. If it were Python2 I could shave off another char since print wouldn't require brackets.

 

B = lambda i,n='n': ', %s bottle%s of beer' % ((n+'o more',i%100)[i!=0], ('s','')[i==1])
n = '.\n'
w = ' on the wall'
for i in range(99,-1,-1):
    print(B(i,'N')[2:]+w+B(i)+n+('Go to the store and buy some more', 'Take one down and pass it around')[i > 0]+B(i-1)+w+n)

 

Edit: Looks like Swiftcoder and I are converging towards the same solution.

 

Edit2: I'm tempted to think that a clever use of a list comprehension or a forward-counting range (a descending range is quite verbose in Python) could shorten it even more. Also, I wonder whether buffering the string and doing some post-processing to fiddle the special cases could work.


Edited by dmatter, 07 July 2013 - 10:09 AM.


#54 jperalta   Members   -  Reputation: 356

Like
2Likes
Like

Posted 07 July 2013 - 10:18 AM

180 non-whitespace, 212 incl. whitespace

 

n=:<'no more'
d=:,"1
b=:<'bottles of beer'
o=:<'on the wall'
t=:<'take one down, pass it around'
c=:b,"_1~;/>:i.99
(|.c d o d c d t d b,"_1~o,"_1~n 0};/i.99),o,~b,~n,b,o,n,b,'go to the store and buy some more';99

Edited by jperalta, 07 July 2013 - 10:49 AM.


#55 rip-off   Moderators   -  Reputation: 8764

Like
0Likes
Like

Posted 07 July 2013 - 06:14 PM

Probably at my limit here with 241 total, 210 without whitespace:

def b i,c=0;"#{i<1?"#{c<1??n:?N}o more":i} bottle#{?s if i!=1} of beer"end
w=" on the wall"
99.downto(0){|i|puts"#{b i,1}#{w}, #{b i}.\n#{i>0?"Take one down and pass it around, #{b i-1}#{w}":"Go to the store and buy some more, #{b 99}#{w}"}."}



#56 dmatter   Crossbones+   -  Reputation: 3300

Like
3Likes
Like

Posted 07 July 2013 - 07:02 PM

Came back to tinker and got it down to a cool 207 non-whitespace lines:

 

B = lambda n='n': ', %s bottle%s of beer on the wall' % ((i%100,n+'o more')[i==0], 's'[i==1:])
e = '.\n'
i = 99
while i >= 0:
    q = B('N')[2:] + B()[:-12]+e + ('Go to the store and buy some more', 'Take one down and pass it around')[i > 0]
    i -= 1
    print(q+B()+e)

 

There might yet be a sneaky way to move the e variable into the B lambda that results in fewer chars but I'm just not seeing it.



#57 tufflax   Members   -  Reputation: 499

Like
3Likes
Like

Posted 09 July 2013 - 02:49 AM


243 with Clojure. It's hard because every kind of operator call requires parens. tongue.png

((fn f [i]
     (let [b " bottle" o " of beer" w " on the wall" p println s str
           t "\nTake one down and pass it around, " m "o more" d \.
           j (dec i) q (= 2 i) a (s b \s o) l "\n" h ", "]
       (p (s i a w h i a d
          t j b (if q "" \s) o w d l))
       (if q
         (p (s 1 b o w h 1 b o d
            t \n m a w d
            l l "N" m a w h \n m a d
            l "Go to the store and buy some more, 99" a w d))
         (f j)))) 99)

Edited by tufflax, 09 July 2013 - 02:57 AM.


#58 Aether_plus   Members   -  Reputation: 103

Like
0Likes
Like

Posted 19 July 2013 - 12:43 PM

Here's my go with ruby: 219 with whitespace 202 without.

b,w,n=" bottles of beer"," on the wall","no more"
a=b+w
99.downto(1){|i|z=i.to_s;t=i-1;print z,a,", ",z,b,".\nTake one down pass it around, #{(t==0)?n:t}",a,"\n"}
print n,a,n,b,"\nGo to the store and buy some more 99",a

Obvious extra characters that I didn't notice at first

 z=i.to_s;

Eliminating those takes the count down to 210/193 respectively.


Edited by Aether_plus, 19 July 2013 - 12:55 PM.


#59 adam4813   Members   -  Reputation: 671

Like
0Likes
Like

Posted 19 July 2013 - 03:57 PM

Here's my C++ attempt

#include <iostream>
#define a(i) <<" bottle" << (i!=1?"s":"") << " of beer"<<
#define n(i) <<i a(i) " on the wall" <<


int main()
{   
    for(int i=100;i-->1;)
      std::cout n(i) ", "<< i a(i) ".\nTake one down and pass it around, " n(i-1) ".\n\n";


    std::cout << "No more" a(0) " on the wall, no more" a(0) "\nGo to the store and buy some more, " n(99) ".";
}

Characters w/o spaces: 282

Characters: 366

 

Edit another tweak

#include <iostream>
#define n(i) << " bottle" << (i!=1?"s":"") << " of beer on the wall" <<
#define b << " bottles of beer.\n" <<


int main()
{   
    for(int i=100;i-->1;)
      std::cout << i n(i) ", " << i b "Take one down and pass it around, " << i-1 n(i-1) ".\n\n";
    std::cout << "No more" n(0) ", no more" b "Go to the store and buy some more, 99" n(99) ".";
}

Characters w/o spaces: 280

Characters: 369


Edited by adam4813, 19 July 2013 - 04:21 PM.


#60 swiftcoder   Senior Moderators   -  Reputation: 10446

Like
0Likes
Like

Posted 19 July 2013 - 04:17 PM

#include <iostream>

 

 

The #include <iostream> is eating up a ton of characters.

 

I wonder if one could make an end run around this by implicitly defining printf()? That's sort of legal C, right? :)


Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]






PARTNERS