Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Minigolf - 99 Bottles of Beer

Geschrieben von: Bernhard Spuida
Kategorie: Tee Off

This printed page brought to you by AlphaSierraPapa

Damit ein wenig Abwechslung ins Golferleben kommt, wurde dieses Mal ein Kurzturnier mit nur 48 Stunden Dauer ausgetragen - Minigolf sozusagen. Die Aufgabe war natürlich passend zum St. Patrick's Day gewählt...

Die Aufgabenstellung

Ein möglichst kurzes ASP-Programm das den Text des Klassikers "99 Bottles of Beer" ausgibt. Zu finden ist der Text hier: http://www.noodleroni.com/beerlyrics.txt

Bitte beachten, daß die letzten zwei Strophen korrekt gedruckt werden müssen - schwindlige "bottle(s)" gelten nicht! Dieses Mal gibt es in Anbetracht der kurzen Dauer keinen offiziellen Tester da keine Testdaten geladen werden müssen, Ausgabe direkt auf den Bildschirm.

Eine einfache, nahezu triviale Aufgabe nicht wahr? Wir werden ja sehen.

Nun zum Leaderboard

Der Bunker war am Ende des Turniers dieses Mal erfreulicherweise leer.

Aus Gründen die wir später erklären werden kann man auch ein zweites, 'echtes' Leaderboard erstellen:

Genug der Vorrede, auf zur Vorstellung einiger interessanter Lösungen. Die Ansätze variieren stärker als man bei dieser simplen Aufgabe meinen könnte.

Gerhard Buchner

Fangen wir mal mit einem offensichtlichen, geradezu 'klassischen' Ansatz an. Gerhards Lösung sei Stellvertreter für alle anderen Golfer die eine Lösung im Sinne der Regeln eingeschickt haben:

Möchte Euch aber zumindest den Code meiner "echten geskripteten" Version mit 183 Zeichen nicht vorenthalten :-)

<%h=" bottle"
c=h&"s"
g=" of beer"
b=" on the wall"
y=",<br>"
z="No More"&c&g
for i=1to 99
f=i&h&g
x=f&b&y&f&y&"Take one down, pass it around"&y&z&b&".<br><br>"&x
z=f
h=c
next%><%=x%>

Dort habe ich versucht den Text so weit wie möglich zu zerpflücken, in Variablen zu speichern und diese dann gezielt wieder zusammen zu setzen. Am besten hatte dies funktioniert als ich von unten nach oben zuerst alles in einer Variablen gespeichert hatte und erst zum Schluß ausgegeben.

Anmerkungen: So gehört sich das. Einfach und bis auf das Minimum reduziert. Die Idee ist bei allen 'richtigen' Lösungen die gleiche: in einer Schleife runter zählen und die Sonderfälle der letzen zwei Strophen abfangen, dann Ausgabe im Browser. Und nun auf zu den 'kreativen' Lösungen.

Wolfgang Kluge

In diesem Minigolf der kreativste Golfer. Unglaublich was man nicht alles tun kann um den Buchstaben, aber nicht den Sinn der Regeln (Ein bekannter Software-Hersteller macht uns das ja seit Jahren erfolgreich vor) zu erfüllen:

Mein erster "einfacher" Lösungsvorschlag wurde ja nicht angenommen :( Vorenthalten will ich diesen deswegen aber noch lange nicht ;)

Der - laut Bernhard "aehm kreative" - Vorstoß wäre 117 (am Anfang mal 129) Bytes lang gewesen - zwar arg zusammengemogelt, aber wenn Windows es sagt muß es doch wohl stimmen.

<%=createObject("scripting.filesystemobject").
OpenTextFile(Request.ServerVariables("PATH_TRANSLATED")&":a").readall%>

Trick dabei wäre gewesen, den gesamten Text in einem weiteren Filestream namens "a" (geht nur unter NTFS) zu halten. Windows zeigt nur die Größe des Hauptstreams an - so war's gedacht. Allerdings wurde es 1. nicht zugelassen und 2. wurde der Stream nicht mit übertragen (weitere Versuche blieben allerdings auch gleich aus *g*)

