d tic tac toe win-checker에 n을 만듭니다.


13

는 n의에서 수상했다 누가 확인하는 가장 짧은 프로그램 만들기 D 콩알 만 발가락 게임.

n(너비) 및 d(치수)가 다음 범위에 있을 때 프로그램이 작동해야 합니다.

n∈[3,6]∩ℕ  ie a number from this list: 3,4,5,6
d∈[2,5]∩ℕ  ie a number from this list: 2,3,4,5

n = 3; d = 2(3 2 즉 3 x 3) :

[][][]
[][][]
[][][]

n = 3; d = 3(3 3 즉 3 by 3 by 3) :

[][][]
[][][]
[][][]

[][][]
[][][]
[][][]

[][][]
[][][]
[][][]

n = 6; d = 2(6 2 즉 6 x 6) :

[][][][][][]
[][][][][][]
[][][][][][]
[][][][][][]
[][][][][][]
[][][][][][]

등등.

승리 (다차원 틱택 토를 충분히 연주 한 경우에도 마찬가지입니다.)

승리하기 위해서는 한 선수가 라인을 따라 인접한 모든 사각형을 가져야합니다. 즉, 해당 플레이어는 n승자가 되려면 한 줄로 이동 해야합니다 .

인접 :

  • 각 타일은 점입니다. 예를 들어 (0,0,0,0,0)은d=5
  • 인접한 타일들은 타일들이 같은 유닛 d- 큐브상의 두 지점들입니다. 즉, 타일 ​​사이의 체비 쇼프 거리는 1입니다.
  • 다시 말해서, 점이 점 p에 인접하면, 대응하는 좌표의 q모든 좌표는 1만큼 차이가 없습니다. 또한 적어도 좌표 쌍이 정확히 하나 다릅니다.pq

윤곽:

  • 선은 벡터와 타일로 정의됩니다. 라인은 방정식에 의해 각 타일이 맞습니다.p0 + t<some vector with the same number of coordinates as p0>

입력 :

입력은 STDIN입니다. 입력의 첫 번째 라인은 두 수있을 것이다 nd형태 n,d.

그 후에 행해진 이동을 지정하는 좌표로 구성된 선이됩니다. 좌표는 다음 형식으로 표시됩니다 1,1;2,2;3,3. 왼쪽 상단이 원점입니다 (2D의 경우 0,0). 일반적인 경우,이 목록은 1,2,...,1,4;4,0,...,6,0;...첫 번째 숫자가 왼쪽-오른쪽, 두 번째 위-아래, 3-3 차원 등을 나타내는 위치와 같습니다. 첫 번째 좌표는 X첫 번째 회전이고 두 번째는 이다 O최초의 회전, ...

입력 다음에 개행이옵니다.

출력 :

출력은 STDOUT이됩니다. 누군가 이겼거나 동점이라면 누가 이겼는지 표시하십시오. 동점이나 승리가 아닌 경우 아무것도 출력하지 마십시오.

또한 이동 충돌이 있는지, 즉 동일한 위치에 둘 이상의 이동이있는 경우 표시하십시오.

입력이 끝나기 전에 승리 / 무승부가 있었다면 프로그램은 원하는대로 할 수 있습니다.

테스트 사례 (누가 더 이상 제안하고 싶은가?) :

입력:

4,3
0,0,0;1,1,1;1,0,1;2,0,2;0,0,1;2,0,0;2,0,1;3,0,2;3,0,1

출력 예 :

X wins

또 다른 가능한 출력 (설명 필요) :

1

대각선을 따라 직선이 무엇인지 결정하기 위해 차원 n> 3의 토폴로지를 어떻게 정의합니까? 예를 들어, 인접한 3 개의 정점을 통과하는 선이 3⁵ 보드에서 승리합니까? 각 3² 평면의 가운데 사각형이 n- 큐브에서 모서리를 공유하는 다른 평면의 모든 점에 연결되어 있습니까?
Comintern

1
@Comintern 어떻습니까 (설명을 어길 수도 있습니다. 확실히 더 간단 할 수 있습니다).
Justin

참고 : 인접 타일에 제공 한 정의는 동일하지 않습니다 (즉, 맨해튼 거리가 1이 아님).
Howard

또한 n승자가 되려면 한 줄로 이동 하는 것을 정의해야합니다 . (샌드 박스에이 발언을 게시하지 못해서 죄송하지만 샌드 박스를 게시 한 직후 게시 되었기 때문에 그 내용을 볼 시간조차 없었습니다.)
Howard

