Kelola toko kue!

12

Ringkasan

Golf kode bagus. Pai bagus . Ketika Anda menggabungkan keduanya, hanya hal-hal baik yang bisa terjadi.

Spesifikasi

Dalam tantangan ini, Anda akan mengelola toko kue. Pengguna akan dapat input lima perintah yang berbeda: list, count, buy, sell, dan exit. Berikut spesifikasi untuk masing-masing:

  • list

    • Cetak daftar semua kue yang dimiliki, dan berapa banyak. Pisahkan dengan |dan pad dengan spasi di kedua sisi. |s harus disejajarkan. Jumlah pie mungkin negatif (itu berarti Anda berhutang kepada seseorang :(). Sebagai contoh:

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

    • Cetak berapa banyak {{type}}pai yang ada. Cetak "Tidak ada {{type}}kue!" jika tidak ada. {{type}}akan selalu cocok dengan regex \w+(yaitu, itu akan selalu menjadi satu kata). Sebagai contoh, jika saya memiliki jumlah kue yang ditunjukkan dalam daftar contoh di atas, maka

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

    • Tambahkan {{n}}ke hitungan {{type}}pai, dan cetak. Buat {{type}}pai jika tidak ada. {{n}}akan selalu cocok dengan regex [0-9]+(yaitu, itu akan selalu berupa angka). Berikut contoh lain (dengan inventaris pie yang sama dengan contoh sebelumnya):

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

    • Kurangi {{n}}dari jumlah {{type}}pai, dan cetaklah. Buat {{type}}pai jika tidak ada. Pai bisa negatif (oh tidak, itu berarti Anda berutang pai pada seseorang!).

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

    • Cetak "Toko pai telah ditutup!" dan keluar dari program.

      > exit
      The pie store has closed!
      

Klarifikasi lebih lanjut

  • Jika fungsi yang tidak ada disebut (kata pertama), maka cetak "Itu bukan perintah yang valid."
  • Jika fungsi yang ada dipanggil dengan argumen yang tidak valid (kata-kata setelah kata pertama), bagaimana program Anda berperilaku tidak masalah. "Argumen tidak valid" mencakup terlalu banyak argumen, terlalu sedikit argumen, {{n}}tidak menjadi angka, dll.
  • Pai bagus.
  • Input Anda harus dibedakan dari output Anda. Jika Anda menjalankan program pada baris perintah / terminal / shell / hal berbasis teks lainnya, Anda harus mengawali input dengan tanda " > ​"(" lebih besar dari "dan spasi) atau beberapa hal awalan input shell lainnya.
  • Pai bagus.
  • Jika semua klarifikasi ini tidak cukup baik, berikut adalah beberapa contoh keluaran:

    > 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!
    
  • Jika Anda membeli menjual kue / dan jumlah bersih menjadi 0, Anda dapat baik tetap di listatau tidak, dan Anda dapat baik kembali 0atau There is no {{type}} pie!ketika Anda countitu.

  • Ini adalah ; kode menang paling pendek.
  • Apakah saya menyebutkan bahwa pai itu enak?
Gagang pintu
sumber
3
Jadi hanya untuk memperjelas ... apakah pie itu baik?
Igby Largeman
4
Apakah dapat diterima menyimpan pie dalam daftar dengan hitungan nol? Seperti jika Anda melakukannya buy 1 appledan sell 1 apple. Dan apakah itu akan berlaku untuk count applekembali, 0bukan There is no apple pie!?
Igby Largeman
@IgbyLargeman Sial, saya pikir saya sudah mengklarifikasi semuanya! : P Menambahkan test case baru ke klarifikasi tambahan
Gagang Pintu
@ Kerjaan hey! Saya mengeluarkan "tidak ada pai apel" setelah yang terakhir telah terjual.
John Dvorak
@ JanDvorak Baiklah, saya kira cara baik akan bekerja. Diperbarui lagi
Gagang Pintu

Jawaban:

3

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

Beberapa trik di sini:

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

Gagasan Doorknob untuk menggunakan formatter diambil selangkah lebih jauh di sini, secara harfiah. Pertama, string terpanjang dalam hash di antara semua kunci dan nilai diformat menggunakan " %%%ds |"untuk menghasilkan string seperti " %6s |". Yap, tidak ada penyusutan setiap kolom secara terpisah. Tidak pernah ada persyaratan untuk itu. Satu ukuran cocok untuk semua. Kemudian string ini digandakan dan digunakan sebagai string pemformatan untuk array dua elemen yang berisi baris saat ini. Akhirnya, +hampir mulai mendapatkan kata-katanya dan menambahkan satu pipa terkemuka. Oh, dan putsmemiliki penanganan array yang bagus.

Ruby memiliki interpolasi dalam regex literals. Ini adalah penyelamatan yang ketat, tetapi sedikit menghemat.

Ruby membutuhkan titik koma setelah whenekspresi, tetapi tidak sebelum kata kunci. Ini mengarah ke artefak render yang aneh ketika titik koma diganti dengan baris baru.

Dan, tentu saja, perlism dikenal sebagai sihir global dan pencocokan literal regex secara otomatis terhadap mereka.

Juga, sebagian besar pernyataan termasuk caseekspresi.

John Dvorak
sumber
Trik yang sangat pintar! +1
Gagang Pintu
Hmm, tapi mengapa Hash.new(0)bukannya {}?
Gagang Pintu
1
@Doorknob Rubi hash dapat memiliki nilai default (jika Anda melewati objek) atau bahkan generator (jika Anda melewati blok (kunci, nilai hash ->). Jika Anda tidak lulus, nilai defaultnya adalah nil(yang tidak bolehkan penambahan.) Secara literal menggunakan nilsebagai nilai default
John Dvorak
Bisa menyimpan beberapa karakter dengan h=Hash.new(0)=> h=Hash.new 0, print"> "=> $><<'> ', dan saya pikir [*h]bisa saja h. Saya mencoba menyusun versi tanpa pernyataan beralih karena semua teks boilerplate benar-benar bertambah: gist.github.com/chron/6315218 . Saya mencoba membuat sesuatu bekerja ruby -aptetapi persyaratan untuk prompt membuatnya sulit: <
Paul Prestidge
@ sinkron, terima kasih! Tidak percaya saya melewatkan yang pertama, dan saya tidak yakin mengapa saya pikir $><<mencetak baris baru. Adapun saran terakhir ... sayangnya, hash tidak memiliki metode "ratakan".
John Dvorak
3

Ruby, 427 384 karakter

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}

Terima kasih kepada Jan Dvorak untuk peningkatan besar dari 427 menjadi 384 (!)

Gagang pintu
sumber
Anda bisa menggunakan loop{...}bukan while 1do...end.
John Dvorak
Anda dapat menggunakan splittanpa argumennya. Secara default, ini terbagi berdasarkan spasi putih (atau $;jika itu diatur)
John Dvorak
p.keys.group_by(&:size).max[0]- Apakah kamu mencari p.keys.map(&:size).maxatau p.map{|x,_|x.size}.max? Di sini: [(t=p.values).max.to_s.size,t.min.to_s.size].maxapakah Anda mencari p.map{|_,x|x.to_s.size}.max? Tapi saya akan mengambil ide Anda dan menyalahgunakan formatter :-)
John Dvorak
p[t]=p[t]+msetara dengan p[t]+=m(kecuali p[t]dievaluasi dua kali alih-alih sekali) dan lebih lama. Gunakan yang terakhir.
John Dvorak
@ JanDvorak Oooh, terima kasih untuk semua tips: DI pikir Ruby tidak punya +=operator; itu sebabnya saya tidak menggunakannya. Mungkin itu hanya untuk ++. Saya akan segera mengedit posting saya
Doorknob
3

