Visualizza il teorema di Nicomaco


35

Il teorema di Nichomachus mette in relazione il quadrato di una somma con la somma dei cubi:

Teorema di Nichomachus

e ha una bella visualizzazione geometrica:

visualizzazione

Sfida: creare la seconda parte di questa visualizzazione in ascii.

Dovrai assicurarti che tutte le demarcazioni visive siano confermate dal tuo diagramma. Questo è più semplice da fare con quattro "colori", sebbene sia possibile ottenerne solo tre (vedere come nell'esempio seguente di seguito). Con quattro colori, ne usi due per distinguere le regioni all'interno di una "striscia" (ovvero le diverse parti che compongono un singolo cubo) e due per distinguere tra strisce adiacenti. Se lo desideri, puoi anche utilizzare più di quattro colori. Se uno di questi è confuso, l'esempio di seguito riportato dovrebbe chiarire.

Input Output

L'input è un singolo intero maggiore di 0. L'output è una griglia ASCII simile agli esempi seguenti, corrispondente alla griglia appiattita per quel numero di input nell'immagine sopra. Gli spazi bianchi iniziali e finali sono ok.

Questo è il golf del codice, con regole standard.

Output di esempio

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

Versione a tre colori per N = 4, grazie a @BruceForte:

#oo+++oooo
o##+++oooo
o##+++####
+++ooo####
+++ooo####
+++ooo####
oo####++++
oo####++++
oo####++++
oo####++++

6
Teorema a quattro colori: D
Leaky Nun,

1
Puoi aggiungere l'output per N = 5 per favore?
Uriel,

1
@Uriel Done. Vedi la mia modifica.
Giona,

Grazie! Inoltre, posso cambiare @ e os solo nella striscia esterna in N = 4? O l'output deve essere una sostituzione rigorosa di questi testi con un altro set di caratteri?
Uriel,

La commutazione @Uriel va bene. Tutto ciò che conta è che i colori adiacenti non siano in conflitto, quindi il motivo è visibile.
Giona,

Risposte:


17

MATL , 30 28 27 byte

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

Provalo online!

Caratteristiche bonus:

  • Per 26 byte , la seguente versione modificata produce un output grafico :

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

    Provalo su MATL Online!

  • L'immagine richiede un po 'di colore e costa solo 7 byte:

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

    Provalo su MATL Online!

  • Oppure usa una versione più lunga (37 byte) per vedere come viene gradualmente costruita la matrice di caratteri :

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

    Provalo su MATL Online!

Esempi di output

Per input è 8, quanto segue mostra la versione di base, l'output grafico e l'output grafico a colori.

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

Spiegazione

Procedura generale

Una matrice numerica è costruita dagli strati esterni a quelli interni a Npassi, dove si Ntrova l'input. Ogni passaggio sovrascrive una parte interna (in alto a sinistra) della matrice precedente. Alla fine, i numeri nella matrice ottenuta vengono cambiati in caratteri.

Esempio

Per input 4la prima matrice è

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

Come secondo passo, la matrice

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

viene sovrascritto nella metà superiore di quest'ultimo. Quindi lo stesso viene fatto

6 5 5
5 4 4
5 4 4

e infine con

3

La matrice risultante è

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

Infine, 30viene aggiunto a ciascuna voce e i numeri risultanti vengono interpretati come punti di codice e convertiti in caratteri (iniziando così da 33, corrispondente a !).

Costruzione delle matrici intermedie

Per l'input N, considerare la riduzione dei valori di kda Na 1. Per ciascuno k, viene generato un vettore di numeri interi da 1a k*(k+1), quindi ciascuna voce viene divisa ke arrotondata per eccesso. Ad esempio, per k=4questo dà (tutti i blocchi hanno dimensioni ktranne l'ultimo):

1 1 1 1 2 2 2 2 3 3

mentre per k=3il risultato sarebbe (tutti i blocchi hanno dimensioni k):

1 1 1 2 2 2

Questo vettore viene aggiunto, in termini di elementi con trasmissione, a una copia trasposta di se stesso; e quindi kviene aggiunto a ciascuna voce. Per k=4questo dà

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