1
프롤로그에는 매우 짧은 해결책이 있어야한다고 생각합니다.
Nate Eldredge

답변:


3

Python, 745 578 자

import sys
x=[]
o=[]
t=1
b=","
k=map
def m(c):
 m=x if t else o
 c=k(int,c.split(b))
 if c in o+x:
  print b
  sys.exit()
 m.append(c)
 r=0
 for p in m:
  r=w(p,m)
 return r
def w(p,m):
 for q in m:
  d=max(k(lambda x,y:abs(x-y),p,q))
  if d==u:
   if e(p,q,m):
    return 1
 return 0
def e(p,q,m):
 v=k(lambda p,q:(p-q)/u,q,p)
 l=p
 for i in range(1,n):
  y=k(lambda j,h:j+h,l,v)
  if y not in m:
   return 0
  l=y
 if not l==q:
  return 0
 return 1
q=sys.stdin.readline
d=q()
v=q()
z=d.split(b)
(n,d)=k(int,z)
a=v.split(";")
u=n-1
for c in a:
 r=m(c)
 if r:
  print t
 t=not t

나는 약간의 변화를 주었고 그것을 약간 줄였다. True의 반환은 x가 이겼 음을 의미하고 False는 y가 이겼 음을 의미하며 유효하지 않은 이동이 이루어 졌음을 의미합니다.


몇 가지 :로 변경 import *하십시오 import*. 1True 및 0False에 사용하십시오 (제거 TF). return -1가능합니다 return-1(공백 제거 확인). 메소드의 이름을 단일 문자 메소드로 바꾸십시오. 더 많은 최적화에 대한 을 확인하십시오 .
Justin

아, 감사합니다, 나는 당신이 그 일의 일부를 할 수 몰랐다 (즉, 수익과 -1 사이의 공간을 제거)
foota

코드에서 약간의 골프를 쳤습니다 (모두 유효하지 않을 수도 있음). 결과는 여기입니다 : ideone.com/Ld2jAH . 답변을 다시 확인하고 가능한 한 코드를 줄이십시오. 파이썬에 대한 질문은 매우 유용합니다
저스틴

@foota if l<>q:대신 할 수 있습니다 if not l==q:.
mbomb007

3

답이 아님-Java

주어진 n, d에 대해 얼마나 많은 다른 방법으로 이길 수 있는지 궁금해서 모든 것을 나열하기 위해이 코드를 작성했습니다.

import java.util.*;

public class MultiDTTT {
    static Set<Win> wins = new HashSet<Win>();
    static final int d = 3;
    static final int n = 3;
    static final char maxChar = (char)(n-1) + '0'; 

    public static void main(String[] args) throws Exception {
        String pad = "";
        for(int i=0; i<d; i++) pad = pad + "0";
        for(int i=0; i<Math.pow(n,d); i++) {
            String s = Integer.toString(i,n);
            s = pad.substring(s.length()) + s;
            buildWin(s,"",0);
        } 
        System.out.println(wins.size());
        for(Win w : wins) System.out.println(w.toString());
    }

    static void buildWin(String s, String p,int i) {
        if(i<d) {
            if(s.charAt(i) == '0') {
                buildWin(s,p+"u",i+1);
                buildWin(s,p+"s",i+1);
            }
            else if(s.charAt(i) == maxChar) {
                buildWin(s,p+"d",i+1);
                buildWin(s,p+"s",i+1);
            }
            else {
                buildWin(s,p+"s",i+1);
            }
        }
        else {
            if(p.contains("u") || p.contains("d")) wins.add(new Win(s,p));
        }
    }

    static class Win {
        String start;
        String pattern;
        Set<String> list = new HashSet<String>();

        Win(String s, String p) {
            start = s;
            pattern = p;
            char[] sc = s.toCharArray();
            for(int i=0; i<n; i++) {
                list.add(new String(sc));
                for(int j=0; j<d; j++) {
                    switch (p.charAt(j)) {
                        case 'u':
                            sc[j]++;
                            break;
                        case 'd':
                            sc[j]--;
                            break;
                        case 's':
                            break;
                    }
                }
            }
        }

        public String toString() {
            String s = ""; //start + ", " + pattern + "\n    ";
            for(String ss : list) s = s + ss + " ";
            return s;
        }

        public boolean equals(Object x) {
            return (x instanceof Win) && this.list.equals(((Win)x).list);
        }
        public int hashCode(){
            return list.hashCode();
        }
    }
}

