Code golf: Mendistribusikan bola (I)


12

Tantangan

Dalam tugas ini Anda telah menghitung jumlah cara kami dapat mendistribusikan bola A ke dalam sel B dengan setiap sel memiliki setidaknya satu bola.

Input A dan B diberikan dalam satu baris yang dipisahkan oleh blank, input diakhiri oleh EOF.

Anda mungkin ingin memeriksa solusi Anda di sini .

Memasukkan

0 0
1 0
12 4
6 3
18 17
20 19
15 13
18 9
20 20
17 14
9 2
14 13
18 11

Keluaran

1
0
14676024
540
54420176498688000
23112569077678080000
28332944640000
38528927611574400
2432902008176640000
21785854970880000
510
566658892800
334942064711654400

Kendala

  • Setiap A dan B dapat dibedakan.
  • 0 <= A, B <= 20
  • Anda dapat menggunakan bahasa pilihan Anda
  • Solusi terpendek menang!

1
Apakah ada batasan waktu?

@Tim Nordenfur: Diperbarui :-)
Quixotic

Tautan itu tidak valid untuk saya.
mellamokb

3
@ Debanjan Saya tidak suka ide menyisipkan pertanyaan dari SPOJ di sini. Orang-orang menyerahkan kode mereka untuk bersaing di sana dan itu tidak adil bagi mereka.
fR0DDY

1
@ Debanjan, saya melihat referensi Anda dan membangkitkan Anda Mathworld ( mis . 5 mengatakan itu S(n,0)adalah 1jika n=0dan 0sebaliknya). Jika mau, saya dapat menemukan referensi untuk pernyataan yang lebih kuat bahwa Stirling2 ada dalam subkelompok asosiatif dari grup Riordan eksponensial.
Peter Taylor

Jawaban:


4

JavaScript (90 93 )

function f(a,b){n=m=r=1;for(i=b;i>0;n*=-1){r+=n*m*Math.pow(i,a);m=m*i/(b-i--+1)}return--r}

http://jsfiddle.net/RDGUn/2/

Jelas, bahasa berbasis matematika seperti APL akan mengalahkan saya karena sintaks verbositas dan kurangnya konstruk matematika bawaan :)

Sunting Juga, saya tidak memiliki fungsionalitas yang berhubungan dengan input kecuali parameter dilewatkan ke fungsi, tidak yakin bagaimana menggunakan input standar dengan JavaScript ...

Sunting: Bergerak i--ke m=m*ekspresi; pindah n*=-1ke for; mulai r=1untuk menggabungkan tugas dan menghapus yang asing sebagai balasannya. (simpan 3 karakter)


Anda dapat menggunakan shell spidermonkey - setidaknya memiliki readlinedan print. Saya tidak tahu apa yang digunakan orang lain di sini.
Jesse Millikan

@Jesse: Menarik. Lagipula aku akan kalah lol.
mellamokb

promptdan alertadalah "standar" dari JavaScript, karena itu adalah panggilan pemblokiran khas untuk panggilan io, meskipun pada kenyataannya Anda tidak akan pernah menggunakan pemblokiran secara default dengan JavaScript.
zzzzBov

4

Golfscript - 56 50 49 48 41 40 38 37 karakter

n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/

Catatan: ini menangani banyak jalur input, cepat (1/8 detik untuk mengerjakan kasus uji), dan tidak merusak input hukum apa pun.

(Versi pertama juga merupakan program Golfscript pertama saya; terima kasih kepada eBusiness karena menunjukkan beberapa trik yang saya lewatkan).

Untuk menjadikan ini sebagai pos pendidikan yang bermanfaat juga, berikut ini penjelasan cara kerjanya. Kita mulai dengan pengulangan f(n, k) = k * (f(n-1, k) + f(n-1, k-1)). Hal ini dapat dipahami secara kombinatoris dengan mengatakan bahwa untuk menempatkan nbola yang dapat dibedakan dalam kember yang dapat dibedakan sedemikian rupa sehingga setiap ember berisi setidaknya satu bola, Anda memilih salah satu kember untuk bola pertama ( k *) dan kemudian ia akan mengandung setidaknya satu bola lagi ( f(n-1, k)) atau itu tidak akan ( f(n-1, k-1)).