Python Pie -thon 437

Saya yakin ada beberapa kelonggaran pada baris terakhir kedua, tetapi persyaratan untuk menyelaraskan bar untuk kedua jenis dan nomor pie adalah doozy.

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

Sebagai per komentar Igby Largeman ini aturan tidak jelas di sekitar apa yang harus dilakukan jika ada adalah kue jenis tertentu, tetapi ada 0sekarang. Jadi saya menafsirkannya untuk kebaikan saya.

Output sampel:

> 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

sumber
Maaf, tetapi yang ini malah > count potatomenghasilkanThat's not a valid command.There is no potato pie!
Doorknob
@ Doorknob Apakah Anda menjalankannya di IDLE?
Iya. Saya akan mencoba dalam file
Gagang Pintu
Sebenarnya, menghitung tampaknya tidak berfungsi sama sekali . Sebenarnya itu kadang-kadang berfungsi tetapi kadang tidak. Ini sangat aneh ...
Gagang Pintu
3
Hehe, saya tahu itu semacam benturan penamaan: P +1 Oh dan juga, file saya untuk program Anda memiliki nama yang lucu pie.py:: P
Doorknob
3

C # - 571 568 559

Membawa bagian belakang seperti biasa dengan C # tanpa harapan verbose.

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

masukkan deskripsi gambar di sini

Saya mengambil beberapa kebebasan dengan aturan tentang output daftar. Untuk menyimpan beberapa karakter saya hardcoded lebar kolom hitung ke lebar maksimum nilai integer. (Aturan tidak mengatakan ruang ekstra tidak diperbolehkan.)

Diformat:

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
    }
}
Igby Largeman
sumber
1
+1, saya terkejut bahwa Anda bisa mendapatkan jumlah karakter yang rendah dengan bahasa yang begitu jelas: D
Doorknob
Tujuan saya dengan Java hanya untuk mengalahkan implementasi C #. Ha ha. Kerja bagus dengan yang satu ini.
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])
Pasang kembali Monica
sumber
1

Jawa - 772 751 739 713 666 619

Saya tahu ini bukan memenangkan kontes, tetapi hanya untuk bersenang-senang!

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

Dengan jeda baris dan tab:

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
sumber
1
+1 untuk bahasa golf non-tradisional :). Dengan C # saya menemukan bahwa pernyataan switch lebih mahal daripada sederhana jika {} membangun. Ini juga berlaku untuk Java.
Igby Largeman
@IgbyLargeman Ya, saya terus berusaha untuk if/elsemenjadi lebih murah, tetapi karena fakta yang harus saya lakukan s[0]=s[0].intern()untuk membandingkan ==, selalu selalu menjadi lebih . Saya tahu, sangat berlawanan dengan intuisi.
asteri