Wizualizuj twierdzenie Nicomachusa

35

Twierdzenie Nichomachusa odnosi kwadrat sumy do sumy kostek:

Twierdzenie Nichomachusa

i ma piękną geometryczną wizualizację:

Wyobrażanie sobie

Wyzwanie: Stwórz drugą część tej wizualizacji w ascii.

Musisz upewnić się, że wszystkie wizualne rozgraniczenia są przestrzegane na diagramie. Najłatwiej jest to zrobić z czterema „kolorami”, choć można to osiągnąć tylko z trzema (jak to zrobić w ostatnim przykładzie poniżej). W przypadku czterech kolorów używasz dwóch, aby rozróżnić regiony w obrębie „paska” (tj. Różnych części tworzących pojedynczy sześcian), a dwóch, aby rozróżnić sąsiednie paski. Możesz także użyć więcej niż czterech kolorów, jeśli chcesz. Jeśli którykolwiek z nich jest mylący, poniższe dane wyjściowe powinny wyjaśnić.

Wejście wyjście

Dane wejściowe to jedna liczba całkowita większa od 0. Dane wyjściowe to siatka ascii podobna do poniższych przykładów, odpowiadająca spłaszczonej siatce dla tego numeru wejściowego na powyższym obrazku. Wiodące i końcowe białe znaki są w porządku.

To jest golf golfowy, ze standardowymi zasadami.

Przykładowe wyniki

N = 1

#

N = 2

#oo   
o@@   
o@@   

N = 3

#oo+++
o@@+++
o@@+++
+++###
+++###
+++###

N = 4

#oo+++oooo
o@@+++oooo
o@@+++@@@@
+++###@@@@
+++###@@@@
+++###@@@@
oo@@@@oooo
oo@@@@oooo
oo@@@@oooo
oo@@@@oooo

N = 5

#oo+++oooo+++++
o@@+++oooo+++++
o@@+++@@@@+++++
+++###@@@@+++++
+++###@@@@+++++
+++###@@@@#####
oo@@@@oooo#####
oo@@@@oooo#####
oo@@@@oooo#####
oo@@@@oooo#####
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++

Trzykolorowa wersja dla N = 4 dzięki @BruceForte:

#oo+++oooo
o##+++oooo
o##+++####
+++ooo####
+++ooo####
+++ooo####
oo####++++
oo####++++
oo####++++
oo####++++
Jonasz
źródło
6
Twierdzenie o czterech kolorach: D
Leaky Nun
1
Czy możesz dodać wynik dla N = 5, proszę?
Uriel
1
@Uriel Done. Zobacz moją edycję.
Jonasz
Dzięki! Czy mogę również przełączać @ i os tylko na pasku zewnętrznym w N = 4? A może wynik musi być ścisłym zastąpieniem tych tekstów innym zestawem znaków?
Uriel
@Uriel przełączanie jest w porządku. Liczy się tylko to, że sąsiednie kolory nie powodują konfliktów, dzięki czemu wzór jest widoczny.
Jonasz

Odpowiedzi:

17

MATL , 30 28 27 bajtów

t:P"@:s:@/Xk&+@+8MPt&(]30+c

Wypróbuj online!

Dodatkowe atrybuty:

  • Dla 26 bajtów następująca zmodyfikowana wersja generuje wyjście graficzne :

    t:P"@:s:@/Xk&+@+8MPt&(]1YG
    

    Wypróbuj w MATL Online!

  • Obraz prosi o jakiś kolor i kosztuje tylko 7 bajtów:

    t:P"@:s:@/Xk&+@+8MPt&(]1YG59Y02ZG
    

    Wypróbuj w MATL Online!

  • Lub użyj dłuższej wersji (37 bajtów), aby zobaczyć, jak stopniowo budowana jest matryca znaków :

    t:P"@:s:@/Xk&+@+8MPt&(t30+cD9&Xx]30+c
    

    Wypróbuj w MATL Online!

Przykładowe dane wyjściowe

