Trình tự nhìn và nói: phiên bản chữ số La Mã


20

Mô tả thử thách

Chúng tôi đã có một vài thử thách liên quan đến chuỗi Nhìn và Nói . Nhắc nhở nhanh:

  • Trình tự bắt đầu bằng 1,
  • Các thuật ngữ tiếp theo của chuỗi này được tạo ra bằng cách liệt kê từng nhóm chữ số lặp lại trong thuật ngữ trước đó,

Vì vậy, một vài điều khoản đầu tiên là:

1        "one"
11       "one one" (we look at the previous term)
21       "two ones"
1211     "one two, one one"
111221   "one one, one two, two ones"
312211   "three ones, two twos, one one"

Bây giờ chúng ta hãy làm điều tương tự, nhưng sử dụng Chữ số La Mã thay thế. Chúng tôi bắt đầu với Ivà làm theo các quy tắc tương tự (chúng tôi áp dụng các quy tắc chữ số đếm để nhân vật thay thế, do chúng ta đọc IVXnhư one one, one five, one tenthay vì one four, one tenhoặc một số cách khác):

I           "one"
II          "one one"
III         "two ones" = "II" + "I"
IIII        "three ones" = "III" + "I"
IVI         "four ones" = "IV" + "I"
IIIVII      "one one, one five, one one"
IIIIIVIII   "three ones, one five, two ones" = ("III" + "I") + ("I" + "V") + ("II" + "I")

