Gå til innhold

6-linjers 99 bottles of beer; feedback forespørsel


Anbefalte innlegg

Jeg har begynt faget objektorientert programmering, Java i høst, og har en innlevering med 99 bottles of beer neste uke.

Jeg var ferdig med dette for en stund siden, så jeg har laget diverse varianter etterpå for morro skyld, og klarte nettop å få en fungerende og gramatisk riktig variant med kun 6 linjer kode:

package bob;public class bob{public static void main(String[] args){
String a=" bottles of beer";String b="1 bottle of beer";String d=" on the wall";
String c=".\n";String e=c+"Take one down and pass it around, ";String h=d+", ";
String f="Go to the store and buy some more, 99"+a+d+".";String g="o more"+a;
String i="n"+g;for(int z=99;z>2;z--)System.out.println(z+a+h+z+a+e+(z-1)+a+d+c);
System.out.println("2"+a+h+"2"+a+e+b+d+c+"\n"+b+h+b+e+i+d+c+"\nN"+g+h+i+c+f);}}

[EDIT]\n gir et linjeskift i kodeboksen som ikke er med i kildekoden til programmet men i teksten som printes. Alle linjer er innenfor 80 tegn brede.[/EDIT]

6 linjer kode, 463 tegn. Har noen noen tanker eller feedback på denne koden? Finnes det noen fler triks jeg kan benytte meg av for å gjøre den færre linjer eller tegn? Det eneste jeg har sett er eventuelt å redusere med ytteligere 4 tegn (ingen linjer) ved å bytte package og class navn fra bob (Bottles of Beer) til èn bokstav (a-z).

 

Den godt kommenterte og oversiktelige varianten jeg skal levere er 54 linjer, 2036 tegn (der er all tekst inne i for loopen). Orginal sangtekst (ren tekst) er 200 linjer, 11687 tegn.

Endret av GullLars
Lenke til kommentar
Videoannonse
Annonse

Du kan spare noen tegn ved å bruke komma mellom hver variabel-deklarasjon, siden alle er av samme type (String). I tillegg trenger du vel egentlig ikke "package bob;"? Hele 12 tegn å spare der :-)

 

Her er koden med mine endringer, klarte akkurat å komme under 400 tegn.

 

public class bob{public static void main(String[] x){
String o=" bottle",r=" of beer",m=" more",a=o+"s"+r,b=1+o+r,d=" on the wall",
c=".\n",e=c+"Take one down and pass it around, ",h=d+", ",
f="Go to the store and buy some"+m+", 99"+a+d+".",g="o"+m+a,i="n"+g;
int z=99;while(z>2)System.out.println(z+a+h+z+a+e+(--z)+a+d+c);
System.out.println(z+a+h+z+a+e+b+d+c+"\n"+b+h+b+e+i+d+c+"\nN"+g+h+i+c+f);}}

Endret av jonny
Lenke til kommentar

Det med komma mellom hver variabel deklarasjon av samme type var veldig kjekk (for å lage komprimerte programmer), jeg hadde prøvd det et par ganger tidligere, men fikk det ikke til :p

 

Det med å droppe package er også kjekt, og jeg ser du har byttet ut String[] args med String[] x. Hva har dette å si? Jeg har lagt merke til at det står args der, men har ikke blitt gitt noen forklaring på hvorfor.

 

I en av de tiligere versjonene mine av 99bob (ikke komprimert) brukte jeg while på samme måte som over for å gjøre teller reduksjon mellom første og andre vers. Jeg var ikke klar over at du kunne redusere z og printe den reduserte samtidig med --z inni en print kommando, den var også kjekk.

 

Takk for feedback Svedge og jonny :)

Endret av GullLars
Lenke til kommentar

Det med komma mellom hver variabel deklarasjon av samme type var veldig kjekk (for å lage komprimerte programmer), jeg hadde prøvd det et par ganger tidligere, men fikk det ikke til :p

 

