Visualisieren Sie den Satz von Nicomachus

35

Der Satz von Nichomachus bezieht das Quadrat einer Summe auf die Summe der Würfel:

Nichomachus Theorem

und hat eine schöne geometrische Visualisierung:

Visualisierung

Herausforderung: Erstellen Sie den zweiten Teil dieser Visualisierung in ASCII.

Sie müssen sicherstellen, dass alle visuellen Abgrenzungen von Ihrem Diagramm eingehalten werden. Dies ist am einfachsten mit vier "Farben" zu tun, obwohl es mit nur drei möglich ist (siehe letztes Beispiel unten für wie). Bei vier Farben werden zwei zur Unterscheidung zwischen Bereichen innerhalb eines "Streifens" (dh den verschiedenen Teilen, aus denen ein einzelner Würfel besteht) und zwei zur Unterscheidung zwischen benachbarten Streifen verwendet. Sie können auch mehr als vier Farben verwenden, wenn Sie möchten. Wenn dies verwirrend ist, sollte das folgende Beispiel klarstellen.

Input-Output

Die Eingabe ist eine einzelne Ganzzahl größer als 0. Die Ausgabe ist ein ASCII-Raster, das den folgenden Beispielen ähnelt und dem abgeflachten Raster für diese Eingabenummer im obigen Bild entspricht. Führende und nachfolgende Leerzeichen sind in Ordnung.

Dies ist Codegolf mit Standardregeln.

Beispielausgaben

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#####
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++
+++++#####+++++

Dreifarbige Version für N = 4 dank @BruceForte:

#oo+++oooo
o##+++oooo
o##+++####
+++ooo####
+++ooo####
+++ooo####
oo####++++
oo####++++
oo####++++
oo####++++
Jona
quelle
6
Vierfarbensatz: D
Leaky Nun
1
Können Sie bitte die Ausgabe für N = 5 hinzufügen?
Uriel
1
@Uriel Fertig. Siehe meine Bearbeitung.
Jonah
Vielen Dank! Kann ich @ und os auch nur in der äußeren Leiste in N = 4 umschalten? Oder muss die Ausgabe eine strikte Ersetzung dieser Texte durch einen anderen Zeichensatz sein?
Uriel
@Uriel-Umschaltung ist in Ordnung. Wichtig ist nur, dass nebeneinander liegende Farben nicht in Konflikt geraten, sodass das Muster sichtbar ist.
Jonah

Antworten:

17

MATL , 30 28 27 Bytes

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

Probieren Sie es online!

Bonusmaterial:

  • Für 26 Bytes erzeugt die folgende modifizierte Version eine grafische Ausgabe :

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

    Probieren Sie es bei MATL Online!

  • Das Bild verlangt nach etwas Farbe und kostet nur 7 Bytes:

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

    Probieren Sie es bei MATL Online!

  • Oder verwenden Sie eine längere Version (37 Byte), um zu sehen, wie die Zeichenmatrix schrittweise aufgebaut wird :

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

    Probieren Sie es bei MATL Online!

Beispielausgaben

Für die Eingabe wird 8im Folgenden die Grundversion, die grafische Ausgabe und die grafische Farbausgabe angezeigt.

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Erläuterung

Allgemeines Verfahren

Eine numerische Matrix wird in NSchritten von der äußeren zur inneren Ebene erstellt, wobei Ndie Eingabe erfolgt. Jeder Schritt überschreibt einen inneren (oben links) Teil der vorherigen Matrix. Am Ende werden die Zahlen in der erhaltenen Matrix in Zeichen geändert.

Beispiel

Für die Eingabe ist 4die erste Matrix

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

In einem zweiten Schritt wird die Matrix

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

wird in die obere Hälfte des letzteren überschrieben. Dann ist das selbe erledigt mit

6 5 5
5 4 4
5 4 4

und schließlich mit

3

Die resultierende Matrix ist

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

Zuletzt 30wird zu jedem Eintrag hinzugefügt und die resultierenden Zahlen werden als Codepunkte interpretiert und in Zeichen umgewandelt (also beginnend bei 33, entsprechend !).

Konstruktion der Zwischenmatrizen

NBerücksichtigen Sie bei der Eingabe abnehmende Werte kvon Nbis 1. Für jedes kwird ein Vektor von ganzen Zahlen von 1bis k*(k+1)erzeugt, und dann wird jeder Eintrag durch dividiert kund aufgerundet. Als Beispiel k=4gibt dies an (alle Blöcke haben eine Größe mit kAusnahme des letzten):

1 1 1 1 2 2 2 2 3 3

während für k=3das Ergebnis wäre (alle Blöcke haben Größe k):

1 1 1 2 2 2

Dieser Vektor wird elementweise mit Broadcast zu einer transponierten Kopie von sich selbst hinzugefügt; und wird dann kzu jedem Eintrag hinzugefügt. Dafür k=4gibt es

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

