파이 가게를 관리하십시오!


12

요약

코드 골프가 좋습니다. 파이는 좋다 . 두 가지를 합치면 좋은 일만 일어날 수 있습니다.

명세서

이 도전에서 당신은 파이 가게를 관리합니다. 사용자는 다섯 개 가지 명령을 입력 할 수있을 것입니다 : list, count, buy, sell,와 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여부, 당신은 할 수 있습니다 중 하나를 반환 0또는 There is no {{type}} pie!때 당신 count을.

  • 이것은 . 가장 짧은 코드가 승리합니다.
  • 파이가 좋다고 언급 했습니까?

3
분명하게 말하자면 파이는 좋은가요?
Igby Largeman

4
카운트가 0 인 목록에 파이를 유지하는 것이 허용됩니까? 당신이 경우에 같이 buy 1 applesell 1 apple. 그리고 대신에 count apple반환 0하는 것이 유효 There is no apple pie!할까요?
Igby Largeman

@IgbyLargeman Darn 그것, 나는 모든 것을 명확히했다고 생각했다! : P 추가 설명을위한 새로운 테스트 사례 추가
Doorknob

@Doorknob 야! 마지막 파이가 팔린 후 "애플 파이가 없습니다"를 출력합니다.
John Dvorak

@ 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 |". 그러나 각 열을 개별적으로 축소하지는 않습니다. 요구 사항이 없었습니다. 하나의 크기는 모두 맞는. 그런 다음이 문자열은 복제되어 현재 행을 포함하는 2 요소 배열의 형식화 문자열로 사용됩니다. 마지막으로, +시작 부분이 가까워지면 단 하나의 선행 파이프 앞에 붙습니다. 아, puts배열을 잘 처리했습니다.

루비는 정규식 리터럴에 보간법을 가지고 있습니다. 타이트한 저장이지만 조금 절약됩니다.

Ruby는 when표현식 뒤에 세미콜론이 필요 하지만 키워드 앞에는 필요 하지 않습니다. 세미콜론을 줄 바꿈으로 바꾸면 이상한 렌더링 결과가 나타납니다.

그리고 물론, 마법 글로벌로 알려진 perlism과 그들에 대한 정규 표현식 리터럴의 자동 매칭.

또한 대부분의 문장 case은 표현입니다.


매우 영리한 트릭! +1
도어 손잡이

흠, 그러나 왜 Hash.new(0)대신에 {}?
Doorknob

1
> 값) 당신도 통과하지 않으면 기본 값은 -. @Doorknob 루비의 해시는 (키, 해시 블록을 전달하면 (또는 발전기 (객체를 전달하는 경우) 기본 값을 가질 수 있습니다 nil하지 않는 ( 리터럴 nil이 기본값으로 사용 됩니다
John Dvorak

h=Hash.new(0)=> h=Hash.new 0, print"> "=> 사용하여 몇 개의 문자를 저장할 수 있으며 그냥 가능 $><<'> '하다고 생각 [*h]합니다 h. 모든 상용구 텍스트가 실제로 추가되기 때문에 switch 문이없는 버전을 조합 해 보았습니다 : gist.github.com/chron/6315218 . 나는 무언가를 만들려고 노력 ruby -ap했지만 프롬프트에 대한 요구로 인해 어려움을
겪었

@chron 감사합니다! 첫 번째 줄을 놓쳤다는 것을 믿을 수 없으며 왜 $><<줄 바꿈을 인쇄 했다고 생각하는지 모르겠습니다 . 마지막 제안에 관해서는 ... 불행히도 해시는 "평평한"방법이 없습니다.
John Dvorak

3

루비, 427384

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인수없이 사용할 수 있습니다 . 기본적으로는 공백으로 분리 (또는 $;그이 설정되어있는 경우)
존 드보락

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]더 이상 한 번으로 두 번 대신 평가)합니다. 후자를 사용하십시오.
John Dvorak

@JanDvorak Oooh, 모든 팁을 주셔서 감사합니다. DI는 Ruby에 +=운영자 가 없다고 생각했습니다 . 그래서 내가 그것을 사용하지 않은 이유입니다. 어쩌면 그것은 단지입니다 ++. 나는 나의 포스트를 곧 편집 할 것이다
Doorknob

3

파이썬 파이는 437 -thon

마지막 두 번째 줄에 약간의 여유가 있다고 확신하지만 파이 유형과 숫자에 대한 막대를 정렬 해야하는 요구 사항은 두껍습니다.

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

실제로 count는 전혀 작동하지 않는 것 같습니다 . 실제로 때로는 작동하지만 때로는 작동하지 않습니다. 매우 이상합니다 ...
Doorknob

3
Hehe, 나는 그것이 일종의 이름 충돌이라는 것을 알았습니다 : P +1 아, 또한 당신의 프로그램을위한 나의 파일은 재미있는 이름을 가지고있었습니다 : pie.py: P
Doorknob

3

C # -571568 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 #을 사용하면 switch 문이 간단한 if {} 구문보다 비쌉니다. Java도 마찬가지입니다.
Igby Largeman

그래 @IgbyLargeman, 내가 가져 오려고 if/else덜 비싼하지만 때문에 내가해야 할 거라고는 사실 s[0]=s[0].intern()과 비교하기 위해 ==, 항상 될 수있을 테니까요 . 나는 매우 직관적 인 것을 알고 있습니다.
asteri
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.