Tạo một n để kiểm tra win tic tac toe


13

Tạo chương trình ngắn nhất để kiểm tra xem ai đã giành được trong một n d tic tac toe trò chơi.

Chương trình của bạn sẽ hoạt động khi n(chiều rộng) và d(số thứ nguyên) nằm trong các phạm vi sau:

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 tức là 3 bằng 3):

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

n = 3; d = 3(3 3 tức là 3 bằng 3 bởi 3):

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

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

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

n = 6; d = 2(6 2 tức là 6 bằng 6):

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

Và như thế.

Chiến thắng (Nếu bạn đã chơi đủ ngón chân tic tac đa chiều, điều này cũng tương tự.)

Để có được chiến thắng, một người chơi phải có tất cả các ô vuông liền kề dọc theo một hàng. Đó là, người chơi đó phải ndi chuyển trên một dòng để trở thành người chiến thắng.

Liền kề:

  • mỗi ô là một điểm; ví dụ (0,0,0,0,0) là một điểm trongd=5
  • gạch liền kề là gạch sao cho cả hai đều trên cùng một khối d-cube. Nói cách khác, khoảng cách Ch Quashev giữa các ô là 1.
  • nói cách khác, nếu một điểm ptiếp giáp với một điểm q, thì mọi tọa độ trong ps tọa độ tương ứng sẽ qkhác nhau không quá một điểm. Ngoài ra, ít nhất trên cặp tọa độ khác nhau bởi chính xác một.

Dòng:

  • Các dòng được xác định bởi các vectơ và gạch. Một dòng là mỗi ô được đánh bởi phương trình:p0 + t<some vector with the same number of coordinates as p0>

Đầu vào :

Đầu vào sẽ là STDIN. Dòng đầu tiên sẽ là hai số ndở dạng n,d.

Sau đó sẽ là một dòng bao gồm các tọa độ chỉ định các di chuyển đã được thực hiện. Các tọa độ sẽ được liệt kê dưới dạng : 1,1;2,2;3,3. Góc trên bên trái là gốc (0,0 cho 2D). Trong trường hợp chung, danh sách này sẽ giống như 1,2,...,1,4;4,0,...,6,0;...trong đó số thứ nhất đại diện cho bên trái, bên phải lên xuống thứ hai, thứ ba đến thứ 3, v.v ... Lưu ý rằng tọa độ đầu tiên là Xlần đầu tiên, lần thứ hai là Olượt đầu tiên, ....

Đầu vào sẽ được theo sau bởi một dòng mới.

Đầu ra :

Đầu ra sẽ là STDOUT. Đơn giản chỉ cần chỉ ra ai thắng nếu ai đó thắng, hoặc nếu đó là hòa. Nếu đó không phải là hòa cũng không phải là thắng, đừng tạo ra bất cứ thứ gì.

Ngoài ra, cho biết nếu có xung đột di chuyển, nghĩa là, nếu có ít nhất hai lần di chuyển trong cùng một vị trí.

Nếu có một chiến thắng / hòa trước khi đầu vào kết thúc, chương trình của bạn có thể làm bất cứ điều gì nó muốn.

Các trường hợp thử nghiệm (có ai muốn đề xuất thêm nữa không?):

Đầu vào:

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

Kết quả ví dụ:

X wins

Một đầu ra có thể khác (yêu cầu giải thích):

1

Làm thế nào để bạn xác định cấu trúc liên kết của kích thước n> 3 để xác định đường thẳng dọc theo đường chéo là gì? Ví dụ, có bất kỳ dòng nào qua 3 đỉnh liền kề tạo thành một chiến thắng trên bảng 3⁵ không? Các hình vuông ở giữa của mỗi mặt phẳng 3² có được kết nối với mọi điểm của mặt phẳng khác có chung cạnh với nó trên khối n không?
Quốc tế cộng sản

1
@Comi INTERN Làm thế nào là điều đó (tôi có thể bỏ qua lời giải thích. Chắc chắn có thể đơn giản hơn).
Justin

Lưu ý: các định nghĩa bạn đưa ra cho các ô liền kề không tương đương (nghĩa là nó không phải là khoảng cách manhattan bằng một).
Howard

Ngoài ra, bạn nên xác định rằng cần phải ndi chuyển trên một dòng để trở thành người chiến thắng. (Xin lỗi vì đã không đăng những nhận xét này trong hộp cát nhưng tôi thậm chí không có thời gian để xem nó ở đó vì nó đã được đăng ngay sau khi hộp cát.)
Howard

1
Tôi cảm thấy nên có một giải pháp rất ngắn trong Prolog ...
Nate Eldredge

Câu trả lời:


