Segmen Garis Angka Romawi

10

Tulis program atau fungsi yang menerima bilangan bulat dalam kisaran 1..3999 sebagai input dan mengembalikan jumlah segmen garis yang diperlukan untuk menyatakan bilangan bulat itu dalam angka Romawi standar (sehingga Anda akan menggunakan XL tetapi bukan VM). Contoh:

   1 -> 1
   4 -> 3
   5 -> 2
   9 -> 3
  10 -> 2
  40 -> 4
  50 -> 2
  90 -> 3
 100 -> 1
 400 -> 3
 500 -> 2
 900 -> 5
1000 -> 4

Builtin jumlah konversi Romawi yang diizinkan, tetapi Anda dapat memecahkan masalah tanpa mereka dengan berulang kali mengurangi jumlah terbesar yang tersisa dari daftar di atas. Contoh: 1234 = 4 + 1 + 1 + 2 + 2 + 2 + 3 = 15.

Ini adalah , jadi program terpendek menang.

Neil
sumber
Mengapa 10 dua segmen garis bukan empat? Saat menulis X, Anda biasanya hanya menulis dua baris, tetapi bukankah persimpangan garis membuatnya menjadi empat segmen?
Alex A.
@AlexA. Definisi segmen garis biasanya kira-kira seperti: "Himpunan titik mengikuti jalur terpendek antara dua titik". Tampaknya tidak ada alasan untuk memotong X berdasarkan ini, Anda hanya perlu dua set titik akhir untuk mendefinisikannya. (Anggaplah orang Romawi menulis pada geometri euclidean, saya kira)
FryAmTheEggman
@FryAmTheEggman Hm oke. Senang tahu, terima kasih.
Alex A.

Jawaban:

2

Pyth, 92 76 70 byte

KsMc."/9hæ²z³Þ§ªW×Oû[Tnè,O¤"\/WQ=Q-Q=Nef!>TQ%2K aY@KhxKN;sY

Coba di sini!

Terima kasih kepada @FryAmTheEggman untuk beberapa saran pengemasan string yang menyelamatkan saya beberapa byte!

Saya masih bertanya-tanya apakah ada cara matematis untuk menyandikan daftar ini. Akan mencoba mencari sesuatu.

Penjelasan

Ini menggunakan algoritma yang diberikan. Kberisi daftar yang diberikan dengan angka dan jumlah segmen garis yang berurutan secara bergantian. Daftar ini dibangun dengan memecah string yang dikemas, yang diterjemahkan ke 0/0/1/1/4/3/5/2/9/3/10/2/40/4/50/2/90/3/100/1/400/3/500/2/900/5/1000/4, pada /dan memetakan setiap elemen ke integer.

KsMc. "..." \ / WQ = QQ = Nef!> TQ% 2K aY @ KhxKN; sY # Q = input

   c. "..." \ / # bagi string menjadi /
KsM # memetakan setiap nomor ke int dan menetapkan ke K
            WQ # saat Q! = 0
                     f% 2K # hanya mengambil setiap elemen ke-2 dari K dan memfilter dengan T
                      !> TQ # T <= Q
                  = Ne # Ambil elemen terakhir itu dan tetapkan itu ke N
              = QQ # Q = Q - N
                                   xKN # indeks kejadian pertama N di K
                                  h # menambah indeks itu karena kami ingin segmen garis
                              aA @ K # mendapatkan segmen garis dari indeks itu dan menambahkannya ke Y
                                      ; sY # akhiri loop dan cetak jumlah semua segmen garis dalam Y
Denker
sumber
3

C, 148 129 karakter

d,x,n[]={1000,900,500,400,100,90,50,40,10,9,5,4,1,4,5,2,3,1,3,2,4,2,3,2,3,1};f(c){while(d+=(c/n[x])*n[x+13],c%=n[x++]);return d;}

