Управляйте магазином пирогов!

12

Резюме

Код гольф это хорошо. Пирог это хорошо . Когда вы соединяете их вместе, могут случиться только хорошие вещи.

Характеристики

В этом испытании вы будете управлять магазином пирогов. Пользователь будет иметь возможность вводить пять различных команд: list, count, buy, sell, и exit. Вот спецификации для каждого:

  • list

    • Распечатайте список всех пирогов, принадлежащих и сколько. Разделяйте |и вставляйте пробел с обеих сторон. |s должны быть выровнены. Количество пирогов может быть отрицательным (это означает, что вы должны кому-то пирог :(). Например:

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

    • Напечатайте, сколько {{type}}там пирогов. Печать "Пирога нет {{type}}!" если нет {{type}}всегда будет соответствовать регулярному выражению \w+(т. е. оно всегда будет одним словом). Например, если у меня было количество пирогов, показанных в приведенном выше списке примеров, то

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

    • Добавьте {{n}}к счетчику {{type}}пирог и распечатайте его. Создать {{type}}пирог, если он не существует. {{n}}всегда будет соответствовать регулярному выражению [0-9]+(то есть, это всегда будет число). Вот еще один пример (с тем же набором пирогов, что и в предыдущих примерах):

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

    • Вычтите {{n}}из счета {{type}}пирог и распечатайте его. Создать {{type}}пирог, если он не существует. Пирог может быть отрицательным (о нет, это означало бы, что вы должны кому-то пирог!).

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

    • Распечатать "Магазин пирогов закрыт!" и выйдите из программы.

      > exit
      The pie store has closed!
      

Дальнейшие уточнения

  • Если вызывается несуществующая функция (первое слово), выведите «Это недопустимая команда».
  • Если существующая функция вызывается с недопустимыми аргументами (словами после первого слова), то, как ведет себя ваша программа, не имеет значения. «Недопустимые аргументы» включают в себя слишком много аргументов, слишком мало аргументов, {{n}}отсутствие числа и т. Д.
  • Пирог это хорошо.
  • Ваш вклад должен отличаться от вашего вывода. Если вы запускаете программу из командной строки / терминала / оболочки / другого текстового объекта, вы должны ввести префикс «» > ​"(знак «больше») и пробел) или какой-либо другой префикс ввода оболочки.
  • Пирог это хорошо.
  • Если все эти пояснения недостаточно хороши, вот несколько примеров вывода:

    > 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!
    
  • Если вы купить / продать пирог и чистый граф становится 0, вы можете либо сохранить его в listили нет, и вы можете либо вернуться 0или There is no {{type}} pie!когда вы countего.

  • Это ; самый короткий код выигрывает.
  • Я упоминал, что пирог хорош?
Дверная ручка
источник
3
Так что просто чтобы уточнить ... это пирог хорошо?
Игби Крупный человек
4
Допустимо ли держать в списке пирог с нулевым счетом? Нравится, если вы делаете buy 1 appleи sell 1 apple. И будет ли тогда правильным count appleвозвращение 0вместо There is no apple pie!?
Игби Ларджман
@IgbyLargeman Черт возьми, я думал, что все прояснил! : P Добавлен новый контрольный пример для дополнительных разъяснений
Ручка двери
@ Doorknob эй! Я выдаю "нет яблочного пирога" после того, как последний был продан.
Джон Дворак
@JanDvorak Хорошо, я полагаю, в любом случае будет работать. Обновлено снова
дверная ручка

Ответы:

3

Рубин, 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}

Некоторые хитрости здесь:

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

Идея Doorknob об использовании форматера - это шаг вперед, буквально. Во-первых, самая длинная строка в хэше среди всех ключей и значений форматируется с помощью " %%%ds |"создания строки, подобной " %6s |". Да, нет сжатия каждой колонки в отдельности. Там никогда не было требования к. Один размер подходит всем. Затем эта строка дублируется и используется в качестве строки форматирования для двухэлементного массива, содержащего текущую строку. Наконец, +слово «начало» получает свое слово и добавляет одну ведущую трубу. О, и putsимеет хорошую обработку массивов.

В Ruby есть интерполяция в литералах регулярных выражений. Это жесткое сохранение, но немного спасает.

Руби требует точек с запятой после whenвыражения, но не перед ключевым словом. Это приводит к странному артефакту рендеринга, когда точка с запятой заменяется на новую строку.

И, конечно же, перлизм, известный как магические глобалы и автоматическое сопоставление литералов регулярных выражений с ними.

