언어 디자인 : 2 차원 패턴 매칭


49

이것은 Fortnightly Challenge # 6 입니다. 주제 : 언어 디자인

거기에 채팅방 이 문제에 대한이. 아이디어를 논의하고 싶다면 우리와 함께하십시오!

그리고 지금 완전히 다른 무언가를 위해 ...

이번 주에는 새로운 유형의 도전을 실험하고 싶습니다. 이 도전에서 당신은 언어를 디자인하게 될 것입니다! 패턴 매칭은 프로그래밍에서 매우 일반적인 문제이며 종종 코드 골프에 매우 유용합니다. 예를 들어 정규식을 사용하여 텍스트 줄에서 패턴을 감지 할 수 있습니다. 그러나, 2 차원 패턴을 기술하고 검출하는 확립 된 방법은 없다.

도전

텍스트 블록으로 2 차원 패턴을 설명 할 수있는 패턴 일치 언어를 설계해야합니다. 동작 모드 (언어가 다른 정규식 공통점이 아무것도하지 않지만) 언어의 정규 표현식과 유사합니다 :

  • 입력으로 직사각형 텍스트 블록이 나타납니다. 텍스트가 그리드의 행을 구분하기 위해 줄 바꿈 (0x0A)뿐만 아니라 인쇄 가능한 ASCII 문자 (0x20 ~ 0x7E)로만 구성되어 있다고 가정 할 수 있습니다.
  • 패턴 설명에 따라이 텍스트 블록의 하위 집합으로 일치하는 항목이있는 경우이 일치 항목을 반환하거나 인쇄해야합니다. 일치하는 사각형이 아닌 경우 예약 된 문자가있는 사각형 영역에 채워 져야합니다. 유효한 일치 항목이 여러 개인 경우 반환 된 일치 항목을 선택하는 방법 (가장 큰 것, 가장 작은 것, 첫 번째 등)을 결정할 수 있습니다.

일부 응용 프로그램의 경우 구현에서 일치 자체 대신 일치 위치를 반환 할 수 있으면 유용 할 수 있지만 필수 사항은 아닙니다.

최소한 언어는 입력의 연속 된 직사각형 하위 영역으로 패턴을 일치시킬 수 있어야합니다.

답은 다음을 포함해야합니다.

  • 설명 언어.
  • 작업을 구현 . 프로그램 또는 선택한 언어의 함수 / 클래스 일 수 있습니다.
  • 아래에 제공된 예제해결하는 데 언어를 사용하는 방법을 보여줌으로써 언어를 보여 주어야합니다 . 귀하의 언어가 모든 언어와 일치 할 필요는 없지만, 이들 중 8 개 이상 을 일치시킬 수 있어야합니다 . 귀하의 언어가 우리가 생각하지 못한 멋진 일을 할 수 있다면 자유롭게 포함 시키십시오.

귀하의 답변이 기존 아이디어를 바탕으로하는 경우에는 문제가 없지만, 예상되는 시점에 크레딧을 제공하십시오.

확장

위는 유효한 제출이 충족해야하는 최소값을 설명합니다. 그러나 몇 가지 일반화로 다음과 같은 패턴 일치 언어를 더욱 유용하게 만들 수 있습니다.

  • 패턴을 하나 이상의 가장자리에 고정 할 수 있으므로 전체 입력 영역에 특정 패턴이 있는지 확인할 수 있습니다.
  • 하나가 아닌 모든 경기를 생성합니다. 겹치는 일치의 의미를 선택할 수 있습니다.
  • 직사각형이 아닌 텍스트를 입력으로 사용.
  • 패턴이 직사각형이 아닌 일치를 지정할 수 있도록합니다. 이러한 경우 출력은 예약 문자가있는 사각형으로 채워 져야합니다.
  • 패턴이 구멍과 일치하도록 지정할 수 있습니다.
  • 특정 오프셋으로 나타나는 두 문자와 같이 비 연속 일치를 허용합니다.
  • 회전 및 반사를 쉽게 지정할 수 있습니다.
  • 선택적으로 입력을 주기적으로 실린더 또는 원환 체로 취급하여 반대쪽 가장자리가 인접 해있는 것으로 간주합니다.

채점

이 과제의 주요 목표는 향후에 사용될 수있는 효과적인 2D 패턴 일치 언어를 생성하는 것입니다. 따라서, "예제를 해결하기위한 가장 짧은 결합 길이"와 같은 스코어링 시스템은 일반적인 유용성을 희생하면서 특정 기능을 하드 코딩 할 수 있습니다. 따라서 우리는이 도전이 인기 콘테스트 로 가장 잘 진행될 것이라고 결정했습니다 . 순 투표 수가 가장 많은 제출이 승리합니다. 사람들이 투표하는 방식을 강요 할 수는 없지만 다음은 유권자가 이상적으로 찾아야 할 사항에 대한 몇 가지 지침입니다.

  • 표현력. 이 질문에 제시된 예를 넘어서서도 언어가 다양한 문제를 해결할 수 있습니까? 제안 된 확장을 지원합니까?
  • 가독성. 표기법이 얼마나 직관적입니까 (적어도 기본 구문을 알고있는 사람들에게는)?
  • Golfitude. 이것은 여전히 ​​CodeGolf.SE입니다. 이 사이트의 목적 상, 패턴을 설명하기 위해 코드가 거의 필요하지 않는 일치하는 언어를 갖는 것이 좋습니다.

예제 문제

다음 스택 스 니펫은 2D 패턴 일치 언어로 처리 할 수있는 16 가지 예제 문제를 보여줍니다. 각 예제에는 간단한 문제점 설명이 포함되어 있으며 일반적으로 일치하는 항목을 찾을 수없는 입력 예제와 일치하는 항목을 찾을 수없는 경우 (해당되는 경우)가 있습니다.

위에서 언급했듯이 귀하의 언어는 이러한 문제 중 8 가지만 해결할 수 있습니다. 그 위에있는 모든 것은 선택 사항이지만 물론 당신이 얻는 투표 수를 늘려야합니다.

(아니요, 해당 HTML 코드를 읽을 필요는 없습니다. "코드 스 니펫 실행"버튼을 누르면 브라우저에서 잘 렌더링되어 전체 화면으로 볼 수 있습니다.)


이러한 문제에 대한 일반적인 시간 제한이 있습니까? 나는 이것을 해결하는데 관심이 있지만 매우 바쁘다. 쉽게 2 주가 걸릴 수있다.
데본 파슨스

7
@DevonParsons 참가 마감일이 없습니다.
PhiNotPi

특히 새 태그를 만들었으므로 흥미로워 보입니다. 2D 언어를 만들려면 보너스 포인트가 있어야한다고 생각합니다.
mbomb007

1
@ mbomb007 2D 언어를 만들 때 보너스 포인트가 있습니다. 나는 그것이 상당한 양의 공감대를 얻을 것이라고 확신합니다. ;)
Martin Ender

@ MartinBüttner 언어를 만드는 법조차 모르겠습니다. 새로운 언어 코드 파일을 가져 와서 정의 된 구문에 따라 해석 / 실행하는 Python 프로그램을 작성하고 출력을 생성하는 것과 같이 (단순합니까?) 일 수 있습니까?
mbomb007

답변:


32

스네이크 엑스

지금까지 15/16 문제를 해결하십시오!

온라인 통역사 ! - 전체 언어 사양 - 자바 스크립트 소스

통역사 스크린 샷

이 언어의 기본 개념은 정규식과 같은 구문을 사용하여 텍스트 확인 문자를 이동하는 '뱀'을 정의하는 것입니다.

SnakeEx의 프로그램은 다른 명령 시퀀스를 사용하는 뱀에 대한 정의 목록으로 구성됩니다. 뱀은이 정의를 사용하여 다른 뱀을 생성 할 수 있습니다.이 정의는 SnakeEx가 대부분의 힘을 얻는 곳입니다. 분지 구조를 일치시키고 재귀를 수행 할 수도 있습니다 (Paren Matching 예 참조).

모든 프로그램은 본질적으로 정규식 세트처럼 보이지만 뱀의 방향을 바꾸는 형태 의 방향 명령이 추가 <dir>되고 더 많은 뱀을 낳는 형태의 명령을 호출 합니다 {label<dir>params}.