Det med å droppe package er også kjekt, og jeg ser du har byttet ut String[] args med String[] x. Hva har dette å si? Jeg har lagt merke til at det står args der, men har ikke blitt gitt noen forklaring på hvorfor.

 

I en av de tiligere versjonene mine av 99bob (ikke komprimert) brukte jeg while på samme måte som over for å gjøre teller reduksjon mellom første og andre vers. Jeg var ikke klar over at du kunne redusere z og printe den reduserte samtidig med --z inni en print kommando, den var også kjekk.

 

Takk for feedback Svedge og jonny :)

 

args er kun et variablenavn på lik linje med feks o, r, og m. x er kun for å spare 3 tegn.

 

Hopper du tilbake til for løkke istedet sparer du også et tegn for(int z=99;z>1;) < int z=99;while(z>2)

 

public på første linje kan du også kaste ut

 

Holder du deg til kun 1 System.out.println(); sparer du mange tegn

 

Skal koden bli kanskje endre mindre må du faktisk bruke args(x) og litt input til programmet.

 

368

class a{public static void main(String[]x){String o=" bottle",r=" of beer",m=" more",a=o+"s"+r,b=1+o+r,d=" on the wall",c=".\n",e=c+"Take one down and pass it around, ",h=d+", ", f="Go to the store and buy some"+m+", 99"+a+d+".",g="o"+m+a,i="n"+g;for(int z=99;z>1;)System.out.println(z>2?z+a+h+z+a+e+--z+a+d+c:z+a+h+z--+a+e+b+d+c+"\n"+b+h+b+e+i+d+c+"\nN"+g+h+i+c+f);}}

 

class a {
  public static void main(String[] x) {
     String o = " bottle", r = " of beer", m = " more", a = o + "s" + r, b = 1 + o + r, d = " on the wall", c = ".\n", e = c + "Take one down and pass it around, ", h = d + ", ", f = "Go to the store and buy some" + m + ", 99" + a + d + ".", g = "o" + m + a, i = "n" + g;
     for (int z = 99; z > 1;) System.out.println(z > 2 ? z + a + h + z + a + e + --z + a + d + c : z + a + h + z-- + a + e + b + d + c + "\n" + b + h + b + e + i + d + c + "\nN" + g + h + i + c + f);
  }
}

Endret av HV
Lenke til kommentar

Ok, ut fra koden til HV leser jeg ut enda et triks jeg ikke kjente til; forkortede conditionals inne i en print.

System.out.println(z>2?z+a+h+z+a+e+--z+a+d+c:z+a+h+z--+a+e+b+d+c+"\n"+b+h+b+e+i
+d+c+"\nN"+g+h+i+c+f);

Der gjør

z>2?[kode]:[rest];

det samme som

if(z>2)[kode];else [rest];

 

Ved å holde på maks 80 tegn pr linje kode får jeg da en kode som ser slik ut:

class a{public static void main(String[]x){String o=" bottle",r=" of beer",m=
" more",a=o+"s"+r,b=1+o+r,d=" on the wall",c=".\n",g="o"+m+a,i="n"+g,e=c+"Take "
+"one down and pass it around, ",h=d+", ",f="Go to the store and buy some"+m+
", 99"+a+d+".";for(int z=99;z>1;)System.out.println(z>2?z+a+h+z+a+e+--z+a+d+c:z+
a+h+z--+a+e+b+d+c+"\n"+b+h+b+e+i+d+c+"\nN"+g+h+i+c+f);}}

Dette er med m-variablen jonny nevner. Jeg kommer til å kikke igjen på denne senere om jeg kan optimalisere string variablene og oppbygningen av dem. I denne omgang har jeg kommet ned til 5 linjer og 370 tegn :)

 

I den første runden i det første forsøket mitt på å minimalisere koden gikk jeg fra 54 linjer 2036 tegn (innleveringen) til, 12 linjer (ca) 800 tegn, og andre runden i første forsøket 9 linjer ca 650 tegn. Det lengste jeg kom på egenhånd i det andre forsøket var 6 linjer 459 tegn, så hjelpen jeg fikk her med triksene for streng variabel listing og conditional i print hjalp betydelig :)

 

