하스켈 , 1080 1033 바이트
;
f=
g
ij=f
a =hi
hi = g
hij= ij
g ' ' =0
g '"' =0;
g '$' =0;
g '&' =0-0
g '(' =0-0-0
g '*' =0-0-0;
g ',' =0-0-0;
g '.' =0-0-0-0
g '0' =0-0-0-0-0
g '2' =0-0-0-0-0;
g '4' =0-0-0-0-0;
g '6' =0; g '8' =0
g ':' =0; g '<' =0-0
g '>' =0; g '@' =0-0;
g 'B' =0; g 'D' =0-0;
g 'F' =0; g 'H' =0-0-0
g 'J' =0; g 'L' =0-0-0-0
g 'N' =0; g 'P' =0-0-0-0;
g 'R' =0; g 'T' =0-0-0-0;
g 'V' =0; g 'X' =0-0-0-0-0
g 'Z' =0; g '^' =0; g '`' =0
g 'b' =0; g 'd' =0; g 'f' =0;
g 'h' =0; g 'j' =0; g 'l' =0;
g 'n' =0; g 'p' =0; g 'r' =0-0
g 't' =0; g 'v' =0; g 'x' =0-0-0
g 'z' =0; g '\92' =0-0; g '|' =0;
g '~' =0; g y = 1 ;z=0; i(-0)z=z;
i m('\10':y ) ="y"; ; ; ; ; ; ; ;
i m(mnmnmnmnm:y ) = i(m - 1 ) y ; ;
i k m ="y"; ; k i [ ] =01<1010101010;
k m('\10':y ) = k(m + 1 )(i m y ) ; ;
k m y =01>10; m o = k 1$'\10':o ; ; ;
o i('\10':y ) = o i y ; ; ; ; ; ; ; ; ;
o i(k:y )|g k<i = o(1 - i ) y ; ; ; ; ; ;
o i(k:y )|g k>i = o(1 - i ) y ; ; ; ; ; ;
o i [ ] =01<10; o i y =01>10;v=01>10101010
s y|o 1 y = m y|o(-0) y = m y ; s y =v; ; ;
온라인으로 사용해보십시오!
설명
이것은 하스켈에게 매우 흥미로운 일이었습니다.
동등
시작하려면 캐릭터에 짝수 또는 홀수 코드 포인트가 있는지 확인하는 방법이 필요합니다. 일반적인 방법은 코드 포인트를 가져 와서 2 씩 수정하는 것입니다. 그러나 알 수 있듯이 문자의 코드 포인트를 가져 오려면 가져 오기가 필요합니다. 소스 제한으로 인해 코드 포인트를 가져올 수 없습니다. 익숙한. 숙련 된 Haskeller는 재귀를 사용한다고 생각합니다. 는 전임자와 후임자를 얻을 수 있도록 typeclass의 Char
일부입니다 Enum
. 그러나 pred
와 succ
그들이 대체 바이트 패리티를하지 않기 때문에도 모두 사용할 수 있습니다.
그래서 이것은 우리가 꽤 붙어있어서 우리는 거의 문자로 조작 할 수 없습니다. 이에 대한 해결책은 모든 것을 하드 코딩하는 것입니다. 우리는 문자를 리터럴로 (대부분의) 짝수로 나타낼 수 있습니다. '
홀수 이기 때문에 문제가 발생할 확률 은 문자 자체 옆에있을 수 없으므로 문자 그대로 홀수 문자를 표현할 수 없습니다. 따라서 모든 짝수 바이트를 하드 코딩 한 다음 끝에 홀수 바이트를 모두 잡습니다.
문제 바이트
작은 따옴표로 감싸서 리터럴을 만들 수없는 짝수 바이트가 있음을 알 수 있습니다. 그들은 인쇄 할 수없는, 개행 및 \
입니다. 인쇄 할 수없는 것을 사용할 필요가없는 한 인쇄 할 수없는 것에 대해 걱정할 필요가 없습니다. 사실 우리는 여전히 탭과 같은 이상한 인쇄 불가능한 것을 사용할 수 있습니다. 줄 바꿈은 어쨌든 프로그램에서 다듬어지기 때문에 현명하게 무시 될 수 있습니다. (코드 포인트가 다소 편리하기 때문에 개행을 포함 할 수는 있지만 필요하지는 않습니다). 이 코드는 \
이제 \
코드 포인트 92를 가지며,이 코드 포인트는 편리하게 홀수 뒤에 짝수가옵니다. 따라서 짝수 \92
와 확률 사이에서 교대로'\92'
완벽하게 유효합니다. 나중에 우리는 개행을 나타낼 필요가있을 때 운 좋게도 같은 속성을 가지고 있음을 알 수있을 것 '\10'
입니다.
간격 문제
이제 실제 코드 작성을 시작하려면 한 줄에 많은 수의 문자를 넣을 수 있어야합니다. 이를 위해 모자를 썼습니다.
;
f=
g
ij=f
a =hi
hi = g
hij= ij
모자는 유효한 Haskell을 제외하고는 아무것도하지 않습니다. 처음에는 나중에 코드에서 우리를 도울 정의를 만들고 싶었지만 그렇지 않았습니다. 공백과 세미콜론과 같이 대문자를 만드는 더 쉬운 방법이 있지만이 방법으로 바이트를 절약하지 않으므로 변경하지 않아도됩니다.
하드 코더
이제 줄에 충분한 공간이 있으므로 값을 하드 코딩하기 시작합니다. 이것은 대부분 지루하지만, 몇 가지 흥미로운 점이 있습니다. 한 줄이 더 길어지기 시작하면 한 줄 ;
에 여러 선언을 넣을 수 있으므로 많은 바이트가 절약됩니다.
두 번째는 항상 줄을 시작할 수 없기 g
때문에 줄을 조금 들여 써야한다는 것입니다. 이제 Haskell은 실제로 들여 쓰기에 관심이 있으므로 이에 대해 불평합니다. 그러나 들여 쓰기 된 줄 앞의 마지막 줄이 세미콜론으로 끝나는 경우 허용됩니다. 왜? 나는 가장 희미하지는 않지만 작동합니다. 따라서 우리는 줄 끝에 세미콜론을 넣는 것을 기억해야합니다.
기능 빌딩 블록
하드 코더가 완료되면 프로그램 끝까지 부드럽게 항해합니다. 몇 가지 간단한 함수를 만들어야합니다. 먼저 drop
이라는 버전을 빌드합니다 i
. 우리가 문자열의 끝을 지나서 떨어지려고하면 그냥 반환한다는 점 i
과 다릅니다 . 그것이 반환하는 줄 바꿈을 삭제하려고하면 그 또한 드롭 다른 , 이들은 도움이 될 것입니다 나중에 우리 프로그램이 우리가 반환 할 수 있도록 삼각형 것을 확인하는 경우 때문에 마지막 줄이 완료 될 때, 또는하지 않을 때 줄은 일찍 끝납니다.drop
"y"
i
"y"
False
k
k
엔에스에스True
엔k
n + 1False
우리는 다음의 별칭을 k
, m
. m
그냥 k
와 1
제 인수 및 개행 번째 인수 앞에 추가.
다음으로 우리는 o
. o
숫자와 문자열을받습니다. g
입력 번호로 시작 하여 문자열 바이트 (개행 무시)가 패리티에서 번갈아 가며 (우리의 사용) 여부를 결정합니다 .
마지막으로 우리는 둘 다로 s
실행 하고 , 성공하면o
1
0
m
. 둘 다 실패하면 그냥 반환합니다 False
. 이것이 우리가 원하는 기능입니다. 입력이 삼각형이고 교대로 결정됩니다.