Unikalna spirala mnożenia

13

Ten jest inspirowany najnowszym wyzwaniem przy tabliczce mnożenia Calvina .

Napisz funkcję lub program, który pobiera liczbę całkowitą Njako dane wejściowe i wypisuje lub zwraca unikalną spiralę mnożenia N-na-N. Kod musi (teoretycznie) działać dla N od 0 do 1000 (jednak generowanie tego może być trudne). Dane wyjściowe powinny być równoważne tabeli utworzonej zgodnie z następującą procedurą:

  1. Wypełnij tabelę mnożenia N-na-N. Np. Dla N = 3:

    1 2 3
    2 4 6
    3 6 9
    
  2. Postępuj zgodnie z ruchem wskazówek zegara od lewego górnego rogu, odnotowując odwiedzane liczby. Gdy odwiedzisz numer, który już odwiedziłeś, zamień go na 0.

Kilka przykładów może to wyjaśnić:

n = 0:
0

n = 1:
1

n = 2:       //   Spiral order:
1  2         //   1  2
0  4         //   4  3

n = 3:
1  2  3      //   1  2  3
0  4  6      //   8  9  4
0  0  9      //   7  6  5

n = 4:
1  2  3  4   //   1   2   3   4
0  0  6  8   //  12  13  14   5
0  0  9 12   //  11  16  15   6
0  0  0 16   //  10   9   8   7

n = 5:
1   2   3   4   5
0   0   6   8  10
0   0   9  12  15
0   0   0  16  20
0   0   0   0  25

n = 10:
1   2   3   4   5   6   7   8   9  10
0   0   0   0   0  12  14  16  18  20
0   0   0   0  15   0  21  24  27  30
0   0   0   0   0   0  28  32  36  40
0   0   0   0  25   0  35   0  45  50
0   0   0   0   0   0  42  48  54  60
0   0   0   0   0   0  49  56  63  70
0   0   0   0   0   0   0  64  72  80
0   0   0   0   0   0   0   0  81  90
0   0   0   0   0   0   0   0   0 100

Liczby znajdują się w następujący sposób:

wprowadź opis zdjęcia tutaj

Każdy rozsądny format wyjściowy jest akceptowany, ale musi to być macierz N-na-N, nie może to być tylko lista. Formaty takie jak te poniżej są akceptowane, ponieważ istnieje N łatwo rozróżnialnych kolumn 1 na N lub wierszy N na 1:

[[1 2 3][0 4 6][0 0 9]]   <-- OK

[[1 0 0][2 4 0][3 6 9]]   <-- OK

ans =                     <-- OK
    1  2  3
    0  4  6
    0  0  9   

Najkrótszy kod w bajtach wygrywa.

Stewie Griffin
źródło
Szpieguję moim małym okiem zmodyfikowane sito eratostenów! Jestem pewien, że istnieje wzór, którego możesz użyć tutaj, który widziałem gdzieś w tym miejscu.
Addison Crump
2
Dlaczego miałoby być wyjście, dla n=0którego nie ma zera w tablicach mnożenia. Rozumiem, n=1że wyjdzie 1, ale po co uwzględniać zero?
Tom Carpenter
@TomCarpenter, być może była to zła decyzja, ale wiedziałem, że będzie pytanie „Co z N = 0?”, Więc postanowiłem, że N = 0 -> 0. Z perspektywy czasu lepiej byłoby powiedzieć, że N> 0, ale obawiam się, że teraz jest trochę za późno = /
Stewie Griffin
2
@StewieGriffin Powiedziałeś, że wyjście musi być macierzą N-na-N, więc wyjście n=0powinno być macierzą 0 na 0, inaczej pytanie byłoby niespójne.
alephalpha

Odpowiedzi:

3

J, 22 bajty

