Knight on the Rim è Grim


48

introduzione

Aron Nimzowitsch era un importante maestro di scacchi e un influente scrittore di scacchi.

Nel suo libro "Il mio sistema", il primo capitolo tratta dell'importanza del centro e del perché dovresti dominarlo. La semplice ragione è che i tuoi pezzi hanno più possibili mosse successive dirette quando si trovano al centro, il che conferisce nuovamente al giocatore più potere.

Questo diventa molto chiaro quando si guardano diverse posizioni di un cavaliere e le sue potenziali mosse successive (mostrate in rosa) su una tavola vuota:

inserisci qui la descrizione dell'immagine

Obbiettivo

Valuta il numero di potenziali mosse successive dirette di un cavaliere su una tavola vuota in base alla sua posizione.

Specifiche di input

La posizione del cavaliere.

Prima la x (colonna) e poi la y (riga). 0 0è l'angolo in basso a sinistra.

Per semplicità, ho cambiato le etichette di una scacchiera solo in numeri. Per i nostri esempi e casi di test utilizziamo un indice basato su 0, tuttavia sei libero di utilizzare un indice basato su 1.

È possibile utilizzare qualsiasi tipo di possibile formato di input, un array, argomenti di funzione, ecc.

Specifiche di uscita

Il numero di potenziali mosse successive dirette per un cavaliere su una tavola vuota.

Casi test

3 4 => 8
4 6 => 6
7 7 => 2
1 0 => 3

I casi di test utilizzano un indice basato su 0. L'intera griglia di valori è:

2 3 4 4 4 4 3 2
3 4 6 6 6 6 4 3
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
3 4 6 6 6 6 4 3
2 3 4 4 4 4 3 2

9
Bella prima sfida! :-)
Luis Mendo,

14
"Knight on the rim is grim"

2
@stacey Il tuo commento sarebbe stato un grande titolo per questo puzzle :)
starcorder il

6
Ora per la domanda davvero difficile: i cavalieri rossi nelle immagini sopra sono tutti dello stesso colore?
mbomb007,

Risposte:


25

Python 2 , 35 byte

lambda x,y:50/(8+x*x/7-x+y*y/7-y)-4

Provalo online!


Python 2 , 39 byte

lambda x,y:50/(8-x*(7-x)/5-y*(7-y)/5)-4

Provalo online!

Accetta input indicizzati 0.

L'espressione x*(7-x)/5assume i valori delle coordinate 0..7di

[0, 1, 2, 2, 2, 2, 1, 0]

( min(x,7-x,2)fa lo stesso, ma è più lungo.) Sommando questo per xe ydà lo schema giusto ma con i numeri sbagliati

0 1 2 2 2 2 1 0
1 2 3 3 3 3 2 1
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
1 2 3 3 3 3 2 1
0 1 2 2 2 2 1 0

(Vedi la soluzione di Neil per un migliore ragionamento sul perché questo dà il giusto modello.)

Infine, la mappatura a -> 50/(8-a)-4con divisione del pavimento fornisce i giusti valori

2 3 4 4 4 4 3 2
3 4 6 6 6 6 4 3
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
3 4 6 6 6 6 4 3
2 3 4 4 4 4 3 2

Una soluzione alternativa altrettanto lunga con input 1 indicizzati:

lambda x,y:(x*(9-x)/6+y*(9-y)/6)**2/6+2

(7-a)*a/5è di 3 byte più breve di min(a,7-a,2).
Neil,

1
*lin realtà ti costa un byte complessivo, lambda a,b:"23468"[(7-a)*a/5+(7-b)*b/5]è solo 41 byte.
Neil,

@Neil Avevo appena trovato la stessa cosa con x*(9-x)/6uno indicizzato.
xnor

1
Perché non usi <strike>come tutti gli altri per mostrare i progressi del golf?
Insane il

