管理一家馅饼店!


12

摘要

打代码高尔夫很好。馅饼很好。将两者放在一起时,只会发生好事。

技术指标

在这个挑战中,您将管理一家馅饼店。用户将能够输入五个不同的命令:listcountbuysell,和exit。这是每个的规格:

  • list

    • 打印所有拥有的馅饼的列表,以及多少。与分开,|并在两侧各留一个空格。|必须对齐。派的金额可能为负(这意味着您欠某人的派:()。例如:

      | 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与否,你可以要么返回0There is no {{type}} pie!当你count吧。

  • 这是;最短的代码胜出。
  • 我是否提到派很好?

3
所以只是为了澄清...馅饼好吗?
Igby Largeman

4
将饼数保持为零是可以接受的吗?就像你做buy 1 applesell 1 apple。那么count apple0代替返回是否有效There is no apple pie!
Igby Largeman

@IgbyLargeman该死,我以为我澄清了一切!:P在新的说明中增加了新的测试用例
门把手

@Doorknob嘿!最后一个卖完后,我输出“没有苹果派”。
约翰·德沃夏克

@JanDvorak好吧,我想任何一种方法都可以。再次更新
门把手

Answers:


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在正则表达式文字中具有插值。节省了很多,但确实节省了一点。

Ruby在when表达式之后需要分号,但在关键字之前不需要分号。当用分行替换分号时,这会导致奇怪的渲染伪像。

而且,当然,perlism被称为魔术全局变量,并且针对它们自动匹配正则表达式文字。

另外,大多数语句包括case表达式。


非常聪明的把戏!+1
门把手

嗯,但是为什么要Hash.new(0)代替{}
门把手

1
@Doorknob Ruby的哈希可以具有默认值(如果您传递一个对象),甚至可以具有生成器(如果您传递一个块(键,哈希->值)。如果您都不传递,则默认值是nil(不传递)–文字nil用作默认值
John Dvorak

可以用h=Hash.new(0)=> h=Hash.new 0print"> "=> 保存几个字符$><<'> ',我认为[*h]可以h。我试过将没有switch语句的版本放在一起,因为所有这些样板文本实际上都累加了: gist.github.com/chron/6315218。我试图与ruby -ap
某人打交道

@chron谢谢!不敢相信我错过了第一个,而且我不确定为什么我想$><<打印换行符。至于最后的建议……不幸的是,哈希没有“扁平化”的方法。
John Dvorak

3

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

感谢Jan Dvorak从427到384的巨大改进(!)


您可以使用loop{...}代替while 1do...end
John Dvorak

您可以split不带参数使用。默认情况下,它按空格分割(或$;设置空格)
John Dvorak

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吗?我会接受您的想法并滥用格式化程序,但是:-)
John Dvorak

p[t]=p[t]+m等于p[t]+=m(除了p[t]两次评估而不是一次评估)和更长的时间。使用后者。
John Dvorak

@JanDvorak Oooh,感谢所有技巧:DI认为Ruby没有+=运算符;这就是为什么我不使用它。也许这只是为了++。我将在不久之后编辑我的帖子
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."

按照Igby Largeman的评论规则是周围是否有做什么不清楚的一种特定类型的馅饼,但也有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中运行它?

是。我将尝试使用一个文件
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;}}

在此处输入图片说明

我对列表输出规则有所保留。为了保存一些字符,我将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
Doorknob

我使用Java的目标仅仅是击败C#实现。哈哈。这项工作做得不错。
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

爪哇- 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#,我发现switch语句比简单的if {}构造要昂贵。Java也应如此。
Igby Largeman

@IgbyLargeman是啊,我一直试图让if/else不那么昂贵,但由于这样的事实,我必须做的s[0]=s[0].intern(),为了与之比较==,它总是最终被更多。我知道,非常违反直觉。
asteri
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.