创建一个到井字游戏检查器的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 x 3 x 3):

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

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

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

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

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

等等。

获胜(如果您玩了足够的多维井字游戏,则是一样的。)

为了获得胜利,一个玩家必须沿着一条线拥有所有相邻的正方形。也就是说,该玩家必须在线上n移动才能成为赢家。

邻:

  • 每个图块都是一个点;例如(0,0,0,0,0)是d=5
  • 相邻的图块是图块,因此它们都是同一单位d多维数据集上的点。换句话说,图块之间的Chebyshev距离为1。
  • 换句话说,如果一个点p与一个点相邻q,则ps中相应坐标中的每个坐标q相差不超过一个。此外,至少在一个坐标对上相差一个。

行数:

  • 线条由矢量和图块定义。一条线是方程式命中的每个图块:p0 + t<some vector with the same number of coordinates as p0>

输入

输入将输入到STDIN。输入的第一行就会两个数字,n并且d在形式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 2014年

1
@Comintern怎么样(我可能只是解释了。肯定可以更简单)。
贾斯汀

注意:您对相邻图块给出的定义不相等(即,曼哈顿距离不等于1)。
2014年

此外,您应该定义必须采取n行动才能成为赢家。(很抱歉没有在沙盒中发布这些评论,但是我什至没有时间在那看到它们,因为它在沙盒发布后不久就发布了。)
Howard

1
我觉得Prolog中应该有一个非常简短的解决方案...
Nate Eldredge 2014年

Answers:


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*。使用1了真,并0为假(删除TF)。return -1可以return-1(查看删除空格)。将您的方法重命名为单个char方法。查看提示以获取更多优化信息。
贾斯汀2014年

哦,谢谢,我不知道您可以做某些事情(即,删除return和-1之间的空格)
foota 2014年

我对您的代码做了一些打高尔夫球(可能并非全部有效)。结果是在这里:ideone.com/Ld2jAH。请再次回答您的问题,并尽可能缩短代码。python 的提示问题非常有用
Justin 2014年

@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 ++ 794849字符

#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,或者是常数。这些点自然会在线性阵列中排序,因此有必要将给定点的坐标称为增加或减少的坐标。

感谢霍华德指出第一个版本中的严重错误。

声援Quincunx,我必须指出,如果C ++答案获胜,那将是愚蠢的


1
我认为,虽然可以说排队意味着算术级数,但反之则不行(例如,0,2,4不会是标准3,2井字游戏的解决方案)。
2014年

@霍华德,谢谢。我做了更正。现在对我来说打高尔夫球已经太迟了,但是我能够修好它(我认为)。
埃里克·特雷斯勒

您可以使用不同的输出进一步打高尔夫球。您不必说完全X winsO wins。只要您在回答中解释它们的意思,输出12(或其他变化)是完全合法的。正如我说的(重点添加):“ 表明谁赢了”。
贾斯丁

做完了 而且,如果我可以了解三元运算符的工作原理,那么我可以节省一些字符。
埃里克·特雷斯勒

领带呢?
贾斯汀
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.