Nilai yang dihasilkan dari formulir ini berupa kisi; mengambil nsebagai indeks baris dan ksebagai indeks kolom dan pengindeksan dari 0 dimulai

1   0   0   0    0    0   0 ...
0   1   0   0    0    0   0 ...
0   1   2   0    0    0   0 ...
0   1   6   6    0    0   0 ...
0   1  14  36   24    0   0 ...
0   1  30 150  240  120   0 ...
0   1  62 540 1560 1800 720 ...
.   .   .   .    .    .   . .
.   .   .   .    .    .   .  .
.   .   .   .    .    .   .   .

Jadi beralih ke program,

n%{~ <<STUFF>> }/

Membagi input menjadi garis dan kemudian untuk setiap baris mengevaluasinya, meletakkan ndan kdi stack, dan kemudian memanggil <<STUFF>>, yaitu sebagai berikut:

),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;

Ini menghitung k+1entri pertama dari n+1baris ke-k dari kisi itu. Awalnya tumpukan itu n k.
),memberi tumpukan n [0 1 2 ... k]
{!}%memberi tumpukan di n [1 0 0 ... 0]mana ada k0s.
\{ <<MORE STUFF>> }*membawa nke atas dan membuatnya menjadi berapa kali kita mengeksekusi <<MORE STUFF>>.
Tumpukan kami saat ini adalah deretan tabel: [f(i,0) f(i,1) ... f(i,k)]
0.@menempatkan beberapa 0 sebelum array itu. Yang pertama akan menjadi jdan yang kedua akan f(i,j-1).
{ <<FINAL LOOP>> }/loop melalui elemen array; untuk masing-masing menempatkannya di atas tumpukan dan kemudian menjalankan loop body.
.@+2$*@)@adalah manipulasi stack membosankan untuk mengambil ... j f(i,j-1) f(i,j)dan menghasilkan ... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]muncul dari sisak+1 f(i,k)dan mengumpulkan semuanya menjadi sebuah array, siap untuk putaran berikutnya loop.
Akhirnya, ketika kita telah membuat nbaris ke-5 dari tabel,
)p;ambil elemen terakhir, cetak, dan buang sisa baris.

Untuk anak cucu, tiga solusi 38-char pada prinsip ini:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/


1
Cukup bagus untuk pemula, ada beberapa kemungkinan pengurangan skala kecil, segera saya temukan [0]-> 1,, ruang setelah zip hanya dapat dihapus, dan ruang lainnya dapat dihapus jika Anda hanya menyimpan di operator bukan k. Saya belum melangkah melalui kode Anda, tetapi saya curiga Anda mungkin lolos dengan hanya menggunakan nilai tanpa meletakkannya dalam array di beberapa tempat.
aaaaaaaaaaaa

1
+1, saya tidak mengerti Golfscript tetapi ini terlihat cukup cepat, namun sangat singkat.
Quixotic

@eBusiness dan @Peter Taylor: Pada nada yang berbeda .. seberapa banyak Anda menilai Golfscript pada skala yang mudah dipelajari?
Quixotic

@ Debanjan, tergantung pada apa yang sudah Anda ketahui. Ini adalah bahasa berbasis stack fungsional. Saya telah menggunakan bahasa fungsional sebelumnya (SML - plus saya telah menulis kode gaya fungsional dalam bahasa OO), dan saya telah menggunakan bahasa berbasis stack sebelumnya (Java bytecode dirakit dengan Jasmin, PostScript), jadi satu-satunya rintangan nyata Wajah saya sedang mempelajari operator apa yang tersedia. Jika Anda hanya tahu bahasa dari keluarga Algol (C, Java, dll) maka Anda akan memiliki tiga rintangan untuk melompat sekaligus.
Peter Taylor

@ Debanjan - Jauh lebih mudah daripada tampilannya, Anda dapat segera mulai menulis kode, tetapi tentu saja perlu waktu untuk mempelajari semua trik kecil.
aaaaaaaaaaaa