Golf kode pertama saya: ^). Karena pertanyaan menyatakan saya dapat menggunakan fungsi, saya telah mengubah main ke fungsi untuk memangkas beberapa karakter (yang paling penting: lulus c sebagai parameter daripada scanf)

dibongkar

d,x,n[]={1000,900,500,400,100,90,50,40,10,9,5,4,1,4,5,2,3,1,3,2,4,2,3,2,3,1};
f(c){
  while(d+=(c/n[x])*n[x+13],
        c%=n[x++]);
  return d;
}
STDQ
sumber
2

Mathematica, 80 72 byte

Tr[Characters[#~IntegerString~"Roman"]/.{"I"|"C"->1,"M"->4,_String->2}]&

Fungsi anonim yang hanya mengubah angka menjadi angka Romawi, mengganti setiap karakter dengan jumlah segmennya, dan mengambil totalnya.

LegionMammal978
sumber
2

Retina, 128 byte

. +
$ *
1 {1000}
t '
1 {900}
td
1 {500}
d
1 {400}
t
1 {100}
'
1 {90}
t
1 {50}
d
1 {40}
t '
1 {10}
d
1 {9}
t
1 {5}
d
1 {4}
t
1
'
t
d '
d
''
'+
$ .0

Pengganti sederhana sampai tidak ada yang tersisa untuk diganti. Kemudian apostrof dihitung dan itu adalah jumlah segmen garis kami.

Jika input dan output dalam unary diizinkan, itu 115 byte (meskipun siapa yang ingin mengetikkan 1234?).

Cobalah online!
Cobalah online! (IO unary)

daavko
sumber
2

Python 3, 95 byte

def f(a,b=0):
 for e in'᝴ᔝ஺ॣəȟĮô>9 ':e=ord(e);d=e//6;b+=a//d*(e%6);a%=d
 return b

String Unicode terdiri dari poin kode:

6004 5405 3002 2403 601 543 302 244 62 57 32 27 7
Lynn
sumber
Jika Anda mengubah string itu menjadi byte literal, Anda dapat menghilangkane=ord(e);
xsot
Saya tidak berpikir itu berhasil dalam kasus saya. Saya membutuhkan string Unicode :( yaitu saya mengulangi codepoint dalam string itu, bukan pada byte.
Lynn
1
Oh begitu. Apakah Anda keberatan menyediakan dump hex string? Itu tidak ditampilkan dengan benar di ponsel saya.
xsot
1

Java, 152 byte

Karena, Anda tahu, Jawa.

n->{int c=0;int[]r={999,4,899,5,499,2,399,3,99,1,89,3,49,2,39,4,9,2,8,3,4,2,3,3,0,1};for(int i=0;i<26;i+=2)while(n>r[i]){n-=r[i]+1;c+=r[i+1];}return c;}

Implementasi literal sederhana dari algoritma yang diberikan. Array mengemas informasi transformasi: bahkan indeks satu kurang dari angka romawi dan indeks ganjil adalah jumlah untuk angka itu.

Ini adalah lambda yang mengambil dan mengembalikan int/ Integer. Ini termasuk IntUnaryOperatoratau UnaryOperator<Integer>.

CAD97
sumber
1

JavaScript (ES6), 79 byte

n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4

String mewakili jumlah segmen garis untuk unit, puluhan dan ratusan digit. (Ribuan hanya empat kali ribuan digit.) Metode ini tampaknya lebih pendek daripada opsi lain seperti algoritma yang disarankan dalam pertanyaan.

Sunting: Disimpan 2 byte berkat @ user81655.

Neil
sumber
Ini adalah algoritma yang keren. Mengatur ulang gips dapat menghemat 2 byte juga:n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4
user81655
@ user81655 Oh, itu bagus: hanya dengan mengubah +s ke -s memungkinkan saya untuk menghapus yang memimpin +, tetapi kemudian pengelompokan menyimpan byte lain.
Neil