,~$[:(*~:)[:,1*/~@:+i.

Wyprowadza macierz 0 na 0 dla n=0.

alephalpha
źródło
8

Mathematica 123 122 117 98 92 73 bajty

Z 24 bajtami zapisanymi dzięki LegionMammal978 i kolejnymi 19 bajkami alephalpha!


Zaskakujące jest to, że w tej tabeli wiele wystąpień dowolnej liczby całkowitej nbędzie miało tę samą względną kolejność w spirali, co w samej tabeli! Pierwsze pojawienie się liczby nznajduje się w samej komórce, w której ta liczba pojawia się jako pierwsza w tabeli (kiedy jeden wiersz wypełnia się w tabeli). Oznacza to, że podejście może całkowicie pominąć ograniczenie spiralne, ponieważ nie ma wpływu na wynik. (Zobacz wyjaśnienie poniżej.)

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&

Przykład

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&[10]

{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {0, 0, 0, 0, 0, 12, 14, 16, 18, 20}, {0, 0, 0, 0, 15, 0, 21, 24, 27, 30}, {0, 0, 0, 0, 0, 0, 28, 32, 36, 40}, {0, 0, 0, 0, 25, 0, 35, 0, 45, 50}, {0, 0, 0, 0, 0, 0, 42, 48, 54, 60}, {0, 0, 0, 0, 0, 0, 49, 56, 63, 70}, {0, 0, 0, 0, 0, 0, 0, 64, 72, 80}, {0, 0, 0, 0, 0, 0, 0, 0, 81, 90}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}}


Grid[%]

tble


Wyjaśnienie

Wykorzystujemy fakt, że porządek spiralny pozycji dowolnej cyfry n jest taki sam, jak porządek pozycji wierszy-kolumn zwracanych przez funkcję Positions!

Lokalizacja pierwszego wystąpienia każdej liczby (niezależnie od tego, czy uporządkuje się według spirali, czy pozycji stołu) będzie pierwszym zwracanym elementem Position. Ta komórka pierwszego wystąpienia pozostanie bez zmian. Pozostałe wystąpienia liczby są zastępowane przez 0.

Spójrzmy, jak to działa, badając przypadek n==18. Chodzi o to, aby zacząć od tabliczki mnożenia:

(t = Table[k Range@#, {k, #}] &[10]) // Grid

i zlokalizuj pozycje wiersza-kolumny dla każdej liczby. Na przykład 18 znajduje się w wierszu 2, kolumnie 9 (pierwsza instancja); Wiersz 3, kol. 6; Wiersz 6, kolumna 3; i wiersz 9, kolumna 2. Mają one odpowiednie pozycje rzędu spirali {44, 58, 68, 82}.

Position[t, 18]

{{2, 9}, {3, 6}, {6, 3}, {9, 2}}

jak pokazuje poniższa tabela.

Tabela 2

Ostatnie 3 wystąpienia 18 muszą zostać zastąpione przez 0. (Użyjemy dużych, pogrubionych niebieskich zer, aby można je było łatwo dostrzec).

ReplacePart[%, {{3, 6}, {6, 3}, {9, 2}} -> Style[0, {Blue, Bold, 16}]]// Grid

Tabela 3

DavidC
źródło
Czy istnieje powód, aby nie pisać Function?
LegionMammal978
1
Miałem problem z zagnieżdżonymi funkcjami czystymi, ale ta iteracja tego nie wymaga. dzięki.
DavidC
Liczę 117 bajtów bez nowego wiersza.
LegionMammal978
Również kilka innych
golfów
Kilka innych ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&
golfów
2

Python, 99 95 90 89 87 81 bajtów

Kod do gry w golfa:

n=range(1,input()+1);m=[]
for x in n:l=[(x*y,0)[x*y in m]for y in n];m+=l;print l

Nie golfowany:

n=range(1,input()+1);
m=[]
for x in n:
  l=[(x*y,0)[x*y in m]for y in n];
  m+=l;
  print l

Wynik:

10 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
[0, 0, 0, 0, 0, 12, 14, 16, 18, 20]
[0, 0, 0, 0, 15, 0, 21, 24, 27, 30] 
[0, 0, 0, 0, 0, 0, 28, 32, 36, 40]
[0, 0, 0, 0, 25, 0, 35, 0, 45, 50] 
[0, 0, 0, 0, 0, 0, 42, 48, 54, 60]
[0, 0, 0, 0, 0, 0, 49, 56, 63, 70] 
[0, 0, 0, 0, 0, 0, 0, 64, 72, 80]
[0, 0, 0, 0, 0, 0, 0, 0, 81, 90] 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 100]
CSᵠ
źródło
thanx @valuah dla golenia bajtów wejściowych
CSᵠ
2

MATLAB, 96 88 87 86 79 bajtów

Jest to 79-bajtowy kod, który następuje po przykładowych danych wyjściowych (konkretnie dla n = 0)

n=input('');m=+(n>0);for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

Ten ma 75 bajtów, zachowuje się tak samo, z wyjątkiem n = 0, które utworzy pustą tablicę zgodnie z implikacją pytania (N przez N tablica = 0 x 0 = pusta tablica).

n=input('');m=[];for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

Działa to również z Octave . Możesz spróbować online tutaj . Kod został już dodany jako plik o nazwie „multspiral.m”. W wierszu oktawy wpisz multspirali naciśnij klawisz Enter. Następnie należy wprowadzić rozmiar tabeli (np. 4). Wydruk zostanie wydrukowany.


Jak to działa?

Najpierw pobiera wymagany numer wejściowy (np. 6, 4 itd.)

n=input('');

Następnie zajmujemy się przypadkami n=0i n=1- są one traktowane w specjalny sposób, ponieważ są one dwa, które nie są zgodne z zasadą, której używam do generowania tablic - w rzeczywistości może to być 5 bajtów krótszych, jeśli nie w n=0przypadku niejasnych przypadków.

m=+(n>0);

Następnie dla wszystkich wartości n>2wykonujemy pętlę, aż matryca osiągnie odpowiedni rozmiar.

for i=2:n;

W rzeczywistości istnieją tylko trzy proste różnice między ni n+1dla wszystkich n>=2. To są:

  1. Nowa kolumna jest dodawana z prawej strony w tablicy zawierającej liczby n(1:n). Można to łatwo obliczyć za pomocą:

     a=i*(1:i);
    
  2. Wszelkie elementy, które zostaną dodane w tej nowej kolumnie, muszą zostać usunięte z istniejącej macierzy (ustawione na zero), ponieważ zawsze pojawią się później w spirali niż w nowej kolumnie. Jest to usuwane za pomocą zagnieżdżonej pętli for, aby ustawić wszystkie elementy w bieżącej macierzy, które są w nowej kolumnie na zero.

    for j=a;
        m(m==j)=0;
    end;
    
  3. Najbardziej dolny wiersz ma nowy wiersz, dla którego każdy element oprócz tego, który znajduje się w nowej kolumnie, będzie wynosił zero. Po dodaniu nowej kolumny, ze względu na poza zakresem, indeksy, które zostały celowo utworzone, są automatycznie uzupełniane przez 0. Jedną z mocnych cech MATLAB-a jest to, że może on powiększać tablice bez specjalnej obsługi, dzięki czemu możemy po prostu dodać nowy wiersz i kolumnę z:

    m(1:i,i)=a;
    

Wreszcie mamy koniec pętli for - która po osiągnięciu macierz mzawiera nasze dane wyjściowe. Ponieważ jesteś elastyczny ze swoim formatem wyjściowym, macierz jest pokazana po prostu mjako nowa linia bez średnika

end;
m

Na przykład, jeśli uruchomimy program, wpisz liczbę 10, otrzymamy następujące dane wyjściowe:

m =
     1     2     3     4     5     6     7     8     9    10
     0     0     0     0     0    12    14    16    18    20
     0     0     0     0    15     0    21    24    27    30
     0     0     0     0     0     0    28    32    36    40
     0     0     0     0    25     0    35     0    45    50
     0     0     0     0     0     0    42    48    54    60
     0     0     0     0     0     0    49    56    63    70
     0     0     0     0     0     0     0    64    72    80
     0     0     0     0     0     0     0     0    81    90
     0     0     0     0     0     0     0     0     0   100
Tom Carpenter
źródło
1

Haskell, 103 99 bajtów

import Data.Lists
f 0=[[0]]
f n=chunksOf n$foldr(\c d->c:replace[c][0]d)[][a*b|a<-[1..n],b<-[1..n]]

Przykład użycia: f 4-> [[1,2,3,4],[0,0,6,8],[0,0,9,12],[0,0,0,16]].

Właśnie odkryłem Data.Listsmoduł, który ma ładne funkcje na listach (takich jak replace) i reeksport Data.List, Data.List.Spliti Data.List.Extras.

nimi
źródło
1

Rubin, 67 63 61 bajtów

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}

63 bajty

->n{s,x=1..n,{};s.map{|c|s.map{|r|e=x[v=c*r]==1?0:v;x[v]=1;e}}}

67 bajtów

->n{s,x=1..n,[];s.map{|c|s.map{|r|e=x.include?(v=c*r)?0:v;x<<v;e}}}

Stosowanie:

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}[10]
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 0, 0, 0, 0, 12, 14, 16, 18, 20], [0, 0, 0, 0, 15, 0, 21, 24, 27, 30], [0, 0, 0, 0, 0, 0, 28, 32, 36, 40], [0, 0, 0, 0, 25, 0, 35, 0, 45, 50], [0, 0, 0, 0, 0, 0, 42, 48, 54, 60], [0, 0, 0, 0, 0, 0, 49, 56, 63, 70], [0, 0, 0, 0, 0, 0, 0, 64, 72, 80], [0, 0, 0, 0, 0, 0, 0, 0, 81, 90], [0, 0, 0, 0, 0, 0, 0, 0, 0, 100]]
Vasu Adari
źródło