3

J, 40

4 :'|-/x(^~*y!~])i.1x+y'/&.".;._2(1!:1)3 

Misalnya

4 :'-/((x^~|.@:>:)*y&(!~))i.y'/x:".>{.;:(1!:1)3
15 13
28332944640000

<1detik untuk semua kasus uji.

Suntingan

  • (52 → 47) Kurangi dengan -/alih - alih bergantian (1 _1)*(ide JB)
  • (47 → 53) Pemberitahuan kebutuhan input multiline: - /
  • (53 → 48) Memanfaatkan simetri binomial.
  • (48 → 48) Buatlah diam-diam!
  • (48 → 41)
  • (41 → 40) Tekan pertambahan + konversi menjadi1x+

1
Hei! Itu saya tahu! O :-)
JB

Ok, saya akan mencuri itu 1x+, tapi itu hanya membeli saya kembali 1 karakter, sedangkan Anda mengambil 5!
JB

3

Gangguan Umum (83)

(defun b (x y)
  (if (= (* x y) 0)
      (if (= (+ x y) 0) 1 0)
      (* y (+ (b (decf x) y) (b x (1- y)))))))

Sepertinya harus ada cara yang lebih pendek untuk menguji kasus dasar, tetapi tidak ada yang terjadi pada saya begitu saja.


3

J, 38 hingga 42

Bergantung pada preferensi ketat Anda tentang bahasa interaktif dan presentasi keluaran, pilihlah dari spektrum solusi:

  • 38 interaktif terpendek: 4 :'|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    Luncurkan jconsole, masukkan, lalu tempel input (akhiri dengan Cd). Anda akan melihat output dipisahkan oleh ruang (J adalah bahasa vektor, ia melakukan perhitungan pada seluruh input secara keseluruhan dan mengembalikannya sebagai vektor 1D, yang presentasi defaultnya adalah pada satu baris). Saya anggap oke, semangat masalah ini adalah perhitungan, bukan presentasi. Tetapi jika Anda bersikeras memiliki baris baru sebagai gantinya:
  • 39 lebih lama interaktif: 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3
    Mengganti Tulisan ( &) dengan Bawah ( &.) mengembalikan vektor string, yang presentasinya berakhir pada baris terpisah.
  • 42 mode batch: 4 :'echo|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    Jalankan dari baris perintah sebagai$ jconsole balls.ijs < balls.in

Jika Anda memilih ini, Anda mungkin ingin memberikan solusi Eelvex juga.


Anda memerlukan Di Bawah &.untuk bekerja dengan baik pada mode interaktif.
Eelvex

@Eelvex Anda harus memiliki interpretasi yang berbeda dari "dengan benar". Saya memulai jconsole, menempelkan kode, menempelkan masukan, Cd, dan menerima hasilnya. Tidak dibutuhkan di bawah. Apa milikmu?
JB

Kode gabungan kami: 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3. 39 karakter.
Eelvex

Tanpa gema atau Di Bawah, saya mendapatkan output hanya dalam satu baris (bukan beberapa baris).
Eelvex

@Eelvex memang, tapi itu tidak dilarang secara eksplisit.
JB

3

GolfScript - 45 38 36 karakter

Relasi rekurensi implementasi kotor-kekuatan sedang ( 38 36 karakter):

