Gestisci un negozio di torte!


12

Sommario

Il codice golf è buono. La torta è buona . Quando metti insieme i due, possono succedere solo cose buone.

specificazioni

In questa sfida gestirai un negozio di torte. L'utente sarà in grado di immettere cinque diversi comandi: list, count, buy, sell, e exit. Ecco le specifiche per ciascuno:

  • list

    • Stampa un elenco di tutte le torte di proprietà e quante. Separare con |e pad con uno spazio su entrambi i lati. |s deve essere allineato. L'importo della torta può essere negativo (ciò significa che devi una torta a qualcuno :(). Per esempio:

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

    • Stampa quante {{type}}torte ci sono. Stampa "Non c'è {{type}}torta!" se non ce n'è. {{type}}corrisponderà sempre alla regex \w+(cioè, sarà sempre una singola parola). Ad esempio, se avessi la quantità di torte mostrata nell'elenco degli esempi sopra, allora

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

    • Aggiungi {{n}}al conteggio della {{type}}torta e stampalo. Crea una {{type}}torta se non esiste. {{n}}corrisponderà sempre alla regex [0-9]+(cioè, sarà sempre un numero). Ecco un altro esempio (con lo stesso inventario di torta degli esempi precedenti):

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

    • Sottrai {{n}}dal conteggio della {{type}}torta e stampalo. Crea una {{type}}torta se non esiste. La torta può essere negativa (oh no, ciò significherebbe che devi una torta a qualcuno!).

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

    • Stampa "Il negozio di torte è chiuso!" e uscire dal programma.

      > exit
      The pie store has closed!
      

Ulteriori chiarimenti

  • Se viene chiamata una funzione inesistente (la prima parola), stampa "Non è un comando valido".
  • Se una funzione esistente viene chiamata con argomenti non validi (le parole dopo la prima parola), il comportamento del programma non ha importanza. "Argomenti non validi" include troppi argomenti, troppo pochi argomenti, {{n}}non essendo un numero, ecc.
  • La torta è buona.
  • Il tuo input deve essere distinto dal tuo output. Se stai eseguendo il programma sulla riga di comando / terminal / shell / altra cosa basata su testo, devi aggiungere un prefisso " > ​"(un segno" maggiore di "e uno spazio) o qualche altra cosa del prefisso di input della shell.
  • La torta è buona.
  • Se tutti questi chiarimenti non sono abbastanza buoni, ecco alcuni esempi di output:

    > 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!
    
  • Se si acquista torta / vendita e il numero di rete diventa 0, è possibile sia tenerlo in listo no, e si può sia ritornare 0o There is no {{type}} pie!quando countesso.

  • Questo è ; vince il codice più breve.
  • Ho già detto che la torta è buona?

3
Quindi, solo per chiarire ... la torta è buona?
Igby Largeman,

4
È accettabile tenere una torta nell'elenco con un conteggio di zero? Come se lo facessi buy 1 applee sell 1 apple. E sarebbe quindi valido count applerestituire 0invece di There is no apple pie!?
Igby Largeman,

@IgbyLargeman Maledizione, pensavo di aver chiarito tutto! : P Aggiunto nuovo test per ulteriori chiarimenti
Maniglia

@Doorknob hey! Sto producendo "non c'è la torta di mele" dopo che l'ultimo è stato venduto.
John Dvorak,

@JanDvorak Bene, suppongo che funzionerà in entrambi i modi. Aggiornato di nuovo
Maniglia

Risposte:


3

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

Alcuni trucchi qui:

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

L'idea di Doorknob di usare un formatter è un passo avanti qui, letteralmente. Innanzitutto, la stringa più lunga nell'hash tra tutte le chiavi e i valori viene formattata usando " %%%ds |"per produrre una stringa simile " %6s |". Sì, nessun restringimento avvolgendo ciascuna colonna separatamente. Non è mai stato necessario. Taglia unica. Quindi questa stringa viene duplicata e utilizzata come stringa di formattazione per l'array a due elementi contenente la riga corrente. Alla fine, +vicino all'inizio prende la parola e antepone una singola pipe iniziale. Oh, e putsha una buona gestione degli array.

Ruby ha interpolazione in letterali regex. È un salvataggio stretto, ma risparmia un po '.

Ruby richiede punto e virgola dopo l' whenespressione, ma non prima della parola chiave. Questo porta a uno strano artefatto di rendering quando il punto e virgola viene sostituito con una nuova riga.

E, naturalmente, il perlismo noto come globi magici e l'abbinamento automatico dei letterali regex contro di loro.

Inoltre, la maggior parte delle dichiarazioni incluse casesono espressioni.


Trucchi molto intelligenti! +1
Maniglia della porta