Кроме того, большинство заявлений в том числе caseявляются выражениями.

Джон дворак
источник
Очень умные трюки! +1
дверная ручка
Хм, а почему Hash.new(0)вместо {}?
Дверная ручка
1
@ Doorknob Хэши Ruby могут иметь значения по умолчанию (если вы передаете объект) или даже генераторы (если вы передаете блок (ключ, хэш -> значение). Если вы не передаете либо, значение по умолчанию равно nil(что не разрешить добавление). Литерал использует nilв качестве значения по умолчанию
Джон Дворжак
Может сохранить несколько символов с h=Hash.new(0)=> h=Hash.new 0, print"> "=> $><<'> ', и я думаю, что [*h]может быть просто h. Я попытался собрать версию без оператора switch, поскольку весь этот шаблонный текст действительно складывается: gist.github.com/chron/6315218 . Я пытался заставить что-то работать, ruby -apно требование к подсказке усложняет: <
Пол Престиж
@chron спасибо! Не могу поверить, что пропустил первый, и я не уверен, почему я подумал, что $><<напечатал новую строку. Что касается последнего предложения ... к сожалению, у хэшей нет метода "сглаживания".
Джон Дворак
3

Рубин, 427 384 символов

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}

Благодаря Яну Двораку огромное улучшение с 427 до 384 (!)

Дверная ручка
источник
Вы можете использовать loop{...}вместо while 1do...end.
Джон Дворак
Вы можете использовать splitбез его аргумента. По умолчанию он разделяется на пробелы (или, $;если это установлено)
Джон Дворжак
p.keys.group_by(&:size).max[0]- ты ищешь p.keys.map(&:size).maxили p.map{|x,_|x.size}.max? Здесь: [(t=p.values).max.to_s.size,t.min.to_s.size].maxвы ищете p.map{|_,x|x.to_s.size}.max? Я собираюсь принять твою идею и злоупотреблять средством форматирования :-)
Джон Дворжак
p[t]=p[t]+mэквивалентно p[t]+=m(за исключением того, p[t]что оценивается дважды, а не один раз) и дольше. Используйте последнее.
Джон Дворак
@JanDvorak Ооо, спасибо за все советы: я думал, у Руби нет +=оператора; вот почему я не использовал его. Может быть, это только для ++. Я скоро отредактирую свой пост
Doorknob
3

питон Пирог -тон 437

Я уверен, что во второй последней строке есть некоторая слабость, но требование выравнивания столбцов как для типа, так и для числа круговых диаграмм является слишком сложным.

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

Согласно комментарию Игби Ларгмана, правила неясно, что делать, если был пирог определенного типа, но 0теперь есть. Поэтому я интерпретировал это в свою пользу.

Пример вывода:

> 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

источник
Извините, но в этом один > count potatoпроизводит That's not a valid command.вместоThere is no potato pie!
дверная ручка
@ Doorknob Вы работаете в IDLE?
Да. Я попробую в файле
Дверная ручка
На самом деле, кажется , что счет вообще не работает . На самом деле это иногда работает, но иногда нет. Это очень странно ...
Дверная ручка
3
Хе-хе, я знал, что это было какое-то столкновение именования: P +1 О, а также, у моего файла для вашей программы было забавное имя pie.py:: P
Ручка двери
3

C # - 571 568 559

Воспитывая тыл как обычно с безнадежно многословным 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;}}

введите описание изображения здесь

Я взял на себя смелость с правилом о выводе списка. Чтобы сохранить некоторые символы, я жестко закодировал ширину столбца count до максимальной ширины целочисленного значения. (Правила не гласили, что лишние пробелы запрещены.)

отформатирован:

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, я удивлен, что вы можете получить такое низкое количество символов с таким многословным языком: D
Ручка двери
Моя цель с Java - побить реализацию C #. Ха - ха. Хорошая работа с этим.
Астери
2

Питон 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

Ява - 772 751 739 713 666 619

Я знаю, что это не победа в конкурсе, а просто для удовольствия!

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

С переносами строк и вкладками:

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
источник
1
+1 за нетрадиционный язык игры в гольф :). С C # я обнаружил, что оператор switch более дорогой, чем простой if {}. Это должно быть верно и для Java.
Игби Крупный человек
@IgbyLargeman Да, я продолжал пытаться if/elseбыть менее дорогим, но из-за того, что мне нужно было сделать s[0]=s[0].intern(), чтобы сравнить с ==ним, всегда получалось больше . Я знаю, очень нелогично.
Астери