Questa è una delle matrici intermedie mostrate sopra, tranne per il fatto che viene capovolta orizzontalmente e verticalmente. Quindi non resta che capovolgere questa matrice e scriverla nell'angolo in alto a sinistra della matrice "accumulata" finora, inizializzata su una matrice vuota per il primo ( k=N) passaggio.

Codice

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

Non conosco affatto MATL, ma potresti salvare dei byte prendendo mod10 invece di aggiungere 30 e convertirli in carattere?
user2390246

O anche mod4 ...
user2390246

@ user2390246 Intendi mantenerli come numeri con una sola cifra ed evitare la conversione in caratteri? Non funzionerebbe, perché la matrice numerica verrebbe stampata con spazi tra i numeri. Ma grazie comunque per l'idea :-)
Luis Mendo,

Giusto. Cosa succede con n> 226? Non andrà al di fuori della gamma di personaggi validi? (Non sorprende,
scade

@ user2390246 Sì, per numeri di input elevati va fuori. E se consideriamo i caratteri ASCII il punto di codice massimo è 127, quindi esce anche prima. Ma come hai notato, la memoria si esaurisce prima che ciò accada (la matrice di caratteri risultante è troppo grande). Ad ogni modo, è consentito lavorare fino a una determinata dimensione di input solo a causa delle limitazioni della memoria o del tipo di dati
Luis Mendo,

7

Python 2 , 187 178 164 162 152 byte

-8 byte grazie a Mr.Xcoder
-1 byte grazie a Stephen
-10 byte grazie a 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]

Provalo online!


Per quando torni a casa, 179 byte .
Mr. Xcoder,

@ Mr.Xcoder 178 byte
Stephen

1
È consentito non includere il conteggio dei byte del nome della funzione lambda quando lo si utilizza in modo ricorsivo, ovvero utilizzando il suo nome nel resto del codice?
Jonathan Frech,

sum(range(y))%y->y*~-y/2%y
Jonathan Frech,

@JonathanFrech sì, quando è ricorsivo deve essere lì.
Rod,

7

Carbone , 50 46 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Versione precedente a 50 byte con spiegazione: provala 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

Nota: cerco il carattere piuttosto che cercare di assegnare direttamente il carattere lperché non è possibile assegnare direttamente il risultato dell'indicizzazione di una stringa a una variabile poiché è un costrutto ambiguo in Carbone. Fortunatamente il conteggio dei byte è lo stesso.


Tecnicamente è possibile, con una variabile ASCII poiché il suo ordine degli argomenti è invertito (si noti che ha bisogno di un operatore per accedere quindi è ancora meno golfy)
ASCII

5

C (gcc) , 135 128 120 byte

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

Provalo online!

Utilizza solo tre colori.

Concettualmente, funziona su una griglia ruotata di 180 gradi:

000111
000111
000111
111220
111220
111001

E calcola i colori secondo la formula:

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


@JonathanFrech Questo non è C valido e si interrompe gcc -O2.
nwellnhof,

Giusto; è possibile che il secondo codice funzioni solo per tre colori a causa del modulo tre ( g(i%m,i/m,n)%3)?
Jonathan Frech,

Suggerisci x/k&&y/kinvece dix>=k&y>=k
ceilingcat il

2

R , 131 126 123 byte

3 byte salvati grazie a @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,,"")}

Provalo online!

Questo utilizza lo stesso algoritmo della risposta MATL di @LuisMendo . L'unica differenza è che, anziché convertirsi in caratteri, la matrice viene emessa con tutti i valori mod4 per garantire che ogni elemento sia un singolo carattere ASCII.


1
123 byte! Ho riportato il forloop per -1 byte :)
Giuseppe,

1

Python 2 , 176 175 byte

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)

Provalo online!


Se si definisce J="".join;(+10 byte) e si sostituiscono entrambi "".joins (-2 * 7 = -14 byte) con J(+2 byte), è possibile salvare un byte (poiché deve esserci uno spazio aggiuntivo dopo il print; +1 byte) .
Jonathan Frech,
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.