n%{~{.2$*{\(.2$f\2$(f+*}{=}if}:f~p}/

Relasi perulangan yang saya curi dari solusi Peter Taylors, seperti ini:

f(x, y) = y * ( f(x-1, y) + f(x-1, y-1) )

Dengan kasus khusus jika salah satu variabel adalah 0.

Implementasi saya tidak menggunakan kembali hasil sebelumnya, sehingga setiap fungsi memanggil cabang ke dua panggilan baru, kecuali salah satu dari nol kasus telah tercapai. Ini memberikan kasus terburuk 2 ^ 21-1 panggilan fungsi yang memakan waktu 30 detik pada mesin saya.

Solusi seri gaya ringan (45 karakter):

n%{~.),0\{.4$?3$,@[>.,,]{1\{)*}/}//*\-}/p;;}/

2

J, 55 karakter

(wd@(4 :'(y^x)--/(!&y*^&x)|.i.y')/@".@,&'x');._2(1!:1)3
  • Lulus uji kasus saat ini. Saya rasa saya mengerti matematika ...
  • j602, hanya konsol ( wd). Input pada stdin, output pada stdout.

Skrip uji bash:

jconsole disballs.ijs <<END
12 4
6 3
END

Apa yang dilakukan j6xx itu wd?
JB

Maksud saya benar-benar j602 ... Saya kira itu juga di j601. Ini didefinisikan sebagai echo, yang didefinisikan sebagai 0 0&$@(1!:2&2). Saya tidak yakin apa artinya itu, tetapi ia melakukan sesuatu seperti item peringkat-cukup-cetak dengan jeda baris. (Saya baru saja memperhatikan bahwa menggunakan 2 daripada 4 ... Saya pikir itu masih pergi ke stdout dalam mode konsol, setidaknya.)
Jesse Millikan

Saya mengalami kesulitan menjalankan kode ini. Apakah saya cukup mengetikkannya di konsol?
mellamokb

@ellamokb Saya sudah menggunakan sesuatu seperti skrip pengujian di atas, dengan program disimpan sebagai disballs.ijs dan jalur yang benar ke j602 / bin / jconsole.
Jesse Millikan

@Jesse: Saya menjalankan ini di windows. Saya mendapat << was unexpected at this time. Maaf saya baru untuk input J, saya selalu menggunakannya dalam mode konsol.
mellamokb

2

Golfscript - 26 karakter

Peringatan: Kasing 12 4 membutuhkan banyak memori (walaupun tidak sebanyak jawaban di bawah) dan membutuhkan waktu yang cukup lama untuk dijalankan

~:)\?:x,{x+)base(;.&,)=},,

Jelas jawaban ini memiliki beberapa masalah, tetapi saya akan meninggalkannya di sini karena komentar merujuk padanya dan jawaban mellamokb didasarkan padanya.

Golfscript - 24 karakter

Peringatan: Kasing 12 4 membutuhkan banyak memori dan perlu waktu cukup lama untuk dijalankan

~:o)\?,{o)base[0]-,o=},,

2
Saya tidak tahu bagaimana Anda membuat kode itu, tidak hanya metode ini kehabisan memori untuk input besar, saya juga tidak tahu apa yang digunakan untuk operator tambahan. Bahwa Anda benar-benar mencapai target untuk 6 3 tampaknya tidak lain adalah keberuntungan.
aaaaaaaaaaaa

Itu bukan badut, itu istriku!
Jesse Millikan

2
Saya tidak mengerti Golfscript tetapi seperti yang Anda katakan dan saya setuju pendekatan Anda terlalu lambat.
Quixotic

3
@ellamokb, bagus untuk Anda karena mengetahui bagaimana seharusnya bekerja :) Hanya butuh 2 karakter tambahan untuk memperbaiki bug itu. Sekarang kita berada di daerah keruh di mana kode terpendek mungkin benar tetapi tidak praktis. Code-golf penuh dengan jawaban-jawaban yang sangat tidak efisien tetapi mikrodetik vs detik biasanya tidak masalah. Ini adalah kasus ekstrim ( banyak memori juga). Debanjan telah mengindikasikan bahwa jawabannya harus lebih cepat, tetapi situs ini bukan SPOJ, pertanyaan ini ditandai dengan kode-golf
gnibbler

1
@gnibbler, 0 0harus menghasilkan 1; 0 kuntuk yang lain kharus menghasilkan 0; n 1untuk n > 0harus menghasilkan 1.
Peter Taylor

2

Python 140 Chars

import sys
f=lambda n,k:(n and k and n>=k and k*(f(n-1,k-1)+f(n-1,k)))or(n+k==0 and 1)or 0
for l in sys.stdin:print f(*(map(int,l.split())))

2

dc, 100 karakter