Mehr dazu ist hier zu finden: Streams in NTFS Dateien

Der 2. kreative Versuch wurde dann angenommen. Diese Lösung ist dann zwar auch mehr künstlerischer Natur als ein "so-programmiert-man-richtig"-Werk, aber es ist ja Golf.

Hier sind es dann 166 Bytes.

<%c=split(right(Request.ServerVariables("URL"),133),2)
for i=1to 99
j=i&c(1)&a
o=replace(replace(replace(c(2),c(3),"<br>"),1,j),"y",c(0))&o
c(0)=j
a="s"
next
%><%=o%>

Der Clou hierbei war, die Datei entsprechend zu nennen: In diesem Fall "No More bottles2 bottle21 of beer on the wall,.asp1 of beer,.aspTake one down, pass it around,.aspy of beer on the wall..asp.asp2.asp"

Der Dateiname ist damit 133 Zeichen lang (was unter Windows keinerlei Auswirkungen auf die Dateigröße hat *g*!!). Die 2 dient als Trennzeichen (Split), die 1 wird ersetzt durch die erste Zahl + "bottel(s)" und "y" durch die 2. Zahl bzw. "No More". ".asp" wird zum Schluß noch durch <BR>´s ersetzt - Der Rest ist gleich wie bei der letzten Lösung.

Und damit kommen wir zur "normalsten" Lösung mit 184 Bytes:

<%m=" of beer on the wall"
k="No More bottles"
t="<BR>"
for i=1to 99
j=i&" bottle"&a
o=j&m&","&t&j&" of beer,"&t&"Take one down, pass it around,"&t&k&m&"."&t&t&o 
k=j
a="s"
next%><%=o%>

Hier ist ja eigentlich alles klar. Durch das "Rückwärts"-Zusammensetzen der Variable o spar' ich mir "Step-1" in der Schleife. If-Abfragen erspar' ich mir, indem zuerst k auf "No More bottles" und später (nach dem zusammensetzen) dann auf die vorherige Ausgabevariable j gesetzt wird. Gleiches gilt für "bottles" mit und ohne "s".

Die 109 sahen dann so aus... Wohl dem, der eine kürzere Domain hat.

<%set t=createObject("MSXML2.ServerXMLHTTP")
t.open"GET","http://www.vbwelt.de/b"
t.send%><%=t.responseText%>

Aber gegenteilig zu Chris´s Ausführung ist das "XMLHTTP"-Objekt doch kürzer zu verwenden. Mit 101 Bytes (leider zu spät eingereicht, 15:04) wäre diese Lösung sehr wohl durchgekommen (statt "false" eben ",0"):

<%set t=createObject("MSXML2.XMLHTTP")
t.open"GET","http://vbwelt.de/b",0
t.send%><%=t.responseText%>

Und dann noch eine Lösung, die ich erst gar nicht vorschlagen wollte (ich will nicht geschlagen werden). Diese ist mit 41 Bytes dabei ;) (Die Datei auf dem Server müsste ich aber noch anpassen, damit die Umbrüche korrekt angezeigt werden):

<%response.redirect"http://vbwelt.de/b"%>

Anmerkungen: Schön gegolft! Kreativ gegolft! Einige Details in den Regeln werden für zukünftige Turniere geändert werden, mehr dazu weiter unten.

Der erste Ansatz kann nicht außerhalb der Entwicklungsmaschine funktionieren, da zusätzliche Streams gewöhnlich nur vom Programm das die Datei erstellt hat erkannt werden. Wird die Datei kopiert, geht der Stream verloren, da ihn zum Beispiel ein Email-Client nicht in das Attachment mit übernimmt. Trotzdem originelle Idee. Nummer zwei kann in einem 'normalen' Golfturnier nicht angewandt werden, da der Dateiname aus dem Teilnehmernamen und einer laufenden Nummer gebildet wird. Der XMLHTTP-Ansatz wird im Folgenden noch weiter diskutiert. Und das Response.Redirect - einfach Pfui! So etwas ist wirklich kein Golf.

Michael Guder

OK, ich schäme mich ja schon ... meine Lösung, die auch akzeptiert wurde:

