이 Tic-Tac-Toe 보드가 유효합니까?


48

도전

모든 형식의 틱택 토 보드가 제공되는지 확인하십시오. 보드가 틱택 토 게임의 결과 일 수 있다면 유효합니다. 예를 들어,이 보드는 유효합니다 :

XOX
옥소
XOX
반대로이 보드는 유효하지 않습니다 :

트리플 엑스
XXO
OOO

입력

  • 전체 (9/9) 틱택 토 보드 (게임이 아닌 결과).

규칙

  • 입력 형식은 512 개의 가능한 입력 보드를 모두 묘사 할 수 있어야합니다. 명확하지 않거나 명확하지 않은 경우 작성 지침과 함께 지정해야합니다. 그래도 보드의 마크를 개별적으로 명시해야합니다.
  • 하나는 유효하고 다른 하나는 무효 인 두 가지 가능한 출력이 있어야합니다.
  • 보드에 빈 자리가 없다고 가정 할 수 있습니다.

테스트 사례

유효한:

XOX
옥소
XOX

XOX
XOX
옥소

XOO
OOX
OXX

옥소
XOX
옥소

유효하지 않습니다 :

트리플 엑스
트리플 엑스
트리플 엑스

OOO
OOO
OOO

트리플 엑스
OOO
트리플 엑스

OOO
OOX
트리플 엑스

XXO
옥소
OOX

작은 도움?

다음 두 가지 조건이 충족되는 경우에만 보드가 유효한 것으로 간주됩니다.

  • 5 X 및 4 O 또는 4 X 및 5 O가 있습니다. 예를 들어,
    트리플 엑스
    옥소
    트리플 엑스
    7 X와 2 Os가 있기 때문에 유효하지 않은 것으로 간주됩니다.
  • 5 점을 얻은 플레이어 만이 이겼거나 그중 어느 것도 이겼지 않았습니다. 예를 들어
    트리플 엑스
    OOO
    OOX
    의 행 O또는 행이 X먼저 형성 되므로 유효하지 않은 것으로 간주됩니다 . 두 선수는 동시에 턴을 할 수 없습니다.

현재 우승자는 ...

... ais523의 젤리 답변 , 놀라운 26 바이트!


2
O O O X O X X O X같은 플레이어가 가로 및 세로 행을 모두 가질 수 있음을 보여주기 위해 테스트 사례를 추가 할 수도 있습니다.
smls

2
그래도 보드의 마크를 개별적으로 명시해야합니다. 나는 그 부분을 이해하지 못한다. 반례를 제시해 주시겠습니까?
Arnauld

3
@Tim X에는 4 개의 마크가 있습니다.
Martin Ender

2
@Sparr "마크가 5 개인 플레이어 만이 이겼거나, 아무도 얻지 못했습니다."
Martin Ender

2
@Kevin (첫 번째 코멘트에 답장) 두 번째 플레이어 (4 점을 가진 플레이어)가 이기면 9/9 보드가 완성되지 않기 때문입니다.
Outgolfer Erik

답변:


11

젤리 , 26 바이트

ṢŒrṪ4=$$Ðfx3ðœ-µẆm€6R¤;/µL

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

입력 형식은 조금 이례적입니다. 보드를 나타내는 문자열이지만 Windows 줄 바꿈 (캐리지 리턴 다음에 줄 바꿈)이 있습니다. 예를 들면 다음과 같습니다 XXO\r\nOXO\r\nOOX. (실제로 줄 사이에 두 문자로 된 패딩 문자열이 작동하지만 Windows 줄 바꿈은 다른 옵션보다 훨씬 방어 적입니다.)

기본 아이디어는 입력에서 4 번 나타나는 문자를 찾지 만 원래 문자열에서 3 개의 간격이 균일하지 않은 문자를 찾는 것입니다. 3 × 3 격자의 선 사이에 2 개 이상의 패딩 문자가 있으면 모든 수평, 수직 및 대각선이 균등 간격으로 배치되지만 다른 균등 간격의 선은 3 개의 요소를 가질 수 없습니다.

설명:

ðµS는 체인 분리기 각각 독립적으로 여러 부분으로 프로그램을 분할. 좀 더 명확하게하기 위해 아래 공백으로 바꿨습니다.