[0q]s5[1q]s6[l2l3>5l3 0>5l2 0=6l2 1-S2l3dS3 1-S3l1xL3s9l1xL2s9+L3*]s1[?z0=5S3S2l1xL3L2+s9fs9l4x]ds4x

Sayangnya, dc sepertinya tidak didukung oleh ideone. Mungkin ada satu atau dua karakter yang masih harus dimatikan, tetapi ini adalah waktu tidur.

Catatan: ini mendukung beberapa jalur input, memiliki presisi yang cukup untuk memberikan output yang benar bahkan untuk 20 19(mengutuk Anda, Perl, untuk waktu saya membuang debugging solusi saya!), Dan memberikan output yang benar untuk 0 0.

Saran dari Nabb memungkinkan pemendekan setidaknya sejauh

[0q]sZ[1q]sI[?z0=ZSkSn[lnlk>Zlk0>Zln0=Iln1-SnlkdSk1-SklFxLks9lFxLns9+Lk*]dsFxfs9l4x]ds4x

dengan biaya meninggalkan sampah di tumpukan register (dan dengan demikian kehabisan memori jika kita menghitung miliaran jawaban).


Register selalu karakter tunggal (Anda dapat menggunakan karakter apa saja, yang akan membuat kode lebih mudah dibaca), jadi l11diuraikan sebagai l1 1(Anda dapat menggunakan Ksebagai token karakter tunggal untuk 0jika Anda tidak akan mengubah ketelitian bagaimanapun). Anda dapat mengubah loop input menjadi ?[...?z1=4]. Anda dapat memasukkan makro dalam register 1. Dan Anda mungkin dapat menyimpan tumpukan lebih banyak karakter secara umum, tetapi saya akan menunggu lebih pendek untuk memahaminya.
Nabb

@Nabb, ah, saya tidak cukup membaca halaman manual. Saya hanya menggunakan 8 atau 9 register, jadi saya tidak mengalami konsekuensi dari kesalahpahaman saya. Terima kasih.
Peter Taylor

1

Golfscript (28 31 37 )

