La spirale de multiplication unique

13

Celui-ci est inspiré du récent défi de la table de multiplication de Calvin's Hobbies .

Écrivez une fonction ou un programme qui prend un entier Nen entrée et imprime ou renvoie une spirale de multiplication unique N par N. Le code doit (en théorie) fonctionner pour N entre 0 et 1000 (la sortie peut cependant être difficile). La sortie doit être équivalente au tableau produit par la procédure suivante:

  1. Remplissez un tableau de multiplication N par N. Par exemple pour N = 3:

    1 2 3
    2 4 6
    3 6 9
    
  2. Suivez une spirale dans le sens horaire à partir du coin supérieur gauche, en notant les chiffres que vous visitez. Lorsque vous visitez un numéro que vous avez déjà visité, remplacez-le par 0.

Quelques exemples pourraient le rendre plus clair:

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

Les chiffres se trouvent comme ceci:

entrez la description de l'image ici

Tout format de sortie raisonnable est accepté, mais il doit s'agir d'une matrice N par N, il ne peut pas s'agir simplement d'une liste. Les formats tels que ceux ci-dessous sont acceptés, car il y a N colonnes 1 par N facilement distinguables, ou N par 1 lignes:

[[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   

Le code le plus court en octets gagne.

Stewie Griffin
la source
J'espionne de mon petit oeil un tamis d'ératosthène modifié! Je suis presque sûr qu'il y a un modèle que vous pouvez utiliser ici que j'ai vu quelque part ou autre.
Addison Crump,
2
Pourquoi y aurait-il une sortie pour n=0où il n'y a pas de zéro dans les tables de multiplication. Je peux comprendre n=1que la sortie 1, mais pourquoi inclure zéro?
Tom Carpenter
@ TomCarpenter, cela aurait pu être une mauvaise décision, mais je savais qu'il y aurait une question "Qu'en est-il de N = 0?", J'ai donc fait la règle N = 0 -> 0. Rétrospectivement, il aurait peut-être été préférable de dire que N> 0, mais il est un peu trop tard maintenant, j'ai peur = /
Stewie Griffin
2
@StewieGriffin Vous avez dit que la sortie devait être une matrice N par N, donc la sortie pour n=0devrait être une matrice 0 par 0, sinon la question serait incohérente.
alephalpha

Réponses:

3

J, 22 octets

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

Il affiche une matrice 0 par 0 pour n=0.

alephalpha
la source
8

Mathematica 123122117 98 92 73 octets

Avec 24 octets enregistrés grâce à LegionMammal978 et 19 autres par alephalpha!


Étonnamment, dans ce tableau, plusieurs instances d'un nombre entier nauront le même ordre relatif dans la spirale que dans le tableau lui-même! La première apparition d'un nombre nse situe à la cellule même où ce nombre apparaît en premier dans le tableau (lorsque l'on remplit le tableau ligne par ligne). Cela signifie que l'approche peut totalement ignorer la contrainte en spirale, car elle n'a aucune incidence sur le résultat. (Voir l'explication ci-dessous.)

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

Exemple

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[%]

table


Explication

Nous exploitons le fait que l'ordre en spirale des positions de n'importe quel chiffre, n, est le même que l'ordre des positions de ligne-colonne renvoyées par la fonction Positions,!

L'emplacement de la première occurrence de chaque nombre (que l'on commande par la spirale ou par la position de la table) sera le premier élément renvoyé par Position. Cette cellule de première occurrence sera laissée telle quelle. Les instances restantes du nombre sont remplacées par 0.

Voyons comment cela fonctionne, en examinant le cas de n==18. L'idée est de commencer par la table de multiplication:

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

et localisez les positions des colonnes de chaque numéro. Par exemple, 18 est situé à Row 2, Col 9 (la première instance); Ligne 3, Col 6; Ligne 6, Col 3; et Ligne 9, Col 2. Celles-ci ont les positions respectives d'ordre en spirale {44, 58, 68, 82}.

Position[t, 18]

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

comme le montre le tableau suivant.

Tableau 2

Les 3 dernières instances de 18 doivent être remplacées par 0. (Nous utiliserons de gros zéros bleus afin qu'ils puissent être facilement repérés.)

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

Tableau 3

DavidC
la source
Y a-t-il une raison pour ne pas écrire un Function?
LegionMammal978
1
J'avais des problèmes avec les fonctions pures imbriquées, mais cette itération ne l'exige pas. Merci.
DavidC
Je compte 117 octets à l'exclusion de la nouvelle ligne.
LegionMammal978
En outre, quelques autres golfs
LegionMammal978
Quelques golfs supplémentaires:ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&
alephalpha
2

Python, 99 95 90 89 87 81 octets

Code golf:

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

Non golfé:

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

Production:

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ᵠ
la source
merci @valuah pour le rasage des octets d'entrée
CSᵠ
2

MATLAB, 96 88 87 86 79 octets

Il s'agit du code de 79 octets, qui suit les sorties d'exemple (pour n = 0 spécifiquement)

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

Celui-ci fait 75 octets, a le même comportement sauf pour n = 0 qui produira un tableau vide selon l'implication de la question (N par N tableau = 0 par 0 = tableau vide).

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

Cela fonctionne également avec Octave . Vous pouvez l'essayer en ligne ici . Le code est déjà ajouté en tant que fichier nommé «multspiral.m». Ainsi, à l'invite Octave, tapez multspiralet appuyez sur Entrée. Vous devez ensuite saisir la taille du tableau (par exemple 4). La sortie sera alors imprimée.


Comment ça marche?

Tout d'abord, cela prend un numéro d'entrée comme requis (par exemple 6, 4, etc.)

n=input('');

Ensuite, nous traitons les cas pour n=0et n=1- ceux-ci reçoivent un traitement spécial car ce sont deux qui ne suivent pas la règle que j'utilise pour générer les tableaux - en fait, cela pourrait être 5 octets plus court si ce n'est pour le n=0cas obscur .

m=+(n>0);

Ensuite, pour toutes les valeurs de n>2, nous effectuons une boucle jusqu'à ce que la matrice atteigne la taille correcte.

for i=2:n;

Il n'y a en fait que trois différences simples entre net n+1pour tous n>=2. Ceux-ci sont:

  1. Une nouvelle colonne est ajoutée à l'extrême droite dans le tableau qui contient les nombres n(1:n). Ceci est facilement calculé avec:

     a=i*(1:i);
    
  2. Tous les éléments qui seront ajoutés dans cette nouvelle colonne doivent être supprimés de la matrice existante (mis à zéro) car ils viendront toujours plus tard dans la spirale que la nouvelle colonne. Ceci est supprimé à l'aide d'une boucle imbriquée pour définir tous les éléments de la matrice actuelle qui sont dans la nouvelle colonne à zéro.

    for j=a;
        m(m==j)=0;
    end;
    
  3. Il y a une nouvelle ligne en bas pour laquelle chaque élément, sauf celui qui est dans la nouvelle colonne, sera nul. Lorsque la nouvelle colonne a été ajoutée, en raison des index hors limites qui ont été intentionnellement créés, elle est automatiquement complétée par 0. L'une des principales caractéristiques de MATLAB est qu'il peut développer des tableaux sans aucune manipulation particulière, nous pouvons donc ajouter simplement la nouvelle ligne et la nouvelle colonne avec:

    m(1:i,i)=a;
    

Enfin, nous avons la fin de la boucle for - qui une fois atteinte, la matrice mcontient notre sortie. Comme vous êtes flexible avec votre format de sortie, la matrice est affichée simplement en ayant mcomme nouvelle ligne sans point-virgule

end;
m

Par exemple, si nous exécutons le programme, entrez le nombre 10, nous obtenons la sortie suivante:

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
la source
1

Haskell, 103 99 octets

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]]

Exemple d'utilisation: f 4-> [[1,2,3,4],[0,0,6,8],[0,0,9,12],[0,0,0,16]].

Je viens de découvrir le Data.Listsmodule qui a de belles fonctions sur les listes (comme replace) et les réexportations Data.List, Data.List.Splitet Data.List.Extras.

nimi
la source
1

Rubis, 67 63 61 octets

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

63 octets

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

67 octets

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

Usage:

->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
la source