¡Administra una pastelería!

12

Resumen

El código de golf es bueno. El pastel está bien . Cuando juntas los dos, solo pueden pasar cosas buenas.

Especificaciones

En este desafío, administrará una pastelería. El usuario será capaz de introducir cinco comandos diferentes: list, count, buy, sell, y exit. Aquí están las especificaciones para cada uno:

  • list

    • Imprima una lista de todos los pasteles que posee y cuántos. Separa con una |almohadilla con un espacio a cada lado. |s debe estar alineado. La cantidad del pastel puede ser negativa (eso significa que le debe pastel a alguien :(). Por ejemplo:

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

    • Imprime cuántas {{type}}tartas hay. Imprimir "¡No hay {{type}}pastel!" si no hay ninguno {{type}}siempre coincidirá con la expresión regular \w+(es decir, siempre será una sola palabra). Por ejemplo, si tuviera la cantidad de pasteles que se muestra en la lista de ejemplos anterior, entonces

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

    • Agregue {{n}}al recuento de {{type}}pastel e imprímalo. Crea un {{type}}pastel si no existe. {{n}}siempre coincidirá con la expresión regular [0-9]+(es decir, siempre será un número). Aquí hay otro ejemplo (con el mismo inventario circular que los ejemplos anteriores):

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

    • Reste {{n}}del recuento de {{type}}pastel e imprímalo. Crea un {{type}}pastel si no existe. El pastel puede ser negativo (¡oh no, eso significaría que le debes pastel a alguien!).

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

    • Imprimir "¡La tarta ha cerrado!" y salga del programa.

      > exit
      The pie store has closed!
      

Aclaraciones adicionales

  • Si se llama a una función no existente (la primera palabra), imprima "Ese no es un comando válido".
  • Si se llama a una función existente con argumentos no válidos (las palabras después de la primera palabra), no importa cómo se comporta su programa. Los "argumentos inválidos" incluyen demasiados argumentos, muy pocos argumentos, {{n}}no ser un número, etc.
  • El pastel está bien.
  • Su entrada debe distinguirse de su salida. Si está ejecutando el programa en la línea de comando / terminal / shell / otra cosa basada en texto, debe prefijar la entrada con " > ​"(un signo" mayor que "y un espacio) o alguna otra cosa de prefijo de entrada de shell.
  • El pastel está bien.
  • Si todas estas aclaraciones no son lo suficientemente buenas, aquí hay algunos resultados de muestra:

    > 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 compra pastel / venta y el recuento neta se convierte 0, puede o bien mantenerlo en el listo no, y puede o bien volver 0o There is no {{type}} pie!cuando countla misma.

  • Este es el ; el código más corto gana.
  • ¿Mencioné que el pastel es bueno?
Pomo de la puerta
fuente
3
Entonces, para aclarar ... ¿está bueno el pastel?
Igby Largeman
44
¿Es aceptable mantener un pastel en la lista con un recuento de cero? Me gusta si lo haces buy 1 appley sell 1 apple. ¿Y entonces sería válido count appleregresar en 0lugar de There is no apple pie!?
Igby Largeman
@IgbyLargeman Maldición, ¡pensé que lo había aclarado todo! : P Se agregó un nuevo caso de prueba a aclaraciones adicionales
Pomo de la puerta
@Doorknob ¡Hola! Estoy mostrando "no hay pastel de manzana" después de que se vendió el último.
John Dvorak
@ JanDvorak Muy bien, supongo que de cualquier manera funcionará. Actualizado de nuevo
Pomo de la puerta

Respuestas:

3

Rubí, 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}

Algunos trucos aquí:

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

La idea de Doorknob de usar un formateador se da un paso más allá, literalmente. Primero, la cadena más larga en el hash entre todas las claves y valores se formatea usando " %%%ds |"para producir una cadena como " %6s |". Sí, no encoge cada columna por separado. Nunca hubo el requisito de hacerlo. Talla única para todos. Luego, esta cadena se duplica y se usa como una cadena de formato para la matriz de dos elementos que contiene la fila actual. Finalmente, +cerca del inicio recibe su palabra y antepone una sola tubería principal. Ah, y putstiene un buen manejo de matrices.

Ruby tiene interpolación en literales regex. Es una salvación apretada, pero ahorra un poco.

Ruby requiere punto y coma después de la whenexpresión, pero no antes de la palabra clave. Esto conduce a un extraño artefacto de representación cuando el punto y coma se reemplaza con una nueva línea.

Y, por supuesto, el perlismo conocido como globals mágicos y la coincidencia automática de literales regex contra ellos.

Además, la mayoría de las declaraciones incluidas caseson expresiones.

