Verwalte einen Tortenladen!

12

Zusammenfassung

Codegolf ist gut. Torte ist gut . Wenn Sie die beiden zusammenfügen, kann nur gutes Zeug passieren.

Spezifikationen

In dieser Herausforderung leiten Sie einen Tortenladen. Der Benutzer wird zur Eingabe von fünf verschiedenen Befehlen können: list, count, buy, sell, und exit. Hier sind die Spezifikationen für jeden:

  • list

    • Drucken Sie eine Liste aller Kuchen im Besitz und wie viele. Trennen Sie sie mit |und füllen Sie sie mit einem Leerzeichen auf beiden Seiten auf. |s muss ausgerichtet sein. Der Kuchenbetrag kann negativ sein (das bedeutet, dass Sie jemandem etwas schulden :(). Beispielsweise:

      | apple     | 500 |
      | blueberry | 2   |
      | cherry    | -30 |
      
  • count [type]

    • Drucken Sie aus, wie viele {{type}}Kuchen es gibt. "Es gibt keine {{type}}Torte!" wenn es keine gibt. {{type}}wird immer mit dem regulären Ausdruck übereinstimmen \w+(dh es wird immer ein einzelnes Wort sein). Wenn ich zum Beispiel die Anzahl der Torten in der obigen Beispielliste hätte, dann

      > count apple
      500
      > count peach
      There is no peach pie!
      
  • buy [n] [type]

    • Addieren Sie {{n}}zur Zählung des {{type}}Kuchens und drucken Sie ihn aus. Erstellen Sie einen {{type}}Kuchen, falls er nicht existiert. {{n}}wird immer mit dem regulären Ausdruck übereinstimmen [0-9]+(dh es wird immer eine Zahl sein). Hier ist ein weiteres Beispiel (mit demselben Kucheninventar wie in den vorherigen Beispielen):

      > count blueberry
      2
      > buy 8 blueberry
      10
      
  • sell [n] [type]

    • Subtrahieren Sie {{n}}von der Anzahl der {{type}}Kuchen und drucken Sie es. Erstellen Sie einen {{type}}Kuchen, falls er nicht existiert. Torte kann negativ sein (oh nein, das würde bedeuten, dass Sie jemandem Torte schulden!).

      > sell 15 blueberry
      -5
      > buy 5 blueberry
      0
      
  • exit

    • Print "Der Tortenladen ist geschlossen!" und beenden Sie das Programm.

      > exit
      The pie store has closed!
      

Weitere Erläuterungen

  • Wenn eine nicht vorhandene Funktion aufgerufen wird (das erste Wort), drucken Sie "Das ist kein gültiger Befehl."
  • Wenn eine vorhandene Funktion mit ungültigen Argumenten (die Wörter nach dem ersten Wort) aufgerufen wird, spielt es keine Rolle, wie sich Ihr Programm verhält. "Ungültige Argumente" enthalten zu viele Argumente, zu wenig Argumente, {{n}}keine Zahl usw.
  • Torte ist gut.
  • Ihre Eingabe muss von Ihrer Ausgabe unterschieden werden. Wenn Sie das Programm auf der Befehlszeile / terminal / shell / other text-based thing ausführen, müssen Sie der Eingabe ein " > ​"(ein" Größer als "-Zeichen und ein Leerzeichen) oder ein anderes Shell-Eingabepräfix voranstellen.
  • Torte ist gut.
  • Wenn all diese Erläuterungen nicht gut genug sind, sehen Sie hier einige Beispiele:

    > list
    > buy 10 apple
    10
    > sell 10 blueberry
    -10
    > list
    | apple     | 10  |
    | blueberry | -10 |
    > count apple
    10
    > count peach
    There is no peach pie!
    > exit
    The pie store has closed!
    
  • Wenn Sie Kuchen kaufen / verkaufen und der Nettozählwert wird 0, können Sie ihn entweder im behalten listoder nicht, und Sie können entweder zurückkehren 0oder There is no {{type}} pie!wann Sie countihn haben.

  • Das ist ; kürzester Code gewinnt.
  • Habe ich schon erwähnt, dass Kuchen gut ist?
Türknauf
quelle
3
Also nur zur Klarstellung ... ist Kuchen gut?
Igby Largeman
4
Ist es akzeptabel, einen Kuchen mit einer Zählung von Null in der Liste zu behalten? Wie wenn du es tust buy 1 appleund sell 1 apple. Und wäre es dann gültig count apple, 0statt zurückzukehren There is no apple pie!?
Igby Largeman
@IgbyLargeman Verdammt, ich dachte ich hätte alles geklärt! : P Zusätzlichen Erläuterungen wurde ein neuer Testfall hinzugefügt
Türknauf
@Doorknob hey! Ich gebe "Es gibt keinen Apfelkuchen" aus, nachdem der letzte verkauft wurde.
John Dvorak
@ JanDvorak Okay, ich nehme an, so oder so wird es funktionieren. Erneut aktualisiert
Türknauf

Antworten:

3

Rubin, 335 330

h=Hash.new 0
loop{$><<"> "
puts case gets when/^list/
h.map{|x|?|+" %%%ds |"%h.flatten.map{|e|e.to_s.size}.max*2%x}when/^count (.*)/
h[$1]!=0?h[$1]:"There is no #{$1} pie!"when/^buy#{m=" (.*)"*2}/
h[$2]+=$1.to_i when/^sell#{m}/
h[$2]-=$1.to_i when/^exit/
puts"The pie store has closed!"
break else"That's not a valid command."end}

Einige Tricks hier:

?|+" %%%ds |"%[*h].flatten.map{|e|e.to_s.size}.max*2%x

Die Idee von Doorknob, einen Formatierer zu verwenden, wird hier buchstäblich einen Schritt weiter geführt. Zunächst wird die längste Zeichenfolge im Hash unter allen Schlüsseln und Werten formatiert " %%%ds |", um eine Zeichenfolge wie zu erzeugen " %6s |". Ja, keine Schrumpffolie für jede Spalte einzeln. Es gab nie das Erfordernis dazu. Eine Grösse passt allen. Diese Zeichenfolge wird dann dupliziert und als Formatierungszeichenfolge für das Array mit zwei Elementen verwendet, das die aktuelle Zeile enthält. Schließlich +bekommt der Nahe am Start sein Wort und stellt eine einzelne führende Pfeife voran. Oh, und putshat eine gute Handhabung von Arrays.

Ruby hat Interpolation in Regex-Literalen. Es ist eine knappe Rettung, aber es spart ein wenig.

Ruby benötigt Semikolons nach dem whenAusdruck, jedoch nicht vor dem Schlüsselwort. Dies führt zu einem seltsamen Rendering-Artefakt, wenn das Semikolon durch eine neue Zeile ersetzt wird.

Und natürlich Perlismus, bekannt als magische Globale und automatische Zuordnung von Regex-Literalen zu diesen.

Auch sind die meisten Aussagen einschließlich caseAusdrücke.

John Dvorak
quelle
Sehr clevere Tricks! +1
Türklinke
Hmm, aber warum Hash.new(0)statt {}?
Türklinke
1
@Doorknob Rubys Hashes können Standardwerte haben oder sogar Generatoren (wenn Sie ein Objekt übergeben) (wenn Sie einen Block (Schlüssel übergeben, Hash -.> Wert) Wenn Sie entweder nicht passieren, ist der Standardwert nil(was nicht Addition zulassen) .Das Literal wird nilals Standardwert verwendet.
John Dvorak
Könnte ein paar Zeichen mit h=Hash.new(0)=> h=Hash.new 0, print"> "=> speichern $><<'> ', und ich denke das [*h]kann einfach sein h. Ich habe versucht, eine Version ohne switch-Anweisung zusammenzustellen, da sich der gesamte Text auf dem Kessel wirklich summiert: gist.github.com/chron/6315218 . Ich habe versucht, etwas zum ruby -ap
Laufen
@chron danke! Ich kann nicht glauben, dass ich die erste verpasst habe und ich bin mir nicht sicher, warum ich gedacht habe $><<, eine neue Zeile zu drucken. Was den letzten Vorschlag angeht ... Hashes haben leider keine "Flatten" -Methode.
John Dvorak
3

Ruby, 427 384 Zeichen

alias x puts
p={}
loop{
print'> '
case(u=gets.chop.split)[0]when'exit'
x'The pie store has closed!'
exit
when'list'
p.each{|k,v|printf"| %-#{p.keys.map(&:size).max}s | %-#{p.map{|e,a|a.to_s.size}.max}s |\n",k,v}
when'count'
x p[t=u[1]]||"There is no #{t} pie!"
when/sell|buy/
m=(u[0]<?s?1:-1)*u[1].to_i
if p[t=u[2]]
x p[t]+=m
else
x p[t]=m
end
else x"That's not a valid command."
end}

Vielen Dank an Jan Dvorak für die enorme Verbesserung von 427 auf 384 (!)

Türknauf
quelle
Sie können loop{...}anstelle von verwenden while 1do...end.
John Dvorak
Sie können splitohne Argument verwenden. Standardmäßig wird nach Leerzeichen geteilt (oder $;wenn dies festgelegt ist)
John Dvorak
p.keys.group_by(&:size).max[0]- suchst du p.keys.map(&:size).maxoder p.map{|x,_|x.size}.max? Hier: [(t=p.values).max.to_s.size,t.min.to_s.size].maxsuchen Sie p.map{|_,x|x.to_s.size}.max? Ich werde Ihre Idee aufgreifen und den Formatierer missbrauchen :-)
John Dvorak
p[t]=p[t]+mist gleichbedeutend mit p[t]+=m(außer p[t]wird zweimal statt einmal ausgewertet) und länger. Verwenden Sie letzteres.
John Dvorak
@ JanDvorak Oooh, danke für all die Tipps: DI dachte, Ruby hätte keinen +=Operator; deshalb habe ich es nicht benutzt. Vielleicht ist das nur für ++. Ich werde meinen Beitrag in Kürze bearbeiten
Türklinke
3

Python Pie- thon 437

Ich bin mir sicher, dass die vorletzte Zeile etwas locker ist, aber die Anforderung, die Balken sowohl für den Tortentyp als auch für die Anzahl auszurichten, ist ein Trottel.

p,C,l={},"count",len
while 1:
 a=raw_input("> ").split();c=a.pop(0)
 if"exit"==c:print"The pie store has closed!";break
 if"sell"==c:a[0]=int(a[0])*-1
 if c in[C,"buy","sell"]:
  y=a[-1]
  if c!=C:p[y]=p.get(y,0)+int(a[0])
  print p.get(y,"There is no %s pie!"%y)
 elif"list"==c:
  for i in p:print"| %s | %s |"%(i.ljust(l(max(p.keys(),l))),str(p[i]).rjust(max([l(str(x)) for x in p.values()])))
 else:print"That's not a valid command."

Wie pro Igby Largeman Kommentar sind die Regeln unklar um was , wenn es zu tun war eine Torte von einem bestimmten Typ, aber es gibt 0jetzt. Also habe ich es zu meinen Gunsten ausgelegt.

Beispielausgabe:

> buy 10 apple
10
> sell 1 blueberry
-1
> buy 1 keylime
1
> sell 3 apple
7
> buy 5 blueberry
4
> list
| keylime   | 1 |
| apple     | 7 |
| blueberry | 4 |
> sell 1 keylime
0
> count keylime
0

quelle
Sorry, aber in dieser > count potatoproduziert man That's not a valid command.stattThere is no potato pie!
Türklinke
@Doorknob Laufen Sie es in IDLE?
Ja. Ich versuche es in einer Datei
Türklinke
Eigentlich scheint die Zählung überhaupt nicht zu funktionieren . Eigentlich funktioniert es manchmal, aber manchmal nicht. Es ist sehr seltsam ...
Türklinke
3
Hehe, ich wusste, dass es sich um eine Art Namenskonflikt handelte: P +1 Oh, und außerdem hatte meine Datei für Ihr Programm einen amüsanten Namen pie.py
::
3

C # - 571 568 559

Wie gewohnt mit hoffnungslos wortreichem C # nach hinten rücken.

using C=System.Console;class Z{static void Main(){var P=new 
System.Collections.Generic.Dictionary<string,int>();int i=0,n;a:C.Write
("> ");var I=C.ReadLine().Split(' ');var c=I[0];object s=c=="exit"?
"The pie store has closed!":"That's not a valid command.";if(c==
"count")try{s=P[c=I[1]];}catch{s="There is no "+c+" pie!";}if(c==
"buy"||c=="sell"){n=int.Parse(I[1]);n=c=="sell"?-n:n;try{n+=P[c=
I[2]];}catch{}s=P[c]=n;i=(n=c.Length)>i?n:i;}if(c=="list")foreach(
var p in P.Keys)C.Write("| {0,"+-i+"} | {1,11} |\n",p,P[p]);else C.
WriteLine(s);if(c!="exit")goto a;}}

Bildbeschreibung hier eingeben

Ich habe mir die Regel zur Listenausgabe ein wenig erlaubt. Um einige Zeichen zu speichern, habe ich die Breite der Zählspalte auf die maximale Breite eines ganzzahligen Wertes fest programmiert. (Die Regeln besagten nicht, dass zusätzliche Leerzeichen nicht zulässig sind.)

Formatiert:

using C = System.Console;
class Z
{
    static void Main()
    {
        var P = new System.Collections.Generic.Dictionary<string, int>();
        int i = 0, n;
    a:
        C.Write("> ");
        var I = C.ReadLine().Split(' ');
        var c = I[0];
        object s = c == "exit" ? "The pie store has closed!" 
                               : "That's not a valid command.";

        // allow Dictionary to throw exceptions; cheaper than using ContainsKey()
        if (c == "count")
            try { s = P[c = I[1]]; }
            catch { s = "There is no " + c + " pie!"; }

        if (c == "buy" || c == "sell")
        {
            n = int.Parse(I[1]);
            n = c == "sell" ? -n : n;

            try { n += P[c = I[2]]; }
            catch { }

            s = P[c] = n;
            i = (n = c.Length) > i ? n : i;
        }

        if (c == "list")
            foreach (var p in P.Keys) 
                C.Write("| {0," + -i + "} | {1,11} |\n", p, P[p]);
        else
            C.WriteLine(s);

        if (c != "exit") goto a; // goto is cheaper than a loop
    }
}
Igby Largeman
quelle
1
+1, ich bin überrascht, dass man mit so einer wortreichen Sprache so wenig Zeichen bekommt: D
Türklinke
Mein Ziel mit Java ist es nur, die C # -Implementierung zu übertreffen. Haha. Gute Arbeit mit diesem.
Asteri
2

Python 3, 310

p={}
c=G=p.get
while c:
 l=("exit list buy count sell "+input("> ")).split();c=l.index(l[5]);*_,n=l
 if~-c%2*c:p[n]=(3-c)*int(l[6])+G(n,0)
 print(["The pie store has closed!","\n".join("| %*s | %9s |"%(max(map(len,p)),k,p[k])for k in p),G(n),G(n,"There is no %s pie!"%n),G(n),"That's not a valid command."][c])
Setzen Sie Monica wieder ein
quelle
1

Java - 772 751 739 713 666 619

Ich weiß, es ist nicht der Gewinn des Wettbewerbs, sondern nur zum Spaß!

import java.util.*;class a{static<T>void p(T p){System.out.print(p);}public static
 void main(String[]s){z:for(Map<String,Long>m=new HashMap();;){p("> ");s=new
 Scanner(System.in).nextLine().split(" ");switch(s[0]){case"list":for(Map.Entry 
e:m.entrySet())System.out.printf("|%12s|%6s|\n",e.getKey(),e.getValue());break;
case"count":p(m.get(s[1])!=null?m.get(s[1]):"There is no "+s[1]+" pie!\n");break;
case"buy":case"sell":long r=(s[0].length()==3?1:-1)*new Long(s[1])+(m.get(s[2])!=null?
m.get(s[2]):0);p(r+"\n");m.put(s[2],r);break;case"exit":p("The pie store has
 closed!");break z;default:p("That's not a valid command.\n");}}}}

Mit Zeilenumbrüchen und Tabulatoren:

import java.util.*;

class a{

    static<T>void p(T p){
        System.out.print(p);
    }

    public static void main(String[]s){
        z:for(Map<String,Long>m=new HashMap();;){
            p("\n> ");
            s=new Scanner(System.in).nextLine().split(" ");
            switch(s[0]){
            case"list":
                for(Map.Entry e:m.entrySet())
                    System.out.printf("|%12s|%6s|\n",e.getKey(),e.getValue());
                break;
            case"count":
                p(m.get(s[1])!=null?m.get(s[1]):"There is no "+s[1]+" pie!");
                break;
            case"buy":
            case"sell":
                long r=(s[0].length()==3?1:-1)*new Long(s[1])+(m.get(s[2])!=null?m.get(s[2]):0);
                p(r);
                m.put(s[2],r);
                break;
            case"exit":
                p("The pie store has closed!");
                break z;
            default:
                p("That's not a valid command.");
            }
        }
    }

}
Asteri
quelle
1
+1 für eine nicht-traditionelle Golfsprache :). Mit C # habe ich festgestellt, dass die switch-Anweisung teurer ist als einfache if {} -Konstrukte. Dies sollte auch für Java gelten.
Igby Largeman
@IgbyLargeman Ja, ich habe immer versucht, if/elsebilliger zu werden, aber aufgrund der Tatsache, dass ich etwas tun musste, s[0]=s[0].intern()um mich damit zu vergleichen ==, ist es immer mehr . Ich weiß, sehr eingängig.
Asteri