สร้างตาราง Graeco-Latin


24

คำแถลงการณ์ปฏิเสธความรับผิดชอบ: ฉันไม่ทราบถึงวิธีแก้ไขปัญหาใด ๆ

สแควร์เกรโคละตินคือสำหรับสองชุดยาวเดียวกันnเป็นn×nการจัดเรียงตัวของเซลล์แต่ละที่ไม่ซ้ำกัน (ในตารางทั้งหมด) คู่ขององค์ประกอบของชุดแรกและองค์ประกอบของชุดที่สองเช่น ว่าองค์ประกอบแรกและองค์ประกอบที่สองทั้งหมดของคู่มีความพิเศษในแถวและคอลัมน์ ชุดที่ใช้บ่อยที่สุดคือหนึ่งตัวอักษรnตัวแรกของตัวอักษรกรีกและละติน

นี่คือภาพของจตุรัส Graeco-Latin ขนาด 4x4:ป้อนคำอธิบายรูปภาพที่นี่

nn×n

อินพุต

n>2n×nn6

เอาท์พุต

ตาราง Graeco-Latin ที่มีความยาวด้าน n เป็นอาร์เรย์สองมิติอาร์เรย์ของอาร์เรย์อาร์เรย์แบบแบนหรือเอาต์พุตโดยตรง

หมายเหตุ

  • คุณไม่จำเป็นต้องใช้ตัวอักษรกรีกและละตินโดยเฉพาะ ตัวอย่างเช่นอนุญาตให้ส่งออกคู่ของจำนวนเต็มบวกได้เช่นกัน
  • หากคุณเลือกที่จะใช้ตัวอักษรที่ไม่สามารถขยายได้ตามอำเภอใจคุณต้อง (ในทางทฤษฎีรหัสของคุณไม่จำเป็นต้องเสร็จสิ้นก่อนที่ความร้อนจากเอกภพจะตาย) สนับสนุนความยาวด้านสูงสุดอย่างน้อย 20

นี่คือดังนั้นรหัสที่สั้นที่สุดชนะ!



เราต้องเอาท์พุทสแควร์เดี่ยวหรือไม่ก็โอเคที่จะเอาท์พุทสแควร์สที่เป็นไปได้ทั้งหมดออกเป็นรายการหรือไม่?
Nick Kennedy

คำตอบ:


2

เยลลี่ ,  21  20 ไบต์

ż"þ`ẎẎQƑ$Ƈ F€p`Z€QƑƇ