Dies ist eine der oben gezeigten Zwischenmatrizen, mit der Ausnahme, dass sie horizontal und vertikal gespiegelt wird. Alles was übrig bleibt ist, diese Matrix umzudrehen und in die obere linke Ecke der "akkumulierten" Matrix zu schreiben, die für den ersten ( k=N) Schritt zu einer leeren Matrix initialisiert wurde.

Code

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
quelle
Ich kenne MATL überhaupt nicht, aber könntest du irgendwelche Bytes sparen, indem du mod10 nimmst, anstatt 30 zu addieren und in Zeichen umzuwandeln?
user2390246
Oder sogar mod4 ...
user2390246
@ user2390246 Wollen Sie sie als Zahlen mit einer einzelnen Ziffer behalten und vermeiden, sie in Zeichen umzuwandeln? Das würde nicht funktionieren, da die numerische Matrix mit Leerzeichen zwischen den Zahlen gedruckt würde. Aber trotzdem danke für die Idee :-)
Luis Mendo
Meinetwegen. Was passiert mit n> 226? Wird das nicht außerhalb des gültigen Zeichenbereichs liegen? (Es ist nicht überraschend, dass bei TIO eine
Zeitüberschreitung auftritt
@ user2390246 Ja, bei hohen Eingangszahlen geht es nach draußen. Wenn wir ASCII-Zeichen berücksichtigen, beträgt der maximale Codepunkt 127, sodass er noch früher nach draußen geht. Wie Sie jedoch bemerkt haben, ist der Speicher fast voll (die resultierende Zeichenmatrix ist zu groß). Wie auch immer, das Bearbeiten einer bestimmten Eingabegröße nur aufgrund von Speicher- oder Datentypbeschränkungen ist normalerweise zulässig
Luis Mendo,
7

Python 2 , 187 178 164 162 152 Bytes

-8 Bytes dank Mr.Xcoder
-1 Bytes dank Stephen
-10 Bytes dank Jonathan Frech

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]

Probieren Sie es online!

Stange
quelle
Denn wenn Sie nach Hause kommen, 179 Bytes .
Mr. Xcoder
@ Mr.Xcoder 178 Bytes
Stephen
1
Darf die Anzahl der Byte des Namens Ihrer Lambda-Funktion nicht mit einbezogen werden, wenn Sie sie rekursiv verwenden, dh wenn Sie den Namen im Rest des Codes verwenden?
Jonathan Frech
sum(range(y))%y->y*~-y/2%y
Jonathan Frech
@ JonathanFrech ja, wenn es rekursiv ist, muss es da sein.
Rod
7

Kohle , 50 46 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Zurück 50-Bit - Version mit Erklärung: Versuchen Sie es 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

Hinweis: Ich durchlaufe das Zeichen, anstatt zu versuchen, das Zeichen direkt zuzuweisen, lda Sie das Ergebnis der Indizierung einer Zeichenfolge nicht direkt einer Variablen zuordnen können, da es sich um ein mehrdeutiges Konstrukt in Charcoal handelt. Zum Glück ist die Anzahl der Bytes gleich.

Neil
quelle
Technisch gesehen können Sie mit einem ASCII - Variable , da ihr Argument , um umgekehrt wird (beachten Sie, dass es einen Operator zugreifen muss , so dass es noch weniger Golfy ist)
ASCII-only
5

C (GCC) , 135 128 120 Bytes

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

Probieren Sie es online!

Verwendet nur drei Farben.

Arbeitet konzeptionell an einem um 180 Grad gedrehten Raster:

000111
000111
000111
111220
111220
111001

Und berechnet Farben nach der Formel:

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
quelle
1
123 Bytes.
Jonathan Frech
@JonathanFrech Dies ist kein gültiges C und bricht mit gcc -O2.
Nwellnhof
Meinetwegen; ist es möglich, dass der zweite code wegen des moduls three ( g(i%m,i/m,n)%3) nur für drei farben funktioniert ?
Jonathan Frech
Schlagen Sie x/k&&y/kanstelle vonx>=k&y>=k
ceilingcat vor
2

R , 131 126 123 Bytes

3 Bytes gespart dank @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,,"")}

Probieren Sie es online!

Dies verwendet den gleichen Algorithmus wie die MATL- Antwort von @LuisMendo . Der einzige Unterschied besteht darin, dass die Matrix nicht in Zeichen konvertiert, sondern mit allen Werten mod4 ausgegeben wird, um sicherzustellen, dass jedes Element ein einzelnes ASCII-Zeichen ist.

user2390246
quelle
1
123 Bytes! Ich habe die forSchleife für -1 Byte zurückgebracht :)
Giuseppe
1

Python 2 , 176 - 175 Bytes

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)

Probieren Sie es online!

TFeld
quelle
Wenn Sie J="".join;(+10 Byte) definieren und beide "".joins (-2 * 7 = -14 Byte) durch J(+2 Byte) ersetzen , können Sie ein Byte speichern (da nach dem print; +1 Byte ein zusätzlicher Speicherplatz erforderlich ist) .
Jonathan Frech