Ini golf kode. Pemenangnya adalah kode yang valid dengan jumlah byte terkecil.
Tantangan
Diberikan input M dan N , lebar dan tinggi kotak persegi panjang, menghasilkan poligon yang memenuhi berikut:
- Tepi poligon hanya terdiri dari tepi persegi: tidak ada tepi diagonal - semuanya vertikal atau horizontal.
- Poligon tidak memiliki lubang: setiap kotak di luar poligon dapat dicapai dengan langkah ortogonal pada kotak di luar poligon, mulai dari kotak di luar poligon pada batas luar persegi panjang.
- Poligon tidak memiliki persimpangan-sendiri: dari pertemuan tepi persegi pada titik, tidak lebih dari 2 dapat menjadi bagian dari perimeter poligon.
- Poligon terhubung: setiap kotak dalam poligon harus dapat dijangkau dari kotak lain dalam poligon melalui langkah ortogonal yang tetap berada dalam poligon.
- Poligon memiliki perimeter maksimum yang mungkin: sesuai dengan rumus di bawah ini.
Kode Anda harus berfungsi untuk M dan N dari 1 hingga 255.
Formula untuk batas maksimum
Tantangannya di sini adalah menemukan poligon yang paling golf dengan batas maksimum. Batas maksimum itu sendiri selalu ditentukan oleh rumus:
Ini benar karena untuk perimeter maksimum, setiap titik persegi harus pada perimeter. Untuk jumlah simpul yang ganjil, ini tidak mungkin dan yang terbaik yang bisa dicapai adalah satu simpul lebih sedikit (karena perimeter selalu genap).
Keluaran
Keluarkan bentuk sebagai string karakter yang dipisahkan baris baru ( N baris tepat karakter M ). Di sini saya menggunakan ruang untuk kotak di luar poligon, dan '#' untuk kotak di dalam poligon, tetapi Anda dapat menggunakan dua karakter yang berbeda secara visual, asalkan artinya konsisten untuk semua input.
Anda dapat memasukkan hingga satu baris baru dan satu baris baru.
Jika Anda mau, Anda bisa menghasilkan baris M dengan karakter N persis , dan Anda dapat memilih output M demi N untuk beberapa input dan keluaran N oleh M untuk yang lain.
Contohnya
Tidak valid karena lubang:
###
# #
###
Tidak valid karena persimpangan (menyentuh secara diagonal - sebuah simpul dengan 4 tepi persegi pada perimeter) dan, kebetulan, sebuah lubang:
##
# #
###
Tidak valid karena terputus:
#
# #
#
Poligon valid perimeter maksimum:
# #
# #
###
Kredit
Saya awalnya meremehkan seberapa cepat nilai perimeter maksimum dapat dihitung, dan hanya akan meminta nilai itu sebagai output. Terima kasih kepada orang-orang yang sangat membantu dalam obrolan karena menjelaskan cara mengerjakan batas maksimum untuk N dan M yang sewenang-wenang dan membantu menjadikannya sebuah tantangan yang akan bertahan selama lebih dari satu jawaban ...
Secara khusus terima kasih kepada:
Sparr , Zgarb , feersum , jimmy23013 .
Jawaban:
CJam, 47 byte
Cobalah online
Penjelasan:
Ada dua kasus utama untuk hasilnya. Jika setidaknya salah satu ukurannya aneh, polanya adalah "rake" polos. Misalnya, untuk input
7 6
:Jika kedua ukuran genap, ada kolom tambahan tempat setiap kotak kedua "menyala". Misalnya, untuk input
8 6
:Sekarang, untuk menunjukkan bahwa pola-pola ini mencapai maksimum teoretis perimeter seperti yang diberikan dalam deskripsi masalah, kita perlu mengkonfirmasi bahwa pola pertama memiliki perimeter
(M + 1) * (N + 1)
, dan yang kedua memiliki nilai yang sama minus 1.Untuk pola pertama, kita memiliki perimeter, dengan
M
dimensi aneh:M
untuk tepi atas.2
di sisi baris atas.(M - 1) / 2
untuk celah di antara gigi.(M + 1) / 2
gigi dengan perimeter2 * (N - 1) + 1
masing-masing.Ini menambahkan hingga:
Untuk kasus kedua di mana keduanya
M
danN
bahkan, perimeter bertambah dari:M
untuk tepi atas.2
di sisi baris atas.M / 2
untuk # terbuka di baris atas.M / 2
gigi dengan perimeter2 * (N - 1) + 1
masing-masing untuk gigi biasa.2 * (N / 2 - 1)
potongan perimeter ekstra untuk jaggies.Menambahkan ini bersama-sama:
sumber
Ruby, Rev 1, 66
Digunakan menaikkan
m
ke daya 0 o 1 untuk memutuskan apakah 1 ataum
#
akan dicetak.Digunakan
>
untuk menguji baris terakhir, bukan==
.Tidak dapat menyingkirkan ruang setelah meletakkan, atau tanda kurung!
Ruby, Rev 0, 69
Ini adalah fungsi lambda anonim. Gunakan seperti ini:
Pada akhirnya, setelah bertanya apakah M dan N bisa dipertukarkan, saya tidak membutuhkannya.
Output khas untuk N odd. Jika kita menghapusnya
#
sendiri di sisi kanan, jelas kita akan memiliki (N +1) (M +1). Termasuk mereka untuk bergabung dengan bentuk menghilangkan 2 kuadrat perimeter horisontal dan menambahkan 2 kuadrat perimeter vertikal, sehingga tidak ada perubahan.Di sini kita bergantung pada ekspresi
"#"*(i%2==0?m:1)
untuk memberikan baris bergantian#
simbol M dan satu#
simbol, dan benar membenarkan untuk karakter M.Output khas untuk N even.
5 6
jelas memiliki perimeter yang sama dengan6 5
, atau peningkatan M + 1 = 6 dibandingkan dengan5 5
penambahan perimeter vertikal karena crenelation baris bawah.6 6
memiliki sama dengan6 5
ditambah kenaikan (M + 1) -1 = 6 di perimeter vertikal. Jadi mereka sesuai dengan formula.Sangat berguna karena Ruby
rjust
memungkinkan Anda menentukan padding yang akan digunakan untuk sel-sel kosong. Biasanya padding diatur ke" "
tetapi untuk baris terakhir kita beralih ke"# "
(perhatikan bahwa padding hanya akan diperlukan pada baris terakhir jika N adalah genap. Dimana N aneh, baris terakhir akan selesai dan tidak akan ada pembenaran, sehingga Anda tidak akan melihat crenelations.)Lihat disini.
sumber
i%2==0
kei%2<1
untuk menyimpan byte (Saya telah membuat perubahan ini ke tautan ideone).#
bantalan untuk baris terakhir? Misalnya, pada gambar terakhir, bukankah perimeter sama tanpa#
di sudut kanan bawah?#
hanya karena sudah cara setiap baris berakhir, jadi lebih sedikit byte daripada meletakkan spasi di sana. (Aku tidak tahu ruby ...)."# "
bukan" #"
karena yang terakhir akan memberikan 2 berdekatan#
untuk M aneh yang pasti tidak diinginkan. 2 berdekatan#
bahkan untuk M tidak ada salahnya, jadi aku pergi dengan itu. Saya belum mencobaljust
, mungkin untuk melakukannya lebih bersih dengan itu, tetapi tidak akan begitu jelas bahwa saya mencetak karakter M persis per baris.C,
10997 byte dan bukti kebenaranSaya sedang mengerjakan solusi saya tetapi @steveverrill mengalahkan saya untuk itu. Saya pikir saya akan membagikannya sama saja, karena saya menyertakan bukti kebenaran untuk strategi yang digunakan.
Kode yang Dikurangi:
Sebelum Pengurangan:
Strategi dan Bukti:
Dengan asumsi kebenaran dari persamaan pembatas maksimum (M + 1) (N + 1) - ((M + 1) (N + 1)) mod 2 , berikut ini menjelaskan strategi optimal yang digunakan dan membuktikan kebenarannya dengan induksi:
Untuk M aneh, kami menggambar bentuk seperti tangan dengan jari-jari M / 2 + 1, misalnya:
Kami sekarang membuktikan strategi ini optimal untuk semua M aneh dengan induksi:
Kasus Dasar: M = N = 1
Sel tunggal terisi. Solusinya benar karena (1 + 1) * (1 + 1) = 2 * 2 = 4, dan kotak memiliki 4 sisi.
Lebar induksi:
Asumsikan bahwa strategi bentuk tangan bekerja untuk (N, M-2) di mana M aneh, yaitu pembatasnya optimal dan (N + 1) (M - 2 + 1) + ((M -1) (N +1)) mod 2 . Kami sekarang menunjukkan bahwa itu akan bekerja untuk (N, M) .
Proses menambahkan jari menghilangkan satu sisi dari poligon, dan menambahkan 3 + 2N . Sebagai contoh:
Menggabungkan ini dengan hipotesis kami bahwa perimeter sebelumnya optimal, perimeter baru adalah:
Karena kita berurusan dengan modulo 2 aritmatika,
Dengan demikian, membuktikan bahwa meningkatkan lebar dengan menambahkan jari mengarah ke perimeter optimal.
Induksi pada ketinggian:
Asumsikan strategi bentuk tangan bekerja untuk (N-1, M) , di mana M aneh, yaitu, perimeternya optimal dan N (M + 1) + ((M + 1) N) mod 2 . Kami sekarang menunjukkan bahwa itu akan bekerja untuk (N, M) .
Meningkatkan tinggi tangan hanya memanjang jari-jari, terletak di x-indeks pertama dan setiap lainnya. Untuk setiap kenaikan tinggi, setiap jari menambahkan dua ke perimeter, dan ada (M + 1) / 2 jari, dengan demikian, peningkatan N mengarah ke peningkatan 2 (M + 1) / 2 = M + 1 di perimeter.
Menggabungkan ini dengan hipotesis, kita memiliki bahwa perimeter baru adalah:
Aritmatika modular memungkinkan kita untuk menyederhanakan istilah terakhir, sehingga kita memperoleh:
Membuktikan bahwa solusinya optimal untuk semua N> 0 dan aneh M> 0.
Untuk genap M, kami mengisi papan seperti yang kami lakukan untuk M aneh, tetapi kami menambahkan crenelation ke segmen terakhir, misalnya:
Kami sekarang membuktikan bahwa strategi ini optimal.
Induksi untuk genap M:
Asumsikan bahwa solusinya benar untuk (N, M-1), dengan M-1 ganjil (seperti yang dibuktikan dalam kasus terakhir), yang memiliki perimeter optimal (N + 1) M - ( M (N + 1)) mod 2 . Kami sekarang menunjukkan bahwa itu akan bekerja untuk (N, M).
Seperti menambah jari, setiap crenelation menambahkan dua ke perimeter poligon. Jumlah total crenelations adalah (N + N mod 2) / 2 , untuk total N + N mod 2 perimeter ditambahkan.
Menggabungkan ini dengan hipotesis, kita memiliki bahwa perimeter baru adalah:
Kami memilikinya
Karena jika N ganjil, maka ini berkurang menjadi 0 = 0, dan jika N adalah genap, itu berkurang menjadi
Dengan demikian strategi optimal untuk semua M, N> 0 .
sumber