Takk for hjelpen alle, om noen har andre triks som kan hjelpe på forkorting her setter jeg pris på det.

Endret av GullLars
Lenke til kommentar

En del år siden jeg gjorde 99 bottles et par ganger.

Nå er java verbose av natur og ikke lett og få så langt ned.

Når man tenker på kort stygg kode med alle mulige triks i kode golf standaren.

Du kan jo se på et par i python(133 bytes) og perl(132 bytes)

Ikke min kode dette.

 

Python

a,t="\n%s bottles of beer on the wall","\nTake one down, pass it around"
for d in range(99,0,-1):print(a%d*2)[:-12]+t+a%(d-1 or'No')

Perl

sub'b{[@b=(abs||No,bottle."s"x!!++$_,of,beer),on,the,wall]}warn
"@{+b},\n@b,\nTake one down, pass it around,\n@{+b}.\n\n"for-99..-1

Endret av SNIPPSAT
Lenke til kommentar
Python

a,t="\n%s bottles of beer on the wall","\nTake one down, pass it around"
for d in range(99,0,-1):print(a%d*2)[:-12]+t+a%(d-1 or'No')

Perl

sub'b{[@b=(abs||No,bottle."s"x!!++$_,of,beer),on,the,wall]}warn
"@{+b},\n@b,\nTake one down, pass it around,\n@{+b}.\n\n"for-99..-1

Om jeg leser kodene over riktig vil de printe mesteparten av 99 bottles of beer, men ikke hele teksten og gramatisk riktig. For eksempel er ikke "go to the store and buy some more" med.

Jeg prøvde meg litt på python for et par år siden, men gikk aldri forbi 1. kapittel i en lærebok jeg lånte. Jeg husker det var ganske lett å printe tekst og lage små matematisk rettede programmer.

EDIT: noe av grunnen til at jeg prøvde meg på en "komprimert" versjon av 99 bottles of beer i java var at jeg kom over "obfuscated code" og "code golf" og synes det så interresant ut. Det virket som en morsom utfordring å se hvor lite jeg kunne lage programmet, og da hvor leselig eller uleselig det ble.

Endret av GullLars
Lenke til kommentar

Denne kunne ha vært skrevet mye kortere, men neppe så vakker :tease:

 

 

(defun bottle-song (&optional (in-stock 99) (stream *standard-output*))

 ;; Original idea and primary coding by Geoff Summerhayes
 ;;   <[email protected]>
 ;; Formatting idea by Fred Gilham <[email protected]>
 ;; Actual formatting & minor recoding by Kent M Pitman
 ;;   <[email protected]>

 (format

          stream 
        "-----~2%~
         ~{~&~1&~
         ~[~^~:;~
         ~1:*~@(~
         ~R~) bo~
        ttle~ o~
       f beer on t~
     he wall~01:*~[.~
     ~:;,~%~1:*~@(~R~
     ~) bottle~:*~P ~
     of beer.~%You t~
     ake one down, p~
     ass it around, ~
     ~01%~[*No* more~
     ~:;~01:*~@(~R~)~
     ~] bottle~:*~P ~
     of beer on the ~
     wall.~2&-----~%~
     ~1%~:*~]~]~}~0%"

  (loop for bottle from in-stock downto 0 collect bottle)))


(bottle-song)

 

Her er output:

 

-----

 

Ninety-nine bottles of beer on the wall,

Ninety-nine bottles of beer.

You take one down, pass it around,

Ninety-eight bottles of beer on the wall.

 

-----

 

Ninety-eight bottles of beer on the wall,

Ninety-eight bottles of beer.

You take one down, pass it around,

Ninety-seven bottles of beer on the wall.

 

...

 

Two bottles of beer on the wall,

Two bottles of beer.

You take one down, pass it around,

One bottle of beer on the wall.

 

-----

 

One bottle of beer on the wall,

One bottle of beer.

You take one down, pass it around,

*No* more bottles of beer on the wall.

 

-----

 

Legg spesielt merke til «Two bottles» og «One bottle».

 