진입 점의 경우, 통역사는 첫 번째 정의를 사용하여 오른쪽으로 이동하여 하나의 뱀을 생성합니다.

매우 간결하지는 않지만 매우 강력하고 읽기 쉽다고 생각합니다.

업데이트

  • 변경되었습니다! 논리적으로 일치하지 않음 및 ~ 일치하지 않음
  • 동일 <!>선상을 해결하기 위해 추가
  • 해결 된 일치하는 십자가
  • 덜 끔찍한 방식으로 체스 판 해결
  • 바운드 클로저 구문 추가 %{min,max}
  • 재귀 예제 추가

솔루션

15 개 해결, 1 개 진행 중

위에 링크 된 온라인 통역사를 사용하여 이러한 프로그램을 쉽게 시험해 볼 수 있습니다!

문제 1-체스 판 찾기

m:{v<R>2}{h<>1}
v:{c<L>A1}+
h:{c<R>A2}+
c:_?(#_)+#?

자세한 소개는 문제점 3에서 시작하십시오.

문제 2-체스 보드 확인

m:{v<R>2}{h<>1}
v:${c<L>A1}+$
h:${c<R>A2}+$
c:$_?(#_)+#?$

범위를 벗어난 기호 $로 적절한 뱀을 북 엔딩하는 것은 프로그램이 전체 입력과 만 일치하도록하는 한 가지 방법입니다.

문제 3-자릿수 사각형 감지

m:{c<R>A1}%{2,}
c:[0-9]%{2,}

m뱀 이동 오른쪽 최소 2 뱀에 스폰 ( %{2,}정의 C를 (이용 "2 무한대"의미 고정 임) c) 및 (오른쪽 이동 <R>사방 현재 뱀에 상대적이기 때문에), 또는 오히려이 경우 다운. APARAM은 산란 뱀이 호출 후 이동해야 함을 지정 설탕이다. 1번호 파라미터는 "그룹"에 뱀을 넣어 - 우리가 사각형에 일치를 제한하는 방법 매개 변수입니다. 같은 그룹의 모든 뱀이 정확히 같은 거리를 이동하지 않으면 경기는 계산되지 않습니다.

문제 4-단어 검색에서 단어 찾기

m:<*>GOLF

direction 명령 <*>은 뱀이 대각선 또는 직교 방향으로 회전하도록 지정합니다. 그런 다음 간단한 정규식을 찾습니다.

문제 5-사각형 입력 감지

m:{v<R>1}{h<>1}
v:${c<L>A1}+$
h:${c<R>A1}+$
c:$.+$

여기서 열쇠는 특수 문자 $이며 뱀이 범위를 벗어난 경우에만 일치합니다. 우리는 수평 뱀과 수직 뱀을 생성합니다. 그것들은 가장자리를 따라 달리면서 더 많은 뱀을 낳습니다. 그리고 그것들은 모두 같은 그룹에 있고 같은 길이 여야합니다.

문제 6-인생의 게임에서 글라이더 찾기

m:<+>[({l1<R>A}{l2<R>A}{l3<R>})({l1<L>A}{l2<L>A}{l3<L>})]
l1:##\.
l2:[(#\.)(\.#)]#
l3:#\.\.

m4 개의 직교 방향 ( <+>) 중 하나로 시작하여 회전합니다. 그런 다음, 3 개의 행을 왼쪽 또는 오른쪽으로 순서대로보고 반영합니다.

(통역에 사용되는 HTML 텍스트 영역이 행에 여러 공백이있는 경우 바보 같은 일을하는 것처럼 보이기 때문에 공백을 마침표로 바꿨습니다.)

문제 7-황천의 Portal과 일치

m:{e<R>A1}{d<R>A1}%{2,22}{e<R>1}
e:~.X%{3,22}~.
d:X\.+X

m뱀 산란 뱀 오른쪽 이동, 오른쪽 가장자리를 확인하는 마지막 뱀 중간 열 확인, 2-22 뱀 좌단을 확인하고있다. ~오퍼레이터는 검사해야 따르지만, 용액의 일부로서 표시되어서는 안 어떤 것을 나타낸다.

경계 폐쇄는 이제 우리가이 문제를 완전하고 적절하게 해결할 수있게합니다!

문제 8-마인 크래프트 상자 배치

m:~{s<>}~!{d<+>}\.
s:<+>.<BR>([$\.]<R>)%{3}
d:.<+>CC

여기서는 논리 !토큰 ( ) 을 사용하는데 , 다음 토큰과 일치하지 않는 경우에만 일치합니다. 이 선언 d은 특정 방향에서 이중 가슴을 감지하므로 !{d<+>}직교 방향에 이중 가슴이 없는지 확인하십시오. s현재 사각형 주위에서 작은 다이아몬드 모양으로 움직여 최소 3 개의 공간이 비어 있거나 보드에서 떨어져 있는지 확인합니다. \.앞의 모든 조건이 성공했다고 가정하면 후행은 마침내 사각형과 일치합니다.

문제 9-수평 및 수직 정렬

m:<R>?#~.*#

뱀 은 순서와 일치하기 전에 m선택적으로 우회전 ( <R>?)합니다. .정규식과 같은 와일드 카드입니다.

문제 10-공 선점

m:<!>#~.*#~.*#

<!>방향을 추가 하면 이제이 문제를 해결할 수 있습니다! <!>처럼 <+>대신 사방 분지 가능한 모든 방향으로 분기.

문제 12-문자 Q를 피하십시오

m:{h<R>A}%{4}
h:[^Qq]%{4}

각각 문자 Q가 아닌 4 개의 문자를 찾는 뱀 4 개를 스폰합니다.

문제 13-다이아몬드 마이닝

m:{tl<RB>1}{tr<RF>1}
tl:X/*{bl<L>1}X
tr:X\\*{br<R>1}X
bl:X\\*X
br:X/*X

이것은 꽤 깔끔합니다. m두 마리의 뱀을 낳습니다. 하나는 뒤쪽으로 가고 다른 하나는 앞쪽으로갑니다. 이들 각각은 슬래시를 따라 X로 이동 한 다음 다른 뱀을 현재 방향과 직각으로 생성합니다.

문제 14-일치하는 십자가

m:{a<R>A}+{b<R>A}+{a<R>A}+
a:{e<>P1}{c<>P2}{e<>P3}
b:{c<>P1}{c<>P2}{c<>P3}
e:\.+
c:#+

P피기 백 매개 변수를 사용한 것은 이번 이 처음 입니다. 일반적으로 뱀은 독립적이지만이 매개 변수를 사용하여 호출하면 호출 뱀이 수신자와 함께 이동합니다. 따라서 e2'.'시퀀스, '#'시퀀스 및 '.'시퀀스를 확인하고 모두 별도의 호출로 만들 수 있으므로 '1,'2 '및'3 '으로 그룹화 할 수 있습니다. 길이를 일치시킵니다.

문제 15-Boggle Board에서 단어 일치

m{I}:<*>p<*>a<*>n<*>a<*>m<*>a

말이 많으면 간단합니다. I매개 변수는 대소 문자를 구분하지 않습니다 (정의 및 호출에서 매개 변수를 지정할 수 있음). 뱀은 어느 방향 으로든 돌아가고 캐릭터와 일치하며 다시 돌아옵니다.

m{EI}:<*>p<*>a<*>n<*>a<*>m<*>a

재사용 할 수없는 문자 버전입니다. Exclusive 매개 변수는 뱀 이 퇴행 충의 점액 흔적과 같이 이미 표시된 문자와 일치하는 것을 금지합니다.

문제 16-가장자리를 감싸십시오

m{W}:{c<R>WA}%{3}
c:###

W매개 변수는 뱀이 범위를 벗어날 때 줄 바꿈 할 수 있도록합니다. 우리는 또한이 HV만 수평 또는 수직 배치를 허용 할 수 있습니다.

추가-미로 찾기

m{E}:$(<P>\.)+$

걸을 수있는 층이 마침표 인 ASCII 미로를 해결합니다. <P>방향 전방, 왼쪽 또는 오른쪽 (설탕 수단 [<F><L><R>]).

추가-Paren Matching

m:\(~{r<>P}\)
r:[^\(\)]*(\({r<>P}\))?[^\(\)]*

아직 Prelude를 수행하는 방법을 찾지 못했지만 첫 단계는 다음과 같습니다. 여기서는 r뱀이 재귀 적으로 사용되어 해당 괄호가 일치하는 괄호가 없는지 확인하여 일치합니다.

추가 -ASCII 토폴로지 : 루프 계산


이 언어가 단순히 일치하는 것 대신 교체 할 수 있도록 구문을 추가 하시겠습니까? codegolf.stackexchange.com/questions/51231/…에 대한 항목을 작성하기 위해이 과제에 대한 솔루션을 사용하고 싶지만 여기서 단일 솔루션은 찾기 및 바꾸기가 아닙니다. (언어 사양 타이밍 규칙으로 인해 답변이 유효하지 않다는 것을 알고 있습니다)
Sparr

@ 스파 르. 나쁜 생각은 아니지만 코드 골프에 더 유용 할 것입니다. 언제 스스로 할 시간이 있는지 잘 모르겠지만 명심하십시오.
BMac

3
별도로 : 방향 변경 구문이 혼동됩니다. 뱀이 캐릭터를 일치시킨 후에 진행되기 때문에, 나는 나에게 의미가있는 곳보다 먼저 방향을 한 캐릭터 씩 바꿔야하는 것 같습니다. 예 : 문자열 "ABC \ nDEF"이고 ABCF에서 정의한 L 자 모양의 테트리스 조각과 일치 시키려면 뱀을 "m : ABC <R> F"로 쓰고 싶지만 "m : AB <R> CF "대신에. 나는 이것이 사양과 일치한다는 것을 이해하지만, 매우 반 직관적이라는 것을 알았습니다.
Sparr

전주곡 구문에 대한 부분적인 해결책이 있습니다. 유일한 문제는 전체 입력과 일치하지 않으면 일치하지 않는 것입니다. m:{a<>} a:[({n<R>A})({n<R>A}*{l<R>A}{a<>P}{r<R>A})]*{n<R>A}* l:$[^\(\)]*\([^\(\)]*$ r:$[^\(\)]*\)[^\(\)]*$ n:$[^\(\)]+$
TheNumberOne

21

슬립, 파이썬 3.4 ( Github Wiki , 온라인 통역사 )

feersum의 제출과 마찬가지로 이것은 그리드 통과를 기반으로하지만 CarpetPython의 제출과 마찬가지로 정규 표현식을 기반으로합니다. 어떻게 든 내가 중간을 차지한 것처럼 보입니다.

추가하고 싶은 구현되지 않은 많은 기능들이 있습니다. 따라서 관련이있는 곳에서 시간이되었을 때 무엇을하려고했는지 언급했습니다.


업데이트

(자세한 뉴스는 Github 페이지 참조)

  • 2015 년 4 월 5 일 : Slip에 온라인 통역사가 있습니다 ! 아직 초기 단계이므로 몇 가지 버그가있을 수 있습니다.

  • 2015 년 4 월 5 일 : 효율성 업데이트! 이제 황천의 차 원문이 훨씬 빠르게 입력됩니다 (2 초). 또한 구문이 많이 변경되었으므로 위키를 확인하십시오. 그룹 번호도 수정되었습니다.


슬립은 특정 사각형에서 시작하고 처음에는 오른쪽을 향하는 일치 포인터를 갖습니다. 문자가 일치하면 포인터가 현재 방향으로 앞으로 이동합니다 (구현은 순서대로 정확하게 수행하지는 않지만).

경기 포인터의 방향으로 특정 방향으로 설정 될 수있다 ^<digit>, ^0, ^1, ^2, ... ^7, N, NE, E 포인터를 설정 ... 각각 NW (시계 방향).

다음과 같은 바로 가기도 사용할 수 있습니다.

  • ^* 직교 또는 대각선 방향을 모두 확인합니다.
  • ^+ 4 개의 직교 방향을 모두 확인합니다.

(미래 계획 : (1, 2)기사의 이동 과 같은 임의의 방향 설정 허용 )

예를 들어 ( 문제 4-단어 검색에서 단어 찾기 )

^*GOLF

8 개의 직교 또는 대각선 방향을 모두 시도하여 "GOLF"라는 단어를 찾습니다. 기본적으로 Slip은 가능한 모든 시작 사각형을 시도하고 각각에서 하나의 결과를 반환하여 중복을 필터링하므로 그리드와 같은

GOLF
O
L
FLOG

맨 위 행과 맨 아래 행 "GOLF"가 동일한 사각형에서 시작하므로 맨 위 행과 맨 아래 행만 일치로 리턴합니다. 모든 일치 항목을 가져 오려면 o겹치는 일치 모드를 사용할 수 있습니다.

마찬가지로 ( 문제 15-Boggle 보드의 단어와 일치 ),

p^*a^*n^*a^*m^*a

panama매번 다른 방향을 시도하여 일치 합니다. i대소 문자를 구분하지 않으 려면 플래그를 사용하십시오 . Slip은 기본적으로 문자를 재사용하지만 r반복 없음 플래그 로 전환 할 수 있습니다 .

(미래 계획 : 반복 ^*할 필요가 없도록 각 이동 후 방향 세트를 자동으로 확인하는 검색 모드 수정 자 )

경기 포인터의 방향은 왼쪽 또는를 잘 작성 90도 회전 할 수 있습니다 <또는 >각각을. 예를 들어

 `#`#< `#<  <`#<`#

패턴을 찾습니다

  #
## 
 ##

다음 순서로 살펴보십시오.

765
894
123

이것은 우리가 해결 할 수 있습니다 찾기 글라이더 - 문제 6

^+(`#`# >`# > `#>`#> |`#`# <`# < `#<`#< | `#`#> `#>  >`#>`#| `#`#< `#<  <`#<`#)

여기서 파트 1과 2는 글라이더 모양을 인코딩하고 파트 3과 4는 반사 된 대응 파트를 인코딩합니다.

Slip은 백틱 `을 사용 하여 이스케이프 처리합니다. Slip은 언어에 이름을주는 다른 형태의 이동 (슬립 명령)이 있기 때문입니다. /일치 포인터를 왼쪽으로 직교 이동 \시키고 일치 포인터를 오른쪽으로 직교 이동시킵니다.

예를 들어

abc   ghi
   def

로 일치시킬 수 있습니다 abc\def/ghi.

그 자체로는 특별히 유용하지는 않지만, (?| <regex> )고정 그룹 과 결합 될 때 미끄러짐이 더 중요해지며 , 이는 일치하는 선견처럼 작동합니다. 정규 표현식 내부가 일치하면 끝 부분에서 일치 포인터의 위치와 방향이 고정 그룹 이전 상태로 재설정됩니다.

예를 들어

abc
def
ghi

와 일치 할 수 있습니다 (?|abc)\(?|def)\(?|ghi).

마찬가지로, 문제 12-문자 Q를 피할 수 있습니다.

%(\(?|[^qQ]{4})){4}

여기서 %첫 번째 \활성화 를 중지하는 슬립 방지 명령이 있습니다.

Slip은 또한 assert 길이를 가지며, (?_(<group num>) <regex> )일치 길이가 주어진 그룹 번호와 길이가 같은 경우에만 정규 표현식과 일치합니다.

예를 들어, 문제 13-다이아몬드 마이닝 을 사용하여 쉽게 해결할 수 있습니다.

^1X(`/*)X>(?_(1)`\*)X>(?_(1)`/*)X>(?_(1)`\*)

다이아몬드의 왼쪽 상단을 먼저 맞추고 나머지 세 변의 길이가 같다고 주장합니다.

( v자세한 출력을 위해 플래그로 실행 )

Match found in rectangle: (8, 0), (12, 4)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (0, 0), (6, 6)
   X
  / \
 /   \
X     X
 \   /
  \ /
   X

Match found in rectangle: (2, 2), (4, 4)
 X
X X
 X

Match found in rectangle: (10, 2), (14, 6)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (5, 3), (9, 7)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (0, 6), (2, 8)
 X
X X
 X

골퍼 대안은

^1X(`/*)(X>(?_(1)`\*)X>(?_(1)`/*)){2}

첫 번째면과 두 번 일치합니다.

다른 많은 문제는 미끄러짐, 고정 그룹 및 길이 어설 션을 사용하여 해결할 수 있습니다.

문제 14-일치하는 십자가 :

(?|(`.+)(`#+)(`.+))(\(?|(?_(2)`.+)(?_(3)`#+)(?_(4)`.+)))*(\(?|(?_(2)`#+)(?_(3)`#+)(?_(4)`#+)))+(\(?|(?_(2)`.+)(?_(3)`#+)(?_(4)`.+)))+

첫 번째 행에서 .s와 #s 의 너비를 캡처 하면 완전히 줄어 듭니다.

산출:

Match found in rectangle: (0, 1), (5, 5)
.###..
######
######
.###..
.###..

Match found in rectangle: (4, 6), (6, 8)
.#.
###
.#.

이 버그는 몇 가지 버그가 발견되면 약간의 재귀로 골프를 칠 수 있습니다.

문제 3-자릿수를 감지합니다 :

(?|`d`d+)(\(?|(?_(1)`d+)))+

두 자릿수 이상의 맨 위 행을 일치시킨 다음 아래의 모든 행의 길이가 동일해야합니다. `d은에 해당하는 사전 정의 된 문자 클래스 [0-9]입니다.

이것은 모든 일치 항목을 찾습니다 .

문제 7-네더 포털과 일치 :

(?|.X{2,22}.)\((?|(?_(1)X`.+X))\){3,22}(?_(1).X+.)

원래 스레드 의 최상위 예를 출력 합니다 .

Match found in rectangle: (2, 1), (5, 5)
XXXX
X..X
X..X
X..X
XXXX

Match found in rectangle: (9, 1), (14, 5)
.XXXX.
X....X
X....X
X....X
.XXXX.

Match found in rectangle: (13, 4), (17, 8)
.XXXX
X...X
X...X
X...X
.XXX.

마지막으로 Slip의 다른 기능은 다음과 같습니다.

  • $0, $1, $2, ..., $7북쪽 가장자리, 북쪽 동쪽 모서리, 동쪽 가장자리 등을 $+고정합니다 . 모든 모서리를 $*고정하고 모서리를 고정합니다.
  • $뒤에 소문자가 오는 경우 현재 위치에 앵커를 설정하고 나중에 $해당하는 대문자 가 뒤에 올 수 있습니다 ( 예 : $a및) $A.
  • # 이동 안함 플래그를 토글하여 다음 일치 후 일치 포인터가 앞으로 이동하는 것을 중지합니다.
  • ,는와 같은 문자와 일치 .하지만 출력에 추가하지 않으므로 연속되지 않은 일치를 허용하면서에 의해 인식됩니다 (?_()).

... 그리고 더. 이 페이지에 나열 할 내용이 너무 많습니다.

다른 문제들

문제 1-체스 판 찾기 :

(?|`#?(`_`#)+`_?)(?_(1)(?|...+))(\(?_(1)(?|`#?(`_`#)+`_?$a)))+<(?|`#?(`_`#)+`_?)(?_(9)(?|...+))(\(?_(9)(?|`#?(`_`#)+`_?)))+$A

두 체스 판 문제는 확실히 Slip의 장점이 아닙니다. 우리는 맨 윗줄은 다음이 사이에 최소 길이 3 교대로 확실하게 일치 #하고 _, 다음 미끄러 이후 행을 일치합니다. 결국 $a앵커는 체스 판의 오른쪽 아래에 있어야합니다.

그런 다음 왼쪽으로 돌아가 열에 대해 반복 $A하여 끝에 일치하는지 확인 합니다.

문제 2-체스 판 확인 :

$7%(\(?|`_?(`#`_)*`#?$2))+$5<%(\(?|`_?(`#`_)*`#?$0))+$3

이전 문제와 마찬가지로 각 행이 올바른지 확인한 다음 왼쪽으로 회전하고 열에 대해서도 동일하게 수행합니다. 앵커는 전체 보드 만 일치하는지 확인하는 데 사용됩니다.

문제 9-가로 및 세로 정렬 :

>?`#,*`#

우리는 옵션을 적용? >회전 명령에 정량화하여 오른쪽 또는 아래쪽으로 일치시킵니다. 우리는 함께 예를 들어 모든 5 찾을 o모드를 중복, 만 4없이 이후 #.,###.,#같은 위치에서 시작합니다.

문제 10-공 선점

^+`#(?|(,*)<(,*))(((?_(2),*)<(?_(3),*),>)+#`#){2}

#가로 문자와 세로 문자를 일치시킨 다음 두 번째 문자까지 #반복하고 세 번째 문자까지 반복하십시오 #.

문제 5-사각 입력 감지 :

$7.(.*)>(?_(1).*)$3>((?|.*)\)*

오른쪽 하단 모서리를 고정하기 전에 왼쪽 상단 모서리를 고정하고 상단 모서리의 길이가 오른쪽 모서리와 같은지 확인하십시오. 입력이 이것을 통과하면 전체 입력과 일치하도록 뒤로 올라갑니다.

문제 8-마인 크래프트 상자 배치 :

`.^+(($^|(?|`.))>){3}($^|`.|C<(($^|(?|`.))>){3})

p플래그 와 함께 실행하여 각 경기의 위치를 ​​가져옵니다. $^다음 움직임이 일치 포인터를 범위 밖으로 놓을 경우 일치하는 앵커입니다.

먼저을 일치시킨 .다음 3 개의 .s / boundaries로 둘러싸여 있는지 확인한 다음 네 번째 주변 사각형도 ./ boundary 또는 단일 가슴인지 확인하십시오 ( 주변 사각형 을 확인 하여 ).

문제 11-Prelude 구문 확인 :

$7>%(/(?|[^()]+$4)(?1)?|/(?|[^()]*`([^()]*$4)(?1)?/(?|[^()]*`)[^()]*$4)(?1)?)$1

몇 번 시도했지만 이것이 맞다고 생각합니다. 여기서는 PCRE와 동일한 구문을 갖는 재귀를 사용합니다.

이 접근법은 입력이 직사각형이어야하지만 직사각형이 아닌 일치가 끝나면 가정이 필요하지 않습니다.

더 많은 재귀로 골프를 치는 동일한 접근법이 있습니다.

$7>%((/(?|([^()]*)$4)|/(?|(?4)`((?3))(?1)?/(?|(?4)`)(?3)))*)$1

문제 16-가장자리를 감싸십시오.

%(\(?|`#{3})){3}

(참고 : 랩핑은 아직 온라인 통역사에게 전달되지 않았습니다)

랩핑 플래그가 필요합니다 w. 기술적 %으로 미끄럼 방지 의 초기 값 은 필요하지 않지만 일치는 1 제곱보다 높은 것으로 계산됩니다.

문제 EX 1-미로 해결사 :

S(^+`.)*^+E

채팅 에서 BMac의 의견에 문제가 있습니다 . r일치 포인터가 앞뒤로 움직이지 않도록 반복 모드 없음 플래그를 사용하십시오 .

문제 EX 2 - 얼굴 인식 :

(?|O(,*),(?_(2),*)O)(?_(2)(\(?|,))*)\(?|,(?_(2),*)O)(?_(2)(\(?|,))*)\`\(?_(2)`_*)`_(?_(2)`_*)`/

나는 얼굴을 일치 시키지만 지우는 것은 아닙니다. 질문에는 유로 기호가 포함되어 있으며, 작동하려면 인쇄 가능한 ASCII로 바꿔야합니다.


해시 패턴은 Conway 글라이더입니다
Heimdall

17

PMA / 달팽이 (C ++)

나는 달팽이가 격자 주위를 이동하고 명령을 실행하는 것으로 생각합니다. 달팽이는 각 사각형에 점액 자국을 남기고 기본적으로 사각형이 일치하지 않습니다. 명령 목록 끝에 도달하면 일치합니다.

이제 우리는 그들을 추적하기 위해 우선 순위 목록이 필요하므로 충분한 연산자가 있습니다. 작업은 다음 순서로 해결됩니다.

  1. 그룹 내부 ( ) [ ]
  2. 대체 문자를 따라 분할 |
  3. `그룹으로 왼쪽에있는 모든 것을 평가하십시오
  4. 수량 자 [m],[n]n
  5. 주장 = !
  6. 연쇄

인터프리터는 C ++로 작성되었습니다. 심연 소스 코드는 여기 에서 찾을 수 있습니다 .

문제 4 : 단어 검색

프로그램

z\G\O\L\F

단어의 발견 여부에 대해 진실하거나 거짓된 가치를 얻기에 충분합니다. z(15 개의 절대 또는 상대 방향 명령 중 하나)는 모든 8 방향으로 일치합니다. 여러 개의 연속 방향 명령이 함께 OR됩니다. 예를 들어 , 오른쪽, 위, 왼쪽, 아래 및 대각선 방향에 대한 명령이므로 ruldy거의 같습니다 z. 그러나 지침은 다른 순서로 테스트됩니다. 일치하는 첫 번째 문자는 방향에 관계없이 항상 달팽이가 시작하는 문자입니다. \<character>는 단일 리터럴 문자와 일치합니다.

기본 전략은 왼쪽 정렬 된 입력의 경계 상자에있는 모든 사각형에서 패턴을 시도하고 일치 횟수를 출력하는 것입니다. 부울 값 1또는 0필요한 경우 다음 프로그램을 사용할 수 있습니다.

?
z\G\O\L\F

소스 파일에 줄 바꿈이 하나 이상 있으면 첫 번째 줄은 입력을 직사각형으로 초기 변환하기위한 옵션으로 처리됩니다. 이 ?옵션은 어디서나 일치하는지 여부에 따라 0 또는 1을 인쇄합니다.

문제 15 : 보글

대체를 구현 한 후 Boggle을 해결할 수 있습니다. 이 경우 대소 문자를 구분하지 않는 일치를 사용하는 것이 좋지만 구현하는 것이 가장 중요하지 않습니다.

\p|\P)z(\a|\A)z{\n|\N)z{\a|\A}z(\m|\M)z(\a|\A

|1 차원 정규식과 정확히 동일하게 작동합니다. 즉, 그룹화 구분 기호의 두 일치하는 쌍있다 (){}. 닫는 괄호는 반대 유형의 열린 그룹을 닫고 같은 유형의 가장 가까운 그룹을 닫습니다. 예를 들어 다음 {({{)에서 가장 왼쪽 그룹 만 열린 상태로 유지됩니다. 보시다시피 가장자리에서 일치하지 않는 그룹화 기호는 암시 적으로 닫힙니다. `내가 지금 가지 않을 다른 그룹화 명령 이 있습니다.

문제 8 : 마인 크래프트 상자

프로그램은 유효한 가슴 배치 수를 인쇄합니다. 이것은 실제로 골프를 타야했던 첫 번째였으며 바이트 수 (17)를 몇 차례 줄였습니다.

\.!(o\C)2o(!\Cw)3
  • \. 일치하는 시작점에서 문자 그대로 점과 일치합니다.
  • !(o\C)2동등 !((o\C)2)정량 어서보다 더 높은 우선 순위이기 때문에. 정확히 시간 <atom> <number>을 반복 <atom>하는 것을 의미합니다 <number>. o달팽이를 직교 방향으로 돌립니다. !부정적인 주장입니다. 따라서이 부분은 인접한 이중 가슴이 없는지 확인합니다.
  • o 직교 방향으로 회전합니다.
    • (!\Cw)3C달팽이 앞에는 없다고 주장한 다음 시계 반대 방향으로 3 번 돌립니다.

문제 2 : 체스 판 확인

&
\#!(o^_)|\_!(o^#

&옵션은 1모든 위치에서 일치하는 것처럼 프로그램의 출력을 설정합니다 0. 정규 표현식 과 동일 ^c하지 않은 문자와 일치합니다 . 전체적으로 프로그램의 의미는 다음과 같습니다. 입력의 경계 사각형의 모든 위치에서 1 이 아닌 문자에 직교하지 않는 문자 또는 1 이 아닌 문자에 직교하지 않는 문자가있는 경우 1을 인쇄합니다. 아닙니다 ; 그렇지 않으면 0.c[^c]#__#


점액 흔적 아이디어는
boggle

이것이 Boggle 문제에 대한 좋은 해결책입니다. 내 접근 방식으로는 해결할 수 없습니다.
Logic Knight

14

Re2d 클래스, Python 2

업데이트 : "9. 정렬"문제가 추가되었습니다.

내 접근 방식은 Python re 모듈을 사용하여 검색하고 일치시키는 것입니다. Re2d 클래스는 처리 할 텍스트를 준비하고 re 함수를 실행하며 출력 결과 형식을 지정합니다.

이 언어는 완전히 새로운 언어가 아니며 추가 2D 모드에 대한 플래그가 추가 된 2 차원으로 투영 된 표준 정규식 언어입니다.

이 클래스의 사용법은 다음과 같습니다.

re2dobject = Re2d(<horizontal pattern>, [<vertical pattern>], [<flags>])

두 패턴 모두 표준 선형 텍스트 RE 패턴입니다. 세로 패턴이 제공되지 않으면 클래스는 가로 패턴을 사용하여 세로도 일치시킵니다. 플래그는 2D 확장자가있는 표준 RE 플래그입니다.

테스팅

1. Finding chessboards
Chessboard pattern at (2, 1, 4, 3)

print '\n1. Finding chessboards'
reob1 = Re2d('#(_#)+_?|_(#_)+#?')
found = reob1.search('~______~\n~##_#_#~\n~#_#_##~\n~##_#_#~\n~______~')
print 'Chessboard pattern at', found
assert not reob1.search('#_##\n_#_#\n__#_\n#_#_\n#_#_')

검색 방법은 체스 판 패턴을 발견하여 4 튜플 위치를 반환합니다. 튜플은 x,y일치하는 첫 번째 문자의 위치와 width, height일치하는 영역 의 위치를 갖습니다 . 하나의 패턴 만 제공되므로 가로 세로 일치에 사용됩니다.

2. Verifying chessboards
Is chess? True

print '\n2. Verifying chessboards'
reob2 = Re2d('^#(_#)*_?|_(#_)*#?$')
print 'Is chess?', reob2.match('_#_#_#_#\n#_#_#_#_\n_#_#_#_#')
assert not reob2.match('_#_#_#__\n__#_#_#_\n_#_#_#__')

체스 판은 부울을 리턴하는 match 메소드로 검증되었습니다. 전체 텍스트 와 일치 하려면 ^$시작 및 끝 문자가 필요 합니다.

3. Rectangle of digits
Found: [(0, 1, 5, 3), (1, 1, 4, 3), (2, 1, 3, 3), (3, 1, 2, 3), (0, 2, 5, 2), (1, 2, 4, 2), (2, 2, 3, 2), (3, 2, 2, 2), (6, 3, 2, 2)]
Not found: None

print '\n3. Rectangle of digits'
reob3 = Re2d(r'\d\d+', flags=MULTIFIND)
print 'Found:', reob3.search('hbrewvgr\n18774gwe\n84502vgv\n19844f22\ncrfegc77')
print 'Not found:', reob3.search('uv88wn000\nvgr88vg0w\nv888wrvg7\nvvg88wv77')

이제 MULTIFIND플래그를 사용 하여 2+ 숫자 블록에 대해 가능한 모든 일치 항목을 반환합니다. 이 방법은 9 개의 가능한 일치 항목을 찾습니다. 그것들은 겹칠 수 있습니다.

4. Word search (orthogonal only)
Words: [(0, 0, 4, 1), (0, 3, 4, 1), (3, 3, -4, -1), (3, 2, -4, -1), (3, 0, -4, -1)] [(0, 0, 1, 4), (3, 0, 1, 4), (3, 3, -1, -4), (0, 3, -1, -4)]
Words: ['SNUG', 'WOLF', 'FLOW', 'LORE', 'GUNS'] ['S\nT\nE\nW', 'G\nO\nL\nF', 'F\nL\nO\nG', 'W\nE\nT\nS']
No words: [] []

print '\n4. Word search (orthogonal only)'
words = 'GOLF|GUNS|WOLF|FLOW|LORE|WETS|STEW|FLOG|SNUG'
flags = HORFLIP | VERFLIP | MULTIFIND
reob4a, reob4b = Re2d(words, '.', flags), Re2d('.', words, flags)
matching = 'SNUG\nTEQO\nEROL\nWOLF'
nomatch = 'ABCD\nEFGH\nIJKL\nMNOP'
print 'Words:', reob4a.search(matching), reob4b.search(matching)
print 'Words:', reob4a.findall(matching), reob4b.findall(matching)
print 'No words:', reob4a.findall(nomatch), reob4b.findall(nomatch)

이 테스트는 수직 및 수평 뒤집기의 사용을 보여줍니다. 이렇게하면 반대 단어를 일치시킬 수 있습니다. 대각선 단어는 지원되지 않습니다. MULTIFIND플래그는 4 개 방향에서 여러 중복 일치 할 수 있습니다. findall 메소드는 검색을 사용하여 일치하는 상자를 찾은 다음 일치하는 텍스트 블록을 추출합니다. 검색에서 반대 방향의 일치를 위해 음의 너비 및 / 또는 높이를 사용하는 방법에 유의하십시오. 세로 방향의 단어에는 줄 바꾸기 문자가 있습니다. 이는 2D 문자 블록의 개념과 일치합니다.

7. Calvins portals
Portals found: [(3, 1, 5, 6)]
Portal not found None

print '\n7. Calvins portals'
reob7 = Re2d(r'X\.{2,22}X|.X{2,22}.', r'X\.{3,22}X|.X{3,22}.', MULTIFIND)
yes = '....X......\n.XXXXXX.XX.\n...X...X...\n.X.X...XXX.\n...X...X.X.\n.XXX...X.X.\nX..XXXXX.X.'
no = 'XX..XXXX\nXX..X..X\nXX..X..X\n..X.X..X\n.X..X.XX'
print 'Portals found:', reob7.search(yes)
print 'Portal not found', reob7.search(no)

이 검색에서는 최소 크기가 다르기 때문에 각 차원마다 별도의 패턴이 필요했습니다.

9. Alignment
Found: ['#.,##', '##'] ['#\n.\n,\n.\n#', '#\n,\n.\n#']
Found: [(3, 4, 5, 1), (6, 4, 2, 1)] [(7, 0, 1, 5), (3, 1, 1, 4)]
Not found: None None

print '\n9. Alignment'
reob9a = Re2d(r'#.*#', r'.', MULTIFIND)
reob9b = Re2d(r'.', r'#.*#', MULTIFIND)
matching = '.,.,.,.#.,\n,.,#,.,.,.\n.,.,.,.,.,\n,.,.,.,.,.\n.,.#.,##.,\n,.,.,.,.,.'
nomatch = '.,.#.,.,\n,.,.,.#.\n.,#,.,.,\n,.,.,.,#\n.#.,.,.,\n,.,.#.,.\n#,.,.,.,\n,.,.,#,.'
print 'Found:', reob9a.findall(matching), reob9b.findall(matching)
print 'Found:', reob9a.search(matching), reob9b.search(matching)
print 'Not found:', reob9a.search(nomatch), reob9b.search(nomatch)

이 2 개의 검색 세트는 2 개의 수직 및 2 개의 수평 일치를 찾았지만 임베드 된 #.,#문자열을 찾을 수 없습니다 .

10. Collinear Points (orthogonal only)
Found: [(0, 1, 7, 1)] [(3, 1, 1, 4)]
Not found: None None

print '\n10. Collinear Points (orthogonal only)'
matching = '........\n#..#..#.\n...#....\n#.......\n...#....'
nomatch = '.#..#\n#..#.\n#....\n..#.#'
reob10h = Re2d(r'#.*#.*#', '.')
reob10v = Re2d('.', r'#.*#.*#')
flags = MULTIFIND
print 'Found:', reob10h.search(matching, flags), reob10v.search(matching, flags)
print 'Not found:', reob10h.search(nomatch, flags), reob10v.search(nomatch, flags)

여기서는 두 가지 검색을 사용하여 양방향으로 일치하는 항목을 찾습니다. 여러 직교 일치를 찾을 수 있지만이 방법은 대각선 일치를 지원하지 않습니다.

12. Avoid qQ
Found: (2, 2, 4, 4)
Not found: None

print '\n12. Avoid qQ'
reob12 = Re2d('[^qQ]{4,4}')
print 'Found:', reob12.search('bhtklkwt\nqlwQklqw\nvtvlwktv\nkQtwkvkl\nvtwlkvQk\nvnvevwvx')
print 'Not found:', reob12.search('zxvcmn\nxcvncn\nmnQxcv\nxcvmnx\nazvmne')

이 검색은 첫 번째 일치를 찾습니다.

13. Diamond Mining
.X.
X.X
.X.

.X.
X.X
.X.

..X..
./.\.
X...X
.\./.
\.X..

..X..
./.\.
X...X
.\./.
..X..

.XX.\
//.\.
X...X
.\./.
..X..

...X...
../.\..
./.X.\.
X.X.X.X
.\.X.//
..\./X.
.X.X..\

Diamonds: [(2, 2, 3, 3), (0, 6, 3, 3)] [(8, 0, 5, 5), (10, 2, 5, 5), (5, 3, 5, 5)] [(0, 0, 7, 7)]
Not found: None None None

print '\n13. Diamond Mining'
reob13a = Re2d(r'.X.|X.X', flags=MULTIFIND)
reob13b = Re2d(r'..X..|./.\\.|X...X|.\\./.', flags=MULTIFIND)
reob13c = Re2d(r'...X...|../.\\..|./...\\.|X.....X|.\\.../.|..\\./..', flags=MULTIFIND)
match = '''
...X......X....
../.\..../.\...
./.X.\..X...X..
X.X.X.XX.\./.\.
.\.X.//.\.X...X
..\./X...X.\./.
.X.X..\./...X..
X.X....X.......
.X.............
'''.strip().replace(' ', '')
nomatch = '''
.X......./....
.\....X.......
...X.\.\...X..
..X.\...\.X.\.
...X.X...X.\.X
../X\...\...X.
.X...\.\..X...
..\./.X....X..
...X..../.....
'''.strip().replace(' ', '')
for diamond in reob13a.findall(match)+reob13b.findall(match)+reob13c.findall(match):
    print diamond+'\n'
print 'Diamonds:', reob13a.search(match), reob13b.search(match), reob13c.search(match)
print 'Not found:', reob13a.search(nomatch), reob13b.search(nomatch), reob13c.search(nomatch)

다이아몬드 문제는 더 어렵다. 세 가지 크기에는 세 가지 검색 개체가 필요합니다. 테스트 세트에서 6 개의 다이아몬드를 찾을 수 있지만 가변 크기의 다이아몬드에는 맞지 않습니다. 이것은 다이아몬드 문제에 대한 부분적인 해결책 일뿐입니다.

파이썬 2 코드

import sys
import re

DEBUG = re.DEBUG
IGNORECASE = re.IGNORECASE
LOCALE = re.LOCALE
UNICODE = re.UNICODE
VERBOSE = re.VERBOSE
MULTIFIND = 1<<11
ROTATED = 1<<12     # not implemented
HORFLIP = 1<<13
VERFLIP = 1<<14
WRAPAROUND = 1<<15  # not implemented

class Re2d(object):
    def __init__(self, horpattern, verpattern=None, flags=0):
        self.horpattern = horpattern
        self.verpattern = verpattern if verpattern != None else horpattern
        self.flags = flags

    def checkblock(self, block, flags):
        'Return a position if block matches H and V patterns'
        length = []
        for y in range(len(block)):
            match = re.match(self.horpattern, block[y], flags)
            if match:
                length.append(len(match.group(0)))
            else:
                break
        if not length:
            return None
        width = min(length)
        height = len(length)
        length = []
        for x in range(width):
            column = ''.join(row[x] for row in block[:height])
            match = re.match(self.verpattern, column, flags)
            if match:
                matchlen = len(match.group(0))
                length.append(matchlen)
            else:
                break
        if not length:
            return None
        height = min(length)
        width = len(length)
        # if smaller, verify with RECURSIVE checkblock call:
        if height != len(block) or width != len(block[0]):
            newblock = [row[:width] for row in block[:height]]
            newsize = self.checkblock(newblock, flags)
            return newsize
        return width, height

    def mkviews(self, text, flags):
        'Return views of text block from flip/rotate flags, inc inverse f()'
        # TODO add ROTATED to generate more views
        width = len(text[0])
        height = len(text)
        views = [(text, lambda x,y,w,h: (x,y,w,h))]
        if flags & HORFLIP and flags & VERFLIP:
            flip2text = [row[::-1] for row in text[::-1]]
            flip2func = lambda x,y,w,h: (width-1-x, height-1-y, -w, -h)
            views.append( (flip2text, flip2func) )
        elif flags & HORFLIP:
            hortext = [row[::-1] for row in text]
            horfunc = lambda x,y,w,h: (width-1-x, y, -w, h)
            views.append( (hortext, horfunc) )
        elif flags & VERFLIP:
            vertext = text[::-1]
            verfunc = lambda x,y,w,h: (x, height-1-y, w, -h)
            views.append( (vertext, verfunc) )
        return views

    def searchview(self, textview, flags=0):
        'Return matching textview positions or None'
        result = []
        for y in range(len(textview)):
            testtext = textview[y:]
            for x in range(len(testtext[0])):
                size = self.checkblock([row[x:] for row in testtext], flags)
                if size:
                    found = (x, y, size[0], size[1])
                    if flags & MULTIFIND:
                        result.append(found)
                    else:
                        return found
        return result if result else None

    def search(self, text, flags=0):
        'Return matching text positions or None'
        flags = self.flags | flags
        text = text.split('\n') if type(text) == str else text
        result = []
        for textview, invview in self.mkviews(text, flags):
            found = self.searchview(textview, flags)
            if found:
                if flags & MULTIFIND:
                    result.extend(invview(*f) for f in found)
                else:
                    return invview(*found)
        return result if result else None

    def findall(self, text, flags=0):
        'Return matching text blocks or None'
        flags = self.flags | flags
        strmode = (type(text) == str)
        text = text.split('\n') if type(text) == str else text
        result = []
        positions = self.search(text, flags)
        if not positions:
            return [] if flags & MULTIFIND else None
        if not flags & MULTIFIND:
            positions = [positions]
        for x0,y0,w,h in positions:
            if y0+h >= 0:
                lines = text[y0 : y0+h : cmp(h,0)]
            else:
                lines = text[y0 : : cmp(h,0)]
            if x0+w >= 0:
                block = [row[x0 : x0+w : cmp(w,0)] for row in lines]
            else:
                block = [row[x0 : : cmp(w,0)] for row in lines]
            result.append(block)
        if strmode:
            result = ['\n'.join(rows) for rows in result]
        if flags & MULTIFIND:
            return result
        else:
            return result[0]

    def match(self, text, flags=0):
        'Return True if whole text matches the patterns'
        flags = self.flags | flags
        text = text.split('\n') if type(text) == str else text
        for textview, invview in self.mkviews(text, flags):
            size = self.checkblock(textview, flags)
            if size:
                return True
        return False

다이아몬드 문제가 명확하지 않은 경우 다이아몬드의 크기는 0, 1 또는 2가 아닌 크기 일 수 있습니다. 편집 : 사양을보다 명확하게하기 위해 사양을 편집했습니다.
PhiNotPi

알았다. Re2d에는이 문제에 대한 부분적인 해결책 만 있습니다. 가변 크기로 확장 할 수 없습니다. 그 확인은?
논리 기사

괜찮아.
PhiNotPi

14

피부를 깨끗하게 , 하스켈

소개

Grime은 부울 문법을 기반으로 합니다. 기본 아이디어는 작은 구성 요소로 직사각형 패턴을 구성하고 입력 매트릭스에서 해당 패턴이 있는지 확인하는 것입니다. 지금까지 Grime은 사각형 일치 만 지원하며 적어도 11 개의 문제를 다소 우아하게 해결합니다.

편집 : 십자가를 수정하고 (벌레를 발견 한 DLosc 덕분에) 다이아몬드 채굴이 추가되었습니다.

EDIT2 : Slip에서 영감을 얻은 캐릭터 클래스가 추가되었습니다. 또한 옵션 플래그의 구문을 변경하고 표현식 파서를 개선했으며 no-Q 문제를 추가했습니다.

EDIT3 : 크기 제한을 구현하고 황천 포털 문제를 추가했습니다.

용법

Grime 프로그램은 grammar 라고하며 문법 에 맞는 올바른 파일 확장자는 .gr이지만 강제 적용되지는 않습니다. 문법은 다음과 같이 평가됩니다

runhaskell grime.hs [options] grammarfile matrixfile

여기서 matrixfile문자 매트릭스를 포함하는 파일입니다. 예를 들어 숫자 문법은 다음과 같이 평가됩니다.

runhaskell grime.hs digits.gr digit-matrix

속도를 높이려면 파일을 최적화하여 컴파일하는 것이 좋습니다.

ghc -O2 grime.hs
./grime digits.gr digit-matrix

기본적으로 인터프리터는 찾은 첫 번째 일치 항목을 인쇄하지만 옵션 플래그를 사용하여이를 제어 할 수 있습니다.

  • -e: 전체 행렬 만 1일치하고 일치하고 0일치하지 않는 경우 인쇄 합니다 .
  • -n: 일치하는 수 또는 -e주어진 경우 전체 행렬을 인쇄합니다 .
  • -a: 모든 일치 항목을 인쇄합니다.
  • -p: 일치하는 위치도 형식으로 인쇄하십시오 (x,y,w,h).
  • -s: 성냥 자체를 인쇄하지 마십시오.
  • -d: 디버그 정보를 인쇄합니다.

문법 앞에 옵션을 지정할 수도 있습니다 (줄 앞에 삽입하고 쉼표 추가) ,(아래 예 참조).

구문과 의미

Grime 문법은 하나 이상의 정의 로 구성되며 각각은 별도의 줄에 있습니다. 각각은 비 터미널 의 값을 정의하고 그중 하나는 익명의 최상위 비 터미널을 정의해야합니다 . 정의 구문은 N=E또는입니다 E. 여기서 N대문자 E표현식 입니다.

식은 다음과 같이 구성됩니다.

  • 이스케이프 처리 된 문자는 해당 문자를 포함하는 \모든 1x1사각형 과 일치합니다 .
  • . 단일 문자와 일치합니다.
  • $1x1문자 매트릭스 외부의 사각형 과 일치합니다 .
  • _ 너비 또는 높이가 0 인 사각형과 일치합니다.
  • 사전 정의 된 문자 그룹은 digit, uppercase, lowercase, alphabetic, alpha numeric 및 ymbol s입니다.
  • 구문으로 새 문자 클래스를 정의 할 수 있습니다 [a-prt-w,d-gu]. 왼쪽의 문자가 포함되고 오른쪽의 문자는 제외되므로 정확하게 문자와 일치합니다 abchijklmnoprtvw. 왼쪽이 비어 있으면 모든 문자가 포함됩니다. 오른쪽이 비어 있으면 쉼표를 생략 할 수 있습니다. 문자 [],-\는로 이스케이프해야합니다 \.
  • 이스케이프 처리되지 않은 대문자는 터미널이 아니며 할당 된 표현식과 일치합니다.
  • Pand Q가 표현식 인 경우 , PQ수평 연결 일 P/Q뿐이고 수직 연결 일뿐 P입니다.
  • P+P수평으로 정렬 된 하나 이상 이며 P/+수직으로 동일하게 정렬됩니다.
  • 부울 연산을 붙이고 P|Q, P&QP!.
  • P?P|_, P*for P+|_P/*for의 줄임말입니다 P/+|_.
  • P#에 일치하는 모든 사각형과 일치합니다 P.
  • P{a-b,c-d}여기서 abcd음이 아닌 정수하는 것입니다 크기 제한P. 경우 P문자 클래스는, 그 표현은 일치 mxn, 만 문자를 포함하는 사각형을 그 제공 m사이 ab포함하고, n사이 cd포함. 다른 경우 식은 올바른 크기를 가지고 있고 일치하는 사각형과 P일치합니다. 경우 a또는 c생략하고, 그들로 촬영 0한 경우, b또는 d생략하고, 그들은 무한하다. a와 사이에 하이픈을 b생략하면 간격의 양쪽 끝에 동일한 숫자를 사용합니다. 전체가c-d부분이 생략되면 두 축이 모두 구속됩니다. 명확히하기 위해 {-b}는에 해당 {0-b,0-b}하고 {a-,c}에 해당합니다 {a-infinity,c-c}.

노트

Grime은 정의 A=A!되지 않은 동작 과 같은 역설적 정의를 허용 합니다. 그러나 충돌이나 무한 루프를 일으키지 않습니다.

Grime은 직사각형이 아닌 입력을 지원합니다. 행은 단순히 왼쪽에 정렬되고 간격을 사용하여 일치시킬 수 있습니다 $.

앞으로 다음을 구현하고 싶습니다.

  • 더 빠른 매칭. 현재 인터프리터는 예를 들어 사각형 .만 일치시킬 수 있다는 사실을 고려하지 않습니다 1x1. 일치하는 것을 찾을 때까지 모든 크기의 모든 사각형을 순서대로 시도하고 각 사각형에 대해 즉시 실패합니다.
  • 단어 검색 및 글라이더 도전을위한 회전 및 반사 작업.
  • context를 사용하여 사각형이 아닌 일치로 Boggle 보드 챌린지에 도움이됩니다. 예를 들어, Pv(Q>R)수단 P바닥 컨텍스트 (함께 Q오른쪽 컨텍스트 R). L 형 패턴과 일치합니다

    PPP
    PPP
    QQQRRRR
    QQQRRRR
    QQQRRRR
    

작업들

대략 복잡성 순서로 제공됩니다.

자릿수

d{2-}

이것은 간단하다 : 최소한 크기의 자릿수 2x2.

아니 q 또는 Q

[,qQ]{4}

이것은 첫 번째 것만큼이나 간단합니다. 이제 더 제한된 크기와 사용자 정의 문자 클래스가 있습니다.

수평 및 수직 정렬

\#.*\#|\#/./*/\#

이제 이스케이프 문자가 있습니다. 기본적으로 이것은 하나 #또는 여러 문자, #가로 또는 세로 와 일치 합니다.

정사각형 입력 감지

S=.|S./+/.+
e,S

이 문법은 매우 간단합니다. 기본적으로 정사각형은 1x1사각형이거나 오른쪽 가장자리에 하나의 열이 있고 아래쪽에 하나의 행이있는 작은 사각형입니다. e전체 입력 확인을 토글하는 최상위 비 터미널 앞에 있는 옵션 도 참고하십시오 .

단어 검색에서 단어 찾기

G=\G
O=\O
L=\L
F=\F
GOLF|FLOG|G/O/L/F|F/L/O/G|G.../.O../..L./...F|...G/..O./.L../F...|F.../.L../..O./...G|...F/..L./.O../G...

Grime에는 회전이나 반사 작업이 없기 때문에 이것은 끔찍합니다. 피부를 깨끗하게이 경기는 크기가 될 수 있다는 것을 알고하지 않기 때문에 그것은 또한 매우 느린 4x1, 1x4또는 4x4.

글라이더 문제는 비슷하게 해결 될 수 있지만, 그것을 적어 쓰기에는 너무 게으 릅니다.

황천의 차 원문

.\X+./\X/+\.{2-22,3-22}\X/+/.\X+.

크기 제한 연산자를 사용하면 어렵지 않습니다. 가운데 부분 은 올바른 크기의 \.{2-22,3-22}사각형과 일치 하고 양쪽 .Xs 열을 추가 X하고 그 상단과 하단에 무시되는 끝이있는 s 행 을 추가합니다.

일치하는 십자가

E=\.+/+
F=\#+/+
EFE/F/EFE&(E/F/E)F(E/F/E)

우리가 가진 것은 두 표현의 결합 (논리적 AND)입니다. 비 터미널은 E의 비어 있지 않은 사각형 일치 .의와 F의 비어 있지 않은 사각형 #들. 연결의 왼쪽은 유형의 사각형과 일치합니다.

...####..
...####..
...####..
#########
#########
.....##..
.....##..

우리가 EFE맨 위에 있고 F, 그리고 EFE다시 한 번. 오른쪽은 이것들의 조옮김과 일치하므로 정확하게 십자가를 얻습니다.

다이아몬드 마이닝

C=./+
T=\X|CTC/\/.+\\
B=\X|\\.+\//CBC
CTC/\X.+\X/CBC

비 터미널 C은 모든 1xn열의 약어입니다 . 다이아몬드의 상단 절반은 다음과 일치합니다 T. 단일 X또는 T양쪽 열과 그 /[something]\아래 행으로 둘러싸인 하나 입니다. B같은 방식으로 다이아몬드의 바닥과 일치하고 최상위 비 터미널은 X[something]X위쪽 절반과 아래쪽 절반 사이의 행입니다 .

체스 판 찾기

(\#\#|\#/\#|\_\_|\_/\_)#!&[#_]{3-}

오른쪽 은 s와 s 의 [#_]{3-}임의의 3x3큰 사각형 과 일치 하지만 왼쪽은 인접한 두 s 또는 s를 포함하지 않습니다 .#_#_

체스 판 확인

e,(\#\#|\#/\#|\_\_|\_/\_)#!&[#_]+/+

비어 있지 않은 사각형을 일치시킬 수 있지만 e전체 입력 확인에 플래그 를 사용해야한다는 점을 제외하면 기본적으로 위와 동일 합니다.

Prelude 구문 확인

A=[,()]/*
P=A*|P(A/\(/A)P(A/\)/A)P
e,P

아마도 지금까지 가장 흥미로운 문법 일 것입니다. 비 터미날은 A포함되지 않은 항목과 일치 (하거나 ), 및 P일부의 수와 일치 하나 A이상 존재하는 사이에 외부의 또는 두 개의 정합 괄호 P들.


@DLosc 버그를 찾아 주셔서 감사합니다.
Zgarb

시겠습니까 \#(.*|./*)\#일?
seequ

@Sieg 정렬을 위해? 불행히도, 그 이유는 " #왼쪽에 하나, 그 다음에 어떤 것의 행이나 열에 이어 오른쪽에 하나"로 해석되기 때문입니다 #. #슬래시를 사용하여 s가 세로로 열에 연결 되도록 지정해야합니다 /.
Zgarb

10

TMARL

템플릿 매칭 및 인식 언어

기술

통역사가 24K 문자 ( 코드 스 니펫이 문자를 사용합니까? )를 차지 하므로 자세한 설명은 여기를 참조하십시오 .

가장 중요한 부분 : 인터프리터는 Javascript로되어 있으므로 여기서 바로 사용해 볼 수 있습니다!

그리고 문제의 경우 :

# 1-체스 판 찾기

$#_#
a
$_#_
bvacvbS5&(avcS5)G0G2P

&검색을 추가합니다. 끝에있는 G2는 실제 일치하는 일치 요소의 세 번째 요소를 가져옵니다. 처음 2 개의 요소는 x 및 y 좌표입니다 (0이 아닌 1을 기준으로 함).

# 3-자릿수 감지

$DD
$DD
S1G2P

나는 이것이 매우 간단하다고 생각합니다.

# 4-단어 검색에서 단어 찾기

$GO\LF
a
$G
$*O
$**\L
$***F
S6&(aS6)G0G2P

S는 모든 회전을 검색합니다 심지어 수 있도록 인수입니다. 다음 검색에 추가 될 수 있기 때문에 4보다 큽니다 (개별 일치를 추가 할 수 없음).

# 5-사각형 입력 감지

IL-(IG0L)!P

입력이 사각형이면 정확하게 사각형 만 결정하므로 이것이 완전히 유효한지 확실하지 않습니다. 입력 IL길이를 첫 번째 행의 길이와 비교하여 IG0L반전시킵니다.

# 6-인생 게임에서 글라이더 찾기

$## 
$# #
$# 
a
$ ##
$## 
$  #
bS6&(bMS6)&(aS6)&(aMS6)G0G2P

마지막으로 거울 사용!

# 12-편지 Q를 피하십시오

$[^Qq]
~4*4S1G2P

S1은 1 개만 필요하기 때문에.

나중에 더 어려운 것들을 할 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.