잠깐, 어떤 테트로 미노 였어?
배경
Tetris 는 tetromino 조각이있는 직사각형 그리드에서 플레이되는 싱글 플레이어 게임입니다.
하나 이상의 라인을 테트로 미노로 채우면 채워진 라인이 제거되고 그 위에있는 모든 블록이 그에 따라 아래로 이동합니다. 다음 다이어그램 에서은 .빈 공간이고 #기존 블록이며 As 로 표시된 tetromino 는 방금 배치 된 블록입니다 .
One line cleared example
#...AA.. -> ........
####AA## #...##..
---
Two lines cleared example
(note that the 3rd line moved down once, while the top line moved twice)
...A.... ........
###A#### ........
##.A.##. -> ...#....
###A#### ##.#.##.
####.### ####.###
도전
두 가지 보드 상태가 입력으로 제공됩니다. 하나는 특정 tetromino가 나타나기 직전 (위 다이어그램의 왼쪽 상태, As 없음)이고 다른 하나는 tetromino가 배치되고 라인 지우기가 완료된 직후 (오른쪽 상태)입니다. 이 정보가 주어지면 다음 7 가지 유형 중 하나 인 두 상태 사이에있는 tetromino 유형을 복구합니다.
O J L S T Z I
## # # ## # ## ####
## ### ### ## ### ##
다음을 가정 할 수 있습니다.
- 입력이 유효합니다. 두 보드의 크기는 동일하며, 하나의 tetromino를 배치하여 게임 상태를 첫 번째에서 두 번째로 변경할 수 있습니다. 또한 배치 된 tetromino는 라인 지우기가 발생하기 전에 그리드 내부에 완전히 있습니다 (즉, 주어진 그리드의 천장 위에 부분적으로도 배치되지 않음).
- 대답은 독특합니다.
- 보드의 너비는 최소 5입니다.
이 도전에서는 실제 Tetris 게임의 회전 규칙을 무시하고 tetromino가 기존 블록과 겹치거나 공중에 떠 있지 않는 한 모든 tetromino 배치가 유효하다고 가정하십시오. 이를 통해 폐쇄 된 방 안에 테트로 미노를 배치 할 수 있습니다 (실제로 일부 이국적인 게임에서 발생 함).
입력 값을 공백과 블록에 대한 두 개의 고유 한 값으로 구성된 행렬 (또는 동등한 값)로 사용할 수 있습니다. 선택한 7 개의 고유 값 중 하나로 tetromino 유형을 출력 할 수 있습니다. 허용되는 출력 형식에는 숫자, 문자열 및 숫자 및 / 또는 문자열의 중첩 또는 다차원 배열이 포함됩니다.
표준 코드 골프 규칙이 적용됩니다. 바이트 단위의 가장 짧은 코드가 이깁니다.
테스트 케이스
표기법은 위의 예와 동일합니다. Before그리고 After두 개의 입력 그리드이며, Answer기대 (알파벳 코드로서 주어진다) 출력되고, Explanation의 Tetromino가 배치 나타낸다.
Before:
......
......
After:
..##..
..##..
Answer: O
Explanation:
..AA..
..AA..
----------------
Before:
..####
...###
#.####
After:
......
......
..####
Answer: T
Explanation:
..####
AAA###
#A####
----------------
Before:
...###
...###
#.....
After:
......
..####
#.....
Answer: L (J doesn't work since the piece will be floating)
Explanation:
..A###
AAA###
#.....
----------------
Before:
##..##
##..##
##..##
After:
......
###.##
##.###
Answer: S
Explanation:
##A.##
##AA##
##.A##
----------------
Before:
##.##
##..#
##.##
After:
.....
.....
.....
Answer: T
Explanation: self-explanatory
----------------
Before:
.###.
#...#
.....
#...#
.###.
After:
.....
.###.
#...#
..#..
.###.
Answer: T
Explanation:
.###.
#...#
..A..
#AAA#
.###.
답변
자바 스크립트 (ES10), 286 282 바이트
예상 (a)(b), 여기서 \$a\$및 \$b\$2 진 문자열 목록입니다. \ 사이의 정수를 반환합니다.$0\$및 \$6\$대한 JLTIOZS, 또는 \$-1\$ 해결책이 없다면 (하지만 우리는 그것을 지원해서는 안됩니다).
a=>b=>"0NF71ZMA13FM000F1F1F1IFL2R8I38LT357N368H".match(/../g).findIndex(p=>b.some((r,y)=>[...r].some((_,x)=>!b.some((s,i)=>[...a.map(B=r=>'0b'+r),~0].flatMap(t=(r,Y,a)=>~(q=((parseInt(p,36)||4369)>>(Y-y)*4&15)<<x,t|=q&a[Y+1],q|=q&r?~0:r)+2**s.length?q:(i--,[]))[i]^B(s)|!t))))%14>>1
온라인으로 시도하십시오!
어떻게?
모양 인코딩
각 모양은 기본 36의 2 자리 숫자로 인코딩되어 다음을 저장할 수 있습니다.
$$\lfloor 2\times\log_2 36\rfloor=10\text{ bits}$$
비트는 \$4\times 4\$오른쪽 상단 모서리에 조각이 쐐기로 고정 된 매트릭스. 최하위 비트는 오른쪽 상단 셀에 매핑되며 6 개의 암시 적 선행 0이 있습니다.
예 :
첫 번째 항목은
0N기본 36에 있으며 \$23\$십진수 및 \$0000010111\$바이너리로. 이것은J.6 번째 항목은
FM기본 36에 있으며 \$562\$십진수 및 \$1000110010\$바이너리로. 이것은T.
vertical을 제외한 모든 모양을 이러한 방식으로 인코딩 할 수 있습니다 I. 이것은 00실제 값 ( \$4369\$ 10 진수)는 별도로 하드 코딩됩니다.
주요 알고리즘
주요 알고리즘은 우리가 각각의 모양을 넣어하려고 5 개 중첩 루프로 구성 \$p\$가능한 각 위치에서 \$(x,y)\$그리드에서 \$a\$그림있는 그리드 한 리드 아웃 \$b\$.
행이 완료 될 때마다, 그 때문에 우리는 하늘의 배열을 얻을 .flatMap()이 행을 삭제하고 우리는 인덱스를 감소 \$i\$ 행 이동을 설명하기 위해 결과 배열에서 읽어야하는 항목의.
우리는 부정적인 \$i\$. 그러나 비교를 위해 XOR을 사용하기 때문에 정의되지 않은 행은 \ 로 설정된 것처럼 작동합니다.$0\$, 그것이 우리가 원하는 것입니다.
"...".match(/../g) // list of shapes
.findIndex(p => // for each shape p:
b.some((r, y) => // for each y:
[...r].some((_, x) => // for each x:
!b.some((s, i)=> // for each row s at position i in b:
[ ...a.map( // using the helper function B, decode a[] by
B = r => '0b' + r // converting each binary string to an integer
), ~0 // and append a full line at the bottom
].flatMap(t = // initialize t to a non-numeric value
(r, Y, a) => // for each row r at position Y in this array:
~( //
q = ( // q is the 4-bit mask of the shape
( parseInt(p, 36) // decoded from the base-36 value p,
|| 4369 ) //
>> (Y - y) * 4 // keeping only the bits for this row
& 15 //
) << x, // and left-shifting by x
t |= q & a[Y + 1], // update the 'touching' mask
q |= q & r ? ~0 // invalidate the row if q overlaps r
: r // otherwise, merge q and r
) + 2 ** s.length ? // if the resulting line is not full:
q // yield q
: // else:
(i--, []) // decrement i and yield an empty array,
// which results in the deletion of this
// line by flatMap()
)[i] // end of flatMap(); extract the i-th row
^ B(s) // the test fails if this row is not equal to s
| !t // or the shape is floating in the air
) // end of some()
) // end of some()
) // end of some()
) // end of findIndex()
최종 결과
모양은 다음 순서로 저장됩니다.
0N F7 1Z MA 13 FM 00 0F 1F 1F 1I FL 2R 8I 38 LT 35 7N 36 8H
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
J J L L T T I I O O Z Z S S J J L L T T
이것이 최종 결과가 .findIndex()모듈로 \$14\$, \ 로 나눈$2\$\ 쪽으로 반올림$0\$.
(주의 : 모양 O은 패턴이 깨지지 않도록 두 번 저장됩니다.)
Brachylog , 156 124 바이트
조각이있는 타일을 나타내는 1빈 타일을 나타내는 두 개의 행렬을 2사용합니다. 지도 O => 15, I => 1, J => 57, L => 60, S => 30, T => 23, Z => 51.
hI{∧Ḋ}ᵐ²O;I{zzᵐ+ᵐ²};21ẹᵗ↔c{≡ᵛ²h|∧1}ᵍbᵐ{-₁ᵐ²}ʰc~t?&h{{∧2}ᵐ}ʰ↺₁;O↰₂c∋3∧O{{¬=₀&}ˢ\}↰₇{\↔ᵐ|}{↔↔ᵐ|}{l₂ccẹ~ḃ{15|23|30|51|57|60}}|1
온라인으로 시도하십시오! 또는 모든 테스트 케이스를 시도해보십시오 (더 좋은 I / O로)! (헤더가 술어 번호를 증가시키기 때문에 바이트 수는 조금 더 깁니다.)
작동 원리
제거 규칙 이후의 O입력 플러스 O가 출력과 같 도록 행렬을 검색합니다 . 그런 다음 Otetromino에 의해 경계가 지정된 부분 행렬을 포함하도록 트리밍 합니다. 모든 방향을 시도해 보면 2 x x 행렬에 맞습니다. 그러면 기본 2에서 변환 할 수 있습니다. 그렇지 않으면 I조각입니다.
h{∧Ḋ}ᵐ²O
이 도전하기 전에, 나는, 입력의 길이를 가지고 그 위에 행 길이를 매핑하고, 모든 요소의 수치로 말하여 동일한 차원의 매트릭스를 만든 것입니다 ...하지만이 훨씬 깔끔 : O입력하지만, 모든 요소에 그것은 단지 임의의 숫자입니다. 이것은 훨씬 깔끔합니다!
;I{zzᵐ+ᵐ²}
O + 입력
;21ẹᵗ↔c{≡ᵛ²h|∧1}ᵍbᵐ
이것은 행을 ((2s 만 포함), (2 만 포함하지 않음))으로 분할하는 매우 복잡한 방법입니다. 기술적으로 더 짧은 버전이 있지만 모든 시도는 숫자의 레이블을 지정하여 프로그램을 순수한 무차별 대입으로 느리게 만듭니다. (전혀 작동하는 버전을 찾는 것은 정말 실망 스러웠습니다.)
{-₁ᵐ²}ʰc~t?
제거 된 행에서 1을 빼고 ((2 개만 포함, 이제 1 개만 포함), (나머지)) 다시 함께 결합합니다. 두 번째 입력 행렬과 같아야합니다.
&h{{∧2}ᵐ}ʰ↺₁;O↰₃c∋3
입력 행렬을 가져 와서 맨 위 행을 2 O초로 설정하고 위로 회전 하고 3 을 추가 한 후에는 tetromino가 부동 상태가 아닙니다.
∧O{{¬=₀&}ˢ\}↰₅
Otetromino 만 포함되도록 트림 하십시오. 이것이 여기서 끝날 수 있다면 좋을 것입니다. 그러나 O지금까지 테트로 미노가 보장되지는 않으며 연결이 끊어진 1 일 수 있습니다. 그래서 ...
{\↔ᵐ|}{↔↔ᵐ|}{l₂ccẹ~ḃ{15|23|30|51|57|60}}|1
모든 회전을 확인하고 2 x x 행렬이면 밑이 2로 변환하고 숫자 중 하나가 일치하는지 확인합니다. 일치하는 것이 없으면 I 조각입니다.