Œ!ṗ⁸Z€Q€ƑƇF€p`Z€QƑƇḢ

ลองออนไลน์! (ช้าเกินไปสำหรับ4ในยุค 60s ใน TIO แต่ถ้าเราเปลี่ยนอำนาจคาร์ทีเซียนด้วยการรวม,œc,มันจะเสร็จสมบูรณ์ - แม้ว่า 5 แน่นอนจะไม่ได้!)

อย่างไร?

Œ!ṗ⁸Z€Q€ƑƇF€p`Z€QƑƇḢ - Link: integer, n
Œ!                   - all permutations of [1..n]
   ⁸                 - chain's left argument, n
  ṗ                  - Cartesian power (that is, all ways to pick n of those permutations, with replacement, not ignoring order)
    Z€               - transpose each
         Ƈ           - filter, keeping those for which:
        Ƒ            -   invariant under:
      Q€             -     de-duplicate each
          F€         - flatten each  
             `       - use this as both arguments of:
            p        -   Cartesian product
              Z€     - transpose each
                  Ƈ  - filter, keeping those for which:
                 Ƒ   -   invariant under:   
                Q    -     de-duplicate (i.e. contains all the possible pairs)
                   Ḣ - head (just one of the Latin-Greaco squares we've found)

นี่คือ 20 ตอนแรกฉันเขียนสิ่งนี้เป็นอิสระจากคุณ แต่จบลงด้วยสิ่งที่คล้ายกันและจากนั้นใช้แรงบันดาลใจจากการใช้พลังคาร์ทีเซียนแทนการเปลี่ยนรูปแบบดังนั้นคุณควรใช้มันเพื่อปรับปรุงของคุณ โปรดทราบว่าคุณได้สะกดผิด Graeco ในคำอธิบายของคุณ
Nick Kennedy

ขอบคุณ Nick ฉันไม่ได้สังเกตว่าเราได้รับอนุญาตให้ส่งออกเวอร์ชั่นเรียบ
Jonathan Allan

3

05AB1E , 26 23 22 ไบต์

-3 ไบต์ขอบคุณ Emigna

-1 ไบต์ต้องขอบคุณ Kevin Cruijssen

Lãœ.ΔIôDζ«D€í«ε€нÙgQ}P

ลองออนไลน์!


1
n<ÝI‰สามารถ<Ýã
Emigna

... และสามารถ Lขอบคุณ!
Grimmy

1
ê}DIùQสามารถÙgQ}Pบันทึกไบต์
Kevin Cruijssen

@KevinCruijssen ขอบคุณ! ฉันแก้ไขสิ่งต่อไปนี้
Grimmy

3

R , 164 148 ไบต์

ไบต์จำนวนมากต้องขอบคุณ Giuseppe

n=scan()
`!`=function(x)sd(colSums(2^x))
m=function()matrix(sample(n,n^2,1),n)
while(T)T=!(l=m())|!(g=m())|!t(l)|!t(g)|1-all(1:n^2%in%(n*l+g-n))
l
g

ลองออนไลน์!

ไม่มีประสิทธิภาพอย่างมาก - ฉันคิดว่ามันเลวร้ายยิ่งกว่าวิธีบังคับกำลังดุร้ายอื่น ๆ แม้ว่าn=3มันอาจจะหมดเวลากับ TIO นี่คือรุ่นสำรอง (155 ไบต์) ซึ่งใช้งานได้n=3ในเวลาประมาณ 1 วินาที

m1nnlg

  1. all(1:n^2%in%(n*l+g-n))n2l × g
  2. มีlและgสี่เหลี่ยมละติน?

!nlg2^l2n+12lt(l)lgsdn=0n=1

หมายเหตุสุดท้าย: บ่อยครั้งในรหัส R กอล์ฟฉันใช้ตัวแปรTซึ่งเริ่มต้นเป็นTRUEเพื่อรับสองสามไบต์ แต่ที่นี้หมายถึงว่าเมื่อผมจำเป็นต้องมีค่าที่แท้จริงTRUEในความหมายของm(พารามิเตอร์replaceในsample) ผมใช้แทน1 Tในทำนองเดียวกันตั้งแต่ฉันกําหนด!เป็นฟังก์ชั่นที่แตกต่างจากการปฏิเสธผมใช้แทน1-all(...)!all(...)


2

JavaScript (ES6),  159 147  140 ไบต์

n×n

นี่เป็นการค้นหาแบบเดรัจฉานแบบง่ายๆและช้ามาก

n=>(g=(m,j=0,X=n*n)=>j<n*n?!X--||m.some(([x,y],i)=>(X==x)+(Y==y)>(j/n^i/n&&j%n!=i%n),g(m,j,X),Y=X/n|0,X%=n)?o:g([...m,[X,Y]],j+1):o=m)(o=[])

ลองออนไลน์! (พร้อมเอาต์พุตที่กำหนดล่วงหน้า)

แสดงความคิดเห็น

n => (                      // n = input
  g = (                     // g is the recursive search function taking:
    m,                      //   m[] = flattened matrix
    j = 0,                  //   j   = current position in m[]
    X = n * n               //   X   = counter used to compute the current pair
  ) =>                      //
    j < n * n ?             // if j is less than n²:
      !X-- ||               //   abort right away if X is equal to 0; decrement X
      m.some(([x, y], i) => //   for each pair [x, y] at position i in m[]:
        (X == x) +          //     yield 1 if X is equal to x OR Y is equal to y
        (Y == y)            //     yield 2 if both values are equal
                            //     or yield 0 otherwise
        >                   //     test whether the above result is greater than:
        ( j / n ^ i / n &&  //       - 1 if i and j are neither on the same row
          j % n != i % n    //         nor the same column
        ),                  //       - 0 otherwise
                            //     initialization of some():
        g(m, j, X),         //       do a recursive call with all parameters unchanged
        Y = X / n | 0,      //       start with Y = floor(X / n)
        X %= n              //       and X = X % n
      ) ?                   //   end of some(); if it's falsy (or X was equal to 0):
        o                   //     just return o[]
      :                     //   else:
        g(                  //     do a recursive call:
          [...m, [X, Y]],   //       append [X, Y] to m[]
          j + 1             //       increment j
        )                   //     end of recursive call
    :                       // else:
      o = m                 //   success: update o[] to m[]
)(o = [])                   // initial call to g with m = o = []

144 ? (บนโทรศัพท์ของฉันดังนั้นจึงไม่แน่ใจว่ามันใช้งานได้ดี)
Shaggy

ฉันไม่คิดว่าคุณต้องการoเช่นกัน; คุณสามารถกลับมาmตอนท้ายของ141
Shaggy

n=5

2

Haskell , 207 143 233 ไบต์

(p,q)!(a,b)=p/=a&&q/=b
e=filter
f n|l<-[1..n]=head$0#[(c,k)|c<-l,k<-l]$[]where
	((i,j)%p)m|j==n=[[]]|1>0=[q:r|q<-p,all(q!)[m!!a!!j|a<-[0..i-1]],r<-(i,j+1)%e(q!)p$m]
	(i#p)m|i==n=[[]]|1>0=[r:o|r<-(i,0)%p$m,o<-(i+1)#e(`notElem`r)p$r:m]

ลองออนไลน์!

ตกลงฉันคิดว่าในที่สุดฉันก็มาถึงเวลานี้ มันใช้งานได้ดีสำหรับ n = 5, n = 6 ครั้งบน TIO แต่ฉันคิดว่าอาจเป็นเพราะอัลกอริทึมใหม่นี้ไม่มีประสิทธิภาพอย่างเหลือเชื่อและตรวจสอบความเป็นไปได้ทั้งหมดโดยทั่วไปจนกว่าจะพบว่าใช้ได้ ฉันกำลังใช้งาน n = 6 บนแล็ปท็อปของฉันตอนนี้เพื่อดูว่าจะสิ้นสุดลงหรือไม่

ขอขอบคุณอีกครั้งที่ @someone สำหรับการชี้จุดบกพร่องในรุ่นก่อนหน้าของฉัน


1
ฉันไม่รู้จัก Haskell แต่ดูเหมือนว่าจะเกิดข้อผิดพลาดสำหรับฉันเมื่อฉันเปลี่ยน "4" ในส่วนท้ายเป็น 5 ฉันจะเรียกใช้สิ่งนี้อย่างถูกต้องหรือไม่
สรรพนามของฉันคือ monicareinstate

@someone จับได้ดีฉันควรทดสอบแล้วฉันไม่แน่ใจว่าเกิดอะไรขึ้นที่นี่นี่อาจใช้เวลาสักครู่ในการดีบัก
user1472751

1
ฉันคิดว่านี่ยังมีข้อผิดพลาด; เมื่อเรียกใช้ n = 5 tuple (1,1) จะปรากฏขึ้นสองครั้ง
สรรพนามของฉันคือ monicareinstate

@someone Man ปัญหานี้ยากกว่าที่ฉันคิดไว้มาก ฉันไม่สามารถหาวิธีที่เชื่อถือได้ในการล็อคข้อ จำกัด ทั้งหมดในครั้งเดียว ทันทีที่ฉันมุ่งเน้นไปที่อีกคนหนึ่งหลุดออกจากมือของฉัน ฉันจะทำเครื่องหมายว่าไม่ใช่การแข่งขันในตอนนี้จนกว่าฉันจะหาเวลาทำงานได้มากกว่านี้ ขออภัยที่ไม่ทดสอบอย่างละเอียดเท่าที่ควร
user1472751

1

C #, 520 506 494 484 ไบต์

class P{static void Main(string[]a){int n=int.Parse(a[0]);int[,,]m=new int[n,n,2];int i=n,j,k,p,I,J;R:for(;i-->0;)for(j=n;j-->0;)for(k=2;k-->0;)if((m[i,j,k]=(m[i,j,k]+ 1) % n)!=0)goto Q;Q:for(i=n;i-->0;)for(j=n;j-->0;){for(k=2;k-->0;)for(p=n;p-->0;)if(p!=i&&m[i,j,k]==m[p,j,k]||p!=j&&m[i,j,k]==m[i,p,k])goto R;for(I=i;I<n;I++)for(J=0;J<n;J++)if(I!=i&&J!=j&&m[i,j,0]==m[I,J,0]&&m[i,j,1]==m[I,J,1])goto R;}for(i=n;i-->0;)for(j=n;j-->0;)System.Console.Write(m[i,j,0]+"-"+m[i,j,1]+" ");}}

อัลกอริทึมของ findinf a square นั้นง่ายมาก มันคือ ... bruteforce ใช่มันโง่ แต่รหัสกอล์ฟไม่เกี่ยวกับความเร็วของโปรแกรมใช่มั้ย

รหัสก่อนทำให้สั้นลง:

using System;

public class Program
{
    static int[,,] Next(int[,,] m, int n){
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                for (int k = 0; k < 2; k++)
                {
                    if ((m[i, j, k] = (m[i, j, k] + 1) % n) != 0)
                    {
                        return m;
                    }
                }
            }
        }
        return m;
    }
    static bool Check(int[,,] m, int n)
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                for (int k = 0; k < 2; k++)
                {
                    for (int p = 0; p < n; p++)
                    {
                        if (p != i)
                            if (m[i, j, k] == m[p, j, k])
                                return false;
                    }
                    for (int p = 0; p < n; p++)
                    {
                        if (p != j)
                            if (m[i, j, k] == m[i, p, k])
                                return false;
                    }
                }
            }
        }

        for (int i_1 = 0; i_1 < n; i_1++)
        {
            for (int j_1 = 0; j_1 < n; j_1++)
            {
                int i_2 = i_1;
                for (int j_2 = j_1 + 1; j_2 < n; j_2++)
                {
                    if (m[i_1, j_1, 0] == m[i_2, j_2, 0] && m[i_1, j_1, 1] == m[i_2, j_2, 1])
                        return false;
                }
                for (i_2 = i_1 + 1; i_2 < n; i_2++)
                {
                    for (int j_2 = 0; j_2 < n; j_2++)
                    {
                        if (m[i_1, j_1, 0] == m[i_2, j_2, 0] && m[i_1, j_1, 1] == m[i_2, j_2, 1])
                            return false;
                    }
                }
            }
        }
        return true;
    }
    public static void Main()
    {
        int n = 3;
        Console.WriteLine(n);
        int maxi = (int)System.Math.Pow((double)n, (double)n*n*2);
        int[,,] m = new int[n, n, 2];
        Debug(m, n);
        do
        {
            m = Next(m, n);
            if (m == null)
            {
                Console.WriteLine("!");
                return;
            }
            Console.WriteLine(maxi--);
        } while (!Check(m, n));


        Debug(m, n);
    }

    static void Debug(int[,,] m, int n)
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                Console.Write(m[i, j, 0] + "-" + m[i, j, 1] + " ");
            }
            Console.WriteLine();
        }
        Console.WriteLine();
    }
}

ทีนี้ถ้าคุณต้องการทดสอบด้วย n = 3 คุณจะต้องรอเหมือนหนึ่งชั่วโมงดังนั้นนี่คือรุ่นอื่น:

public static void Main()
{
    int n = 3;
    Console.WriteLine(n);
    int maxi = (int)System.Math.Pow((double)n, (double)n*n*2);        
    int[,,] result = new int[n, n, 2];
    Parallel.For(0, n, (I) =>
    {
        int[,,] m = new int[n, n, 2];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
            {
                m[i, j, 0] = I;
                m[i, j, 1] = I;
            }
        while (true)
        {
            m = Next(m, n);
            if (Equals(m, n, I + 1))
            {
                break;
            }
            if (Check(m, n))
            {
                Debug(m, n);
            }
        }
    });
}

อัปเดต: ลืมลบ "สาธารณะ"

อัปเดต: ใช้ "ระบบ" แทนที่จะเป็น "using System;"; นอกจากนี้ต้องขอบคุณKevin Cruijssenใช้ "a" แทน "args"

ปรับปรุง: ขอบคุณที่gastropnerและใครบางคน


argsสามารถa:)
Kevin Cruijssen

แต่ละลูปสามารถเปลี่ยนจากfor(X = 0; X < Y; X++)เป็นfor(X = Y; X-->0; )ซึ่งควรบันทึกไบต์ต่อลูป
Gastropner

1
คุณได้ลองใช้ Visual C # Interactive คอมไพเลอร์แล้วหรือยัง? มันสามารถบันทึกไบต์ คุณยังสามารถส่งฟังก์ชั่นที่ไม่ระบุชื่อ นอกจากนี้คุณยังสามารถกำหนดได้อย่างi = 0แม่นยำiและบันทึกไบต์
สรรพนามของฉันคือ monicareinstate

405 ไบต์ตามข้อเสนอแนะของ @ someone แน่นอนมันหมดเวลาหลังจาก 60 วินาทีใน TIO Systemแต่จะประหยัดไบต์โดยใช้แลมบ์ดาและคอมไพเลอร์แอคทีฟที่มีนัย นอกจากนี้ยังสามารถif((m[i,j,k]=(m[i,j,k]+ 1) % n)!=0) if((m[i,j,k]=-~m[i,j,k]%n)>0)
Kevin Cruijssen

@ เควินฉันไม่รู้สึกอยากอ่านรหัสที่พยายามเล่นกอล์ฟ คุณแน่ใจหรือว่าส่วนการพิมพ์นั้นถูกต้อง? ดูเหมือนว่าควรใช้Writeหรือสามารถบันทึกไบต์ด้วยการเพิ่ม\nสตริงในการโทรหรือจะแตก ฉันคิดว่าคุณสามารถคืนค่าอาร์เรย์ได้โดยตรง
คำสรรพนามของฉันคือ monicareinstate

1

ระดับเสียงคู่ , 182 ไบต์

วิธีการบังคับเดรัจฉาน, TIO ยังคงหมดเวลาและฉันต้องเรียกใช้หลายครั้งเพื่อให้ได้ผลลัพธ์สำหรับ n = 3 แต่ในทางทฤษฎีแล้วสิ่งนี้น่าจะดี แทนที่จะเป็นคู่เช่น (1,2) มันจะส่งออกเมทริกซ์ของคอนจูเกตที่ซับซ้อนเช่น 1 + 2i นี่อาจเป็นการยืดกฏเล็กน้อย แต่ในความคิดของฉันมันเต็มไปด้วยข้อกำหนดด้านผลลัพธ์ ต้องมีวิธีที่ดีกว่าในการทำสองบรรทัดภายใต้การประกาศ functino ว่า แต่ฉันไม่แน่ใจในขณะนี้

function[c]=f(n)
c=[0,0]
while(numel(c)>length(unique(c))||range([imag(sum(c)),imag(sum(c.')),real(sum(c)),real(sum(c.'))])>0)
a=fix(rand(n,n)*n);b=fix(rand(n,n)*n);c=a+1i*b;
end
end

ลองออนไลน์!


0

ภาษา Wolfram (Mathematica) , 123 ไบต์

P=Permutations
T=Transpose
g:=#&@@Select[T[Intersection[x=P[P@Range@#,{#}],T/@x]~Tuples~2,2<->4],DuplicateFreeQ[Join@@#]&]&

ลองออนไลน์!

ฉันใช้TwoWayRuleสัญกรณ์Transpose[...,2<->4]เพื่อสลับมิติที่ 2 และ 4 ของอาร์เรย์ ไม่เช่นนั้นจะค่อนข้างตรงไปตรงมา

Ungolfed:

(* get all n-tuples of permutations *)
semiLSqs[n_] := Permutations@Range@n // Permutations[#, {n}] &;

(* Keep only the Latin squares *)
LSqs[n_] := semiLSqs[n] // Intersection[#, Transpose /@ #] &;

isGLSq[a_] := Join @@ a // DeleteDuplicates@# == # &;

(* Generate Graeco-Latin Squares from all pairs of Latin squares *)
GLSqs[n_] := 
  Tuples[LSqs[n], 2] // Transpose[#, 2 <-> 4] & // Select[isGLSq];

0

Python 3 , 271 267 241 ไบต์

วิธีเดรัจฉานบังคับ: สร้างการเรียงสับเปลี่ยนทั้งหมดของคู่จนกว่าจะพบสแควร์ Graeco-Latin ช้าเกินไปที่จะสร้างสิ่งที่มีขนาดใหญ่กว่าn=3TIO

ขอบคุณalexz02สำหรับการเล่นกอล์ฟ 26 ไบต์และถึงเพดานแมวสำหรับการเล่นกอล์ฟ 4 ไบต์

ลองออนไลน์!

from itertools import*
def f(n):
 s=range(n);l=len
 for r in permutations(product(s,s)):
  if all([l({x[0]for x in r[i*n:-~i*n]})*l({x[1]for x in r[i*n:-~i*n]})*l({r[j*n+i][0]for j in s})*l({r[j*n+i][1]for j in s})==n**4for i in s]):return r

คำอธิบาย:

from itertools import *  # We will be using itertools.permutations and itertools.product
def f(n):  # Function taking the side length as a parameter
 s = range(n)  # Generate all the numbers from 0 to n-1
 l = len  # Shortcut to compute size of sets
 for r in permutations(product(s, s)):  # Generate all permutations of all pairs (Cartesian product) of those numbers, for each permutation:
  if all([l({x[0] for x in r[i * n : (- ~ i) * n]})  # If the first number is unique in row i ...
        * l({x[1] for x in r[i * n:(- ~ i) * n]})  # ... and the second number is unique in row i ...
        * l({r[j * n + i][0] for j in s})  # ... and the first number is unique in column i ...
        * l({r[j * n + i][1] for j in s})  # ... and the second number is unique in column i ...
        == n ** 4 for i in s]):  # ... in all columns i:
   return r  # Return the square

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.