Visualiser le théorème de Nicomaque

35

Le théorème de Nichomachus relie le carré d'une somme à la somme de cubes:

Théorème de Nichoma

et a une belle visualisation géométrique:

Visualisation

Défi: Créez la partie 2d de cette visualisation en ascii.

Vous devrez vous assurer que toutes les démarcations visuelles sont respectées par votre diagramme. Ceci est plus simple à faire avec quatre "couleurs", bien qu'il soit possible d'obtenir avec seulement trois (voir le dernier exemple ci-dessous pour savoir comment). Avec quatre couleurs, vous en utilisez deux pour distinguer les régions d'une "bande" (c'est-à-dire les différentes parties qui constituent un seul cube) et deux pour distinguer les bandes adjacentes. Vous pouvez également utiliser plus de quatre couleurs si vous le souhaitez. Si l'une de ces choses est source de confusion, l'exemple de sortie ci-dessous devrait clarifier.

Entrée sortie

L'entrée est un entier unique supérieur à 0. La sortie est une grille ascii similaire aux exemples ci-dessous, correspondant à la grille aplatie de ce numéro d'entrée dans l'image ci-dessus. Les espaces de début et de fin sont acceptables.

C'est du code golf, avec des règles standards.

Exemples de sorties

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

Version trois couleurs pour N = 4, grâce à @BruceForte:

#oo+++oooo
o##+++oooo
o##+++####
+++ooo####
+++ooo####
+++ooo####
oo####++++
oo####++++
oo####++++
oo####++++
Jonas
la source
6
Théorème des quatre couleurs: D
Leaky Nun
1
Pouvez-vous ajouter la sortie pour N = 5 s'il vous plaît?
Uriel
1
@ Uriel Fait. Voir mon édition.
Jonah
Merci! Aussi, puis-je changer les @ et os seulement dans la bande extérieure en N = 4? Ou bien la sortie doit-elle être une substitution stricte de ces textes par un autre jeu de caractères?
Uriel
@ Uriel, ça va. Tout ce qui compte, c'est que les couleurs adjacentes ne soient pas en conflit, de sorte que le motif soit visible.
Jonah

Réponses:

17

MATL , 30 28 27 octets

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

Essayez-le en ligne!

Bonus caractéristiques:

  • Pour 26 octets , la version modifiée suivante génère une sortie graphique :

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

    Essayez-le sur MATL Online!

  • L'image demande de la couleur et ne coûte que 7 octets:

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

    Essayez-le sur MATL Online!

  • Ou utilisez une version plus longue (37 octets) pour voir comment la matrice de caractères est construite progressivement :

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

    Essayez-le sur MATL Online!

Exemple de sorties

Pour l'entrée is 8, voici la version de base, la sortie graphique et la sortie graphique couleur.

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

Explication

Procédure générale

Une matrice numérique est construite par Nétapes des couches externe vers interne .N se les entrées. Chaque étape remplace une partie interne (en haut à gauche) de la matrice précédente. A la fin, les nombres dans la matrice obtenue sont changés en caractères.

Exemple

Pour entrer 4la première matrice est

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

Dans un deuxième temps, 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

est écrasé dans la moitié supérieure de ce dernier. Puis on fait la même chose avec

6 5 5
5 4 4
5 4 4

et enfin avec

3

La matrice résultante est

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

Enfin, 30est ajouté à chaque entrée et les nombres résultants sont interprétés comme des points de code et convertis en caractères (commençant ainsi à 33, correspondant à !).

Construction des matrices intermédiaires

Pour la saisie N, considérez les valeurs décroissantes de kde Nà 1. Pour chacune d'elles k, un vecteur d'entiers allant de 1à k*(k+1)est généré, puis chaque entrée est divisée par ket arrondie. Par exemple, pour k=4cela donne (tous les blocs ont une taille ksauf le dernier):

1 1 1 1 2 2 2 2 3 3

alors que pour k=3le résultat serait (tous les blocs ont une taille k):

1 1 1 2 2 2

Ce vecteur est ajouté élément par émission avec une copie transposée de lui-même; et kest ensuite ajouté à chaque entrée. Pour k=4cela donne

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

