Tantangannya adalah untuk membuat kode angka Romawi yang valid dalam bahasa yang Anda pilih.
Mereka seharusnya tidak muncul di dalam string atau sesuatu yang serupa, tetapi berfungsi seperti token lainnya, literal seperti angka, karakter atau string ( Arab ); atau pengenal variabel / metode / fungsi, dll.
Misalnya, di Jawa, berikut ini harus dikompilasi dan dijalankan seperti jika i
diinisialisasi ke 42
:
int i = XLII;
Penguraian angka yang sebenarnya adalah sekunder, sehingga Anda dapat menggunakan perpustakaan jika Anda mau, tetapi ini adalah kontes popularitas, jadi kreativitas dianjurkan.
Anda tidak dapat menggunakan bahasa apa pun yang benar-benar menggunakan angka romawi, jika ada hal seperti itu.
Semoga berhasil.
Process
ast
untuk mem-parsing sumber. Masukkan di bagian atas AST definisi angka romawi dari 1 hingga 3999. Kompilasi semuanya dan jalankan. Membosankan hanya menulis kode untuk menangani proses.Jawaban:
C
Hanya ada begitu banyak angka Romawi, karena 4000 dan lebih tinggi tidak memiliki notasi standar, dan preprosesor adalah alat dekompresi yang luar biasa, terutama jika Anda tidak memiliki masalah dengan fakta bahwa kode memiliki perilaku yang tidak terdefinisi.
Ini mendefinisikan semua angka Romawi dari
I
hinggaMMMCMXCIX
sebagai konstanta enumerasi, ditambah_
(yang dapat diganti dengan apa pun yang Anda suka) sebagai nol.sumber
scanf
juga :) @ klingt.net Saya tidak yakin contoh seperti apa yang Anda cari. Yang cukup sederhana adalahint main() { return MMMCMXCIX - M - M - M - CM - XC - IX; }
Rubi
Setiap angka Romawi (huruf besar) sekarang akan diuraikan seperti ekivalen desimalnya. Satu-satunya masalah adalah bahwa mereka masih ditugaskan: Anda dapat melakukannya
X = 9
, tetapi tidak10 = 9
. Saya tidak berpikir ada cara untuk memperbaikinya.sumber
JavaScript (ES6)
Gunakan
Proxy
untuk menangkap angka romawi.Dapat diuji di Firefox (terbaru) di JSFiddle .
Tidak dapat diuji di Chrome (dengan Traceur) karena
Proxy
implementasi rusak.Pemakaian:
sumber
C & C ++ (Jawaban Diperbarui)
Seperti yang diamati dalam komentar, solusi asli saya memiliki dua masalah:
Karena saya ingin kode saya menjadi generik mungkin untuk bekerja pada platform lama, saya memutuskan untuk mengambil bacokan lain. Ini lebih lama dari sebelumnya, tetapi bekerja pada kompiler dan preprosesor yang diatur ke mode kompatibilitas C89 / C90. Semua makro diberikan sejumlah argumen yang sesuai dalam kode sumber, meskipun terkadang makro itu "tidak berkembang".
Visual C ++ 2013 (alias versi 12) memancarkan peringatan tentang parameter yang hilang, tetapi tidak mcpp (preprocessor open source yang mengklaim kepatuhan tinggi dengan standar) atau gcc 4.8.1 (dengan -std = iso9899: 1990 -pedantic-errors switches) memancarkan peringatan atau kesalahan untuk doa makro dengan daftar argumen kosong yang efektif.
Setelah meninjau standar yang relevan (ANSI / ISO 9899-1990, 6.8.3, Penggantian Makro), saya pikir ada ambiguitas yang cukup bahwa ini tidak boleh dianggap non-standar. "Jumlah argumen dalam doa makro seperti fungsi harus setuju dengan jumlah parameter dalam definisi makro ...". Tampaknya tidak menghalangi daftar argumen kosong selama tanda kurung yang diperlukan (dan koma dalam kasus beberapa parameter) tersedia untuk menjalankan makro
Adapun masalah trailing koma, yang diselesaikan dengan menambahkan pengenal ekstra untuk enumerasi (dalam kasus saya, MMMM yang tampaknya masuk akal seperti apa pun untuk pengidentifikasi untuk mengikuti 3999 bahkan jika itu tidak mematuhi aturan yang diterima dari pengurutan angka Romawi. persis).
Solusi yang sedikit lebih bersih akan melibatkan memindahkan enum dan mendukung makro ke file header terpisah seperti yang tersirat dalam komentar di tempat lain, dan menggunakan undef dari nama makro segera setelah mereka digunakan untuk menghindari polusi namespace. Nama-nama makro yang lebih baik tidak diragukan lagi harus dipilih juga, tetapi ini cukup untuk tugas yang ada.
Solusi saya yang diperbarui, diikuti oleh solusi asli saya:
Jawaban asli (yang menerima enam upvotes pertama, jadi jika tidak ada yang pernah memperbaiki ini lagi, Anda seharusnya tidak berpikir solusi saya yang diperbarui mendapat upvotes):
Dengan semangat yang sama dengan jawaban sebelumnya, tetapi dilakukan dengan cara yang seharusnya portabel hanya menggunakan perilaku yang didefinisikan (meskipun lingkungan yang berbeda tidak selalu setuju pada beberapa aspek preprosesor). Memperlakukan beberapa parameter sebagai opsional, mengabaikan yang lain, itu harus bekerja pada preprosesor yang tidak mendukung
__VA_ARGS__
makro, termasuk C ++, menggunakan makro tidak langsung untuk memastikan parameter diperluas sebelum menempelkan token, dan akhirnya lebih pendek dan saya pikir lebih mudah dibaca ( meskipun masih sulit dan mungkin tidak mudah dibaca, hanya saja lebih mudah):sumber
__VA_ARGS__
.Gangguan umum
Berikut ini adalah penjelasan yang agak panjang tentang bagaimana saya membuat makro yang dapat Anda gunakan seperti ini:
Ketika makro disebut dalam Common Lisp, pada dasarnya ia bertindak seperti fungsi, hanya argumen yang diterima sebelum dievaluasi. Sebenarnya, karena dalam kode Common Lisp hanya data, apa yang kami terima adalah daftar (bersarang) yang mewakili pohon sintaksis yang tidak diuraikan yang dapat kami lakukan dengan apa pun yang kami inginkan, dan itu dilakukan dalam waktu kompilasi.
Fungsi pembantu
Langkah pertama dari rencana ini adalah mengambil pohon ini dan memindai untuk apa pun yang tampak seperti Angka Romawi. Ini adalah Lisp dan semuanya, mari kita coba untuk melakukannya secara fungsional: Kita memerlukan fungsi yang akan melakukan traversal yang dalam dari sebuah pohon dan mengembalikan setiap objek yang fungsi yang disediakannya
searchp
mengembalikan true. Yang ini bahkan (semi) rekursif.Kemudian beberapa kode untuk menguraikan angka romawi, milik Rosetta Code :
Makro yang sebenarnya
Kami mengambil pohon sintaks (
body
), mencari dengan prosedur deep-find-all kami dan entah bagaimana membuat angka romawi yang kami temukan tersedia.Jadi apa
1 + 2 + 3 + (4 * (5 + 6)) + 7
?Dan untuk melihat apa yang sebenarnya terjadi ketika makro dipanggil:
sumber
Lua
Cukup mundur __index untuk tabel global. Konversi yang sebenarnya menggunakan gsub ternyata jauh lebih cantik daripada yang saya bayangkan.
sumber
Nota bene
Saya mencoba mengikuti yang C tetapi saya tidak memahaminya. Jadi saya melakukannya dengan cara ini:
Postscript tidak memiliki
enum
tetapi kita dapat membuat kamus dengan nilai integer berurutan dan melipatnya menjadi sebuah array. Ini mengurangi masalah untuk menghasilkan semua string secara berurutan, yang dilakukan dengan menggabungkan dalam 4 loop bersarang. Jadi itu menghasilkan semua string, lalu interleave setiap string dengan nilai penghitung yang meningkat, menghasilkan serangkaian panjang <string> <int> pasangan pada tumpukan yang dibungkus<<
...>>
untuk menghasilkan objek kamus.Program ini membangun dan menginstal kamus yang memetakan semua nama untuk angka romawi ke nilai yang sesuai. Jadi menyebutkan nama-nama dalam teks sumber memanggil pencarian nama otomatis dan menghasilkan nilai integer pada stack.
cetakan
sumber
Smalltalk (Smalltalk / X) (87/101 karakter)
tentu saja kita dapat dengan mudah memodifikasi tokenizer parser (karena itu adalah bagian dari perpustakaan kelas, dan karena itu terbuka untuk modifikasi, dan selalu ada), tetapi tantangannya adalah untuk mempengaruhi hanya evaluasi dalam konteks yang diberikan, sehingga sisa sistem bekerja seperti biasa.
Versi 1:
mendefinisikan sejumlah variabel dalam namespace evaluasi. Jadi ini akan memengaruhi doIts interaktif (alias evals):
maka saya bisa melakukan (dalam doIt, tetapi tidak dalam kode yang dikompilasi):
-> 2019
Perhatikan: 101 karakter mencakup spasi; sebenarnya itu bisa dilakukan dengan 87 karakter.
Juga perhatikan, ketika mendefinisikan dalam namespace Smalltalk global, saya akan melihat konstanta-konstanta itu juga dalam kode yang dikompilasi.
Versi 2:
Gunakan hook methodWrapper, yang memungkinkan kode apa pun yang ada untuk dibungkus tanpa kompilasi ulang. Berikut ini membungkus tokenizer Parser untuk mencari pengidentifikasi roman yang akan dipindai dan menjadikannya bilangan bulat. Bagian yang sulit adalah mendeteksi secara dinamis apakah konteks panggilan berasal dari kekaisaran Romawi atau tidak. Ini dilakukan dengan menggunakan sinyal kueri (yang secara teknis merupakan pengecualian yang dapat diproses):
tentukan kueri:
Jadi kita dapat meminta kapan saja ("permintaan InRomanScope") untuk mendapatkan false secara default.
Kemudian bungkus metode checkIdentifier pemindai:
Sekarang pemindai berfungsi seperti biasa, kecuali kita berada di kekaisaran Romawi:
-> 2525
kita bahkan dapat mengkompilasi kode:
usaha yang bagus; tetapi ini gagal dengan kesalahan sintaks (yang persis seperti yang kita inginkan). Namun, di kekaisaran Romawi, kita BISA mengkompilasi:
dan sekarang, kita dapat meminta bilangan bulat apa pun (mengirim pesan itu) dari dalam dan luar Roma:
-> 2525
sumber
Haskell, menggunakan meta-programming di Template Haskell dan roman-numerals :
Pengidentifikasi cadangan Haskell dimulai dengan huruf besar untuk konstruktor, jadi saya menggunakan huruf kecil.
sumber
J - 78 char
Ini hanya naik ke MMMCMXCIX = 3999, seperti solusi lainnya.
Memecahnya (ingat J biasanya dibaca dari kanan ke kiri, kecuali digantikan oleh tanda kurung):
M`CDM`XLC`IVX
- Empat kotak surat. Kita akan menggunakan array numerik ke dalam indeks ke dalam surat-surat ini dan membangun subword dari angka Romawi.841,3#79bc5yuukh
- Ini adalah data numerik, yang dikodekan dengan ketat. *(_1,~3#.inv])
- Ini akan memecahkan kode data di atas, dengan memperluas di ternary dan menambahkan -1.('';&;:(...){' ',[)&.>
- Memasangkan nomor di sebelah kiri dengan kotak di sebelah kanan (&.>
), mendekode array angka dan menggunakannya untuk mengindeks ke dalam huruf-huruf. Kami memperlakukan 0 sebagai spasi dengan menambahkan karakter spasi ke daftar surat. Prosedur ini membangun daftar kata-kata sepertiI II III IV V VI VII VIII IX
danM MM MMM
.{
- Ambil produk Cartesian dari empat kotak ini penuh dengan kata-kata. Sekarang kita memiliki array 4D dari semua angka Romawi.}.,;L:1
- Jalankan semua itu ke daftar angka Romawi 1D tunggal, dan hapus string kosong di depan karena itu akan membuat kesalahan. (L:
Adalah pemandangan langka di J golf! Biasanya tidak banyak level tinju yang terlibat.)}.i.4e3
- Bilangan bulat dari 0 hingga 4000, tidak termasuk titik akhir.=:
. J memungkinkan Anda memiliki daftar nama kotak pada LHS, sebagai bentuk penugasan berganda yang dikomputasi, jadi ini berfungsi dengan baik.Sekarang namespace J penuh dengan variabel yang mewakili angka Romawi.
* Saya memerlukan nomor 2933774030998 untuk kemudian dibaca di base 3. Kebetulan saya bisa mengekspresikannya di base 79 menggunakan angka tidak lebih dari 30, yang bagus karena J hanya bisa memahami angka hingga 35 (0-9 dan kemudian az). Ini menghemat 3 karakter lebih dari desimal.
sumber
Python
Ide itu sederhana seperti jawaban lainnya. Tapi Hanya agar rapi dan tidak mencemari namespace global, manajer konteks digunakan. Ini juga memberlakukan batasan, bahwa Anda harus menyatakan sebelumnya, sejauh mana angka Romawi yang Anda rencanakan untuk digunakan.
Catatan Hanya untuk membuatnya tetap sederhana, dan bukan untuk menemukan kembali roda, saya telah menggunakan paket python Romawi
Pelaksanaan
Demo
sumber
Python
Ini mungkin solusi paling sederhana menggunakan Python:
sumber
globals()[var] = value
daripadaexec()
.D
menggunakan evaluasi fungsi waktu kompilasi D
sumber
APL (Dyalog APL) , 77 byte
Meminta panjang maksimum angka Romawi dan mendefinisikan semua variabel.
t←
t mendapat'IVXLCDM',
Karakter Romawi diikuti oleh⊂
sebuah tertutup⍬
daftar kosongt[
...]
indeks t dengan ...⍉
yang dialihkan (untuk mendapatkan urutan yang benar)8⊥⍣¯1
lebar yang sesuai basis-delapan representasi⍳
indeks n pertama , di mana n adalah¯1+
satu kurang dari8*⎕
delapan pangkat input numerik,/
ratakan baris (setiap representasi){
...}¨
terapkan fungsi anonim berikut pada setiap representasi ...(
...)[t⍳⍵]
sesuai dengan posisi item argumen di t , pilih dari ...∊
yang terdaftar1 5∘ר
masing-masing satu dan lima kali10*
sepuluh pangkat dari⍳4
nol hingga tiga0,⍨
tambahkan nol2(…)/
pada setiap jendela geser panjang-panjang, terapkan fungsi kereta anonim berikut ...⊣×
kali argumen kiri¯1*
negatif terhadap kekuatan<
apakah argumen kiri kurang dari argumen kanan+/
jumlah⍵'←',
tambahkan argumen (angka Romawi) dan panah tugas⍕
format (untuk meratakan dan mengonversi angka menjadi teks)⍎
jalankan itu (membuat tugas di luar fungsi anonim)Cobalah online! (menggunakan max-length 5)
sumber
PHP
Ada beberapa aturan untuk angka romawi yang valid
Tulis nilai terbesar sebelum nilai yang lebih rendah
Kurangi hanya
[I,X,C]
sebelum 2 nilai berikutnya yang lebih besarKurangi dua kali lipat
[I,X,C]
sebelum 2 nilai selanjutnya yang lebih besarKurangi dua kali
[I,X,C]
sebelum nilai yang lebih besarGabungkan 4 + 5
Versi Online
Langkah 1 Buat aturan
adalah output JSON untuk semua angka romawi yang valid
Langkah 2 Buat daftar untuk semua aturan hingga 3999
Langkah 3 Buat konstanta
Gabungkan semua daftar dan tetapkan konstanta
Keluaran
Dalam contoh, gonta-ganti dua versi nomor 8 yang valid
sumber
Rebol
Contoh
Keluaran:
Penafian: Saya yakin ada cara lain (dan mungkin lebih baik!) Untuk melakukan ini di Rebol juga.
PS.
roman-to-integer
Fungsi saya adalah transliterasi dari algoritma Ruby yang bagus milik histokrat untuk mengubah string Angka Romawi menjadi angka. Kembali dengan terima kasih! +1sumber
Lua
Ini efek metatable dari tabel global, memberikannya fungsi indeks baru. Ketika variabel global yang hanya berisi angka romawi diminta, misalnya
XVII
, ia menguraikannya.Mudah diuji;
Cobalah online!
sumber
VBA, 204 byte
Sebuah menyatakan subroutine yang tidak membutuhkan input, dan ketika dijalankan, menciptakan
public
ly diaksesEnum
,R
yang berisi semua nilai-nilai Romawi Angka. Nilai-nilai ini dapat digunakan secara langsung, tanpa merujuk pada Enum.Enum memegang nilai dari 1 hingga 3999.
Catatan: Terminal
"
pada baris 3 dan 7 disertakan hanya untuk penyorotan sintaks, dan tidak berkontribusi pada bytecountTidak Diikat dan Dijelaskan
sumber