Rycerz na krawędzi jest ponury

48

Wprowadzenie

Aron Nimzowitsch był czołowym mistrzem szachowym i wpływowym pisarzem szachowym.

W swojej książce „Mój system” pierwszy rozdział mówi o znaczeniu centrum i dlaczego należy go zdominować. Prostym powodem jest to, że twoje pionki mają więcej możliwych bezpośrednich następnych ruchów, gdy znajdują się w centrum, co ponownie daje graczowi więcej mocy.

Staje się to bardzo jasne, patrząc na różne pozycje rycerza i jego potencjalne kolejne ruchy (pokazane na różowo) na pustej planszy:

wprowadź opis zdjęcia tutaj

Cel

Oceń liczbę potencjalnych bezpośrednich ruchów rycerza na pustej planszy na podstawie jego pozycji.

Dane wejściowe

Pozycja rycerza.

Najpierw x (kolumna), a następnie y (wiersz). 0 0to lewy dolny róg.

Dla uproszczenia zmieniłem etykiety szachownicy na same cyfry. W naszych przykładach i przypadkach testowych korzystamy z indeksu opartego na 0, jednak możesz swobodnie korzystać z indeksu opartego na 1.

Możesz użyć dowolnego rodzaju możliwych formatów wejściowych, tablicy, argumentów funkcji itp.

Dane wyjściowe

Liczba potencjalnych bezpośrednich następnych ruchów rycerza na pustej planszy.

Przypadki testowe

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

Przypadki testowe wykorzystują indeks oparty na 0. Pełna siatka wartości to:

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
StarCorder
źródło
9
Ładne pierwsze wyzwanie! :-)
Luis Mendo
14
„Rycerz na brzegu jest ponury”
2
@stacey Twój komentarz byłby świetnym tytułem dla tej układanki :)
starcorder
6
Teraz naprawdę trudne pytanie: czy czerwoni rycerze na powyższych obrazkach są tego samego koloru?
mbomb007

Odpowiedzi:

25

Python 2 , 35 bajtów

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

Wypróbuj online!


Python 2 , 39 bajtów

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

Wypróbuj online!

Przyjmuje wejścia 0-indeksowane.

Wyrażenie x*(7-x)/5przyjmuje wartości współrzędnych 0..7do

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

( min(x,7-x,2)robi to samo, ale jest dłuższe.) Podsumowując to xi ydaje właściwy wzór, ale z niewłaściwymi liczbami

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

(Zobacz rozwiązanie Neila, aby uzyskać lepsze uzasadnienie, dlaczego daje to odpowiedni wzór).

Wreszcie mapowanie a -> 50/(8-a)-4z podziałem podłogi daje prawidłowe wartości

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

Alternatywne równie długie rozwiązanie z wejściami 1-indeksowanymi:

lambda x,y:(x*(9-x)/6+y*(9-y)/6)**2/6+2
xnor
źródło
(7-a)*a/5jest o 3 bajty krótszy niż min(a,7-a,2).
Neil
1
*lfaktycznie kosztuje Cię bajt, lambda a,b:"23468"[(7-a)*a/5+(7-b)*b/5]to tylko 41 bajtów.
Neil
@ Nee Właśnie znalazłem to samo z x*(9-x)/6jednym indeksem.
xnor
1
Dlaczego nie używasz <strike>jak wszyscy inni do pokazania postępów w golfa?
Szalony
4
@Insane Myślę, że wygląda brzydko i tak naprawdę nie pomaga. Kod jest ważną rzeczą i każdy, kto chce zobaczyć jego ewolucję, musi zajrzeć do historii edycji. Kiedy mój stary kod jest na tyle inny, że warto go wyświetlić, pokazuję wersje jak tutaj . Ale w tym pytaniu chodzi o drobne ulepszenia tej samej strategii, więc uznałem, że jest czystsze, żeby wspomnieć o różnych możliwościach.
xnor
17

MATL , 17 14 13 12 bajtów

Dzięki @Neil za 1 bajt off!

