Costruzione di una piazza greco-latina ortogonale-diagonale


11

Considera una griglia di Nx Nelementi unici. Ogni elemento ha una lettera (dalla A alla NTh lettera, incluso) e un numero (da 1 a N, incluso). Quindi, ogni coppia numero / lettera è nella griglia esattamente una volta.

Il tuo compito è organizzare una griglia in modo tale che:

Ogni riga, colonna e diagonale (incluso il wrapping) contiene ogni lettera e numero esattamente una volta.

Concludendo, intendo quello

* * * # *
* * # * * 
* # * * *
# * * * *
* * * * #

è una diagonale, insieme a tutte le diagonali simili che colpiscono i bordi.

Una 5x5griglia di esempio è:

A1 B2 C3 D4 E5
C4 D5 E1 A2 B3
E2 A3 B4 C5 D1
B5 C1 D2 E3 A4
D3 E4 A5 B1 C2

Il tuo compito è scrivere un programma che accetta un numero Ne stampare una griglia Nx Ncome descritto sopra. Il tuo programma dovrebbe funzionare per qualsiasi 0 < N <= 26. Se una griglia particolare non è possibile, è necessario stampare Impossible.

Non è consentita la codifica hardware della risposta per nessuno N. Un programma è hard coded se calcola la griglia in modo diverso (come giudicato da me) per qualsiasi N > 26(o se non riesce a calcolare). (Questo ha lo scopo di prevenire il precalcolo, comprese le griglie non valide precalcolate o gli offset per le griglie date).

Questo è un problema con il codice più veloce e il tuo punteggio è la somma dei tempi necessari per eseguire il programma su tutto il possibile Nsul mio computer. Nella tua risposta, esegui il tuo programma su tutti N(quindi devo solo cronometrarlo una volta). Se nessun programma può calcolarlo in meno di 60 secondi, allora il vincitore è la risposta che può calcolare la griglia con il più grande Nin 60 secondi. Se più programmi hanno lo stesso massimo N, il tiebreaker è la soluzione più veloce.

(Ho una macchina Windows 8 decentemente alimentata e tutti i compilatori o gli interpreti necessari devono essere disponibili gratuitamente per essa).


Il fatto che la tua macchina sia Windows e non Linux potrebbe essere fastidioso per alcune tecnologie.
orlp

+1 per la domanda, ma dato che l'analisi del tuo esempio sembra dare un algoritmo piuttosto veloce, mi chiedo se sarai davvero in grado di misurare la velocità. Possiamo scrivere una funzione che restituisce una stringa? Perché credo che il tempo impiegato dalle chiamate API per eseguire la stampa effettiva sarà più lungo del calcolo.
Level River St

@steveverrill yes, per scopi di temporizzazione, è accettabile la restituzione di una stringa.
Nathan Merrill,

Qual è lo scopo di lettere e numeri. Ogni numero appare solo una volta accanto a ciascuna lettera oppure 1 può apparire sempre accanto a A, 2 accanto a B, ...?
Jakube

@Jakube sì. Ogni elemento deve essere unico, il che significa che ogni coppia numero / lettera nella griglia deve essere unica.
Nathan Merrill,

Risposte:


5

Python 3

letters = []
numbers = []
for n in range(1,27): 
    if n%2==0 or n%3==0:
        offsets=False
    else:
        offsets = [x for x in range(0,n,2)]
        offsets.extend([x for x in range(1,n,2)])
    letters.append(chr(96+n))
    numbers.append(n)
    if offsets :
        for y in range(n):
            for x in range(n):
                let=letters[(x+offsets[y])%n]
                num=numbers[(offsets[y]-x)%n]
                print (let+str(num), end= "  " if num<10 else " ")
            print("\n")     
    else: 
        print("Impossible\n")

Come funziona?

L'implementazione ingenua sarebbe quella di esaminare tutte le possibili disposizioni di lettere e numeri in una griglia NxN e cercarne una che sia anche un quadrato latino ortogonale-diagonale (ODLS) (e quindi, per alcuni dovrebbe solo passare attraverso tutti configurazioni e ritorno impossibili). Un simile algoritmo non sarebbe adatto a questa sfida a causa dell'assurda complessità temporale. Quindi ci sono tre principali semplificazioni e giustificazioni (prove parziali e approfondimenti sul perché funziona) alle costruzioni ODLS utilizzate nella mia implementazione:

La prima è l'idea che abbiamo solo bisogno di generare un quadrato latino diagonale valido (una griglia NxN tale che ogni riga, colonna, diagonale avvolta contenga ogni elemento di un insieme di N elementi distinti esattamente una volta) delle prime N lettere del alfabeto. Se siamo in grado di costruire un tale Diagonal Latin Square (DLS), allora un ODLS può essere costruito usando il DLS con un adeguato scambio di elementi e lanciando. Giustificazione:

Let us first look at an example using the example grid
a1 b2 c3 d4 e5
c4 d5 e1 a2 b3
e2 a3 b4 c5 d1
b5 c1 d2 e3 a4
d3 e4 a5 b1 c2
Every ODLS can be separated into two DLS (by definition), so
we can separate the grid above into two DLS, one containing letters, the other - numbers
a b c d e
c d e a b
e a b c d
b c d e a
d e a b c
and
1 2 3 4 5 
4 5 1 2 3
2 3 4 5 1
5 1 2 3 4 
3 4 5 1 2
If we transform the number DLS by the mapping 1-->e, 2-->d, 3-->c, 4-->b, 5-->a,
1 2 3 4 5 --> e d c b a
4 5 1 2 3 --> b a e d c
2 3 4 5 1 --> d c b a e
5 1 2 3 4 --> a e d c b
3 4 5 1 2 --> c b a e d
Now if we put the transformed number grid next to the original letter grid,
Original  | Transformed
a b c d e | e d c b a
c d e a b | b a e d c
e a b c d | d c b a e
b c d e a | a e d c b
d e a b c | c b a e d
It can be clearly seen that the number grid is a horizontal flip of
the letter grid withminor letter to number substitutions.
Now this works because flipping guarantees that no two pairs occur more than once,
and each DLS  satisfies the requirements of the ODLS.