ṢŒrṪ4=$$Ðfx3 œ- Ẇm€6R¤;/ L
Ṣ                           sorted version of the input
 Œr                         run-length-encode it
        Ðf                  keep only elements where
   Ṫ                        delete the last element, and it was
    4=                      equal to 4
      $$                    parse Ṫ4= as a group
          x3                repeat each element three times

                Ẇ           all sublists of the input
                 m€         take every nth element of each (€) sublist
                   6R       for each n in 1..6
                     ¤      parse 6R as a group
                      ;/    flatten one level (m€ creates a nested structure)

             œ-             multiset difference
                         L  length of that difference

다시 말해, 입력에서 정확히 4 번 나타나는 문자 목록을 찾아 각각 3 개의 사본으로 구성된 목록을 만듭니다. 원래 문자열에서 균등 한 간격을 가진 모든 하위 시퀀스 목록을 찾습니다. 첫 번째에서 두 번째를 빼면 결과의 길이가 1이되기를 원합니다 (즉, 플레이어는 4 번 플레이했지만이기는 것은 아닙니다). 우리가 3 × 3 그리드에 있고 모든 정사각형이 가득 찼기 때문에 선수가 4 번 플레이하는 것은 불가능합니다 . Jelly에서 1은 진실이고 0은 거짓이므로 결과 목록을 부울로 변환하기 위해 특별한 작업을 수행 할 필요가 없습니다. (는 µL달리 모두 있기 때문에,하지만, 필요 “XXX”하고 “OOO”가능한 truthy 출력 값 및 문제 될 것이 유효한 모든 보드가 동일한 출력을 제공해야합니다.)


3
이것은 완전히 읽을 수 있습니다.
pabrams

21

자바 스크립트 (ES6), 88 87 바이트

s=>(a=[...s]).sort()[5]-a[3]&[7,56,73,84,146,273,292,448].every(j=>j&i,i=`0b`+s^~-a[4])

입력을 9의 문자열 01문자 로 가져와 1유효 0하고 유효하지 않은 경우 리턴 합니다 . 문자를 순서대로 정렬합니다. 중간 3자가 이제 동일하면 한 장이 너무 많아 보드가 유효하지 않습니다. 그렇지 않으면, 우리는 원래 보드를 바이너리로 변환하고 0s보다 1s 가 더 많으면 비트를 뒤집습니다 . 이 시점에서 보드는 03 줄이 없으면 유효 하므로 비트 마스크 배열을 통해 8 줄을 모두 테스트하면됩니다. 편집 : @ETHproductions 덕분에 1 바이트가 절약되었습니다.


@ETHproductions 아, 물론 결과는 단지 0 또는 1이 될 것입니다.
Neil

14

파이썬 (3), 131 (127) 125 (100) 96 바이트

다른 알고리즘 접근법 (및 내장 압축 기능이있는 이러한 멀티 바이트 골프 언어에 실제로 적합한 방법)의 경우 보드가 유효한지 계산하는 대신 각 비트가 512 비트 수인지 여부를 나타냅니다. 특정 보드는 유효하거나 유효하지 않으며 보드를 나타내는 이진 값을 전달합니다. 또한 대칭으로 인해 테이블의 후반부를 제거하고 많은 영점을 제거 할 수 있습니다.

def z(b):return int('agqozfx67wwye6rxr508ch2i8qicekpreqkap0725pk',36)<<24&1<<b+(b>255)*(511-b-b)

테스트 값 :

X X X
O X O
X X X

이진 값으로 표시되며 0b111010111보드가 유효한 경우 함수는 0이 아닌 값을 반환합니다.


더 적은 4 바이트에 대한 중간 변수 제거
Ken YN

a&(1<<b)대괄호가 필요하지 않으므로 2 바이트 가 적습니다 .
Ken YN

대칭을 사용하여 25 바이트를 빼내고 24 개의 가장 낮은 0 비트를 줄여서 1 바이트를 더 떨어 뜨 렸습니다 if b>255:b=511-b.
Ken YN

를 수행하는 골퍼 방법을 찾았습니다 if.
Ken YN

11

배치, 140 바이트