~):$\.($\?:@;?,{@+}%{$base$,\-[0]=},,

Modifikasi ke gnibblersolusi GolfScript. Saya pikir ini adalah solusi yang berfungsi - diuji dengan [3,2], [4,2], [6,3], dan [9,2] dengan jawaban yang benar. (Saya menggunakan $dan @untuk variabel untuk memperketat ruang di sekitar basekata kunci).

Ada dua masalah dengan gnibblersolusi saat ini.

  1. Memeriksa panjang setelah melepas [0] tidak menjamin solusi, karena [1,1,1,1] akan valid untuk input [4,2], meskipun semua 4 bola berada di sel yang sama (1). Jadi saya telah dimodifikasi untuk memeriksa juga bahwa semua digit digunakan, yaitu array berisi 1-2, sehingga setiap sel mengandung setidaknya satu bola.
  2. Dalam hal input [4,2], format basis-3 angka 0-27 kurang dari 4 digit, dan paling kiri 0 tidak termasuk. Itu berarti [1,1] dimasukkan sebagai solusi yang valid, meskipun secara teknis sebenarnya [0,0,1,1], yang berarti dua bola pertama tidak ditempatkan di mana pun. Saya perbaiki dengan menambahkan 3 ^ 3 ke setiap entri (umumnya k ^ n-1 ke array entri k ^ n) sehingga entri pertama digeser ke atas untuk memiliki setidaknya n-digit dalam format basis-k, dan yang terakhir entri secara otomatis akan menjadi tidak valid dan tidak akan mempengaruhi solusi (karena digit kedua akan selalu 0).

Edit

~:@\?:$,{$+}%{@base(;@,\-,0=},,

`~:@\?:$,{$+@base(;@,\-,0=},,`

Solusi yang lebih baik! Tidak perlu naik, tambahkan saja semua angka sehingga mereka mulai dengan [1], dan tidak ada digit yang akan hilang (termasuk padding kiri 0's) setelah Anda menentukan digit pertama itu. Solusi ini harus berfungsi dan telah diuji dengan entri yang sama di atas. Ini juga jauh lebih cepat karena kita tidak menambah sebelum mengambil eksponen untuk menghasilkan array (tetapi masih menderita masalah kinerja / memori yang sama untuk input yang lebih besar).

Sunting : Gunakan gnibblergagasan untuk memindahkan penambahan bagian $dalam filter alih-alih sebagai langkah tambahan. (simpan 3 karakter).


Istirahat pada input 0 0.
Peter Taylor

Tampaknya juga menangani hanya satu jalur input.
Peter Taylor

Dan istirahat n 1untuk n apa pun, menyebabkannya menggantung. hmm ..
mellamokb

1
mengonversi angka ke basis 1 akan melakukan itu :)
gnibbler

@gnibbler: Apakah Anda punya saran? Apakah saya hanya perlu memasukkan beberapa jika pernyataan di awal untuk menangkap kasus-kasus itu? Sepertinya saya akan kehilangan banyak tanah seperti itu.
mellamokb

0

05AB1E , 19 byte

#D`ULX.Œʒ€gßĀ}gs_P+

CATATAN: Ini sangat lambat, dan sudah waktunya habis 12 4. Ini berfungsi sebagaimana dimaksud, meskipun. Akan melihat apakah saya dapat menemukan metode alternatif yang berfungsi untuk semua kasus uji dalam waktu yang wajar. Lihat di bawah untuk versi yang jauh lebih cepat yang menjalankan semua kasus uji dalam waktu kurang dari satu detik.

Cobalah secara online atau verifikasi beberapa kasus uji (yang lebih kecil) .

Penjelasan:

#               # Split the (implicit) input-string by spaces
 D              # Duplicate it
  `             # Push both values to the stack
   U            # Pop and store the second value in variable `X`
    L           # Create a list in the range [1,n] for the first value
     X        # Create a list of all possible ways to divide this list into `X` partitions
                # (including empty sublists, so we'll have to filter them out:)
        ʒ       # Filter this list of lists of partition-lists by:
         g     #  Get the length of each partition-list
           ß    #  Get the minimum length
            Ā   #  Truthify; 0 remains 0 (falsey); anything else becomes 1 (truthy)
             }g # After the filter, take the length to get the amount left
 s              # Swap so the duplicated input-list is at the top of the stack again
  _             # Check for each value if they're equal to 0 (1 if truthy; 0 if falsey)
   P            # Take the product of the two to check if both input-values are 0
    +           # And add it to the earlier calculated product (edge case for [0,0] = 1)
                # (After which the result is output implicitly)

05AB1E , 29 byte

Berikut versi yang jauh lebih cepat yang berfungsi untuk semua kasus uji dalam waktu sekitar 0,5 detik pada TIO:

Î#R`V©LRvyYmX*NÈ·<*+Xy*®y->÷U

Port dari jawaban JavaScript @mellamokb , jadi pastikan untuk menghapusnya!

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

Î                    # Push (result=) 0 and the input
 #                   # Split the input by spaces
  R`                 # Push the values to the stack reversed
    V                # Pop and store the first value in variable `Y`
     ©               # Store the second value in variable `®` (without popping)
      LRv            # Loop `y` in the range [`®`,1], with index `N` in the range [0,`®`):
         yYm         #  Calculate `y` to the power `Y`
            X*       #  Multiply it by `X`
                     #  (Note: `X` is 1 before setting it to another value initially)
              NÈ     #  Check if index `N` is even (1 if truthy; 0 if falsey)
                ·<   #  Double it; and decrease it by 1 (1 if truthy; -1 if falseY0
                  *  #  Multiply it to the earlier number
                   + #  And add it to the result
         Xy*         #  Push `X` multiplied by `y`
         ®y->        #  Push `®` - `y` + 1
             ÷       #  Integer divide them
              U      #  Pop and store it as new variable `X`
                     # (output the result at the top of the stack implicitly after the loop)

CATATAN: Berfungsi untuk kasus tepi 0 0dalam kasus ini (tidak seperti jawaban JavaScript yang saya gunakan untuk porting metode ini), karena Lbuiltin akan membuat daftar [0,1].

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.