로마에있을 때 로마인처럼 카운트?


20

배경

이 과제는 다음 다이어그램을 게시 한이 웹 사이트에서 영감을 얻은 것입니다 .

여기에 이미지 설명을 입력하십시오

이 다이어그램은 250 미만의 가장 긴 로마 숫자 표현이 188의 표현이므로 9 개의 숫자가 필요하다는 것을 보여줍니다.

도전

가장 로마 숫자를 표현하기 위해 사용되는 표준 기호는 다음과 같다 : { I, V, X, L, C, D, M}, 문자 '수치는 어디 M= 1000, D= 500, C= 100, L= 50, X= 10, V= 5 I= 1.

이 과제에서 목표는 양의 정수 n이 주어지면 n 개의 표준 심볼 을 연결하여 구성 할 수있는 유효한 로마 숫자 표현의 수를 계산하는 것 입니다.

그런 다음 프로그램에서이 계산 결과를 출력해야합니다!

입력 : 양의 정수 n .

출력 : 길이 n 의 유효한 로마 숫자 표현의 수 .

로마 숫자 표현 규칙

로마 숫자는 원래 "첨가"쌍만 있었으며 숫자는 항상 내림차순으로 작성되었으며 모든 숫자 값의 합은 숫자 값이었습니다.

나중에, 빼기 쌍화에서 더 작은 것을 더 크게 빼기 위해 더 큰 숫자 앞에 더 큰 숫자를 배치하는 것은 로마 숫자 표현을 단축하는 흔한 일이되었습니다. 다음과 같은 잘못된 식과 같이 빼기 쌍을 연결할 수 없습니다 IXL.

다음은 가산 및 감산 페어링에 대한 최신 규칙입니다.

  1. 빼기 쌍의 일부에서 선행 숫자로 하나의 I, X 및 C 만 사용할 수 있습니다.
  2. 빼기 쌍으로 V 또는 X 앞에만 배치 할 수 있습니다.
  3. X는 빼기 쌍에서 L 또는 C 앞에만 배치 할 수 있습니다.
  4. C는 빼기 쌍에서 D 또는 M 앞에만 배치 할 수 있습니다.
  5. 빼기 쌍 이외의 숫자는 내림차순이어야합니다 (즉, 각 빼기 쌍의 선행 숫자를 삭제하면 숫자가 내림차순 임).
  6. M, C 및 X는 더 작은 단위로 같거나 초과 할 수 없습니다.
  7. D, L 및 V는 각각 한 번만 나타날 수 있습니다.
  8. M 만 4 번 이상 반복 할 수 있습니다.

추가 사항

  • 우리는 막대 표기법을 사용하지 않을 것입니다 . 오히려, 우리는 단순히 숫자를 표현하기 위해 더 많은 M을 추가 할 것 입니다.

  • 이것이 로마 숫자에 대해 따를 유일한 규칙입니다. 즉,와 같은 이상한 표현 IVI도 시스템에서 유효한 것으로 간주됩니다.

  • 또한 일부 숫자는 여러 개의 표현식을 가지므로 길이 n의 표현식을 갖는 숫자의 수는 계산하지 않습니다 . 대신, 우리는 단지 유효한 표현의 수를 세고 있습니다.

테스트 사례

17

231

3105

위의 내용을 직접 확인 했으므로 테스트 사례를 다시 확인하고 가능한 경우 추가하십시오.

승리 기준

이것은 도전이므로 재미있게 보내십시오! 적어도 1에서 9까지의 입력을 처리 할 수있는 솔루션 만 허용합니다. 더 이상 보너스입니다!

편집하다

주석 작성자의 요청에 따라 아래 또는이 pastebin 링크에서 n = 3으로 계산 한 105 콤보를 찾으십시오.

III IVI IXI IXV IXX VII XII XIV XIX XVI XXI XXV XXX XLI XLV XLX XCI XCV XCX XCL XCC LII LIV LIX LVI LXI LXV LXX CII CIV CIX CVI CXI CXV CXX CXL CXC CLI CLV CLX CCI CCV CCX CCL CDCC CD CD CDC CD CD CDC CD CDC CD CDC CD CDC CD CD CDC CD CDC CD CDC CD CDC CD CDC CD CDC CD CMI CMV CMX CML CMC CMD CMM DII DIV DIX DVI DXI DXV DXX DXL DXC DLI DLV DLX DCI DCV DCX DCL DCC MII MIV MIX MVI MXI MXV MXX MXL MXC MLI MLV MLX MCI MCV MCX MCL MCC MCD MCM MDI MDV MDX MDL MDC MMX MML MMC MMD MMM

편집 2 :

Jonathan Allan이 제공 한 다음 골프 공 코드를 사용 하여 결과를 확인하십시오.

편집 3 :

이 과제의 모든 오류에 대해 사과드립니다. 다음에 더 나은 일을하도록하겠습니다!


의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
Mego

답변:


3

망막 , 111 바이트