@set/aXXX=OOO=O=0
@for %%l in (%* %1%2%3 %1%4%7 %1%5%9 %2%5%8 %3%5%7 %3%6%9 %4%5%6 %7%8%9)do @set/a%%l+=1
@cmd/cset/a!XXX*!(O-=5)+!OOO*!~O

1유효하고 0유효하지 않은 입력을 9 개의 개별 명령 행 인수 로 사용합니다 . 또는 O의 직교 선이 보이는 횟수를 추적하여 작동합니다 . 편리하게 Batch를 사용하면 정수 산술을 간접적으로 수행 할 수 있으므로 증가하지 않고 대신 변수가 있습니다 (앞서 언급 한 세 가지 변수에만 관심이 있지만). 그런 다음 이기지 않고 5 s 또는 이기지 않았고 4 s 가 있는지 테스트해야합니다 .OOOXXX%%lXOOO


10

Mathematica, 82 75 바이트

7 바이트를 절약 한 Martin Ender에게 감사합니다!

t=Total;3<(b=#~t~2)<6&&{t[c=If[b>4,1-#,#]],t/@c,Tr@c,Tr@Reverse@c}~FreeQ~3&

1과 0의 3x3 중첩 목록을 입력 및 출력으로 사용하는 명명되지 않은 함수 True또는 False.

Total함수 의 편리한 유연성을 사용 합니다 (여기서는 골프를 쳤습니다 t). 예를 들어 array가 주어지면 e = { {1,2,3} , {4,5,6} , {7,8,9} }명령 t[e]은 세 개의 벡터를 합산합니다 (여기서는 항복 {12,15,18}). 이 명령은 t/@e각 하위 목록을 개별적으로 합산합니다 (여기서 생성 {6,15,24}). 그리고 명령은 e~t~29 개의 모든 요소를 ​​합산합니다 (여기서 항복 45).

먼저 3<(b=#~t~2)<6총 1의 개수가 4인지 5인지를 테스트 합니다. 그렇지 않으면로 종료합니다 False. 그렇다면 c=If[b>4,1-#,#]5 개가 아닌 4 개가되도록 강제로 사용 합니다. 그런 다음 열 합계 t[c], 행 합계 t/@c, 주 대각선 Tr@c의 합계 및 반대 대각선의 합계를 계산하고 계산 된 합계의 모든 수준에 나타나지 않는지 확인하는 데 Tr@Reverse~c사용 ~FreeQ~3합니다 3.

재미있는 참고 사항 :이 사이트의 대부분의 모양과 달리 여기 Tr에서는 1 차원 목록을 합산하는 데 사용되지 않지만 실제로는 2 차원 행렬의 추적을 계산하기 위해 설계된대로 사용됩니다!



5

자바 스크립트 (ES6), 101 바이트

9 비트 바이너리 마스크 곳으로의 입력을 받고, X = 1그리고 O = 0(MSB = 왼쪽 셀 LSB = 하단 오른쪽 셀).

n=>[7,56,73,84,146,273,292,448,o=x=0].map((m,i)=>(c-=n>>i&1,m&n^m?m&n||o++:m&&x++),c=4)&&!(c|x&&~c|o)

테스트 사례


나는 약간의 간단한 비트 단위 솔루션이 있어야한다는 것을 알고있었습니다. 좋은 일
ETHproductions

5

파이썬 2, 158 132 109 92 91 123 바이트

def v(b):f=sum(b,());w={x[0]for x in b+zip(*b)+[f[::4],f[-3:1:-2]]if len(set(x))==1};return sum(map(`b`.count,w))==len(w)*5

입력은 행의 목록 / 튜플이며 각각 3 튜플의 문자열입니다. 예 :
[('X', 'O', 'X'), ('O', 'X', 'O'), ('X', 'O', 'X')]

@Maltysen의 답변 당 대각선을 무시하여 일부 바이트를 절약했으며 다음 표현식도 단축했습니다.

저장해 주셔서 감사합니다 @vaultah 17 18 바이트

대각선을 확인하는 것이 필요하다는 것이 밝혀 졌으므로 위의 많은 절약 효과가 제거되었습니다.

여기에서 시도하십시오.

설명

def v(b):
  f=sum(b,())
  w={x[0]for x in b+zip(*b)+[f[::4],f[-3:1:-2]]if len(set(x))==1}
  return sum(map(`b`.count,w))==len(w)*5

f슬라이싱을위한 평탄화 된 입력입니다.
w우승 순서가있는 캐릭터를 포함합니다.
각 당첨 캐릭터의 발생 횟수를 계산합니다. w비어있는 경우 0, 1 인 경우 5 len(w)입니다. 우승 시퀀스가 ​​모두있을 때 10 합계는 불가능합니다. 5를 가진 승자는 패자가 4임을 나타냅니다. 우승 순서없이> 5를 가질 수 없습니다.


lambda b:len({x[0]for x in b+zip(*b)if len(set(x))==1})<2and set(map(b .count,'XO'))=={4,5}는 일부 바이트를 저장합니다.
vaultah

방금 ...and{4,5}==set(map(b .count,'XO'))가 1 바이트를 더 절약 한다는 것을 알았습니다 .
vaultah

나는 이것이 승자가 5 점을 가진 선수임을 보장하지 않기 때문에 질문에서 마지막 "유효하지 않은"예제를 유효하다고 잘못 생각하는 것 같습니다.
smls

@smls 당신이 맞아요. 해당 상태를 확인하는 데 많은 바이트가 소요될 수 있으며 추가로 골프를 칠 수 있습니다.
Jake Cobb

5

R, 88 82 바이트

x=scan();`if`(sum(x)%in%4:5,all(apply(combn(which(x==(sum(x)<5)),3),2,sum)!=15),F)

1에서 9까지의 총 3 개의 정수 조합은 최대 15 개이며 아래 표시된 사각형의 행 / 열 / 대각선입니다.

2 7 6
9 5 1
4 3 8

이 함수는 보드의 평면화 된 표현 인 "X"에 대한 T, "X"에 대한 F, "O"에 대한 부울 벡터로 입력을받습니다. 그러나 인덱스는 순서가 (2,7,6,9,5,1,4,3,8) 인 사각형의 숫자와 동일하도록 재정렬됩니다. 이 순서는 보드를 정상적인 방식으로 평평하게 한 다음 c (6,1,8,7,5,3,2,9,4)로 슬라이싱하여 달성 할 수 있습니다. 그래서 이건

X O X
O X O
X O X

다음과 같이 표현됩니다 :

c(T, F, T, F, T, F, T, F, T)[c(6,1,8,7,5,3,2,9,4)]

이것은 :

c(F, T, F, T, T, T, F, T, F)

이 기능은 먼저 정확히 4 개의 마크가있는 플레이어가 있는지 확인합니다. 그렇다면이 함수는 15의 추가 사실을 사용하여 해당 플레이어가 3 행을 가지고 있는지 여부를 판단합니다 (보드가 해당 플레이어에 대해 유효하지 않은 경우).

일반적으로 평평한 보드를 입력으로 사용하려면 코드는 다음과 같습니다.

f=function(x)ifelse(sum(x)%in%4:5,all(apply(combn(c(2,7,6,9,5,1,4,3,8)[which(x==(sum(x)<5))],3),2,sum)!=15),F)

나는 이것에 익숙하지 않아 조언을 부탁드립니다.


1
if()대신 사용 하는 경우 2 바이트를 절약하십시오 . f=function(x)if (sum(x)%in%4:5,all(apply(combn(which(x==(sum(x)<5)),3),2,sum)!=15),F). 광범위하게 테스트되지 않았습니다. 백 틱스는 코드를 망치지 만 backtick if backtick(.
Jonathan Carroll

1
더 나은 아직; x=scan();만약 (sum(x)%in%4:5,all(apply(combn(which(x==(sum(x)<5)),3),2,sum)!=15),F)입력으로 1하고 0. 82 바이트
Jonathan Carroll

3

자바 스크립트 (ES6) 145 139 131 127 바이트

s=>!(q="XO"[s.split`O`.length-5])|![...s].some((c,i)=>c==q&!/(.)(\1|..(\1|.(\1|.\1.).)..)\1/.test(s.slice(0,i)+0+s.slice(i+1)))

공백으로 구분 된 문자열로 입력하십시오 (예 :) "XOX OXO XOX". 1유효하지 않은 보드에 0대한 출력 . 이것은 적어도 JavaScript가 아닌 최고의 기술은 아닙니다 ...

기본적으로 다음 두 가지가 모두 유지되는지 확인합니다.

  • 정확히 4 또는 5 O초가 있으며
  • 제거 할 때 결정되지 않은 게임을 만드는 5 개 인스턴스 조각 중 하나 이상이 있습니다.

정규식은 게임이 결정되었는지 확인하는 것입니다. 각 쌍을 분리하는 0 (행), 2 (오른쪽 대각선), 3 (열) 또는 4 (왼쪽 대각선) 문자가있는 한 문자 중 길이가 3 인 런이 있으면 보드와 일치합니다.

테스트 스 니펫


2

루비, 104 99 91 바이트

->x{[7,56,448,292,146,73,84,273].none?{|y|b=x.to_i 2;((a=x.count'1')==4?b:a==5?~b:7)&y==y}}

입력 형식 : 보드를 나타내는 9 개의 기호 (0과 1)의 이진 문자열입니다. 예를 들어 첫 번째 테스트 사례는 101010101입니다. 먼저 이진수로 변환하고, popcount가 4 또는 5인지 확인하고, 숫자가 5 인 경우 항상 4를 갖도록하십시오. 3 개가 정렬되어 있는지 확인하십시오 (가로, 세로, 대각선으로 마스킹).

TL; DR : 4 점을 얻은 플레이어가 이기면 false, 그렇지 않으면 true를 반환합니다.

의견을 보내 주셔서 감사합니다.

다른 바이트를 저장하는 UTF-8 문자열을 재생할 수 없습니다.


당신은 대체 할 수 있습니다 .select{...}[0].find{...}.
Jordan

숫자 배열을 바꾸어 바이트를 하나 더 절약 할 수 있습니다 "8ǀĤITđ".unpack("U*")(번역에서 무언가가 손실되는 경우 문자열은 pack("U*")원래 배열 을 호출 한 결과 12 바이트입니다).
Jordan

any?대신 none?출력을 뒤집고 전체 바이트를 저장하는 대신 사용할 수 있습니까?
Alexis Andersen

나는 하나를 시도 했습니까? 대신에? 하지만 난 필요해! 출력을 뒤집습니다.
GB

1

펄 6 , 103 99 바이트

{my \c=%(.flat.Bag.invert)<5>;?all c,|(.[0]===c if [eq] $_ for |.flat[<0 4 8>,<2 4 6>],|$_,|.&zip)}

와 같은 목록 목록을 허용 (('X','O','X'), ('O','X','O'), ('X','O','X'))하고 Bool을 반환하는 람다 .

다음과 같이 작동합니다.

  1. 정확히 5 번 나타나는 마크를 확인하고에 저장하십시오 c. (표시가 정확히 5 번 나타나지 않으면 잘못된 값이 포함됨)
  2. 모든 대각선, 행 및 열을 반복하고 "우승 한"것 (즉, 세 글자 모두가 같은 것)을 필터링합니다 .
  3. c진실한지 확인 하고 각 우승 라인이 유형 인지 확인하십시오 c.

1

PHP, 125 바이트

for($p=$n=$argv[1];$p;$p/=2)$i+=$p&1;foreach([7,56,448,73,146,292,273,84]as$m)$n&$m^$m?$n&$m||$o++:$x++;echo!$x|!$o&&2>$i^=4;

나는 같은 생각을했다 Arnauld : 설정 중 4 또는 5 비트가있는 경우 보드가 유효하고 하나 X또는 O또는 아무도 행진이 없습니다 (하지만 모두).

Xwith 1Owith 필드 교체에서 입력을 생성하려면 0행을 결합하고 2 진을 10 진수로 변환하여 명령 행 인수로 제공하십시오.

1유효한 인쇄 ; 유효하지 않은 빈 출력. 로 실행하십시오 -r.

고장

// count set bits
for($p=$n=$argv[1];$p;$p/=2)$i+=$p&1;
    /* ($p/=2 takes longer than $p>>=1, but eventually
       $p will come close enough to 0 for the loop to finish */
// count streaks for X and O
foreach([7,56,448,73,146,292,273,84]as$m)
    $n&$m^$m            // ($n masked with streak)!=streak <=> no streak for X
        ?$n&$m||$o++    // true: O has a streak if ($n masked with streak) is empty
        :$x++;          // false: X has a streak
echo!$x|!$o&&2>$i^=4;   // valid if not both have a streak
                        // AND $i is 4 or 5 (toggle 4 -> result 0 or 1)

1

스위프트, 178 바이트

func t(i:String)->Bool{let r=i.characters.filter({$0=="X"}).count;let g=i.characters.split(separator:"\n").map(String.init).contains;return(r==5||r==4)&&(!g("XXX") && !g("OOO"))}

0

ES6 (자바 스크립트) 130, 138, 117 바이트

EDITS :

  • @Neil의 훌륭한 조언 덕분에 21 바이트가 줄었습니다!
  • 초기 버전은 버그가 발생하기 쉬웠으며 이제 +8 바이트의 비용으로 수정해야합니다. (@ETHproductions가 지적 해 주셔서 감사합니다)

매우 철저한 접근 방식. 아마 조금 더 골프를 칠 수 있습니다.

입력을 9 개의 개별 인수, 1과 0으로 허용

  • 1X입니다
  • 0O입니다

인수 : 1-3-첫 번째 행, 4-6-두 번째 행, 7-9-세 번째 행.

골프

(a,b,c,d,e,f,g,h,j)=>![a+b+c,d+e+f,g+h+j,a+d+g,b+e+h,c+f+j,a+e+j,g+e+c,7].some(x=>x=="7777307777"[a+b+c+d+e+f+g+h+j])

대화식 "테스트 베드"

var a=b=c=d=e=f=g=h=j=0;

T=(a,b,c,d,e,f,g,h,j)=>![a+b+c,d+e+f,g+h+j,a+d+g,b+e+h,c+f+j,a+e+j,g+e+c,7].some(x=>x=="7777307777"[a+b+c+d+e+f+g+h+j]);

function test() {
  if(T(a,b,c,d,e,f,g,h,j)) {
     grid.style.backgroundColor='green';
     msg.innerHTML="GOOD"
  } else {
     grid.style.backgroundColor='red';
     msg.innerHTML="BAD"
  }
}
<table id=grid style="background: red">
<thead>
  <tr>
     <td id=msg align="center" colspan="3">BAD</td>
    </tr>
  </thead>
  <tr>
      <td><input type="checkbox" onchange="a=this.checked*1;test();" id="ca"/></td>
      <td><input type="checkbox" onchange="b=this.checked*1;test();" id="cb"/></td>
      <td><input type="checkbox" onchange="c=this.checked*1;test();" id="cc"/></td>
    </tr>
    <tr>
      <td><input type="checkbox" onchange="d=this.checked*1;test();" id="cd"/></td>
      <td><input type="checkbox" onchange="e=this.checked*1;test();" id="ce"/></td>
      <td><input type="checkbox" onchange="f=this.checked*1;test();" id="cf"/></td>
    </tr>
    <tr>
      <td><input type="checkbox" onchange="g=this.checked*1;test();" id="cg"/></td>
      <td><input type="checkbox" onchange="h=this.checked*1;test();" id="ch"/></td>
      <td><input type="checkbox" onchange="j=this.checked*1;test();" id="cj"/></td>
    </tr>
 </table>


내가 틀렸을 수도 있지만, 승자가 있는지 확인하는 것 같습니다. 유효한 보드는 승자가 될 수 없습니다. 예를 들어 [1,0,1,1,0,1,0,1,0]( XOX XOX OXO)와 같습니다.
ETHproductions

네, 골프를하면서 부정을 잃었습니다. 반대편 이 승자 가 아닌지 확인해야합니다 . 지금 수정해야합니다. 고마워 !
zeppelin

(최신 편집 전에 주석을 달기 시작했습니다) a) a+b+c+d+e+f+g+H+i대신 F.reduce((r,c)=>r+=c*1)(필요하지 않은 시점에 F) b) 쓰기 .includes(C)(및 인라인 C값으로 진행) 할 수 있습니까?
Neil

@ Neil, 이것은 아마도 작동 할 것입니다. 내일 시도해 볼 것입니다. 고마워 !
zeppelin

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