Gérez une tarte!

12

Sommaire

Le golf de code est bon. La tarte est bonne . Lorsque vous associez les deux, seules les bonnes choses peuvent arriver.

Caractéristiques

Dans ce défi, vous gérerez une boutique de tarte. L'utilisateur sera en mesure de saisir cinq commandes différentes: list, count, buy, sell, et exit. Voici les spécifications de chacun:

  • list

    • Imprimez une liste de toutes les tartes possédées et combien. Séparez avec |et garnissez avec un espace de chaque côté. |s doivent être alignés. Le montant du gâteau peut être négatif (cela signifie que vous devez un gâteau à quelqu'un :(). Par exemple:

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

    • Imprimez le nombre de {{type}}tartes. Imprimer "Il n'y a pas de {{type}}tarte!" s'il n'y en a pas. {{type}}correspondra toujours à l'expression régulière \w+(c'est-à-dire qu'il s'agira toujours d'un seul mot). Par exemple, si j'avais le nombre de tartes indiqué dans la liste d'exemples ci-dessus, alors

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

    • Ajoutez {{n}}au nombre de {{type}}tartes et imprimez-le. Créez une {{type}}tarte si elle n'existe pas. {{n}}correspondra toujours à l'expression rationnelle [0-9]+(c.-à-d., ce sera toujours un nombre). Voici un autre exemple (avec le même inventaire à tarte que les exemples précédents):

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

    • Soustrayez {{n}}le nombre de {{type}}tartes et imprimez-le. Créez une {{type}}tarte si elle n'existe pas. La tarte peut être négative (oh non, cela voudrait dire que vous devez une tarte à quelqu'un!).

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

    • Imprimer "Le magasin de tarte a fermé!" et quittez le programme.

      > exit
      The pie store has closed!
      

Précisions supplémentaires

  • Si une fonction inexistante est appelée (le premier mot), imprimez «Ce n'est pas une commande valide».
  • Si une fonction existante est appelée avec des arguments invalides (les mots après le premier mot), le comportement de votre programme n'a pas d'importance. "Arguments invalides" comprend trop d'arguments, trop peu d'arguments, {{n}}n'étant pas un nombre, etc.
  • La tarte est bonne.
  • Votre entrée doit être distinguée de votre sortie. Si vous exécutez le programme sur la ligne de commande / terminal / shell / autre élément textuel, vous devez préfixer l'entrée avec " > ​"(un signe" supérieur à "et un espace) ou un autre élément de préfixe d'entrée de shell.
  • La tarte est bonne.
  • Si toutes ces clarifications ne sont pas suffisantes, voici quelques exemples de sortie:

    > 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!
    
  • Si vous achetez / vendez une tarte et que le nombre net devient 0, vous pouvez le conserver dans le listou non, et vous pouvez soit le retourner, 0soit There is no {{type}} pie!quand vous countle souhaitez .

  • C'est du ; le code le plus court gagne.
  • Ai-je mentionné que la tarte est bonne?
Poignée de porte
la source
3
Alors juste pour clarifier ... la tarte est-elle bonne?
Igby Largeman
4
Est-il acceptable de garder une tarte dans la liste avec un compte de zéro? Comme si vous le faites buy 1 appleet sell 1 apple. Et serait-il alors valable pour count applerevenir à la 0place de There is no apple pie!?
Igby Largeman
@IgbyLargeman Bon sang, je pensais avoir tout clarifié! : P Ajout d'un nouveau cas de test à des clarifications supplémentaires
Poignée de porte
@ Doorknob hey! Je produis "il n'y a pas de tarte aux pommes" après que le dernier a été vendu.
John Dvorak
@JanDvorak Très bien, je suppose que l'une ou l'autre façon fonctionnera. Mise à jour à nouveau
Poignée de porte

Réponses:

3

Rubis, 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}

Quelques astuces ici:

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

L'idée de Doorknob d'utiliser un formateur est prise un peu plus loin ici, littéralement. Tout d'abord, la chaîne la plus longue du hachage parmi toutes les clés et valeurs est formatée en utilisant " %%%ds |"pour produire une chaîne comme " %6s |". Oui, pas d'emballage sous film rétractable séparément. Il n'y a jamais eu l'obligation de le faire. Taille unique. Cette chaîne est ensuite dupliquée et utilisée comme chaîne de formatage pour le tableau à deux éléments contenant la ligne actuelle. Enfin, le +début du mot obtient son mot et ajoute un seul tuyau de tête. Oh, et putsa une belle gestion des tableaux.

Ruby a une interpolation dans les littéraux d'expression régulière. C'est une sauvegarde serrée, mais ça économise un peu.

Ruby requiert des points-virgules après l' whenexpression, mais pas avant le mot-clé. Cela conduit à un artefact de rendu étrange lorsque le point-virgule est remplacé par une nouvelle ligne.

Et, bien sûr, le perlisme connu sous le nom de globaux magiques et l'appariement automatique des littéraux d'expression régulière contre eux.

De plus, la plupart des instructions, y compris des caseexpressions.

