Tantangan ini didasarkan pada teka-teki yang saya baca di beberapa buku beberapa waktu lalu, yang saya temukan lagi di sini . Ini adalah tentang peluru yang ditembakkan dari senapan sekali per detik dengan kecepatan bervariasi yang bergerak dalam garis lurus selamanya. Ketika satu peluru mengenai yang lain, keduanya hancur sepenuhnya. (Jangan ragu untuk mengganti semua instance "peluru" dengan "rudal".)
Tugas
Diberi daftar kecepatan peluru dalam urutan menembak, tentukan apakah semua peluru dihancurkan.
Aturan
- Input adalah daftar bilangan bulat non-negatif, dipisahkan oleh pembatas apa pun dan dengan satu karakter opsional sebelum dan sesudah. Ini adalah input yang valid:
1 2 3 4 5 6
dan[1,2,3,4,5,6]
. Pemrogram membuat pilihan. - Keluarkan nilai kebenaran jika setidaknya satu peluru bertahan selamanya dan nilai palsu sebaliknya.
- Kecepatan peluru diberikan dalam satuan per detik.
- Peluru bergerak secara simultan dan terus menerus.
- Peluru dapat bertabrakan pada offset fraksional.
- Beberapa peluru yang secara bersamaan mencapai posisi yang sama persis, apakah pada offset integral atau fraksional dari asal, semua saling bertabrakan.
Contohnya
Dalam diagram ini, G
perlihatkan pistol, >
peluru, dan *
saat peluru bertabrakan dan meledak.
Sejujurnya
Memasukkan: 0
0123456789
Time 0 G>
1 G>
2 G>
...
Keluaran: 1
Memasukkan: 0 0 0
0123456789
Time 0 G>
1 G*
2 G>
3 G>
4 G>
...
Keluaran: 1
Memasukkan: 1
0123456789
Time 0 G>
1 G >
2 G >
3 G >
...
Keluaran: 1
Memasukkan: 2 1
0123456789
Time 0 G>
1 G> >
2 G > >
3 G > >
4 G > >
...
Keluaran: 1
Memasukkan: 2 3 1
0123456789
Time 0 G>
1 G> >
2 G> >>
3 G > *
4 G >
5 G >
...
Keluaran: 1
Palsu
Memasukkan: 1 2 3 4 5 6
Unit 1111111111
01234567890123456789
Time 0 G>
1 G>>
2 G> *
3 G> >
4 G> > >
5 G> > >>
6 G > > *
7 G > >
8 G > >
9 G >>
10 G *
111111111122222222223
0123456789012345678901234567890
Keluaran: 0
Memasukkan: 1 0 0 3
Unit
0123456789
Time 0 G>
1 G>>
2 G* >
3 G> >
4 G >>
5 G *
(Tabrakan kedua adalah pada waktu 4,5)
Output:0
Memasukkan: 2 1 2 3 6 5
Unit 1111111111
01234567890123456789
Time 0 G>
1 G> >
2 G>> >
3 G> * >
4 G> > >
5 G> * >
6 G > >
7 G > >
8 G >>
9 G *
1111111111
01234567890123456789
Keluaran: 0
Memasukkan: 2 3 6
Unit
0123456789
Time 0 G>
1 G> >
2 G> >>
3 G *
Keluaran: 0
sumber
1<enter>2<enter>3...
?Jawaban:
Python 2,
388392388346342336331 byteYa Tuhan benda ini sangat besar, tapi saya percaya itu benar-benar berhasil. Setelah Anda melihat semua seluk beluknya, tantangan ini sangat sulit.
Saya tidak yakin apakah saya bisa menjelaskan cara kerjanya secara detail tanpa mengetik selama berjam-jam, jadi saya hanya akan memberikan ringkasan eksekutif.
Loop sementara utama utama adalah perulangan sampai daftar input tidak menyusut.
Nested for loop (dapatkah Anda percaya bahwa nested for loop sebenarnya adalah yang terpendek di sini?) Mengulangi setiap kecepatan peluru dan
menggunakanperhitungan pada waktu mana peluru akan bertabrakan dengan setiap peluru yang datang setelahnya. Di sini,numpy.roots
untuk menghitung""
digunakan untuk berarti infinity (tidak ada persimpangan). Kondisional tambahan harus disertakan untuk memastikan bahwa peluru yang berhenti ditandai bertabrakan pada saat mereka muncul daripada pada saat nol.Untuk setiap nomor, kami melacak peluru mana yang akan terkena paling cepat, jika ada, dan kemudian
o
diperbarui dengan waktu tabrakan minimum untuk peluru yang terlibat.Setelah pengulangan ganda ini berakhir, kami mengulangi daftar input dan menghapus setiap peluru yang akan bertabrakan pada minimum semua waktu tabrakan, jika ada. Ini memungkinkan kita untuk secara bersamaan menghapus sejumlah besar peluru jika semuanya bertabrakan pada saat yang sama.
Kemudian kami mengulangi seluruh proses pada sisa peluru, karena mereka mungkin bisa mendapatkan sekarang bahwa peluru yang mereka akan bertabrakan telah dihancurkan.
Segera setelah tidak ada peluru yang dihapus (ditunjukkan oleh daftar yang tidak menyusut), kami lolos dari loop sementara dan mencetak panjang daftar yang tersisa. Dengan demikian, program ini tidak hanya mencetak kebenaran jika peluru bertahan, itu sebenarnya mencetak dengan tepat jumlah peluru yang bertahan.
EDIT: Terima kasih khusus kepada feersum untuk membuat kasus pengujian untuk membantu saya menemukan bug.
EDIT 2: Menyelamatkan 42 byte dengan menyelesaikan persamaan linier dengan tangan alih-alih menggunakan numpy, dan membagi waktu mulai menjadi daftar terpisah dan merestrukturisasi suatu kondisi.
EDIT 3: Disimpan 4 byte dengan mengubah nama rentang
EDIT 4: Menyimpan 6 byte lebih banyak dengan mengganti spasi ganda dengan tab. Juga, feersum cukup baik untuk memberikan implementasinya menggunakan fraksi dan set untuk perbandingan. Saya telah membuatnya sedikit dan menghasilkan 331 byte, mengikat solusi saya.
EDIT 5: menyimpan 5 byte dengan menghapus inisialisasi yang tidak perlu dan menulis ulang suatu kondisi
sumber