1:<%set s=createobject("Internetexplorer.Application")
2:s.navigate("www.wig3.de/b")
3:while s.ReadyState<>4
4:wend%><%=s.Document.Body.InnerText%>

1: ich mach's mit dem IE direkt ... erzeuge mir also ein Object
2: navigiere zu einer URL wo das komplette File liegt...
3: frage ab, ob der schon fertig ist ...
4: gebe den Body des Dokuments aus ..

Diese Lösung ist kreativ, elegant und erfüllt den Buchstaben der Aufgabenstellung perfekt - vorausgesetzt auf dem Server ist der Internet Explorer vorhanden...

Christoph Wille

Christoph in seiner Rolle als Schiedsrichter kann natürlich nicht in die offizielle Wertung aufgenommen werden, aber seine Erklärung des Lösungsweges mittels XMLHTTP soll trotzdem wiedergegeben werden, immerhin hat er diesen Ansatz als erster entdeckt:

Meine Lösung reizt sowohl die Angabe als auch die Regeln des Golfens bis aufs letzte aus. Wolfgang Kluge (er als erster) und andere sind mir im Laufe des Turniers noch auf die Schliche gekommen, was ich gemacht habe. Stellvertretend erkläre ich meine und zeige dann noch Wolfgang's weiterführendes runtergolfen.

Rekapitulieren wir einmal die wichtigsten Teile der Angabe:

"Ein möglichst kurzes ASP-Programm das den Text des Klassikers "99 Bottles of Beer" ausgibt."

Die Betonung liegt auf "ausgibt", später kommt auch noch "daß die letzten zwei Strophen korrekt gedruckt werden müssen". Gut. Sehen wir uns eine wichtige Golfregel an:

"Verwendung externer Komponenten außer solchen die im Betriebssystem ausgeliefert werden (zB CDONTS) ist nicht erlaubt. "

Was jetzt kommt kann sich der geneigte Leser vielleicht schon denken, wenn man an Bernd's Angabe sich erinnert - da war doch die URL vom Liedtext... hier also meine erste Lösung mit 165 Bytes:

<%
Set o = CreateObject("MSXML2.ServerXMLHTTP")
o.open "GET", "http://www.noodleroni.com/beerlyrics.txt"
o.send
Response.Write Replace(o.responseText,vbLf,"<br>")
%>

Leerzeichen, wie verschwenderisch (die kamen erst viel später raus...)! Das Problem warum ich Replace brauche ist daß es sich beim Text um .txt handelt, und der dann im Browser nicht korrekt mit Zeilenumbrüchen dargestellt wird, das vbLf weil es ein Unix-System war.

Das war klarerweise zu viel, aber wie bekomme ich die Zeilenumbrüche "billiger"? Siehe da:

<pre><%
Set o = CreateObject("MSXML2.ServerXMLHTTP")
o.open "GET", "http://www.noodleroni.com/beerlyrics.txt"
o.send
Response.Write o.responseText
%>

Wer sagt, daß man ein PRE Tag korrekt zumachen muß? Neee. 16 Bytes gespart (das war dann die eingereichte 149er Lösung).

Noch ist nicht aller Tage Abend, da geht noch was. Ich kann Response.Write durch <%=%> ersetzen:

<pre><%
Set o = CreateObject("MSXML2.ServerXMLHTTP")
o.open "GET", "http://www.noodleroni.com/beerlyrics.txt"
o.send
%><%=o.responseText%>

Damit sind wir bei 138. Da muß doch noch was gehen... Klar, viele Website mappen nicht nur www.domain.com auf den Webserver, sondern auch domain.com:

<pre><%
Set o = CreateObject("MSXML2.ServerXMLHTTP")
o.open "GET", "http://noodleroni.com/beerlyrics.txt"
o.send
%><%=o.responseText%>

Yes, somit sind wir auf 134 Bytes ("www." = 4 Bytes). Noch schnell die Leerzeichen bei Set o= und "GET"," rausnehmen, und es sind nur noch 131.