4
@Insane Penso che sembri brutto e in realtà non aiuta. Il codice è la cosa importante e chiunque voglia vederne l'evoluzione deve ancora guardare nella cronologia delle modifiche. Quando il mio vecchio codice è abbastanza diverso da valere la pena mostrarlo, mostro le versioni come qui . Ma su questa domanda, sono tutti piccoli miglioramenti della stessa strategia, quindi l'ho trovato più pulito solo per citare le diverse possibilità.
xnor

17

MATL , 17 14 13 12 byte

Grazie a @Neil per 1 byte di sconto!

8:HZ^ZP5X^=s

L'input è basato su 1.

Provalo online!

Spiegazione

Questo calcola la distanza euclidea dall'ingresso a ciascuna delle 64 posizioni nella scacchiera e trova quanti di questi valori equivalgono alla radice quadrata di 5.

Poiché le coordinate sono valori interi, possiamo essere certi che i due valori in virgola mobile che rappresentano la radice quadrata di 5 (quella calcolata dalle coordinate e quella calcolata direttamente) sono effettivamente le stesse.

8:      % Push array [1 2 ... 8]
H       % Push 2
Z^      % Cartesian power. Gives 2D array [1 1; 1 2; ... 1 8; 2 1; ... 8 8]     
ZP      % Implicit input. Compute Euclidean distances, considering each row as a point
5X^     % Square root of 5
=s      % Compute how many squared distances equal sqrt(5). Implicit display

1
Impressionante e grazie per la spiegazione
videocamera stellare

1
Se il confronto del quadrato della radice quadrata da 5 a 5 fallisce a causa di errori di arrotondamento, non puoi almeno confrontare la radice quadrata di 5 con la radice quadrata di 5?
Neil,

@Neil Grazie per l'idea! Sì, poiché i calcoli sono con numeri interi, posso essere sicuro che le due "radici di 5" hanno lo stesso doublenumero. Ant risparmia un byte
Luis Mendo il

15

Mathematica 63 43 byte

Con 20 byte salvati grazie ai suggerimenti di Martin Ender!