Dla danych wejściowych 8poniżej pokazano wersję podstawową, wyjście graficzne i kolorowe wyjście graficzne.

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Wyjaśnienie

Generalna procedura

Matryca numeryczna jest budowana od warstw zewnętrznych do wewnętrznych w Nkrokach, gdzie Njest wejście. Każdy krok zastępuje wewnętrzną (lewą górną) część poprzedniej macierzy. Na koniec liczby w uzyskanej macierzy są zamieniane na znaki.

Przykład

Dla danych wejściowych 4pierwszą macierzą jest

10 10  9  9  9  9  8  8  8  8
10 10  9  9  9  9  8  8  8  8
 9  9  8  8  8  8  7  7  7  7
 9  9  8  8  8  8  7  7  7  7
 9  9  8  8  8  8  7  7  7  7
 9  9  8  8  8  8  7  7  7  7
 8  8  7  7  7  7  6  6  6  6
 8  8  7  7  7  7  6  6  6  6
 8  8  7  7  7  7  6  6  6  6
 8  8  7  7  7  7  6  6  6  6

Jako drugi krok macierz

7 7 7 6 6 6
7 7 7 6 6 6
7 7 7 6 6 6
6 6 6 5 5 5
6 6 6 5 5 5
6 6 6 5 5 5

jest nadpisywany w górnej połowie tego ostatniego. To samo dzieje się z

6 5 5
5 4 4
5 4 4

i wreszcie z

3

Otrzymana macierz to

3 5 5 6 6 6 8 8 8 8
5 4 4 6 6 6 8 8 8 8
5 4 4 6 6 6 7 7 7 7
6 6 6 5 5 5 7 7 7 7
6 6 6 5 5 5 7 7 7 7
6 6 6 5 5 5 7 7 7 7
8 8 7 7 7 7 6 6 6 6
8 8 7 7 7 7 6 6 6 6
8 8 7 7 7 7 6 6 6 6
8 8 7 7 7 7 6 6 6 6

Na koniec 30jest dodawany do każdego wpisu, a uzyskane liczby są interpretowane jako punkty kodowe i konwertowane na znaki (zaczynając od 33, odpowiadając !).

Konstrukcja macierzy pośrednich

W przypadku danych wejściowych Nrozważ zmniejszenie wartości kod Ndo 1. Dla każdego generowany jest kwektor liczb całkowitych od 1do k*(k+1), a następnie każdy wpis jest dzielony przez ki zaokrąglany w górę. Jako przykład k=4podajemy (wszystkie bloki mają rozmiar koprócz ostatniego):

1 1 1 1 2 2 2 2 3 3

natomiast dla k=3wyniku byłoby (wszystkie bloki mają rozmiar k):

1 1 1 2 2 2

Wektor ten jest dodawany, elementarnie z rozgłoszeniem, do transponowanej kopii samego siebie; a następnie kjest dodawany do każdego wpisu. Do k=4tego daje

6  6  6  6  7  7  7  7  8  8
6  6  6  6  7  7  7  7  8  8
6  6  6  6  7  7  7  7  8  8
6  6  6  6  7  7  7  7  8  8
7  7  7  7  8  8  8  8  9  9
7  7  7  7  8  8  8  8  9  9
7  7  7  7  8  8  8  8  9  9
7  7  7  7  8  8  8  8  9  9
8  8  8  8  9  9  9  9 10 10
8  8  8  8  9  9  9  9 10 10

Jest to jedna z pośrednich matryc pokazanych powyżej, z tym wyjątkiem, że jest odwracana poziomo i pionowo. Pozostaje tylko odwrócić tę macierz i zapisać ją w lewym górnym rogu dotychczasowej macierzy „nagromadzonej”, zainicjowanej na pustą macierz dla pierwszego ( k=N) kroku.

Kod

t       % Implicitly input N. Duplicate. The first copy of N serves as the
        % initial state of the "accumulated" matrix (size 1×1). This will be 
        % extended to size N*(N+1)/2 × N*(N+1)/2 in the first iteration
 :P     % Range and flip: generates vector [N, N-1, ..., 1]
