9의 배수에 대한 정규식


14

9의 배수를 인식하는 유한 상태 머신을 쉽게 설명 할 수 있습니다. 숫자 합 (mod 9)을 추적하고 다음에 허용되는 숫자를 추가하십시오. 이러한 FSM에는 9 개의 상태 만 있으며 매우 간단합니다! FSM 인식과 정규 언어의 동등성으로 인해 9의 배수에 대한 정규 표현식이 있습니다. 그러나 그러한 정규 표현식은 ... 매우 길다. 마찬가지로 기가 바이트 정도입니다.

https://www.quaxio.com/triple/ 에 3의 배수에 대한 실제 예제가 있습니다 . 페이지 하단에서 저자는 순진한 전환보다 약간 짧은 "손으로 최적화 된"솔루션을 제공합니다. 정규식에 FSM.

도전 과제 :

9의 배수를 탐지하려면 정규식을 만들어야합니다. 이러한 정규식은 매우 길 것으로 예상되므로 정규식을 인쇄 할 수있는 프로그램을 제공 할 것을 요청합니다. (정말로 전체 정규 표현식을 제공하려면 다른 곳에서 호스팅하고 여기에 연결하십시오!)

프로그램 출력의 정확한 문자 수를 알려줄 수 있어야합니다. 따라서 모든 정규 표현식을 특정 길이까지 시도하는 프로그램은 작동하는 것을 찾을 때까지 허용되지 않습니다. 완료까지 실행하고 결과 정규식 길이를 제공하십시오!

포인트는 물론 프로그램 길이를 기준으로하지 않고 가장 짧은 출력 정규식을 갖기위한 것입니다. 정규식은 내가 요청하는 "프로그램"이므로 여기에 편리하게 전송하기에는 너무 길기 때문에 여전히이 코드 골프에 태그를 지정하고 있습니다.

규칙 :

  • 입력은 일치하는 문자 만 포함합니다 [0-9]*.
  • 정규식은 9의 배수 와 일치 하지만 다른 것은 일치 하지 않아야합니다. 숫자 0-9로만 만들어지지 않은 경우와 유효하지 않은 입력은 원하는대로 일치하거나 실패 할 수 있습니다.
  • DFA에서 쉽게 인식 할 수있는 동기를 감안할 때 정규 표현식 은보다 이론적 인 용어 로 정규 표현식 이어야합니다 . 즉 정규 언어를 닫는 연산자 만 사용해야합니다 . 정확히 말하면, 허용되는 유일한 것 :
    • 리터럴 문자 범위 ( [ab], [a-f], [^k]), 149) 클린의 별 (Kleene star ( *), 앵커 ( ^$), 괄호를 통해, 교대 (그룹화 |), 선택적인 용어 ( ?), 하나 또는-이상의 용어 ( +), lookaheads ( (?=)), 부정적인 lookaheads을 ( (?!)) lookbehinds ( (?<=)), 네거티브 lookbehinds는 ( (?<!)), 조건식 (같이 https://www.regular-expressions.info/conditional.html - (?(?=test)then|else)), 및 제한된 길이의 역 참조 (아래 참조).
  • 허용 되지 않는 것들의 예 :
    • 임의의 길이, 순방향 참조, 재귀, 서브 루틴, 루핑 구문, 실행 코드, 'eval'변형 또는 문자열을 산술 값으로 캐스팅하기위한 내장 구문의 역 참조
  • 제한된 길이의 바인딩 문자열을 갖는 것으로 표시 될 수있는 역 참조는 유한 상태로 저장 될 수 있고 언어의 규칙 성을 변경하지 않기 때문에 허용됩니다. 예를 들어, (..2.[3-5])4\1.\1캡처 그룹에 바인딩 된 길이가 있으므로 정규식을 사용할 수 \1있습니다. 이것은 일반적인 구조입니다. (2*)0\1캡처 된 그룹을 유한 상태로 저장할 수 없으므로 와 같은 구성 은 허용되지 않습니다.
  • 정규식은 원하는대로 외부 0을 갖는 정수를 자유롭게 허용하거나 거부합니다. 그러나 문자열 "0"을 승인해야합니다.

2
관련 , 이것이 중복으로 간주되는지 확실하지 않음
ASCII 전용

아 흠! "regex multiple"을 검색했지만 "regex divisible"은 검색하지 않았습니다. 나는 그것이 끔찍하게 비슷하다고 가정합니다.
Alex Meiburg

11
아직 알려지지 않았으므로 PPCG에 오신 것을 환영합니다. 다른 사용자가 언급했듯이 샌드 박스에 챌린지 제안을 게시하여 제안을 게시하기 전에 피드백을받을 수 있도록 하는 것이 권장되지만 필수는 아닙니다 . 그러나 이것은 잘 생각되고 분명한 도전이므로 샌드 박스로 옮길 이유가 없습니다. 우리 커뮤니티를 즐기시기 바랍니다!
caird coinheringaahing

200 킬로바이트 미만의 솔루션도 가능하므로 그렇게 크지 않을 것입니다
Ton Hospel

3
.NET의 확장을 사용하는 솔루션 :^(0|9|(?<c>1|(?<c>2|(?<c>3|(?<c>4|(?<c>5|(?<c>6|(?<c>7|(?<c>8))))))))((?<-c>){9})?)*$(?(c).)
Neil

답변:


3

하스켈 , 207,535 202,073 바이트

가능한 경우 0|9대신 사용하여 5,462 바이트를 절약했습니다 [09].

digits n
  | x == 0    = "0|9"
  | otherwise = show x
  where x = mod n 9

regex 0 = "[09]*"
regex n = (regex' n (-1) (-1)) ++ "*"

regex' 0 start end = digits (end - start)
regex' n start end = '(':(regex' 0 start end) ++ (concat ['|':(regex' (n-x) (start-x) (-1)) ++ (regex (n-x))
                                                  ++ (regex' (n-x) (-1) (end-x)) | x <- [1..n]]) ++ ")"

main = do
  putStr ("^" ++ (regex 8) ++ "$")

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

링크 된 기사의 각주에 주어진 정규 표현식을 빠르게 적용하여 시작하십시오.

출력 정규 표현식의 Pastebin , Herman Lauenstein 제공.

전체 정규 표현식을 테스트 할 수는 없었지만 3으로 나누기를 검사하기 위해 프로그램을 수정하면 대신이를 기반으로하는 정규 표현식과 정확히 동일한 것을 제공합니다. 또한 숫자 합의 4 또는 5로 나눌 수 있는지 확인하도록 프로그램을 수정하면 테스트 한 숫자에서도 작동하는 것으로 보입니다.


또한 분석법이 2로 나눌 수있는 것 (같은 것이어야 함 /even$/)과 5로 나눌 수있는 것 (같은 것이어야 함 )을 테스트 할 수 있습니다 /[05]$/. PS : 코드의 언어를 언급하십시오
Ton Hospel

다음 은 출력을 가진 pastebin입니다 (모든 바이트가 수천 바이트를 절약하기 위해 ([09]|대체 됨 (0|9|)
Herman L
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.