John Dvorak
fuente
¡Trucos muy ingeniosos! +1
Pomo de la puerta
Hmm, pero ¿por qué en Hash.new(0)lugar de {}?
Pomo de la puerta
1
Los hashes de @Doorknob Ruby pueden tener valores predeterminados (si pasa un objeto) o incluso generadores (si pasa un bloque (clave, hash -> valor). Si no pasa ninguno, el valor predeterminado es nil(que no permitir la adición). El literal utiliza nilcomo valor predeterminado.
John Dvorak
Podría guardar algunos caracteres con h=Hash.new(0)=> h=Hash.new 0, print"> "=> $><<'> ', y creo que [*h]puede ser h. Intenté armar una versión sin la declaración de cambio ya que todo ese texto repetitivo realmente se suma: gist.github.com/chron/6315218 . Estaba tratando de hacer que algo funcionara, ruby -appero el requisito para el aviso lo dificulta: <
Paul Prestidge
@chron gracias! No puedo creer que me perdí el primero, y no estoy seguro de por qué pensé que $><<imprimí una nueva línea. En cuanto a la última sugerencia ... desafortunadamente, los hashes no tienen un método de "aplanamiento".
John Dvorak el
3

Rubí, 427384 caracteres

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}

Gracias a Jan Dvorak de gran mejora de 427 a 384 (!)

Pomo de la puerta
fuente
Puedes usar en loop{...}lugar de while 1do...end.
John Dvorak
Se puede usar splitsin su argumento. Por defecto, se divide por espacios en blanco (o $;si está configurado)
John Dvorak
p.keys.group_by(&:size).max[0]- ¿Estás buscando p.keys.map(&:size).maxo p.map{|x,_|x.size}.max? Aquí: [(t=p.values).max.to_s.size,t.min.to_s.size].max¿estás buscando p.map{|_,x|x.to_s.size}.max? Sin embargo, tomaré tu idea y abusaré del formateador :-)
John Dvorak
p[t]=p[t]+mes equivalente a p[t]+=m(excepto que p[t]se evalúa dos veces en lugar de una vez) y más largo. Usa el último.
John Dvorak
@ JanDvorak Oooh, gracias por todos los consejos: DI pensó que Ruby no tenía +=operador; Por eso no lo usé. Tal vez eso es solo para ++. Editaré mi publicación en breve
Doorknob
3

Pitón Pie -thon 437

Estoy seguro de que hay un poco de holgura en la segunda última línea, pero el requisito de alinear las barras tanto para el tipo de tarta como para el número es muy confuso.

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

De acuerdo con el comentario de Igby Largeman las reglas no están claras en torno a qué hacer si no era un pastel de un tipo específico, pero hay 0ahora. Entonces lo he interpretado a mi favor.

Salida de muestra:

> 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

fuente
Lo sentimos, pero en este se > count potatoproduce en That's not a valid command.lugar deThere is no potato pie!
Pomo
@Doorknob ¿Lo estás ejecutando en IDLE?
Si. Lo intentaré en un archivo
pomo de la puerta
En realidad, el conteo no parece estar funcionando en absoluto . En realidad funciona a veces, pero a veces no. Es muy extraño ...
Pomo de la puerta
3
Jeje, sabía que era un choque de nombres de algún tipo: P +1 Ah, y también, mi archivo para su programa tenía un nombre divertido pie.py:: P
Pomo de la puerta
3

C # - 571 568 559

Levantando la parte trasera como de costumbre con el irremediablemente detallado C #.

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

ingrese la descripción de la imagen aquí

Me tomé un poco de libertad con la regla sobre la salida de la lista. Para guardar algunos caracteres, codifiqué el ancho de la columna de conteo al ancho máximo de un valor entero. (Las reglas no decían que no se permitían espacios adicionales).

Formateado:

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
fuente
1
+1, me sorprende que puedas obtener un recuento de caracteres tan bajo con un lenguaje tan detallado: D
Pomo de la puerta
Mi objetivo con Java es solo superar la implementación de C #. Jaja. Buen trabajo con este.
asteri
2

Pitón 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])
Reinstalar a Mónica
fuente
1

Java - 772 751 739 713 666 619

Sé que no está ganando el concurso, ¡sino solo por diversión!

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 saltos de línea y pestañas:

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
fuente
1
+1 para un idioma de golf no tradicional :). Con C # descubrí que la declaración de cambio es más costosa que simple si {} construye. Esto también debería ser cierto para Java.
Igby Largeman
@IgbyLargeman Sí, seguí tratando de llegar if/elsea ser menos costoso, pero debido al hecho de que tendría que hacer s[0]=s[0].intern()para comparar ==, siempre termina siendo más . Lo sé, muy contradictorio.
asteri