[EDIT] Glemte output.

Endret av asicman
Lenke til kommentar

...og i Java kan det bli omtrent slik :!: :

 



         class B  {
       static  String
       o=" bottle",r=
        " of beer",w
        =r+ " on th"
        +"e wall",m=
        "no more",t=
       "teen"; static
     String[] N={"one",
   "two","three", "four",
  "five", "six",  "seven",
 "eight",   "nine",  "ten",
 "eleven","twelve","thir"+t
 ,"four"+t,"fif"+t,"six"+t,
 "seven"+t,"eigh"+t,"nine"+
 t}, H={"twenty", "thirty",
 "fourty","fifty", "sixty",
 "seventy","eighty","ninet"
 +"y"}; static String n(int
 i){return (i<20?N[i-1]:H[i
 /10-2]+(i%10!=0?"-"+N[i%10
 -1] : ""));} static String
 U ( String s ) { return s.
 substring(0,1).toUpperCase
 ()+s.substring(1); }public
 static void main(String[]x
 ){String a,b,c=n(99)+o+"s"
 ;for(int i=99;i>=0;){a=i>0
 ?c:U(m)+o+"s";b=c;c=(i>1?n
 (i-1):m)+ o+(i!=2?"s":"");
 System.out.println(U(a)+w+
 ", " + b+r + ".\n"+(i-->0?
 "Take one down and pass "+
 "it around, " +c+w+ ".\n":
 "Go to the store and buy"+
  " some more, "+ n(99)+o+
   "s" + w + ".\n" ));}}}

 

Utskriften blir slik ved kjøring:

 

Ninety-nine bottles of beer on the wall, ninety-nine bottles of beer.
Take one down and pass it around, ninety-eight bottles of beer on the wall.

Ninety-eight bottles of beer on the wall, ninety-eight bottles of beer.
Take one down and pass it around, ninety-seven bottles of beer on the wall.

Ninety-seven bottles of beer on the wall, ninety-seven bottles of beer.
Take one down and pass it around, ninety-six bottles of beer on the wall.

...

Three bottles of beer on the wall, three bottles of beer.
Take one down and pass it around, two bottles of beer on the wall.

Two bottles of beer on the wall, two bottles of beer.
Take one down and pass it around, one bottle of beer on the wall.

One bottle of beer on the wall, one bottle of beer.
Take one down and pass it around, no more bottles of beer on the wall.

No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, ninety-nine bottles of beer on the wall.

Endret av jonny
Lenke til kommentar
  • 1 måned senere...

Apropos 99 bottles of beer on the wall. På http://99-bottles-of-beer.net/ ligger kildekode til samme type program for hele 1434 forskjellige programmeringsspråk. Noen av språkene er virkelig sære, som Brainfuck, Befunge, LOLCODE, Malbolge og Whitespace, men også normale språk som Java, C/C++ og C#. Java-versjonen der er en del lenger enn dette. Uansett, det er artig å se på hvor store forskjeller det er, og interessant å se på språk som er designet for å være vanskelige.

Endret av Blodappelsin
Lenke til kommentar

