Управління пиріжком!


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

@Doorknob ей! Я виводжу "немає яблучного пирога" після того, як був проданий останній.
Джон Дворак

@JanDvorak Добре, я вважаю, що будь-який спосіб буде працювати. Оновлено знову
Doorknob

Відповіді:


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. Я спробував скласти версію без оператора перемикання, оскільки весь текст цього шаблону дійсно додається: gist.github.com/chron/6315218 . Я намагався змусити щось попрацювати, ruby -apале вимога до підказок робить це важким: <
Paul Prestidge

@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 О, дякую за всі поради: DI подумав, що у Рубі немає +=оператора; тому я цим не користувався. Можливо, це просто для ++. Я скоро відредагую своє повідомлення
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

@Doorknob Ви працюєте в IDLE?

Так. Спробую у файлі
Doorknob

Власне, підрахунок, здається, не працює взагалі . Насправді це працює іноді, але іноді - ні. Це дуже дивно ...
Doorknob

3
Хе-хе, я знав, що це якесь зіткнення іменування: P +1 О, а також мій файл для вашої програми мав кумедне ім’я pie.py:: P
Doorknob

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

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

Я взяв деяку свободу з правилом про вихід списку. Щоб зберегти деякі символи, я жорстко кодував ширину стовпця підрахунку до максимальної ширини цілого числа. (У правилах не вказано, що додаткові пробіли заборонені.)

Відформатовано:

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
Doorknob

Моя мета з Java - лише перемогти реалізацію C #. Ха-ха. Гарна робота з цим.
asteri

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

}

1
+1 за нетрадиційну мову гольфу :). За допомогою C # я виявив, що оператор перемикання дорожчий, ніж простий, якщо {} конструкції. Це має бути справедливо і для Java.
Ігбі Ларгеман

@IgbyLargeman Так, я намагався if/elseстати менш дорогим, але через те, що мені доведеться зробити s[0]=s[0].intern()для порівняння ==, це завжди стає більше . Я знаю, дуже контрінтуїтивний.
астері
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.