~(`.+
*$(CM)CDXCXCXCXLIXIXIXIVII
.(.)
.+¶$$&$¶$$&$1$¶$$&$&¶L`.{0,$+}\b¶D`¶
¶$
¶.+¶$$&$¶$$&I¶L`[A-Z]{$+}\b¶D`¶.+

온라인으로 사용해보십시오! 난 당신이 하나의 감산 각각 사용할 수 있다는 것을 의미하는 1을 지배 오해 이것은 완전한 재 작성 I, XC. 설명 : 스크립트의 첫 번째 부분은 입력을 한 CM쌍 의 문자열로 확장 한 후 다른 가능한 빼기 쌍으로 확장합니다. 각 쌍은 선택 사항이며 각 쌍의 첫 문자도 쌍 내에서 선택 사항입니다. 그런 다음 세 번째 단계에서는 쌍 목록을 Retina 명령 목록으로 확장하여 입력을 받고 쌍에서 두 번째 또는 두 문자 옵션을 사용하여 세 개의 사본을 만든 다음 결과를 자르고 중복 제거합니다. 마지막 단계에서는 최종 작업을 수행하기위한 코드를 추가합니다. 먼저 입력을 확장하여 최종 작업을 추가합니다.I그런 다음 잘못된 길이의 결과를 필터링 한 다음 결과를 중복 제거하고 결과를 계산합니다. 결과 Retina 스크립트가 평가됩니다.

참고 : 이론 상으로는 4 번째 줄 끝에서 15 바이트를 저장할 수 있지만이 경우에도 스크립트가 TIO에서 시연하기에는 너무 느립니다 n=1.


@JonathanAllan Ah, 같은 선행 숫자를 가진 여러 뺄셈 쌍을 포함하고 있습니다.
Neil

2
@JonathanAllan 정확히 동일한 바이트 수를 위해 새로운 재 작성!
Neil

5

파이썬 2 , 177168162 바이트

import re,itertools as q
f=lambda n:sum(None!=re.match("^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$",(''.join(m)))for m in q.product('MDCLXVI',repeat=n))

온라인으로 사용해보십시오!

나는 아주 새롭고, 이것을 도와주세요! 이것은 실제 로마 숫자를 확인합니다. 정규식은IVI

@Dead Possum 덕분에 -9 바이트 !

-6 바이트@ovs 덕분에


예에서 n = 3 경우가 잘못되었을 수 있습니다. 나는 처음으로 93을 얻고 있었다^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
이스턴 Bornemeier


1
@JonathanAllan 나는이 규칙이 맞는지 확인하기 위해 Math stackexchange를 묻는 데 약 이틀을 보냈습니다. 내가 충분하지 않은 것 같아 :(
Don Thousand

1
@RushabhMehta 이것은 매우 체계적인 도전이며 프로그램하기에 재미 있고, 로마 숫자 정의의 유쾌한 뉘앙스에 대해 나쁘게 느끼지 않습니다. 그것은 당신의 도전입니다, 당신이 적합하다고 생각하는대로 지정하십시오. 그것은 다른 의미로, 더 어려울 수 있습니다
Easton Bornemeier

1
이것은 93대신 3에 대한 정답을 제시하지 않는 것 같습니다105
Jo King

3

자바 스크립트 (ES7), 133 바이트

편집 : Jonathan Allan의 코드 에서 반환 한 결과와 일치하도록 수정되었으며 OP에 의해 참조 구현으로 제공되었습니다.


n=>[...Array(m=k=7**n)].reduce(s=>s+/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test((--k+m).toString(7).replace(/0[62]|2[34]|4[51]/g,s=>s[1])),0)

온라인으로 사용해보십시오!

방법?

N1

[...Array(m = k = 7 ** n)].reduce(s => … (--k + m).toString(7) …, 0)

이제부터 각 숫자는 로마 숫자 기호로 해석됩니다.

0I,1M,2X,3L,4C,5D,6V

2) 유효한 모든 빼기 쌍을 다음 ABB같이 바꿉니다 .

.replace(/0[62]|2[34]|4[51]/g, s => s[1]))  // in the code
.replace(/I[VX]|X[LC]|C[DM]/g, s => s[1]))  // with Roman symbols

예 :

  • XLIXIV 된다 LXV
  • XIIV하게 XIV이탈, I다음 테스트가 실패 할 것이다을
  • IC또한 잘못된 잎, 이는 변경되지 I자리에

3) 나머지 기호의 순서가 올바른지 확인하고 허용 된 횟수보다 여러 번 표시되지 않습니다.

/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test(…)  // in the code
/^M*D?C{0,3}L?X{0,3}V?I{0,3}$/.test(…)  // with Roman symbols

성스러운 소, 나는 이것이 비의 비언어적 인 언어로 200 바이트 미만으로 이루어질 것으로 기대하지 않았습니다! 이것이 어떻게 작동하는지 설명해 주시겠습니까?
Don Thousand

그러나 TIO에서는 * n *> 4에서 작동하지 않는 것으로 나타났습니다.
Don Thousand

@RushabhMehta 더 높은 값을 테스트하기 위해 비 재귀 버전을 추가했습니다. 골프를 마치면 설명을 추가하겠습니다.
Arnauld

0

C, 150 123 바이트

설명을 충분히 읽지 않았으므로 표준 로마 숫자가 생성됩니다 (예 :식이 IVI계산되지 않음). 나는 그것에 노력을 기울 였기 때문에 어쨌든 나을 것이라고 생각했다.

#define F(X) for(X=10;X--;)
x[]={0,1,2,3,2,1,2,3,4,2};f(i,o,a,b,c){for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];return o;}

원본 (150 바이트) :

#define F(X) for(X=10;X--;)
i,o,a,b,c,x[]={0,1,2,3,2,1,2,3,4,2};main(){scanf("%i",&i);for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];printf("%i\n",o);}

1
유효한 제출물 만 게시 할 수 있습니다.
Okx

@CurtisBechtel 당신은 내가 생각하는 솔루션을 여기에 유지할 수 있지만 도전의 규칙을 만족시키기 위해 수정하려고합니다.
Don Thousand

1
난 당신이 사이의 공간을 제거 할 수 있다고 생각 F(X)하고for(X=10;X--;)
재커리
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.