Den Trick, den ich dann auspacken wollte, der hat nicht hingehauen - das Ersetzen des Domainnamens durch die IP Adresse (hätte direkt 1 Byte, bzw mehr durch alternative Codierung gebracht). Leider verwenden die Herrschaften Host Header auf dem Web Server, schade schade. Klar hätte ich es auf einen eigenen Server mit kurzer IP legen können, aber das war mir dann zu mühsam gewesen - aber das hat dann Wolfgang ausgepackt, der wie Alex Zeitler (und Buchi) auch auf die Idee gekommen ist (109 Bytes):

<%set t=createObject("MSXML2.ServerXMLHTTP")
t.open"GET","http://www.vbwelt.de/b"
t.send%><%=t.responseText%>

Einfach fertig formatiert auf den eigenen Server gelegt, presto. Allerdings: er hätte noch 4 Byte auf 105 runtergolfen können, weil auch bei seinem Server ist "www." nicht notwendig.

Zum "Abrunden" eine weitere meiner Lösungen, die tatsächlich funktioniert, aber einen gewissen kreativen Wahnsinn erkennen läßt (138 Bytes):

<pre><%
With CreateObject("Msxml2.ServerXmlHttp")
.open "GET","http://noodleroni.com/beerlyrics.txt"
.send%><%=.responseText%><%End With%>

Schirimitteilung: in Zukunft wird - außer es ist bei einem Turnier explizit erlaubt - das Abholen von statischen oder dynamischen Inhalten/Rechenergebnissen von fremden Servern via XmlHTTP nicht mehr erlaubt sein. Desgleichen gilt für die IE Control (Michael Guder's Lösung).

Alle zusammen

Geht ja nicht an, daß bei 104 bzw. 101 (zu spät eingereicht) Schluß: ist. Die magische Hundert muß durchbrochen werden! Und das geschah denn auch bei der Diskussion auf der Liste:

<%set x=CreateObject("Msxml2.XMLHTTP")
x.open"get","http://uhj.de.vu",0
x.send%><%=x.responseText%>

Und presto - 99! (Bytes, nicht bottles). Die Änderungen gegenüber den oben gezeigten XMLHTTP-Lösungen sind klein, aber bringen doch noch was: FALSE läßt sich durch 0 ersetzen (synchroner Transfer), die URL möglichst kurz wählen und das Leerzeichen vor 'open' kann man auch getrost weglassen. Um die entsprechende Originalmail zu zitieren:

Ich meine 0 statt false natürlich, dann haben 'wir' 99 Bytes, gell?

CU
Schmiddl

Am Mittwoch, 19.03.03, um 15:32 Uhr (Europe/Berlin) schrieb Michael
Schmidt:

> <%set x=CreateObject("Msxml2.XMLHTTP")
> x.open"get","http://uhj.de.vu",false
> x.send%><%=x.responseText%>
>
> Bei mir klappt es auch ohne Leerzeichen nach dem open!!
>
> CU
> Schmiddl
>
> Am Mittwoch, 19.03.03, um 15:17 Uhr (Europe/Berlin) schrieb Buchner
> Gerhard:
>
>>> da geht noch was ;)
>>> false = 0 ;)
>>
>> Dann fehlt noch 1 Byte um die 100 zu knacken ;-)
>> Wer sieht noch was?
>>
>> Buchi

Nicht schlecht - 36 Minuten nach Turnierende war die Mutter aller Lösungen gefunden! Das zeigt was Teamgeist leisten kann.

Schlußbemerkung

So, liebe Golffreunde, das wars wieder einmal vom Golfplatz. Schalten sie sich wieder ein wenn sie das nächste mal 'Fore!' hören.

This printed page brought to you by AlphaSierraPapa

Verwandte Artikel

Streams in NTFS Dateien
http:/www.aspheute.com/artikel/20000821.htm
Tee Off! Wolpertinger Genome Project
http:/www.aspheute.com/artikel/20031222.htm

Links zu anderen Sites

99 Bottles of Beer
http://www.noodleroni.com/beerlyrics.txt
ASP Golf Diskussionsliste
http://www.aspgerman.com/aspgerman/listen/anmelden/golf.asp
Virtueller ASP Golfplatz
http://www.aspgerman.com/golf/

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.