8:HZ^ZP5X^=s

Dane wejściowe są oparte na 1.

Wypróbuj online!

Wyjaśnienie

Oblicza to odległość euklidesową od wejścia do każdej z 64 pozycji na szachownicy i określa, ile z tych wartości równa się pierwiastkowi kwadratowemu z 5.

Ponieważ współrzędne są liczbami całkowitymi, możemy być pewni, że dwie wartości zmiennoprzecinkowe reprezentujące pierwiastek kwadratowy z 5 (obliczone ze współrzędnych i obliczone bezpośrednio) są rzeczywiście takie same.

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
Luis Mendo
źródło
1
Imponujące i dziękuję za wyjaśnienie
starcorder
1
Jeśli porównanie kwadratu pierwiastka kwadratowego z 5 do 5 nie powiedzie się z powodu błędów zaokrąglania, czy nie możesz przynajmniej porównać pierwiastka kwadratowego z 5 z pierwiastkiem kwadratowym z 5?
Neil
@Neil Dzięki za pomysł! Tak, ponieważ obliczenia dotyczą liczb całkowitych, mogę być pewien, że dwa „pierwiastki z 5” mają tę samą doubleliczbę. Mrówka oszczędza bajt
Luis Mendo
15

Mathematica 63 43 bajty

Z 20 bajtami zapisanymi dzięki sugestiom Martina Endera!

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

Powyżej znajduje się liczba kwadratów, które są 1 skok od danej komórki na pełnym wykresie trasy rycerzy.


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

wyświetla pełny wykres trasy rycerza z nazwami i współrzędnymi wierzchołków. Zauważ, że Mathematica domyślnie indeksuje współrzędne w oparciu o jeden indeks.

wykres


#+1+8#2&[r,f]konwertuje zwraca wierzchołek odpowiadający kwadratowi na poziomie (wiersz) ri plikowi (kolumna) f, używając wartości zerowych jako danych wejściowych.

Na przykład #+1+8#2&[2,1]zwraca 11.


EdgeCount podaje liczbę krawędzi na wykresie sąsiedztwa.


Krawędzie dla rangi 2, plik 1 (kwadrat 11):

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

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

Podświetlone krawędzie:

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]

atrakcja


Metoda 2: Odległość euklidesowa

70 bajtów

Ta metoda jest dłuższa, ale może budzi pewne zainteresowanie. Podejście polega na sprawdzeniu odległości euklidesowej między środkiem szachownicy a interesującą komórką.

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]&

Przykłady

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


Aby zobrazować, w jaki sposób odległość od środka szachownicy jest wystarczająca do przypisania wartości.

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], 

Okrąg [{4.5, 4.5}, 4],

Okrąg [{4.5, 4.5}, 4.6], Spłaszcz [f / @ {2, 3, 4, 6, 8}, 1]}, Osie -> True, AxesOrigin -> {-1, -1}]


Liczby 2.2, 3, 4 i 4.6 to promienie okręgów.

wizerunek

DavidC
źródło
1
Świetny wykres trasy
starcorder
20
KnightTourGraphMathematica i jej wbudowane ... :-)
Luis Mendo
Myślę, że #na końcu twojego kodu źródłowego (tuż przed ]) jest błąd. Powinieneś być w stanie użyć IncidenceListzamiast EdgeList@NeighborhoodGraphtego. (Alternatywnie też jest EdgeCount, ale myślę, że to się wydłuża.)
Martin Ender
1
Och, czekaj, tak naprawdę jest krótszy:EdgeCount[8~KnightTourGraph~8,#+1+8#2<->_]&
Martin Ender
EdgeCountjest bardzo fajny!
DavidC
12

JavaScript (ES6), 38 bajtów

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

Przyjmuje wejścia 0-indeksowane. Objaśnienie: Spójrz na kwadraty odległości do centrum:

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

Liczba osiągalnych kwadratów dzieli się na pięć pasm:

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

Faktycznie obliczam 24,5 - (3,5 - x) ** 2 - (3,5 - y) ** 2 = (7 - x) * x + (7 - y) * y, ponieważ jest to krótsze obliczenie, ale wszystko jest odwrotne kolejność pasm.

Neil
źródło
Bardzo zwięzłe i bardzo miłe podejście, więc nie muszę już zaczynać własnego rozwiązania JS :)
starcorder
Dobrze, że wzór jest równoważny kwadratowi o promieniu. Pomyślałem, że to po x*(7-x)prostu operacja, która wygląda jak łuk skierowany w dół 0..7i zdarza się, że dopasowuje się do krzywej, ale to wyjaśnia, dlaczego tworzy tak ładny wzór, gdy jest sumowany xi y.
xnor
11