EdgeCount[8~KnightTourGraph~8,#+1+8#2/<->_]&

Quanto sopra trova il numero di quadrati che sono 1 hop di distanza dalla cella data nel grafico completo del tour dei cavalieri.


g=KnightTourGraph[8,8,VertexLabels->"Name",Axes->True]

visualizza il grafico completo del tour del cavaliere, con nomi e coordinate dei vertici. Si noti che Mathematica utilizza per impostazione predefinita l'indicizzazione su una base per le coordinate.

grafico


#+1+8#2&[r,f]converts restituisce il vertice corrispondente al quadrato al rango (riga) re al file (colonna) f, usando come input valori a base zero.

Ad esempio, #+1+8#2&[2,1]restituisce 11.


EdgeCount indica il numero di spigoli nel grafico del vicinato.


I bordi per il rango 2, file 1 (quadrato 11):

IncidenceList[8~KnightTourGraph~8, 8 #2 + # + 1] &[2, 1]

(*{1 <-> 11, 5 <-> 11, 11 <-> 17, 11 <-> 21, 11 <-> 26, 11 <-> 28}*)

I bordi evidenziati:

HighlightGraph[g, {1, 5, 11, 17, 21, 26, 28, Style[1 <-> 11, Thick, Blue], Style[5 <-> 11, Thick, Blue], Style[11 <-> 17, Thick, Blue], Style[11 <-> 21, Thick, Blue], Style[11 <-> 26, Thick, Blue], Style[11 <-> 28, Thick, Blue]},GraphHighlightStyle -> "DehighlightFade", PlotRangePadding -> .5]

evidenziare


Metodo 2: distanza euclidea

70 byte

Questo metodo è più lungo, ma probabilmente di un certo interesse. L'approccio è quello di verificare la distanza euclidea tra il centro della scacchiera e la cella di interesse.

Which[(x=Sqrt@Tr[({3.5, 3.5}-#)^2])<2.2,8,x<3,6,x<4,4,x<4.6,3,x>4.6,2]&

esemplificando

Which[(x=Sqrt@Tr[({3.5, 3.5}-#)^2])<2.2,8,x<3,6,x<4,4,x<4.6,3,x>4.6,2]&@{0, 0}
Which[(x=Sqrt@Tr[({3.5, 3.5}-#)^2])<2.2,8,x<3,6,x<4,4,x<4.6,3,x>4.6,2]&@{3, 3}

2

8


Per aiutare a visualizzare come la distanza dal centro della scacchiera è sufficiente per assegnare un valore.

values={{2,3,4,4,4,4,3,2},{3,4,6,6,6,6,4,3},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{3,4,6,6,6,6,4,3},{2,3,4,4,4,4,3,2}};
f[x_]:=Text[x,#]&/@Position[values,x]r_~w~p_:=RegionMember[{3.5`,3.5`}~Disk~r,p]
h@y_:=Which[2.2~w~y,8,3~w~y,6,4~w~y,4,4.6~w~y,3,2<3,2]

Graphics[{Circle[{4.5, 4.5}, 2.3], Circle[{4.5, 4.5}, 3], 

Cerchia [{4.5, 4.5}, 4],

Cerchio [{4.5, 4.5}, 4.6], Flatten [f / @ {2, 3, 4, 6, 8}, 1]}, Axes -> True, AxesOrigin -> {-1, -1}]


I numeri 2.2, 3, 4 e 4.6 sono i raggi dei cerchi.

Immagine


1
Ottimo grafico del tour
stellare

20
KnightTourGraphMathematica e i suoi builtins: :-)
Luis Mendo,

Penso che ci sia un randagio #alla fine del codice sorgente (appena prima del ]). Dovresti essere in grado di utilizzare IncidenceListinvece di EdgeList@NeighborhoodGraphperò. (In alternativa, c'è anche EdgeCount, ma penso che finisca per essere più lungo.)
Martin Ender,

1
Oh aspetta, in realtà è più breve:EdgeCount[8~KnightTourGraph~8,#+1+8#2<->_]&
Martin Ender il

EdgeCountè molto bello!
DavidC,

12

JavaScript (ES6), 38 byte

(x,y)=>+"23468"[((7-x)*x+(7-y)*y)/5|0]

Accetta input indicizzati 0. Spiegazione: Guarda i quadrati delle distanze dal centro:

24.5 18.5 14.5 12.5 12.5 14.5 18.5 24.5
18.5 12.5  8.5  6.5  6.5  8.5 12.5 18.5
14.5  8.5  4.5  2.5  2.5  4.5  8.5 14.5
12.5  6.5  2.5  0.5  0.5  2.5  6.5 12.5
12.5  6.5  2.5  0.5  0.5  2.5  6.5 12.5
14.5  8.5  4.5  2.5  2.5  4.5  8.5 14.5
18.5 12.5  8.5  6.5  6.5  8.5 12.5 18.5
24.5 18.5 14.5 12.5 12.5 14.5 18.5 24.5

Il numero di quadrati raggiungibili si divide in cinque bande:

8    0-5
6    5-10
4   10-15
3   15-20
2   20-25

In realtà calcolo 24,5 - (3,5 - x) ** 2 - (3,5 - y) ** 2 = (7 - x) * x + (7 - y) * y in quanto è un calcolo più breve, ma tutto ciò che fa è invertire l'ordine delle bande.


Approccio super conciso e molto bello, quindi non devo più avviare la mia soluzione JS :)
Starcorder

Un buon punto sulla formula equivale al raggio al quadrato. Avevo pensato x*(7-x)a un'operazione che sembra un arco discendente acceso 0..7e sembra adattarsi alla curva, ma questo spiega perché produce un modello così bello quando viene sommato per xe y.
xnor

11

Gelatina, 10 byte

8ṗ2_³²S€ċ5

1-indicizzati. Accetta un singolo argomento del modulo [x,y]. Provalo qui.

8ṗ2          Cartesian square [[1,1],[1,2]…[8,8]]
   _³        Subtract the input
     ²S€     Compute the norm of each vector
        ċ5   Count fives

Dennis ha salvato un byte!


Solo undici byte, wow!
videocamera

Ho visto questa domanda al mattino e questo è l'algoritmo esatto che pensavo di implementare in Jelly quando avessi avuto tempo. : P
PurkkaKoodari,

8

Mathematica, 44 40 byte

Al momento ho tre soluzioni con lo stesso numero di byte:

2[3,4,6,8][[Tr@⌊3.2-.8Abs[#-4.5]⌋]]&
Tr@⌈.85(4-Abs[#-4.5])⌉/.{5->6,6->8}&
⌊Tr@⌈.85(4-Abs[#-4.5])⌉^1.1608⌋&

Tutte queste sono funzioni senza nome che accettano coppie di coordinate simili {3, 4}, che sono basate su 1.

Ho provato a trovare una formula in qualche modo esplicita. Il modello generale sull'intera scheda è simile al seguente:

inserisci qui la descrizione dell'immagine

I valori effettivi di quei colori (dal più chiaro al più scuro) sono 2, 3, 4, 6, 8. Questo è:

2 3 4 4 4 4 3 2
3 4 6 6 6 6 4 3
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
3 4 6 6 6 6 4 3
2 3 4 4 4 4 3 2

Innanzitutto sfruttiamo la simmetria spostando l'origine al centro, prendendo il valore assoluto e sottraendo il risultato 4. Questo ci dà le coordinate 0.5per 3.5aumentare da ogni angolo. Al fine di rendere le coordinate del centro uguali, dobbiamo mappare 0.5e 1.5valori diversi 2.5e 3.5allo stesso valore. Questo è fatto facilmente moltiplicando per 0.8(dà {0.4, 1.2, 2., 2.8}) e pavimentando il risultato. Quindi ora abbiamo {0, 1, 2, 2}le distanze dal centro. Se sommiamo le coordinate in ogni cella, otteniamo questa tabella:

0 1 2 2 2 2 1 0
1 2 3 3 3 3 2 1
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
1 2 3 3 3 3 2 1
0 1 2 2 2 2 1 0

Questo ha valori univoci per tutti i diversi risultati possibili, quindi lo utilizziamo semplicemente come indice in 2[3,4,6,8].

Nella seconda versione usiamo il soffitto invece del pavimento. In questo modo, 2, 3e 4sono già corretti, ma si ottiene 5e 6invece di 6e 8, quindi correggiamo quelli manualmente con una regola di sostituzione.

Infine, nella terza versione, estendiamo 5e 6verso l'alto 6e 8per mezzo di esponenziazione, seguita da un'altra operazione di piano.


Mi piace moltissimo l'approccio usando lo schema generale del tabellone, fantastico!
videocamera stellare

6

APL, 21 caratteri

{+/,5=+/¨×⍨(⍳8 8)-⊂⍵}

In inglese:

  • (⍳8 8): Matrice 8x8 di rango 2 contenente le coordinate di tutte le celle;
  • +/¨×⍨(⍳8 8)-⊂⍵: quadrato delle distanze euclidee della cella data rispetto a ogni cella sulla scheda;
  • 5=: matrice di 0/1, dove gli 1 appaiono a distanze quadrate pari a 5;
  • +/,: somma la matrice appiattita

Test (in origine 1):

    f←{+/,5=+/¨×⍨(⍳8 8)-⊂⍵}
    f¨1+(3 4)(4 6)(7 7)(1 0)
8 6 2 3

In questa forma:

f←{+/,5=+/¨×⍨(⍳⍺)-⊂⍵}

l'argomento di sinistra può specificare le dimensioni della scheda. Quindi 8 8 ffunzionerà per la scacchiera quadrata standard. Ma su una tavola più grande e rettangolare, i casi di test darebbero risultati diversi. Ad esempio, su una scheda 12x10:

    g←(10 12)∘f
    g¨1+(3 4)(4 6)(7 7)(1 0)
8 8 8 3

Nel gergo APL, una matrice è una matrice di grado 2, nulla di detto sul contenuto delle celle. Anni di (ab) uso dei termini mi hanno reso insensibile ad esso. Aggiornerò la descrizione per i lettori più tradizionalmente propensi. Grazie.
lstefano,

@Istefano Quell'uso del "rango" come "numero di dimensioni" sembra soffrire della stessa afflizione :-P
Luis Mendo,

Sarò ... hai ragione! Puoi vedere che è passato un po 'di tempo da quando ho preso Linear Algebra. Mi arrendo :-)
lstefano il

1
Programma completo, 27: ≢⍸5=+/¨×⍨-∘⎕¨⍳8 8 provalo online!
Adám

@ Adám vuoi dire 17
NGN

6

Java - 160 150 byte

int m(int r,int c){int m=0,i,j;for(i=0;i<3;i+=2)for(j=0;j<3;j+=2){m+=r+i>0&r+i<9&c+2*j>1&c+2*j<11?1:0;m+=r+2*i>1&r+2*i<11&c+j>0&c+j<9?1:0;}return m;}

Ungolfed:

public static int m(int r, int c) {
    int m=0;
    for(int i=-1;i<2;i+=2)
        for(int j=-1;j<2;j+=2){
            m += r+i>-1 && r+i<8 && c+2*j>0 && c+2*j<8 ? 1:0;
            m += r+2*i>0 && r+2*i<8 && c+j>1 && c+j<8 ? 1:0;
        }
    return m;
}

Il codice non modificato è identico, tranne per la modifica dei limiti del ciclo for per salvare 4 byte. Funziona ripetendo ogni possibile mossa ed eseguendo un controllo dei limiti (> 0 e <8). Usa il fatto che gli offset sono (1, 2), (2, 1), (-1, 2), (-2, 1), ecc. Ed è in grado di controllare 2 mosse per ogni valore di i e j.

Modifica: 10 byte salvati grazie ai suggerimenti di Leaky Nun e u902383.


Anche questo è stato veloce, carino!
videocamera stellare

Si è verificato un errore, è stato corretto.
ejaszewski,

1
int m=0,i=-1,j;per salvare alcuni byte
Leaky Nun,

1
cambia AND logico in AND bit per bit e questo ti permetterà di rimuovere altri 6 caratteri
user902383


5

Haskell, 49 48 byte

w=[0..7]
x%y=sum[1|a<-w,b<-w,(a-x)^2+(b-y)^2==5]

1
È possibile salvare [0..7]in una variabile per 1 byte.
xnor

5

Java, 81 caratteri (113 byte)

int r(int a,int b){return "⍄䐲㑦晃䚈衤䚈衤䚈衤䚈衤㑦晃⍄䐲".codePointAt(a*2+b/4)>>(3-b%4)*4&15;}

Codifica l'intera tabella dei risultati come tabella unicode e quindi ottieni byte appropriati eseguendo operazioni bit per bit.

Puoi vederlo online qui: https://ideone.com/K9BojC


3

Python, 94 byte

lambda x,y,a=[2,1,-1,-2,-2,-1,1,2]:list((9>x+a[i]>0)&(9>y+a[5-i]>0)for i in range(8)).count(1)

Utilizza 1 indicizzazione basata.

Demo su https://repl.it/C6gV .





1

In realtà, 18 byte

`;7-2km`MΣ8-:50\¬¬

Provalo online!

Questo implementa la stessa formula che molte altre risposte hanno utilizzato: 50/(8-x*(7-x)//5+y*(7-y))//5)-4. L'input viene preso come un elenco: [x,y](o qualsiasi letterale iterabile in Python, come (x,y)o x,y).

Spiegazione:

`;7-2km`MΣ8-:50\¬¬
`;7-2km`M           for each value in input:
 ;7-                  make a copy, subtract from 7
    2                 push 2
     km               minimum of the three values (x, 7-x, 2)
         Σ          sum
          8-        subtract from 8
            :50\    integer divide 50 by the value
                ¬¬  subtract 2 twice

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.