John Dvorak
la source
Astuces très intelligentes! +1
Poignée de porte
Hmm, mais pourquoi Hash.new(0)au lieu de {}?
Poignée de porte
1
Les hachages de @Doorknob Ruby peuvent avoir des valeurs par défaut (si vous passez un objet) ou même des générateurs (si vous passez un bloc (clé, hachage -> valeur). Si vous ne passez pas non plus, la valeur par défaut est nil(qui ne autoriser l'ajout). Le littéral utilise nilcomme valeur par défaut.
John Dvorak
Pourrait enregistrer quelques caractères avec h=Hash.new(0)=> h=Hash.new 0, print"> "=> $><<'> ', et je pense que cela [*h]peut être juste h. J'ai essayé de créer une version sans l'instruction switch car tout ce texte passe-partout s'additionne vraiment: gist.github.com/chron/6315218 . J'essayais de faire fonctionner quelque chose, ruby -apmais l'exigence de l'invite rend la
tâche
@chron merci! Je ne peux pas croire que j'ai raté le premier, et je ne sais pas pourquoi j'ai pensé $><<imprimer une nouvelle ligne. Quant à la dernière suggestion ... malheureusement, les hachages n'ont pas de méthode "aplatir".
John Dvorak
3

Ruby, 427 384 caractères

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}

Merci à Jan Dvorak d'une énorme amélioration de 427 à 384 (!)

Poignée de porte
la source
Vous pouvez utiliser à la loop{...}place de while 1do...end.
John Dvorak
Vous pouvez utiliser splitsans son argument. Par défaut, il se divise par des espaces (ou $;si cela est défini)
John Dvorak
p.keys.group_by(&:size).max[0]- cherchez-vous p.keys.map(&:size).maxou p.map{|x,_|x.size}.max? Ici: [(t=p.values).max.to_s.size,t.min.to_s.size].maxcherchez-vous p.map{|_,x|x.to_s.size}.max? Je vais prendre votre idée et abuser du formateur, cependant :-)
John Dvorak
p[t]=p[t]+mest équivalent à p[t]+=m(sauf p[t]est évalué deux fois au lieu d'une fois) et plus long. Utilisez ce dernier.
John Dvorak
@JanDvorak Oooh, merci pour tous les conseils: DI pensait que Ruby n'avait pas d' +=opérateur; c'est pourquoi je ne l'ai pas utilisé. Peut-être que c'est juste pour ++. Je modifierai mon article sous peu
Poignée de porte
3

Python Pie -thon 437

Je suis sûr qu'il y a un peu de jeu sur l'avant-dernière ligne, mais l'exigence d'aligner les barres pour le type et le nombre de tarte est un doozy.

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."

Selon le commentaire d'Igby Largeman, les règles ne sont pas claires sur ce qu'il faut faire s'il y avait une tarte d'un type spécifique, mais il y en a 0maintenant. Je l'ai donc interprété en ma faveur.

Exemple de sortie:

> 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

la source
Désolé, mais dans celui-ci > count potatoproduit That's not a valid command.au lieu deThere is no potato pie!
Poignée de porte
@ Doorknob Le lancez-vous dans IDLE?
Oui. Je vais essayer dans un fichier
Poignée de porte
En fait, le décompte ne semble pas fonctionner du tout . En fait, cela fonctionne parfois, mais parfois non. C'est très étrange ...
Poignée de porte
3
Héhé, je savais que c'était une sorte de conflit de dénomination: P +1 Oh et aussi, mon fichier pour votre programme avait un nom amusant pie.py:: P
Poignée de porte
3

C # - 571 568 559

Amener l'arrière comme d'habitude avec le C # désespérément verbeux.

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;}}

entrez la description de l'image ici

J'ai pris une certaine liberté avec la règle sur la sortie de liste. Pour enregistrer certains caractères, j'ai codé en dur la largeur de la colonne de comptage à la largeur maximale d'une valeur entière. (Les règles ne disaient pas que les espaces supplémentaires n'étaient pas autorisés.)

Formaté:

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
la source
1
+1, je suis surpris que vous puissiez obtenir un nombre de caractères aussi bas avec une langue aussi verbeuse: D
Poignée de porte
Mon objectif avec Java est uniquement de battre l'implémentation C #. Haha. Beau travail avec celui-ci.
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])
Réintégrer Monica
la source
1

Java - 772 751 739 713 666 619

Je sais que ce n'est pas gagner le concours, mais juste pour le plaisir!

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");}}}}

Avec les sauts de ligne et les tabulations:

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
la source
1
+1 pour une langue de golf non traditionnelle :). Avec C #, j'ai trouvé que l'instruction switch est plus chère que la simple construction si {}. Cela devrait également être vrai pour Java.
Igby Largeman
@ IgbyLargeman Oui, j'ai continué à essayer d' if/elseêtre moins cher, mais en raison du fait que je devais le faire s[0]=s[0].intern()pour pouvoir comparer ==, cela finit toujours par être plus . Je sais, très contre-intuitif.
asteri