Galaretka, 10 bajtów

8ṗ2_³²S€ċ5

1-indeksowany. Przyjmuje pojedynczy argument formularza [x,y]. Wypróbuj tutaj.

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

Dennis uratował bajt!

Lynn
źródło
Tylko jedenaście bajtów, wow!
starcorder
Widziałem to pytanie rano i jest to dokładny algorytm, który, jak miałem nadzieję, zaimplementuję w Jelly. : P
PurkkaKoodari
8

Mathematica, 44 40 bajtów

Obecnie mam trzy rozwiązania o tej samej liczbie bajtów:

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⌋&

Wszystkie są funkcjami nienazwanymi, które przyjmują parę współrzędnych {3, 4}, na przykład 1.

Próbowałem wymyślić nieco wyraźną formułę. Ogólny wzór na całej planszy wygląda następująco:

wprowadź opis zdjęcia tutaj

Rzeczywiste wartości tych kolorów (od najjaśniejszego do najciemniejszego) to 2, 3, 4, 6, 8. To jest:

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

Najpierw wykorzystujemy symetrię, przenosząc początek na środek, przyjmując wartość bezwzględną i odejmując wynik 4. To daje nam współrzędne 0.5do 3.5zwiększenia z każdego rogu. Aby współrzędne środka były takie same, musimy odwzorować 0.5i 1.5na różne wartości 2.5i 3.5na tę samą wartość. Można to łatwo zrobić, mnożąc przez 0.8(daje {0.4, 1.2, 2., 2.8}) i wyrównując wynik. Teraz mamy już {0, 1, 2, 2}odległości od centrum. Jeśli dodamy współrzędne w każdej komórce, otrzymamy tę tabelę:

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

Ma unikalne wartości dla wszystkich różnych możliwych wyników, więc po prostu używamy go jako indeksu do 2[3,4,6,8].

W drugiej wersji używamy sufitu zamiast podłogi. W ten sposób 2, 3a 4już są poprawne, ale mamy 5i 6zamiast 6a 8, więc skorygować te ręcznie z reguły podstawiania.

Wreszcie w trzeciej wersji rozszerzamy 5i zwiększamy 6do 6i 8za pomocą potęgowania, a następnie kolejnej operacji na podłodze.

Martin Ender
źródło
Bardzo podoba mi się podejście oparte na ogólnym wzorze planszy, świetnie!
starcorder
6

APL, 21 znaków

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

Po angielsku:

  • (⍳8 8): Tablica 8x8 rangi-2 zawierająca współrzędne wszystkich komórek;
  • +/¨×⍨(⍳8 8)-⊂⍵: kwadrat euklidesowych odległości danej komórki w odniesieniu do każdej komórki na planszy;
  • 5=: macierz 0/1, gdzie 1s pojawiają się w kwadratowych odległościach równych 5;
  • +/,: zsumuj spłaszczoną macierz

Test (w oryginale 1):

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

W tej formie:

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

lewy argument może określać wymiary tablicy. Dlatego 8 8 fbędzie działać na standardowej kwadratowej szachownicy. Ale na większej i prostokątnej płycie przypadki testowe dałyby inne wyniki. Na przykład na płycie 12x10:

    g←(10 12)∘f
    g¨1+(3 4)(4 6)(7 7)(1 0)