Hmm, ma perché Hash.new(0)invece di {}?
Maniglia della porta

1
Gli hash di @Doorknob Ruby possono avere valori predefiniti (se si passa un oggetto) o persino generatori (se si passa un blocco (chiave, hash -> valore). Se non si passa neanche uno, il valore predefinito è nil(che non consentire l'aggiunta) .Il nilvalore letterale viene utilizzato come valore predefinito.
John Dvorak,

Potrei salvare alcuni caratteri con h=Hash.new(0)=> h=Hash.new 0, print"> "=> $><<'> ', e penso che [*h]possa essere h. Ho provato a mettere insieme una versione senza l'istruzione switch dal momento che tutto il testo del bollettino si aggiunge davvero: gist.github.com/chron/6315218 . Stavo cercando di far funzionare qualcosa ruby -apma il requisito per il prompt lo rende difficile: <
Paul Prestidge

@chron grazie! Non riesco a credere di aver perso il primo, e non sono sicuro del motivo per cui ho pensato di $><<stampare una nuova riga. Per quanto riguarda l'ultimo suggerimento ... sfortunatamente, gli hash non hanno un metodo "appiattisci".
John Dvorak,

3

Rubino, 427384 caratteri

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}

Grazie a Jan Dvorak di enorme miglioramento da 427 a 384 (!)


Puoi usare loop{...}invece di while 1do...end.
John Dvorak,

Puoi usare splitsenza il suo argomento. Per impostazione predefinita, si divide per spazi bianchi (o $;se impostato)
John Dvorak,

p.keys.group_by(&:size).max[0]- stai cercando p.keys.map(&:size).maxo p.map{|x,_|x.size}.max? Qui: [(t=p.values).max.to_s.size,t.min.to_s.size].maxstai cercando p.map{|_,x|x.to_s.size}.max? Prenderò la tua idea e abuserò del formattatore, però :-)
John Dvorak il

p[t]=p[t]+mè equivalente a p[t]+=m(tranne che p[t]viene valutato due volte anziché una volta) e più a lungo. Usa quest'ultimo.
John Dvorak,

@JanDvorak Oooh, grazie per tutti i suggerimenti: DI pensava che Ruby non avesse un +=operatore; ecco perché non l'ho usato. Forse è solo per ++. Modificherò il mio post a breve
Maniglia della porta

3

Pitone Pie -thon 437

Sono sicuro che ci sia un po 'di tensione sulla seconda ultima riga, ma il requisito di allineare le barre sia per il tipo che per il numero di torta è 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."

Secondo il commento di Igby Largeman le regole non sono chiare su cosa fare se ci fosse una torta di un tipo specifico, ma 0ora ci sono . Quindi l'ho interpretato a mio favore.

Uscita campione:

> 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

Siamo spiacenti, ma in questo > count potatoproduce That's not a valid command.inveceThere is no potato pie!
Maniglia

@Doorknob Lo stai eseguendo in IDLE?

Sì. Proverò in un file
Maniglia della porta

In realtà, il conteggio non sembra funzionare affatto . In realtà funziona a volte ma a volte no. È molto strano ...
Maniglia della porta

3
Hehe, sapevo che si trattava di uno scontro di nomi di qualche tipo: P +1 Oh, e anche, il mio file per il tuo programma aveva un nome divertente pie.py:: P
Maniglia della porta

3

C # - 571 568 559

Solleva la parte posteriore come al solito con il C # irrimediabilmente prolisso.

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

inserisci qui la descrizione dell'immagine

Mi sono preso un po 'di libertà con la regola sull'output dell'elenco. Per salvare alcuni caratteri ho codificato la larghezza della colonna di conteggio alla larghezza massima di un valore intero. (Le regole non dicevano che non fossero ammessi spazi extra.)

formattato:

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

1
+1, sono sorpreso che puoi ottenere un conteggio dei caratteri così basso con un linguaggio così prolisso: D
Maniglia della porta

Il mio obiettivo con Java è solo quello di battere l'implementazione in C #. Haha. Bel lavoro con questo.
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])

1

Java - 772 751 739 713 666 619

So che non sta vincendo il concorso, ma solo per divertimento!

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

Con interruzioni di riga e schede:

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

}

1
+1 per una lingua di golf non tradizionale :). Con C # ho scoperto che l'istruzione switch è più costosa che semplice se {} costruisce. Questo dovrebbe essere vero anche per Java.
Igby Largeman,

@IgbyLargeman Sì, ho continuato a cercare di if/elseessere meno costoso, ma a causa del fatto che dovrei fare s[0]=s[0].intern()per confrontarmi ==, finisce sempre per essere più . Lo so, molto controintuitivo.
asteri,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.