C'est l'une des matrices intermédiaires montrées ci-dessus, sauf qu'elle est retournée horizontalement et verticalement. Il ne reste donc qu’à retourner cette matrice et à l’écrire dans le coin supérieur gauche de la matrice "accumulée" jusqu’à présent, initialisée en une matrice vide pour la première k=Nétape ( ).

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
la source
Je ne connais pas du tout MATL, mais pourriez-vous économiser des octets en prenant mod10 plutôt que d'ajouter 30 et de les convertir en caractères?
user2390246
Ou même mod4 ...
user2390246
@ user2390246 Voulez-vous dire de les conserver sous forme de nombres avec un seul chiffre et d'éviter de les convertir en caractères? Cela ne fonctionnerait pas, car la matrice numérique serait imprimée avec des espaces entre les nombres. Mais merci pour l'idée quand même :-)
Luis Mendo
C'est suffisant. Que se passe-t-il avec n> 226? Cela ne va-t-il pas sortir de la plage de caractères valides? (Sans surprise, le temps passe sur TIO, donc je n'ai pas pu vérifier)
user2390246
@ user2390246 Oui, pour les nombres d'entrée élevés, il sort de l'extérieur. Et si nous considérons les caractères ASCII, le point de code maximum est 127, il sort donc encore plus tôt. Mais comme vous l'avez remarqué, il manque de mémoire avant que cela ne se produise (la matrice de caractères résultante est trop grande). Quoi qu'il en soit, il est généralement permis de travailler jusqu'à une taille donnée uniquement en raison de limitations de mémoire ou du type de données
Luis Mendo
7

Python 2 , 187 178 164 162 152 152 octets

-8 octets grâce à Mr.Xcoder
-1 octet grâce à Stephen
-10 octets grâce à 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]

Essayez-le en ligne!

Barre
la source
Pour quand vous rentrez à la maison, 179 octets .
M. Xcoder le
@ Mr.Xcoder 178 octets
Stephen
1
Est-il permis de ne pas inclure le nombre d'octets du nom de votre fonction lambda lorsque vous l'utilisez de manière récursive, c'est-à-dire en utilisant son nom dans le reste du code?
Jonathan Frech
sum(range(y))%y->y*~-y/2%y
Jonathan Frech
@ JonathanFrech Ouais, quand c'est récursif, ça doit être là.
Rod
7

Charbon de bois , 50 46 octets

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

Essayez-le en ligne! Le lien est vers la version verbeuse du code. Version précédente de 50 octets avec explication: essayez-la en ligne!

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

Remarque: j'effectue une boucle sur le caractère plutôt que d'essayer de l'affecter directement au personnage, lcar vous ne pouvez pas affecter directement le résultat de l'indexation d'une chaîne à une variable car il s'agit d'une construction ambiguë dans Charcoal. Heureusement, le nombre d'octets est le même.

Neil
la source
Techniquement, vous pouvez le faire avec une variable ASCII puisque l'ordre des arguments est inversé (notez qu'il faut un opérateur pour y accéder, donc c'est encore moins gaie)
ASCII seulement
5

C (gcc) , 135 128 120 octets

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

Essayez-le en ligne!

Utilise seulement trois couleurs.

Conceptuellement, fonctionne sur une grille pivotée à 180 degrés:

000111
000111
000111
111220
111220
111001

Et calcule les couleurs selon la formule:

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
la source
1
123 octets.
Jonathan Frech
@ JonathanFrech Ce n'est pas valide C et rompt avec gcc -O2.
nwellnhof
C'est suffisant; Est-il possible que le second code ne fonctionne que pour trois couleurs à cause du module trois ( g(i%m,i/m,n)%3)?
Jonathan Frech
Proposer au x/k&&y/klieu dex>=k&y>=k
ceilingcat
2

R , 131 126 123 octets

3 octets sauvés grâce à @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,,"")}

Essayez-le en ligne!

Ceci utilise le même algorithme que la réponse MATL de @LuisMendo . La seule différence est que plutôt que de convertir en caractères, la matrice est sortie avec toutes les valeurs mod4 pour garantir que chaque élément est un seul caractère ascii.

utilisateur2390246
la source
1
123 octets! J'ai ramené la forboucle pour -1 octet :)
Giuseppe
1

Python 2 , 176 175 octets

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)

Essayez-le en ligne!

TFeld
la source
Si vous définissez J="".join;(+10 octets) et remplacez les deux "".joins (-2 * 7 = -14 octets) par J(+2 octets), vous pouvez enregistrer un octet (car il doit y avoir un espace supplémentaire après le print; +1 octet) .
Jonathan Frech