Cho một số nguyên dương N, hoặc:

  • Đầu ra các Nchữ số đầu tiên của chuỗi này (bất kỳ dấu tách hợp lý nào cũng được, cũng như["I", "II", "III", ...]
  • NThuật ngữ đầu ra của chuỗi này (nó có thể được lập chỉ mục 0).

Hãy nhớ làm cho mã của bạn càng ngắn càng tốt, vì đây là một thử thách !

EDIT: Tôi tin rằng luôn có một cách biểu thị số nguyên / tiêu chuẩn ưa thích là số La Mã, (như 95-> XCVthay vì VC). Vài bộ chuyển đổi số La Mã tôi tìm thấy trực tuyến chứng thực quan điểm của tôi. Nếu nghi ngờ, hãy sử dụng một trình chuyển đổi trực tuyến , vì liệt kê tất cả các trường hợp cạnh có thể và quy tắc cụ thể viết chữ số La Mã không phải là điểm của thách thức này.

EDIT2: @PeterTaylor và @GregMartin chỉ ra rằng chỉ số ít hoặc tương đương để 5xuất hiện trong chuỗi, vì vậy bạn không cần phải lo lắng về sự nhập nhằng của chữ số La Mã (số 1- 8I, II, III, IV, V, VI, VII, và VIII)


Không có biểu thức số La Mã duy nhất cho mỗi số nguyên. Những số nào có thể cần thiết để thể hiện, và biểu thức nào của những số đó là hợp lệ?
Peter Taylor

Ý bạn là gì khi "không có biểu thức số La Mã duy nhất cho mỗi số nguyên"? Thích 4/ IV/ IIII? Hoặc 95/ XCV/ VC? Có thể không phải lúc nào cũng có một cách duy nhất để biểu thị một số nguyên, nhưng tôi khá chắc chắn rằng luôn có một cách ưa thích (tiêu chuẩn) - sửa tôi nếu tôi sai.
shooqie

1
chúng ta phải đi bao xa với số La Mã?
Maltysen

Vâng, cả hai trường hợp đó. Trong trường hợp thứ hai, tôi nghĩ đó là vấn đề quan điểm rất thích hợp.
Peter Taylor

9
@shooqie nếu những chi tiết này không được làm rõ, bạn sẽ so sánh câu trả lời như thế nào? Nếu có một số trường hợp cạnh còn lại để giải thích thì điểm thực tế trở nên vô nghĩa bởi vì chúng có thể tạo ra sự khác biệt lớn hơn bất kỳ thủ thuật đánh gôn nào bạn có thể nghĩ ra.
Martin Ender

Câu trả lời:


17

Perl, 49 byte

Bao gồm +1 cho -p

Chạy với chỉ mục dựa trên 0 trên STDIN, ví dụ:

ecce.pl <<< 14

ecce.pl:

#!/usr/bin/perl -p
s,(.)\1*,$&/$1%182 .$1,eg for($_=/$/)x$`;y;19;IV

Công thức ma thuật rất kỳ diệu.

Thông thường tôi sẽ sử dụng ($_=//)x$'để làm cho điều khiển vòng lặp ngắn hơn một byte, nhưng việc ghi điểm trên trang web này mang lại cho điểm chấp là 2 để kết thúc lâu hơn 1 byte. Trên các perls cũ hơn, bạn có thể thả không gian trước for. Một số phiên bản của perl buộc bạn phải thêm một bản cuối cùng ;để đóng phiên âm. Nhưng những gì được đưa ra ở trên là mã hoạt động trên hệ thống của tôi.

Giải trình

Làm việc ngược từ giải pháp sang mã:

Các phép biến đổi chuỗi chúng ta cần:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

Mỗi sự thay thế kết thúc với ký tự lặp đi lặp lại. Tôi sẽ nhận được một chuỗi các ký tự giống nhau bằng regex /(.)\1*/, vì vậy điều này có thể được thực hiện bằng cách nối thêm $1. Phần trước ->là trong $&. Với điều đó tôi vẫn cần:

I     -> I
II    -> II
III   -> III
IIII  -> IV
IIIII -> V

V     -> I
VV    -> II

Viết Inhư 1V9:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

9     -> 1
99    -> 11

Bằng cách chia phần trước ->cho chữ số lặp lại, điều này trở thành:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

1     -> 1
11    -> 11

Vì vậy, bây giờ lặp lại ban đầu Vkhông phải là một ngoại lệ nữa. Vì vậy, tôi muốn một biểu thức làm cho điều này xảy ra:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

Và điều này có thể được thực hiện bằng một modulo đơn giản 182:

1     % 182 = 1
11    % 182 = 11
111   % 182 = 111
1111  % 182 = 19
11111 % 182 = 9

(điều này thậm chí còn được IIIIIIđể VIngay mặc dù nó không phải là cần thiết ở đây)

Tất cả những gì còn lại là khởi tạo biến làm việc 1cho chỉ số 0, lặp lại phép biến đổi này trong một vòng lặp và ở cuối thay thế 1bằng I9bởiV

1, 9182là sự kết hợp chỉ số mà đơn giản này các công trình công thức.


2
Đây là thiên tài! :)
Lynn

10

Toán học, 113 90 83 byte

Cảm ơn Martin Ender vì những gợi ý đã giảm hơn 25% thời lượng!

Hiển thị các lệnh cấp cao trong Mathematica.

Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&

Một hàm thuần túy, lấy một đối số N và xuất ra phần tử thứ N của chuỗi (0-index) này, như một danh sách các ký tự. Trải ra một chút:

Nest[
  Flatten[
    Characters @ {RomanNumeral@#,#2}& @@@
      Reverse @@@ Tally /@ Split@ #
    ]& ,
  {"I"}, #]&

Bên ngoài Nestlặp lại chức năng bốn dòng giữa, bắt đầu từ{"I"} , N lần. Dòng 4 chia danh sách ký tự của chữ số La Mã đầu vào thành các ký tự giống như, đếm từng lần chạy Tallyvà đặt số đếm trước các ký tự mà chúng đang đếm. Dòng 3 biểu diễn các số đếm dưới dạng chữ số La Mã, sau đó chia các chữ số La Mã đó thành các danh sách các ký tự. Các Flattenlệnh giảm danh sách-of-danh sách toàn bộ vào một danh sách một chiều.

Đây là phiên bản ban đầu:

Nest[
  "" <> Flatten[{RomanNumeral@#[[1]], #[[2]]} & /@
    (Reverse@#[[1]] & /@ 
      Tally /@
        Split@Characters@#)] &,
  "I", #] &

3
Grrr Mathematica;)
Beta Decay

Nếu bạn sử dụng @@@thay vì /@bạn có thể sử dụng ##2thay vì #[[1]]#[[2]]. Ngoài ra, danh sách các ký tự là loại chuỗi có thể chấp nhận, vì vậy bạn có thể làm việc với những loại đó và tránh sử dụng Characters@.
Martin Ender

@MartinEnder Aha, tôi biết phải có một @@@lối tắt giống như! Đối với danh sách các ký tự là loại chuỗi có thể chấp nhận (mà tôi đồng ý sẽ rút ngắn mã): có bài đăng nào trên trang web này bạn có thể chỉ cho tôi mô tả (các) tiêu chuẩn cộng đồng không?
Greg Martin


1
Thêm một vài khoản tiết kiệm: Characterschủ đề tự động để bạn có thể sử dụng @, Reverse@#&tất nhiên giống như đơn giản Reverse, trong trường hợp đó bạn cũng không cần những dấu ngoặc đơn đó. Và ký hiệu tiền tố (trong trường hợp Flatten) không lưu bất cứ thứ gì nếu bạn cần thêm dấu ngoặc đơn để làm cho nó hoạt động. Kết hợp tất cả những thứ đó:Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&
Martin Ender

8

CJam ( 33 30 byte)

"I"{e`{(4md1$^'I*\'V*@}%e_}ri*

Bản demo trực tuyến

Chìa khóa cho tính đúng đắn của việc thực hiện là định lý sau:

Nếu thế hệ đầu tiên là I , không có chiều dài chạy nào lớn hơn năm

Bổ đề: nếu thế hệ đầu tiên là I, không có chuỗi nào chứa VVV. Bằng chứng là do mâu thuẫn. Giả sử rằng có một chỉ mục đầu tiên nnthế hệ thứ chứa VVV. Nếu điều đó VVVbị phá vỡ (a)V VVthì chuyển đổi từ thế hệ trước là xấu: đáng lẽ nó phải như vậy (a+5)V. Vì vậy, nó phải VV V(d), và thế hệ trước chứa đựng VVVVV, mâu thuẫn với sự lựa chọn củan .

Bây giờ, giả sử có một chỉ mục đầu tiên mmthế hệ thứ chứa ...IIIIII.... Lưu ý rằng không thể có chữ số nào khác ngoài IVtrong chuỗi, bởi vì không có thế hệ trước nào có một chuỗi chín Ihoặc chín Vgiây. Nhiều nhất là bốnI s đến từ một chuỗi Is trong chuỗi trước đó, vì vậy phần tương ứng của chuỗi trước đó phải được ...IIIVV...đưa ra ... IIII IIV .... Vì VVthế hệ m-1không xuất phát VVVVV(xem bổ đề), nên thế hệ thứ hai Vphải là một chữ số dài I, vì vậy trong thế hệ m-1chúng ta có ...IIIVVI.... Và vì chúng tôi muốn các Is ban đầu cho IIIIvà không IVIhoặcVI , nó được bắt đầu bằng chuỗi bắt đầu hoặc bởi a V.

Nếu chúng ta có (...V)?IIIVVI...trong thế hệ m-1, chúng ta có gì trong thế hệ m-2? Chúng tôi đã quan sát thấy rằng các VVgen. m-1phải được phân tích cú pháp như (a)V V(I).

Giả sử chúng ta lấy a=2:(...V)?I IIV VI... Thực tế nó phải như vậy ...VI IIV VI..., mặc dù việc dẫn đầu đó Vcó thể là một phần của IV; Vì vậy, ở thế hệ trước chúng ta có (...V)? IIII VV IIIII...hoặc (...V)? IIIII VV IIIII. Dù bằng cách nào chúng ta cũng gặp rắc rối với VVIIIII: thứ hai Vphải là một chiều dài chạy, nhưng sau đó ...VI IIII...yêu cầu một cặp (chiều dài, chữ số) sau có cùng một chữ số.

Vì vậy nó phải a=1 : (...V)?II IV VI.... Kể từ thế hệ mlà lần đầu tiên với một hoạt động trong sáu Is, mà phải được (...V)? II IV VI..., vì vậy mà thế hệ m-2(...V)? I V IIIII.... ...VIVIIIII...là không thể: tuy nhiên chúng tôi chọn giải thích lần thứ hai Vchúng tôi kết thúc bằng hai cặp liên tiếp (chiều dài, chữ số) có cùng một chữ số.

Do đó thế hệ m-2 phải được ^IVIIIII..., phân tích thành ^IV IIII I(V)...hoặc ^IV III II(V).... Chúng cho thế hệ tương ứng m-3^V III V ...hoặc ^V II VV....

Nhưng nếu chúng ta nhìn vào điểm bắt đầu của chuỗi bắt đầu bằng chuỗi đầu tiên bắt đầu V, chúng ta sẽ có một chu kỳ:

    VI IV I...
    IV III IV ...
    II IV IVI ...
    IIII IV II IV ...

và vì vậy không bao giờ thế hệ bắt đầu với một trong hai VIIIVhoặc VIIVV. Chúng ta phải kết luận rằng không có như vậy m.

Mổ xẻ

"I"          e# Initial generation
{            e# Loop...
  e`         e#   Run-length encode
  {          e#   Foreach [run-length char] pair...
    (        e#     Extract the run-length r
    4md1$^   e#     Get the number of Vs and the number of Is
             e#     The number of Vs is r/4 ; the number of Is is (r%4)^(r/4)
    'I*\'V*@ e#     Repeat strings the appropriate number of times and reorder
  }%
  e_         e#  Flatten to a simple string
}ri*         e# ... n times, where n is taken from stdin

6

Python 3, 195 byte

Có rất nhiều byte bị lãng phí trên các chữ số La Mã, vì vậy có khả năng một số môn đánh gôn sẽ được thực hiện ở đó.

Cảm ơn @ El'endiaStarman, @ Sherlock9 và @Shooqie

import re
def f(x,r=""):
 for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*a
 return r
s="I"
for i in[0]*int(input()):print(s);s=re.sub(r'(.)\1*',lambda m:f(len(m.group()))+m.group()[0],s)

Nghĩa là nó!


Bạn có thể bỏ qua dấu ngoặc vuông:for v,i in(5,"V"),(4,"IV"),(1,"I")
shooqie

@shooqie Tôi không biết bạn có thể làm điều đó: D
Beta Decay

for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*atiết kiệm một byte.
Sherlock9

@ αγ: Ngoài ra, bạn dường như không sử dụng i(như trong for i in range(...)). Tôi đã thử tìm hiểu execnhưng điều này đã thoát 1trong phương thức 'phụ' dường như đang làm rối mã, tôi không thể tìm ra cách giải quyết.
shooqie

@shooqie Tôi rút ngắn lại một chút bằng cách loại bỏrange
Beta Decay

4

R, 110 107 byte

as.romankết hợp với rlelàm cho điều này dễ dàng. Lạm dụng phạm vi và được xây dựng trong hành vi của mèo <<-tiết kiệm một vài byte.

x="I"
replicate(scan(),{r=rle(strsplit(x,"")[[1]])
x<<-paste(rbind(paste(as.roman(r$l)),r$v),collapse="")})

Mất trong N từ bàn điều khiển. Xuất ra 2 đến N điều khoản đầu tiên của chuỗi (mà tôi tin là trong thông số ...)

 [1] "II"                                                                                                                                                                                                                                     
 [2] "III"                                                                                                                                                                                                                                    
 [3] "IIII"                                                                                                                                                                                                                                   
 [4] "IVI"                                                                                                                                                                                                                                    
 [5] "IIIVII"                                                                                                                                                                                                                                 
 [6] "IIIIIVIII"                                                                                                                                                                                                                              
 [7] "VIIVIIII"                                                                                                                                                                                                                               
 [8] "IVIIIIVIVI"                                                                                                                                                                                                                             
 [9] "IIIVIVIIVIIIVII"                                                                                                                                                                                                                        
[10] "IIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                                               
[11] "VIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                                                
[12] "IVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                                                          
[13] "IIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                                                                   
[14] "IIIIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                      
[15] "VIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                 
[16] "IVIIIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                         
[17] "IIIVIVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                            
[18] "IIIIIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                           
[19] "VIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                              
[20] "IVIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                    
[21] "IIIVIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                             
[22] "IIIIIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIIVIVIIVIIIIIVVIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                      
[23] "VIIVIIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVVIIVIIIVIIIIVVIIIVIIIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                   
[24] "IVIIIIVVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIIVIIIIVIIIIIVIVIIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                             
[25] "IIIVIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIVIIVVIIVIIIVIIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"

1

JavaScript (ES6), 107

Hàm đệ quy trả về số hạng thứ 0 dựa trên

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

Kiểm tra

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

function update() {
  O.textContent=f(I.value)
}

update()
<input id=I value=25 type=number oninput='update()'><pre id=O></pre>


1

Perl 6 , 62 byte

{("I",{S:g/(.)$0*/{<I II III IV V>[$/.chars-1]~$0}/}...*)[$_]}

Hàm ẩn danh chấp nhận chỉ mục dựa trên zero.

Làm cho việc sử dụng thực tế là số La Mã cao hơn 5 không cần thiết, bởi vì các nhóm chữ số lặp lại duy nhất có thể xảy ra là:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

( thử trực tuyến )

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.