3

Python, 745 578 Nhân vật

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

Tôi đã thực hiện một số thay đổi và thu nhỏ nó xuống một chút. Lưu ý rằng trả về True có nghĩa là x đã thắng, Sai có nghĩa là y đã thắng và có nghĩa là một động thái không hợp lệ đã được thực hiện.


Một số điều: thay đổi import *thành import*. Sử dụng 1cho Đúng và 0Sai (loại bỏ TF). return -1có thể return-1(kiểm tra loại bỏ không gian). Đổi tên phương thức của bạn thành phương thức char duy nhất. Kiểm tra lời khuyên để tối ưu hóa hơn.
Justin

Ồ, cảm ơn, tôi không biết bạn có thể làm một số điều đó (cụ thể là xóa khoảng cách giữa trả lại và -1)
foota

Tôi đã chơi golf một chút về mã của bạn (điều đó có thể không hợp lệ). Kết quả là đây: ideone.com/Ld2jAH . Vui lòng xem lại câu trả lời của bạn và rút ngắn mã càng nhiều càng tốt. Câu hỏi mẹo cho trăn rất hữu ích
Justin

@ feeta Bạn có thể làm if l<>q:thay if not l==q:.
mbomb007

3

Không phải là một câu trả lời - Java

Tôi tò mò muốn xem có bao nhiêu cách khác nhau để giành chiến thắng cho một n nhất định, vì vậy tôi đã viết mã này để liệt kê tất cả.

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();
        }
    }
}

Tôi đã thử nghiệm nó trên n, d = 2..3,2..3 và có vẻ như nó hoạt động được sau đó số cách có thể để giành chiến thắng tăng lên nhanh chóng như dưới đây:

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

Sau khi tạo tất cả các bộ thắng, tôi có thể mở rộng chương trình để kiểm tra đầu vào đã cho so với các bộ thắng, nhưng, tất nhiên, phương pháp đó sẽ không bao giờ thắng được gôn. Vì vậy, tôi đã có ý định dừng lại ở đây - ngoại trừ có vẻ như tôi có thể tìm thấy một giải pháp dạng đóng cho số cách để giành chiến thắng như là một hàm của n và d. Đó là Số cách để giành chiến thắng = 0,5 ((n + 2) ^ d - n ^ d).


2

C ++ 794 849 ký tự

#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;}

Đầu ra là: "X" (X thắng), "O" (O thắng) hoặc "!" (cố gắng di chuyển bất hợp pháp).

Điều này chỉ ánh xạ các điểm thành một mảng tuyến tính và kiểm tra tất cả các tập hợp con có thể có kích thước n, đầu tiên là không đổi tại X hoặc O, và sau đó là trong một dòng. Để kiểm tra xem có nằm trong một dòng không, tọa độ của các điểm trong mỗi tập hợp con được kiểm tra từng điểm một; mỗi cái phải tăng từ 0 đến n-1, giảm từ n-1 xuống 0 hoặc không đổi. Các điểm được sắp xếp tự nhiên trong mảng tuyến tính, do đó, sẽ hợp lý khi gọi tọa độ tăng hoặc giảm đối với một tập hợp các điểm nhất định.

Cảm ơn Howard đã chỉ ra một lỗi nghiêm trọng trong phiên bản đầu tiên.

Để đoàn kết với Quincunx, tôi phải chỉ ra rằng sẽ là một trò hề nếu câu trả lời của C ++ thắng


1
Tôi nghĩ rằng trong khi bạn có thể nói rằng việc xếp hàng ngụ ý tiến trình số học, thì nó không theo cách khác (ví dụ: 0,2,4 sẽ không phải là một giải pháp cho ngón chân tac tac chuẩn 3,2).
Howard

@ Xin chào, cảm ơn. Tôi đã sửa chữa. Bây giờ đã quá muộn để tôi hoàn thành việc đánh gôn, nhưng tôi đã có thể sửa nó (tôi nghĩ vậy).
Eric Tressler

Bạn có thể chơi gôn hơn nữa bằng cách sử dụng các đầu ra khác nhau. Bạn không cần phải nói chính xác X winshay O wins. Nó là hoàn toàn hợp pháp để đầu ra 1hoặc 2(hoặc một số biến thể khác) miễn là bạn giải thích trong câu trả lời của bạn những gì họ đại diện cho. Như tôi đã nói (nhấn mạnh thêm): " cho biết ai đã thắng".
Justin

Làm xong. Và nếu tôi có thể tìm hiểu cách thức hoạt động của toán tử ternary, tôi có thể lưu một vài ký tự.
Eric Tressler

Còn quan hệ thì sao?
Justin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.