La seconda semplificazione è l'idea che se trovassimo una configurazione adatta (SC) di un elemento (una griglia NxN tale che ogni riga, colonna, diagonale avvolta contenga quell'elemento esattamente una volta), allora un DLS potrebbe essere costruito sostituendo l'elemento e spostando il SC. Giustificazione:

If "_" is an empty space and "a" the element then a valid SC of a 7x7 grid is
a _ _ _ _ _ _
_ _ a _ _ _ _
_ _ _ _ a _ _
_ _ _ _ _ _ a
_ a _ _ _ _ _ 
_ _ _ a _ _ _
_ _ _ _ _ a _
or
a _ _ _ _ _ _
_ _ _ a _ _ _
_ _ _ _ _ _ a
_ _ a _ _ _ _
_ _ _ _ _ a _ 
_ a _ _ _ _ _
_ _ _ _ a _ _
(the second one can actually be obtained from the first one via rotation)
now say we took the second SC, shifted it one unit to the right and 
replaced all "a" with "b"
a _ _ _ _ _ _       _ a _ _ _ _ _       _ b _ _ _ _ _
_ _ _ a _ _ _       _ _ _ _ a _ _       _ _ _ _ b _ _
_ _ _ _ _ _ a       a _ _ _ _ _ _       b _ _ _ _ _ _
_ _ a _ _ _ _  -->  _ _ _ a _ _ _  -->  _ _ _ b _ _ _
_ _ _ _ _ a _       _ _ _ _ _ _ a       _ _ _ _ _ _ b
_ a _ _ _ _ _       _ _ a _ _ _ _       _ _ b _ _ _ _
_ _ _ _ a _ _       _ _ _ _ _ a _       _ _ _ _ _ b _
Now if we overlaid the SC of "a" with the SC of "b" we get
a b _ _ _ _ _
_ _ _ a b _ _
b _ _ _ _ _ a
_ _ a b _ _ _
_ _ _ _ _ a b 
_ a b _ _ _ _
_ _ _ _ a b _
If we repeated these steps for the other five letters, we would arrive at a DLS
a b c d e f g
e f g a b c d
b c d e f g a
f g a b c d e
c d e f g a b 
g a b c d e f
d e f g a b c
This is a DLS, since each SC follows the general requirements of a DLS 
and shifting ensured that each element has its own cell.
Another thing to note is that each row contains the string "abcdefg" that is offset 
by some cells. This leads to another simplification: we only need to find the 
offsets of the string in every row and we are finished.

L'ultima semplificazione è la seguente: tutti i DLS di N primo, tranne N = 2 o N = 3, possono essere costruiti e se N può essere scomposto in due numeri il cui DLS appropriato può essere costruito, allora un DLS di tale N può essere costruito. Suppongo che valga anche il contrario. (In altre parole, possiamo solo costruire un DLS per N che non è divisibile per 2 o 3)

Pretty obvious why 2x2 or 3x3 cant be made. For any other prime this can be done
by assigning a each consecutive row a shift that is by two bigger than the previous, 
for N=5 and N=7 this looks like (with elements other than "a" ommited)
N=5
a _ _ _ _ offset = 0
_ _ a _ _ offset = 2
_ _ _ _ a offset = 4
_ a _ _ _ offset = 6 = 1 (mod 5)
_ _ _ a _ offset = 8 = 3 (mod 5)
N=7
a _ _ _ _ _ _ offset = 0
_ _ a _ _ _ _ offset = 2
_ _ _ _ a _ _ offset = 4
_ _ _ _ _ _ a offset = 6
_ a _ _ _ _ _ offset = 8 = 1 (mod 7)
_ _ _ a _ _ _ offset = 10 = 3 (mod 7)
_ _ _ _ _ a _ offset = 12 = 5 (mod 7
(Why this works on all prime N (actually all N that are not divisible
by 3 or 2) can probably be proven via some kind of induction but i will
omit that, this is just what my code uses and it works)
Now, the first composite number that is not
divisible by 2 or 3 is 25 (it also occurs in the range our program must test)
Let A denote the DLS of N = 5
a b c d e 
d e a b c 
b c d e a 
e a b c d 
c d e a b
Let F be the DLS A where each letter is substituted by the letter five postions after it 
a-->f, b-->g etc. So F is 
f g h i j 
j e f g h 
g h i j f 
j f g h i 
h i j f g
Let K be the DLS a where each letter is substituted by the letter ten postions after it
a-->k, b--> l etc.
Let P be defined likewise (so a-->p, b-->q etc)
Let U be defined likewise (so a-->u, b-->v etc)
Now, since the DLS A could be constructed, then by substituting a --> A, b--> F etc.
we get a DLS of N=5*5 (A has five rows and five columns and each is filled with a 
grid of five rows and five columns)
A F K P U
P U A F K
F K P U A
U A F K P
K P U A F
Now since smaller DLS in the big DLS satisfies the 
conditions of a DLS and the big one also satisfies the DLS conditions,
then the resulting grid is also a DLS 

inserire il codice qui

Un'immagine di cosa intendevo con il DLS più piccolo - più grande

Now this kind of thing works for all constructible N and can be proven similiarly.

I have a strong sense that the converse (if some N isnt constructible
(2 and 3) then no multiple of that N is constructible) is also true but have a hard time 
proving it (test data up to N=30 (took a veeery long time to calculate) confirm it though)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.