나는 그것을 n, d = 2..3,2..3에서 손으로 테스트했으며 작동하는 것처럼 보입니다 ... 그 후 가능한 승리 방법의 수는 다음과 같이 빠르게 커집니다.

n       1       2       3       4       5       6
d                           
1       1       1       1       1       1       1
2       1       6       8       10      12      14
3       1       28      49      76      109     148
4       1       120     272     520     888     1400
5       1       496     1441    3376    6841    12496
6       1       2016    7448    21280   51012   107744

모든 우승 세트를 생성 한 후, 주어진 세트를 우승 세트와 비교하여 프로그램을 확장 할 수 있었지만 물론 그 방법은 결코 골프에서 이길 수 없었습니다. 그래서 여기서 멈추기로 만족했습니다-n과 d의 함수로이기는 방법의 수에 대한 폐쇄 형 솔루션을 찾을 수있는 것처럼 보였습니다 ... 그것은 승리하는 방법의 수 = 0.5 ((n + 2) ^ d-n ^ d).


2

C ++ 794 849

#include <algorithm>
#include <iostream>
#include <cmath>
#include <string>
#define _ return
#define Y int
#define Z(a) cout<<#a
#define W(a,b,c) for(a=c;a++<b;)
using namespace std;Y n,d,A[5],P[6],T=1,x[7776]={},i,j,k,a,z,p=pow(n,d);char c;bool B;string s;Y K(){a=P[j];W(k,i,0)a/=n;_ a%n;}Y M(){j=0;z=K();W(j,n,1){if(K()!=z){_ 1;}}_ 0;}Y N(){W(j,n,0)if(K()!=n-1-j)_ 1;_ 0;}Y O(){W(j,n,0)if(K()!=j)_ 1;_ 0;}Y S(){z=0;W(i,d,0){z*=n;z+=A[i];}_ z;}Y C(){a=z=0;W(i,p,0){if(s[i]-'0'){P[z]=i;++z;if(a){if(x[i]!=a)_ 0;}else a=x[i];}}_ a;}Y L(){W(i,d,0)if(M()*N()*O())_ 0;_ 1;}Y main(){cin>>n>>c>>d;while(1){W(i,d,0)B=cin>>A[i]>>c;if(x[S()]){Z(!);_ 0;}x[S()]=T;T*=-1;if(!B)break;}W(i,p,0)i<n?s+="1":s+="0";do if(C()&&L()){C()==1?Z(X):Z(O);_ 0;}while(prev_permutation(s.begin(),s.end()));_ 0;}

출력은 "X"(X 승), "O"(O 승) 또는 "!"입니다. (잘못된 이동 시도).

이것은 점을 선형 배열로 매핑하고 크기가 n 인 모든 가능한 하위 집합을 먼저 확인합니다. 먼저 X 또는 O에서 일정하고 선에 있는지 확인합니다. 한 줄에 있는지 확인하기 위해 각 하위 집합의 점 좌표를 한 번에 하나씩 검사합니다. 그것들은 각각 0에서 n-1로 증가하거나 n-1에서 0으로 감소하거나 일정해야합니다. 점은 선형 배열에서 자연스럽게 정렬되므로 주어진 점 세트에 대해 좌표를 증가 또는 감소시키는 것이 좋습니다.

첫 번째 버전에서 심각한 실수를 지적한 Howard에게 감사드립니다.

Quincunx와의 연대에서 C ++ 답변이 이기면 그것이 비극적 일 것이라고 지적해야합니다.


1
나는 당신이 줄을서는 것이 산술적 진행을 의미한다고 말할 수 있지만, 다른 방식으로 유지하지는 않습니다 (예를 들어, 0,2,4는 표준 3,2 틱 전술 발가락에 대한 해결책이 아닙니다).
Howard

@Howard, 감사합니다. 수정했습니다. 골프를 마치기에는 너무 늦었지만, 고칠 수있었습니다 (제 생각에).
Eric Tressler

다른 출력을 사용하여 더 골프를 칠 수 있습니다. 당신은 정확하게 X wins또는 말할 필요가 없습니다 O wins. 답변에서 설명하는 내용을 설명 하는 한 출력 1또는 2다른 변형 을 완벽하게 합법적 입니다. 내가 말했듯이 (강조 추가) : " 승자 표시 ".
저스틴

끝난. 삼항 연산자의 작동 방식을 배울 수 있으면 몇 문자를 절약 할 수 있습니다.
Eric Tressler

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