Jeg så siden 99-bottles-of-beer.net når jeg søkte på sangteksten. En ting dere gjorde forskjellig i stream versjonen og den under (innlegg #11 og 12) er dere skrev antallet flasker med bokstaver, mens oppgaven var å skrive det med tall 99-1, og "no more" for 0.

Jeg vurderer om jeg skal rydde opp litt i strengene og poste versjonen min på 99-bottles-of-beer.net sida.

  • Liker 1
Lenke til kommentar
  • 3 uker senere...

package bob;public class bob{public static void main(String[] args){
String a=" bottles of beer";String b="1 bottle of beer";String d=" on the wall";
String c=".\n";String e=c+"Take one down and pass it around, ";String h=d+", ";
String f="Go to the store and buy some more, 99"+a+d+".";String g="o more"+a;
String i="n"+g;for(int z=99;z>2;z--)System.out.println(z+a+h+z+a+e+(z-1)+a+d+c);
System.out.println("2"+a+h+"2"+a+e+b+d+c+"\n"+b+h+b+e+i+d+c+"\nN"+g+h+i+c+f);}}

 

Det er juks å sette sammen linjer og allikevel telle dem som én linje. Egentlig er koden din slik:

 

public class bob{
   public static void main(String[] args){
       String a=" bottles of beer";
       String b="1 bottle of beer";
       String d=" on the wall";
       String c=".\n";
       String e=c+"Take one down and pass it around, ";
       String h=d+", ";
       String f="Go to the store and buy some more, 99"+a+d+".";
       String g="o more"+a;
       String i="n"+g;
       for(int z=99;z>2;z--) System.out.println(z+a+h+z+a+e+(z-1)+a+d+c);
       System.out.println("2"+a+h+"2"+a+e+b+d+c+"\n"+b+h+b+e+i+d+c+"\nN"+g+h+i+c+f);
   }
}

 

...som er femten linjer. Ekte golfere teller dessuten antall tegn :)

Lenke til kommentar

Jeg har begynt faget objektorientert programmering, Java i høst, og har en innlevering med 99 bottles of beer neste uke.

Jeg var ferdig med dette for en stund siden, så jeg har laget diverse varianter etterpå for morro skyld, og klarte nettop å få en fungerende og gramatisk riktig variant med kun 6 linjer kode:

Altså, du kan stappa alt på én lang linje om du gidder, linjeskift har ingen funksjon i Java. Det du burde telle er antall tegn om du er en "golfer". Eller kjøretid om du heller vil det.

 

Er det objektorientert programmering ved NTNU? Stusser litt på at dere har en 99 bottles of bear innlevering.

Lenke til kommentar

Ble ganske fornøyd med min egen nå, tror den blir kortere tegnmessig enn de andre foreslått.

public class bottles {
 public static void main (String[] args) {
   String b = " of beer";
   String c = " on the wall";
   String a = " bottles";
   String d = " Take one down and pass it around";
   for (int i = 99; i > -1; --i) {
     if (i == 0) {
       d = " Go to the store, buy some more";
       a = a + 's';
     }
     if (i == 1) {
       a = " bottle";
     }
     System.out.println(i + a + b + c + ',' + " " + i + a + b + '.' + d + ',' + " " + i + a + b + c + '.');
   }
 }
}

Lenke til kommentar

Ble ganske fornøyd med min egen nå, tror den blir kortere tegnmessig enn de andre foreslått.

public class bottles {
 public static void main (String[] args) {
   String b = " of beer";
   String c = " on the wall";
   String a = " bottles";
   String d = " Take one down and pass it around";
   for (int i = 99; i > -1; --i) {
     if (i == 0) {
       d = " Go to the store, buy some more";
       a = a + 's';
     }
     if (i == 1) {
       a = " bottle";
     }
     System.out.println(i + a + b + c + ',' + " " + i + a + b + '.' + d + ',' + " " + i + a + b + c + '.');
   }
 }
}

Du kan fjerne 2 tegn ved å ta bort klammene i den andre if-testen. Usikker på hvordan det er i Java, men ville tro du kunne fjerne "public" på både klassen og metoden. I C# kan du også fjerne "String[] args" fra signaturen - kan Java også det?

 

a = a + 's'; kan også endres til a += 's';

 

Og klassenavnet "bottles" er jo litt i lengste laget :)

Endret av torbjørn marø
Lenke til kommentar

Du kan ta bort public på klassen, men på main metoden er java ganske bestemt på hvordan den skal se ut. Beste du kan klare er å endre "args" til èn bokstav.

 

Som tidligere nevnt så kan du droppe flere "String" ved å bruke komma:

String b = " of beer", c = " on the wall", a = " bottles", d = " Take one down and pass it around";

 

De to if setningene kan kortes ned litt:

		d = (i == 0 ? " Go to the store, buy some more" : d);
		a = (i == 0 ? a+'s' : i == 1 ? " bottle" : a);

  • Liker 2
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...