8 8 8 3
lstefano
źródło
W żargonie APL macierz jest tablicą rangi 2, nic nie mówi się o zawartości komórek. Lata (ab) używania terminów uczyniły mnie niewrażliwym na to. Zaktualizuję opis dla bardziej tradycyjnie skłonnych czytelników. Dziękuję Ci.
lstefano
@Istefano To użycie „rangi” jako „liczby wymiarów” wydaje się cierpieć z powodu tej samej dolegliwości :-P
Luis Mendo
Będę ... Masz rację! Widać, że minęło trochę czasu, odkąd wziąłem Algebrę Liniową.
Poddaję
1
Pełny program, 27 lat: ≢⍸5=+/¨×⍨-∘⎕¨⍳8 8 Wypróbuj online!
Adám
@ Adám masz na myśli 17
ngn
6

Java - 160 150 bajtów

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

Nie golfowany:

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

Nieskluczony kod jest identyczny, z wyjątkiem zmiany granic pętli for w celu zaoszczędzenia 4 bajtów. Działa poprzez iterowanie każdego możliwego ruchu i przeprowadzanie kontroli granic (> 0 i <8). Wykorzystuje fakt, że przesunięcia to (1, 2), (2, 1), (-1, 2), (-2, 1) itd. I jest w stanie sprawdzić 2 ruchy dla każdej wartości i i j.

Edycja: 10 bajtów zapisanych dzięki sugestiom Leaky Nun i u902383.

ejaszewski
źródło
To było również szybkie, miłe!
starcorder
Wystąpił błąd, został on naprawiony.
ejaszewski
1
int m=0,i=-1,j;zaoszczędzić trochę bajtów
Leaky Nun
1
zmień logiczne AND na bitowe AND, co pozwoli ci usunąć dodatkowe 6 znaków
user902383
6

C, 44 bajtów

f(x,y){return "23468"[((7-x)*x+(7-y)*y)/5];}

Ale to jest lepsze:

f(x,y){return "2344443234666643468888644688886446888864468888643466664323444432"[x*8+y];}
Giacomo Garabello
źródło
1
Brakuje ;. Nie kompiluje się.
ugoren
@GiacomoGarabello Patrz: meta.codegolf.stackexchange.com/a/1146/55729
Jacajack
1
To nie jest fragment kodu, to funkcja i nie jest zabronione funkcje publikowania. Przepraszamy za brakujący średnik. Naprawiony.
Giacomo Garabello,
5

Haskell, 49 48 bajtów

w=[0..7]
x%y=sum[1|a<-w,b<-w,(a-x)^2+(b-y)^2==5]
Damien
źródło
1
Możesz zapisać [0..7]do zmiennej na 1 bajt.
xnor
5

Java, 81 znaków (113 bajtów)

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

Zakoduj całą tabelę wyników jako tabelę Unicode, a następnie uzyskaj odpowiednie bajty wykonując operacje bitowe.

Możesz to zobaczyć online tutaj: https://ideone.com/K9BojC

Cliffroot
źródło
3

Python, 94 bajty

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)

Wykorzystuje indeksowanie 1.

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

Chuck Morris
źródło
2

Pyth - 33 15 bajtów

Dzięki @LeakyNun za zmniejszenie mojego rozmiaru o połowę.

Zmiana rozmieszczenia map i map Vprawdopodobnie trochę zaszkodzi.

/sM*Fm^R2-Rd8Q5

Pakiet testowy .

Maltysen
źródło
1
To było szybkie, miłe!
starcorder
2
15 bajtów
Leaky Nun
1

Właściwie 18 bajtów

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

Wypróbuj online!

Ten realizuje tę samą formułę, że wiele innych odpowiedzi zostały przy użyciu: 50/(8-x*(7-x)//5+y*(7-y))//5)-4. Dane wejściowe są traktowane jako lista: [x,y](lub dowolny literał iterowalny w Pythonie, taki jak (x,y)lub x,y).

Wyjaśnienie:

`;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
Mego
źródło