パイショップを経営しよう!


12

概要

コードゴルフは良いです。パイがいい。この2つを組み合わせると、良いことが起こるだけです。

仕様書

この課題では、パイショップを管理します。ユーザーは、5つの異なるコマンドを入力することができるようになります: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に戻るのに有効でしょうか?0There is no apple pie!
— イグビーラージマン

@IgbyLargemanくそー、私はすべてを明確にしたと思った!:P追加の説明に新しいテストケースを追加
— Doorknob

@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 |"。はい、各列を個別にシュリンクラップしません。要件はありませんでした。ワンサイズですべてに合います。次に、この文字列が複製され、現在の行を含む2要素配列のフォーマット文字列として使用されます。最後に、+スタート近くで単語が取得され、単一の先頭パイプが追加されます。ああ、そしてputs配列の素晴らしい取り扱いがあります。

Rubyには正規表現リテラルに補間があります。厳しい節約ですが、少しは節約できます。

Rubyでは、when式の後にセミコロンが必要ですが、キーワードの前には必要ありません。これにより、セミコロンが改行に置き換えられると、奇妙なレンダリングアーティファクトが発生します。

そして、もちろん、マジックグローバルとして知られているperlismと、それらに対する正規表現リテラルの自動マッチング。

また、含むほとんどのステートメント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に大幅に改善されたJan Dvorakに感謝します(!)


の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 Oooh、すべてのヒントをありがとう:DIはRubyには+=演算子がないと思った。それが私がそれを使わなかった理由です。たぶんそれはのためだけです++。間もなく投稿を編集します
— Doorknob

3

Python パイ 437 -thon

最後の2行目には多少のゆるみがあると思いますが、パイの種類と数の両方に合わせてバーを揃えるという要件は途方もないものです。

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

@Doorknob IDLEで実行していますか?

はい。ファイルを試してみます
— Doorknob

実際、カウントはまったく機能していないようです。実際には動作することもありますが、動作しないこともあります。非常に奇妙です...
— ドアノブ

3
Hehe、それはある種の名前の衝突だとわかっていました: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
— ドアノブ

Javaでの私の目標は、C#実装に勝つことだけです。ハハ。これでいい仕事だ。
— アステリー

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

コンテストに勝っていないことは知っていますが、ただ楽しんでいるだけです!

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にも当てはまります。
— イグビーラージマン

@IgbyLargemanええ、私はif/elseもっと安くなるように努力し続けましたがs[0]=s[0].intern()、比較するためにやらなければならないという事実のために==、それは常により多くなります。直観に反することを知っています。
— アステリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.