D tic tac toe win-checker için n oluşturun


13

Bir n kazandı kim kontrol için en kısa program oluşturun d tic tac toe oyunu.

Programınız n(genişlik) ve d(boyut numarası) şu aralıklarda olduğunda çalışmalıdır:

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 yani 3 x 3):

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

n = 3; d = 3(3 3 yani 3 x 3 x 3):

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

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

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

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

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

Ve bunun gibi.

Kazanan (Yeterince çok boyutlu tic tac toe oynadıysanız, bu aynıdır.)

Kazanmak için, bir oyuncunun bir çizgi boyunca tüm bitişik karelere sahip olması gerekir. Yani, bir oyuncunun nkazanan olabilmesi için bir hatta hamle yapması gerekir .

bitişik:

  • her karo bir noktadır; örneğin (0,0,0,0,0),d=5
  • bitişik karolar aynı birim d-küpünde her iki nokta olacak şekilde karolardır. Başka bir deyişle, fayanslar arasındaki Chebyshev mesafesi 1'dir.
  • diğer bir deyişle, bir nokta bir noktaya pbitişikse, s'deki ilgili koordinattaki qher koordinat, birden fazla farklı değildir. Ek olarak, en azından koordinat çifti tam olarak bir farklılık gösterir.pq

Hatları:

  • Çizgiler vektörler ve bir döşemeyle tanımlanır. Bir çizgi, denklemin vurduğu her bir döşemedir:p0 + t<some vector with the same number of coordinates as p0>

Giriş :

Giriş STDIN olacaktır. Girişin ilk çizgisi, iki sayılar, olacak nve dformu n,d.

Bundan sonra, yapılan hareketleri belirten koordinatlardan oluşan bir çizgi olacaktır. Koordinatlar şeklinde listelenir: 1,1;2,2;3,3. Sol üst köşe başlangıç ​​noktasıdır (2D için 0,0). Genel durumda, bu liste 1,2,...,1,4;4,0,...,6,0;...ilk sayının sola-sağa, ikinci yukarı-aşağıya, üçüncü ila üçüncü boyuta vb. Gösterdiği gibi olacaktır. İlk koordinatın Xilk dönüş, ikinci olduğu Oilk dönüş, ....

Girdiyi bir satırsonu izleyecektir.

Çıktı :

Çıktı STDOUT olacak. Birisinin kazandığını veya bir kravat olup olmadığını kimin kazandığını belirtmeniz yeterlidir. Eğer bir beraberlik ya da galibiyet yoksa, hiçbir şey çıkarmayın.

Ek olarak, bir hareket çakışması olup olmadığını, yani aynı konumda en az iki hareket olup olmadığını belirtin.

Giriş bitmeden bir galibiyet / beraberlik olsaydı, programınız ne isterse yapabilir.

Test senaryoları (daha fazla önermek isteyen var mı?):

Giriş:

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

Örnek Çıktı:

X wins

Başka bir olası çıktı (açıklama gerektirir):

1

Diyagonal boyunca düz çizgilerin ne olduğunu belirlemek için n> 3 boyutlarının topolojisini nasıl tanımlıyorsunuz? Örneğin, bitişik 3 köşeden herhangi bir çizgi 3⁵ tahtada bir kazanç mı oluşturuyor? Her 3² düzleminin orta kareleri, n-küp üzerinde kenarını paylaşan başka bir düzlemin her noktasına bağlı mı?
Komintern

1
@Comintern Bu nasıl (Muhtemelen açıklamayı değiştirdim. Kesinlikle daha basit olabilir).
Justin

Not: bitişik karolar için verdiğiniz tanımlar eşdeğer değildir (yani manhattan mesafesi bire eşit değildir).
Howard

Dahası n, kazanan olmak için bir çizgi üzerinde hamle yapıldığını tanımlamanız gerekir . (Bu açıklamaları kum havuzuna göndermediğim için özür dilerim, ancak kum havuzundan hemen sonra yayınlandığı için orada bile görmek için zamanım bile yoktu.)
Howard

1
Prolog'da çok kısa bir çözüm olması gerektiğini hissediyorum ...
Nate Eldredge

Yanıtlar:


3

Python, 745 578 Karakterler

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

Bazı değişiklikler yaptım ve biraz küçüldüm. True döndürmesinin x'in kazandığını, False'nin y kazandığını ve geçersiz bir hamle yapıldığı anlamına geldiğini unutmayın.


Bazı şeyler: değişim import *için import*. 1True ve 0False için kullanın ( Tve kaldırın F). return -1olabilir return-1(boşlukların kaldırılmasına bakın). Yöntemlerinizi tek karakter yöntemleriyle yeniden adlandırın. Daha fazla optimizasyon için ipuçlarına göz atın .
Justin

Oh, teşekkürler, bu şeylerden bazılarını yapabileceğinizi bilmiyordum (yani, dönüş ile -1 arasındaki boşluğu kaldırın)
foota

Ben kod üzerinde biraz golf yaptım (hepsi geçerli olmayabilir). Sonuç burada: ideone.com/Ld2jAH . Lütfen cevabınızı tekrar gözden geçirin ve kodu olabildiğince kısaltın. İpuçları piton için soru çok yararlıdır
Justin

@foota Bunun if l<>q:yerine yapabilirsiniz if not l==q:.
mbomb007

3

Yanıt değil - Java

Belirli bir n, d için kazanmak için kaç farklı yol olduğunu görmek için merak ettim, bu yüzden hepsini listelemek için bu kodu yazdım.

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

Bunu n, d = 2..3,2..3 üzerinde elle test ettim ve işe yarıyor gibi görünüyor ... bundan sonra kazanmanın olası yollarının sayısı aşağıda gösterildiği gibi hızla artıyor:

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

Tüm şarap setlerini ürettikten sonra, verilen girdiyi kazanan setlere karşı kontrol etmek için programı uzatabilirim, ancak elbette bu yöntem golfü asla kazanamaz. Bu yüzden burada durmaktan memnun oldum - n ve d'nin bir fonksiyonu olarak kazanmanın yol sayısı için kapalı formlu bir çözüm bulabilmem dışında ... Kazanmanın yol sayısı = 0.5 ((n + 2) ^ d - n ^ d).


2

C ++ 794 849 karakter

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

Çıktı: "X" (X kazanır), "O" (O kazanır) veya "!" (yasadışı taşıma girişimi).

Bu sadece noktaları doğrusal bir dizide eşler ve n veya boyutundaki tüm olası altkümeleri kontrol eder, önce X veya O'da sabit olmak ve sonra bir çizgide olmak için. Bir çizgide olup olmadığını kontrol etmek için, her alt kümedeki noktaların koordinatları birer birer incelenir; her biri ya 0'dan n-1'e yükselmeli, n-1'den 0'a düşmeli ya da sabit olmalıdır. Noktalar doğal olarak doğrusal dizide sıralanır, bu nedenle belirli bir nokta kümesi için artan veya azalan bir koordinat çağırmak mantıklıdır.

İlk versiyonda ciddi bir hatayı işaret ettiği için Howard'a teşekkürler.

Quincunx ile dayanışma içinde, bir C ++ cevabı kazanırsa bir travesti olacağını belirtmeliyim


1
Bence sıralı olmanın aritmetik ilerlemeyi ima ettiğini söylese de, bunun tersi de geçerli değildir (örneğin, 0,2,4 standart 3,2 tic tac toe için bir çözüm olmayacaktır).
Howard

@Howard, teşekkürler. Düzeltmeleri yaptım. Golfü bitirmek için artık çok geç, ama düzelttim (sanırım).
Eric Tressler

Farklı çıktılar kullanarak daha fazla golf oynayabilirsiniz. Tam olarak söylemek zorunda değilsin X winsya da O wins. Cevabınızda neyi temsil ettiklerini açıkladığınız sürece çıktı 1veya 2(veya başka bir varyasyon) mükemmel bir şekilde meşrudur . Dediğim gibi (vurgu eklenmiştir): " işaret kim kazandı".
Justin

Bitti. Üçlü operatörün nasıl çalıştığını öğrenebilirsem, birkaç karakter kaydedebilirim.
Eric Tressler

Kravatlar ne olacak?
Justin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.