"       % For each k in that vector
  @:    %   Push vector [1, 2, ..., k]
  s     %   Sum of this vector. This gives 1+2+···+k = k*(k+1)/2
  :     %   Range: gives vector [1, 2, ..., k*(k+1)/2]
  @/    %   Divide each entry by k
  Xk    %   Round up
  &+    %   Add vector to itself transposed, element-wise with broadcast. Gives
        %   a square matrix of size k*(k+1)/2 × k*(k+1)/2
  @+    %   Add k to each entry of the this matrix. This is the flipped
        %   intermediate matrix
  8M    %   Push vector [1, 2, ..., k*(k+1)/2] again
  Pt    %   Flip and duplicate. The two resulting, equal vectors are the row and
        %   column indices where the generated matrix will be written. Note that
        %   flipping the indices has the same effect as flipping the matrix
        %   horizontally and vertically (but it's shorter)
  &(    %   Write the (flipped) intermediate matrix into the upper-left
        %   corner of the accumulated matrix, as given by the two (flipped)
        %   index vectors 
]       % End
30+     % Add 30 to each entry of the final accumulated matrix
c       % Convert to char. Implicitly display
Luis Mendo
źródło
W ogóle nie znam MATL-a, ale czy możesz zapisać jakieś bajty, biorąc mod10 zamiast dodawać 30 i konwertować na postać?
user2390246,
Lub nawet mod4 ...
user2390246
@ user2390246 Czy chcesz zachować je jako liczby z jedną cyfrą i unikać konwersji na znak? To nie zadziałałoby, ponieważ macierz numeryczna byłaby drukowana ze spacjami między liczbami. Ale i tak dzięki za pomysł :-)
Luis Mendo
Słusznie. Co dzieje się z n> 226? Czy to nie wykracza poza zakres prawidłowych znaków? (Nie jest zaskakujące, że
upłynął limit
@ user2390246 Tak, przy wysokich liczbach wejściowych wychodzi na zewnątrz. A jeśli weźmiemy pod uwagę znaki ASCII, maksymalny punkt kodowy to 127, więc wychodzi jeszcze wcześniej. Ale, jak zauważyłeś, zabrakło pamięci, zanim to się stanie (wynikowa macierz znaków jest zbyt duża). W każdym razie zazwyczaj dozwolona jest praca z danym rozmiarem wejściowym tylko z powodu ograniczeń pamięci lub typu danych
Luis Mendo,
7

Python 2 , 187 178 164 162 152 bajtów

-8 bajtów dzięki Mr.Xcoder
-1 bajtów dzięki Stephenowi
-10 bajtów dzięki Jonathanowi Frechowi

g=lambda y:y>1and[l+y*f(y,i)for i,l in enumerate(g(y-1))]+y*[''.join(f(y,i)for i in range(y*-~y/2))]or['#']
f=lambda y,i:'0@+#'[(y*~-y/2%y+i)/y%2+y%2*2]

Wypróbuj online!

Pręt
źródło
Gdy wrócisz do domu, 179 bajtów .
Pan Xcoder,
@ Mr.Xcoder 178 bajtów
Stephen
1
Czy wolno nie uwzględniać liczby bajtów nazwy funkcji lambda, gdy używasz jej rekurencyjnie, tj. Używając jej nazwy w pozostałej części kodu?
Jonathan Frech,
sum(range(y))%y->y*~-y/2%y
Jonathan Frech
@JathanathanFrech tak, jeśli jest rekurencyjny, musi tam być.
Rod
7

Węgiel , 50 46 bajtów

F⮌…·¹N«≔⊘×ι⊕ιθF⊕⊘ι«F§#+@⁺ικ«UO⁻θ×ικθλUOθ⁻θ×ικλ

Wypróbuj online! Link jest do pełnej wersji kodu. Poprzednia 50-bajtowa wersja z wyjaśnieniem: Wypróbuj online!

F⮌…·¹N«≔÷×ι⁺¹ι²θF⁺¹÷鲫F§#+@⁺ικ«UO⁻θ×ικθλUOθ⁻θ×ικλ

F     «     Loop over
  …·¹       Inclusive range from 1 to
     N      Input as a number
 ⮌          Reversed

   ι⁺¹        Add 1 to current index
  ×   ι       Multiply by current index
 ÷     ²      Divide by 2
≔       θ     Assign to q

F     «      Loop over
             Implicit range from 0 to
   ÷ι²       Half the current index
 ⁺¹          Plus 1

F       «    Loop over
  #+@        Literal string
 §           Circularly indexed by
     ⁺ικ     Sum of outer and inner index

    ×ικ     Multiply outer and inner index
  ⁻θ        Subtract from q
UO     θλ   Draw an oblong (q-ik, q) using that character

UOθ⁻θ×ικλ   Draw an oblong (q, q-ik) using that character

Uwaga: Pętlę nad znakiem, zamiast próbować przypisać go bezpośrednio, lponieważ nie można bezpośrednio przypisać wyniku indeksowania łańcucha do zmiennej, ponieważ jest to niejednoznaczna konstrukcja w grafice. Na szczęście liczba bajtów jest taka sama.

Neil
źródło
Technicznie możesz, stosując zmienną ASCII, ponieważ kolejność argumentów jest odwrócona (pamiętaj, że potrzebuje operatora, aby uzyskać dostęp, więc jest jeszcze mniej golfowy)
tylko ASCII
5

C (gcc) , 135 128 120 bajtów

f(n,m,i,x,y,k){for(m=n*-~n/2,i=m*m;i--;printf("\n%d"+!!(~i%m),(x/k+y/k+k)%3))for(x=i%m,y=i/m,k=n;x>=k&y>=k;x-=k--)y-=k;}

Wypróbuj online!

Używa tylko trzech kolorów.

Koncepcyjnie działa na siatce obróconej o 180 stopni:

000111
000111
000111
111220
111220
111001

I oblicza kolory według wzoru:

c(x,y,n) = c(x-n,y-n,n-1)                   if x >= n and y >= n
         = (x div n + y div n + n) mod 3    otherwise
nwellnhof
źródło
1
123 bajty.
Jonathan Frech,
@JonathanFrech To nie jest poprawne C i zrywa gcc -O2.
nwellnhof,
Słusznie; czy jest możliwe, że drugi kod działa tylko dla trzech kolorów z powodu modułu three ( g(i%m,i/m,n)%3)?
Jonathan Frech,
Zaproponuj x/k&&y/kzamiastx>=k&y>=k
ceilingcat
2

R , 131 126 123 bajtów

3 bajty zapisane dzięki @Giuseppe

function(n){l=w=sum(1:n)
m=matrix(,l,l)
for(i in n:1){m[l:1,l:1]=outer(x<-(1:l-1)%/%i,x,`+`)+i
l=l-i}
write(m%%4,"",w,,"")}

Wypróbuj online!

Używa tego samego algorytmu, co odpowiedź MATL @LuisMendo . Jedyna różnica polega na tym, że zamiast konwertowania na znaki macierz jest wyprowadzana ze wszystkimi wartościami mod4, aby zapewnić, że każdy element jest pojedynczym znakiem ascii.

użytkownik2390246
źródło
1
123 bajty! Przywróciłem forpętlę dla -1 bajtów :)
Giuseppe,
1

Python 2 , 176 175 bajtów

n=input()
R,J=range,''.join;r=[]
for i in R(n+1):
 S=sum(R(i));c='AxBo'[i%2::2]
 for j in R(S):r[~j]+=c[j/i%2]*i
 r+=[J(c[-j/i%2]for j in R(S+i,0,-1))]*i
for l in r:print J(l)

Wypróbuj online!

TFeld
źródło
Jeśli zdefiniujesz J="".join;(+10 bajtów) i zamienisz oba "".joins (-2 * 7 = -14 bajtów) na J(+2 bajty), możesz zapisać bajt (ponieważ po bajcie musi być dodatkowa spacja print; +1 bajt) .
Jonathan Frech,