Table de diviseur principal

28

Intro

Quelque chose avec lequel j'ai joué en mathématiques récréatives a été la construction d'une table de diviseurs pour comparer / contraster visuellement les diviseurs premiers d'un ensemble de nombres. L'ensemble des numéros d'entrée se trouve en haut sous forme d'étiquettes de colonne, les diviseurs principaux sont à gauche sous forme d'étiquettes de ligne, et une marque indique où les deux s'alignent.

Par exemple, pour l'entrée, 6, 9, 14, 22une table similaire à la suivante serait construite:

    6  9 14 22
 2  *     *  *
 3  *  *
 7        *
11           *

En effet, 6a des diviseurs premiers de 2et 3, 9a des diviseurs premiers de 3, et ainsi de suite.

Construction

  • Le tableau est construit de telle sorte que les numéros d'entrée forment des étiquettes de colonne séparées par des espaces et dans l'ordre croissant (vous pouvez supposer qu'ils sont pré-triés), et les diviseurs premiers sont répertoriés sur la gauche dans l'ordre croissant un par ligne formant la ligne Étiquettes.
  • Notez que les espaces de tête sur les diviseurs premiers et les nombres d'entrée peuvent être requis si les nombres sont de longueurs différentes, de sorte que toutes les colonnes ont la même largeur et s'alignent de manière appropriée.
  • Chaque diviseur est représenté par un seul *(ou un autre caractère ASCII approprié de votre choix, tant que le même caractère est utilisé pour toutes les occurrences).
  • Les diviseurs multiples sont ignorés (par exemple, 3 x 3 = 9mais il n'y en a qu'un *pour cette intersection).
  • Le *peut être placé n'importe où horizontalement dans la colonne, tant qu'il n'est pas ambigu (j'ai tous mes exemples avec le *aligné à droite).

Contribution

  • Une liste d'entiers positifs dans n'importe quel format pratique , chacun >1.
  • Vous pouvez supposer que l'entrée est pré-triée.
  • L'entrée est garantie d'avoir uniquement des valeurs uniques.

Sortie

Représentation artistique ASCII résultante de la table des diviseurs premiers.

Règles

  • Les sauts de ligne ou les espaces de début ou de fin sont tous facultatifs, tant que les caractères eux-mêmes s'alignent correctement.
  • S'il est plus court d'avoir une ligne de séparation séparant les en-têtes de colonne / ligne des données tabulaires, cela est également autorisé.
  • Un programme complet ou une fonction sont acceptables. S'il s'agit d'une fonction, vous pouvez renvoyer la sortie plutôt que de l'imprimer.
  • Si possible, veuillez inclure un lien vers un environnement de test en ligne afin que les gens puissent essayer votre code!
  • Les failles standard sont interdites.
  • Il s'agit de donc toutes les règles de golf habituelles s'appliquent et le code le plus court (en octets) l'emporte.

Exemples

6,9,14,22

    6  9 14 22
 2  *     *  *
 3  *  *
 7        *
11           *


2,3,5,7

  2 3 5 7
2 *
3   *
5     *
7       *

2,4,8,16,32

   2  4  8 16 32
2  *  *  *  *  *

75,99,151,153

     75  99 151 153
  3   *   *       *
  5   *
 11       *
 17               *
151           *
AdmBorkBork
la source
1
Pouvons-nous avoir des lignes de séparation après la ligne du haut et la colonne de gauche?
ngenisis
@ngenisis Bien sûr, je le permettrai. La formulation exacte du tableau est assez ouverte, car ce n'est pas le sens exact de ce défi.
AdmBorkBork

Réponses:

5

Mathematica, 101 90 octets

Merci à ngenisis pour avoir économisé 11 octets!

TableForm[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}],TableHeadings->‌{f,g}]&

Le caractère environ un tiers du chemin est U + 2223 (3 octets). Fonction sans nom d'un nombre variable d'arguments, dont chacun est un entier différent de zéro, qui renvoie un TableFormobjet (sortie formatée) comme suit:

Sortie TableForm

f=#&@@@FactorInteger[1##]définit fêtre l'ensemble de tous les nombres premiers divisant l'une des entrées (de manière équivalente, divisant leur produit 1##), tandis que gla liste est constituée des entrées. Outer[If[#∣#2,Y,""]&,f,g]crée un tableau de Ys et de chaînes vides correspondant à la divisibilité (nous utilisons le jeton non défini Yau lieu d'une chaîne "Y"ou "*"pour enregistrer deux octets). Ensuite, nous utilisons TableForm[...,TableHeadings->‌{f,g}]pour formater le tableau résultant avec des en-têtes de ligne et de colonne appropriés.

Soumission précédente:

Grid[p=Prepend;Thread[q[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}]~p~g,f~p~""]]/.q->p]&
Greg Martin
la source
Vous pouvez laisser de côté le premier "".
Martin Ender
2
TableForm[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}],TableHeadings->{f,g}]&si les séparateurs sont autorisés
ngenisis
Et le second aussi si vous le changez en p[f,].
Martin Ender
Les lignes de quadrillage pour séparer les en-têtes sont autorisées.
AdmBorkBork
1
TableFormest cool, j'espère que cela restera dans ma boîte à outils!
Greg Martin
3

Gelée , 18 octets

PÆfQ0;ðḍ€+W}⁸;"o⁶G

Utilise 1au lieu de *, comme le permettent les règles.

Essayez-le en ligne!

Comment ça marche

PÆfQ0;ðḍ€+W}⁸;"o⁶G  Main link. Argument: A (array of integers greater than 1)

P                   Take the product of the integers in A.
 Æf                 Compute all prime factors (with multiplicity) of the product.
   Q                Unique; deduplicate the prime factors.
    0;              Prepend a 0. Let's call the result P.
      ð             Begin a new, dyadic chain. Left argument: P. Right argument: A
       ḍ€           Divisible each; for each p in P, test all integers in A for
                    divisibility by P. Yields one row of the shape of A for each p.
                    Note that the first element of P is 0, so the first row of the
                    resulting matrix contains only zeroes.
          W}        Wrap right; yield [A].
         +          Add the results to both sides. Because of how Jelly's auto-
                    vectorization works, this adds the first row of [A] (just A) to
                    the first row of the divisibility matrix (all zeroes) and
                    leaves the other rows untouched.
            ⁸;"     Prepend the elements of P to the corresponding rows of the
                    previous result.
               o⁶   OR space; replace all zeroes with spaces.
                 G  Grid; format the matrix as requested in the challenge spec.
Dennis
la source
2

Gelée , 25 23 octets

PÆfQ©ḍþµị⁾* ³;"Z⁶;®¤;"G

Essayez-le en ligne!

Comment?

Il peut être plus court à utiliser ÆEet à filtrer les lignes vides.

PÆfQ©ḍþµị⁾* ³;"Z⁶;®¤;"G - Main link: list of numbers, L
       µ                - monadic chain separation
P                       - product of L - multiply them all together
 Æf                     - prime factors (with repetitions, in ascending order)
   Q                    - unique items, maintaining order
                              - note that the product was performed to keep order
    ©                   - place in the register for later use, and yield
      þ                   - form the outer product of that and L using the dyad:
     ḍ                  -     isDivisor - 1 if divides, 0 if not
        ị⁾* <space      - index into "* " (1s to "*", 0s to " ")
            ³           - program's first input, L
             ;"         - zip with concatenation (column headers to the left)
               Z        - transpose (get it around the right way)
                   ¤    - nilad followed by link(s) as a nilad
                ⁶;®     - space (⁶) concatenated with (;) the register value (®)
                    ;"  - zip with concatenation (row labels to the left)
                      G - format the result as a grid (join items with spaces and
                                               rows with line feeds so they align)
                        - implicit print
Jonathan Allan
la source
2

JavaScript (ES6), 264 260 ... 179 173 octets

a=>[for(c of s=' '.repeat(w=a.slice(-1),i=0))if(!+(r=[i++?i:s,...i<2?a:a.map(x=>x%i&&c)].map(y=>(s+y).slice(-(w+1).length),a=a.map(d=x=>i<2|x%i?x:d(x/i))).join``))r].join`
`

Je pense que cette approche a dépassé de façon permanente celle récursive (actuellement 178 octets):

f=(a,i=0,w=a.slice(-1))=>i++-w?(+(r=[i<2?'':i,...i<2?a:a.map(x=>x%i&&' ')].map(y=>(' '.repeat(w)+y).slice(-(w+1).length)).join``)?'':r+`
`)+f(a.map(d=x=>i<2|x%i?x:d(x/i)),i,w):''

Utilise 0à la place de *, ce qui est permis par le défi.

Extrait de test

ETHproductions
la source
Si je ne me trompe pas, vous pouvez utiliser l' |opérateur dans l'instruction if, puisque vous comparez 2 booléens ...
Luke
@ Luke Hé, tu as raison. Je ne sais pas comment j'ai raté ça
ETHproductions
N'est-il pas plus court de déplacer le i<2chèque à l'intérieur de la .mapfonction?
Luke
@Luke Si vous changez moyenne ...i<2?a:a.map(x=>x%i&&c)de ...a.map(x=>i<2?x:x%i&&c), qui est pas plus courte. Si vous voulez le déplacer dans l' autre .map , peut-être ...
ETHproductions
2

Python 2 - 197 octets

Passé à Python 2 pour une gestion plus facile des entrées et permettant `` la conversion de chaînes. Utilise gmpy2pour générer le premier prime. Format de sortie toujours basé sur la soumission Python 3 précédente (voir ci-dessous), à savoir remplir une liste gavec des symboles et la formater.

import gmpy2
i=input()
n=len(i)+1
p=1;g=[' ']+i
while p<i[-1]:
 p=gmpy2.next_prime(p)
 t=['*'[m%p:]for m in i]
 if'*' in t:g+=[p]+t
print((('{:>%d}'%(len(`i[-1]`)+1)*n+'\n')*(len(g)/n)).format(*g))

Essayez-le en ligne!

Explication

Pour ceux qui ne veulent pas le décoder eux-mêmes.

import gmpy2                    # arithmetic library
i=input()
n=len(i)+1                      # saves bytes by not needing ()
                                # afterwards
p=1                             # starting number
g=[' ']+i                       # initialsing header row
while p<i[-1]:                  # looping until last character
  p=gmpy2.next_prime(p)         # get the next prime
  t=['*'[m%p:] for m in i]      # verify whether p is a 
                                # divisor of each number
  if'*'in t:g+=[p]+t            # if any divisor found, append
                                # p + divisors to g.
print(
    (('{:>%d}'%(len(`i[-1]`)+1) # compute right formatting element
                                # for length of last character + 1
        *n+'\n'                 # repeat for each input + once
                                # for the prime and add newline
     )*(len(g)/n)               # repeat row format until g
                                # can be inserted
    ).format(*g)                # format using g
)


précédent

Python 3 - 251 octets

Je suis sûr que quelqu'un peut faire mieux. Basé sur cette réponse pour générer les nombres premiers < k.

i=list(map(int,input().split(',')))
l=len(str(i[-1]))+1
n=len(i)+1
g=[0]+i+sum([l for l in [[k]+[j%k==0for j in i]for k in range(2,i[-1])if all(k%f for f in range(2,k))]if 1in l],[])
print((('{:>%d}'%l*n+'\n')*(len(g)//n)).format(*g).replace('0',' '))

Une version non expliquée et une explication suivront.

PidgeyUsedGust
la source
4
Bienvenue chez PPCG!
AdmBorkBork
1
Au lieu de i=list(map(int,input().split(','))), vous pouvez simplement le faire i=input()et prendre une entrée dans le formulaire [1, 2, 3, 4].
nedla2004
Merci, je ne le savais pas. Mais je vais quand même le retravailler plus tard :).
PidgeyUsedGust
Vous pouvez enregistrer 2 octets avec p=gmpy2.next_prime(p);t=['*'[m%p:]for m in i]et supprimer l'espace dans if"*" in.
Trelzevir
1

Mathematica, 165 octets

Plutôt verbeux - peut-être que quelqu'un peut en faire quelque chose:

(j=Join;a=#[[All,1]]&/@FactorInteger@#;b=Sort@DeleteDuplicates@Flatten@a;Grid[j[{j[{""},#]},Transpose@j[{b},Table[If[MemberQ[a[[t]],#],"*",""]&/@b,{t,Length@a}]]]])&
Martin
la source
1

Bash utilitaires GNU +, 134 133 132 125 123 octets

q=printf\ ;u=$q%9s
$u
$q%9d $@
echo
for p in $($u\\n `factor $@`|bc|sort -un)
{
$q%9d $p
for x;{ ((x%p))&&$u||$u X;}
echo
}

Essayez-le en ligne!

Mitchell Spector
la source
1

Python 2 , 181 179 octets

-2 octets grâce à FlipTack

n=input()
p=[]
t="%%%ss "%len(`n[-1]`)*-~len(n)
print t%(('',)+n)
i=2
while n[-1]/i:
 if all(i%j for j in p):
	p+=[i];s=['*'[m%i:]for m in n]
	if'*'in s:print t%tuple([i]+s)
 i+=1

L'entrée doit être un tuple.
Essayez-le en ligne!

Barre
la source
Fonctionne all(i%j for j in p)au lieu d'utiliser map?
FlipTack
@FlipTack oui, c'était mieux, mais j'ai changé quelque chose et j'ai oublié la mise à jour
Rod
1

Lot, 451 octets

@echo off
set/am=0,w=2,p=1
for %%n in (%*)do set/a"n=m-%%n,m+=(n>>31)*n
for /l %%i in (0,1,9)do set/am/=10,w+=!!m
set s=
for %%n in ("" %*)do set t=%%~n&call:t
set v=%*
:g
if not %s: =%==%p% echo%s%
if %m%==1 exit/b
set/at=p+=1,m=0
set s=
call:t
set v=&for %%n in (%v%)do set n=%%n&set t=&call:c
goto g
:c
set/ar=n%%p
if %r%==0 set/an/=p&set t=*&goto c
set/a"m|=n
set v=%v% %n%
:t
set t=           %t%
call set s=%%s%%%%t:~-%w%%%

Explication: Commence par calculer la largeur du champ wvia le maximum des valeurs d'entrée m. Génère la première ligne de sortie en remplissant une chaîne vide et les nombres d'entrée à la largeur wà l'aide du sous-programme t. Parcourt ensuite les entiers à partir de 2, générant la ligne de sortie en remplissant l'entier puis en appelant le sous-programme cpour remplir une chaîne vide ou un astérisque selon le cas pour chaque valeur, mais la ligne générée est ensuite ignorée si elle ne contient pas d'astérisques. Lorsque la sortie est générée, chaque valeur est divisée par l'entier jusqu'à ce qu'elle laisse un reste, de sorte que la boucle se termine lorsqu'aucune valeur n'est supérieure à 1.

Notez que le set v=obtient exécuté après que le %v%est substitué dans la forboucle sur la même ligne.

Neil
la source
1

Python 2 , 157 148 146 145 145 143 octets

def p(*t):print'%%%ds '%len(`x[-1]`)*len(t)%t
def f(x):k=m=1;p(' ',*x);exec"r=[n%k and' 'for n in x]\nif 0in m%k*r:p(k,*r)\nm*=k*k;k+=1;"*x[-1]

Utilise 0au lieu de *, comme le permettent les règles.

Essayez-le en ligne!

Contexte

Pour identifier les nombres premiers, nous utilisons un corollaire du théorème de Wilson :

corollaire du théorème de Wilson

Comment ça marche

La première ligne définit une fonction d'assistance.

def p(*t):print'%%%ds '%len(`x[-1]`)*len(t)%t

p prend un nombre variable d'arguments qu'il stocke dans le tuple t .

Le '%%%ds '%len(`x[-1]`)utilise une chaîne de format pour construire une chaîne de format; %%est un signe de pourcentage littéral, %dest un espace réservé pour l'entier qui len(`x[-1]`)renvoie, c'est-à-dire le nombre de chiffres du dernier élément de x (l'entrée, pas encore définie), et est littéral.

Si, par exemple, le dernier élément de x a trois chiffres, cela donne %3s , qui se *len(t)répète une fois pour chaque élément de x . Enfin, %tapplique cette chaîne de format au tuple t , construisant une chaîne d' éléments de t , séparés par des espaces et tous justifiés à droite jusqu'à une certaine longueur.

La deuxième ligne définit la soumission réelle: une fonction f qui prend une liste x en entrée. Après avoir remplacé l' execinstruction, qui exécute la chaîne qu'elle précède x[-1]fois, par une forboucle, nous obtenons le code suivant.

def f(x):
    k=m=1;p(' ',*x)
    for _ in range(x[-1]):
        r=[n%k and' 'for n in x]
        if 0in m%k*r:p(k,*r)
        m*=k*k;k+=1

Tout d'abord, f initialise k et m à 1 . Notez que (k - 1)! = 0! = 1 = m .

Ensuite, p(' ',*x)imprime un espace et les entiers en x , en utilisant la fonction p .

Maintenant, nous entrons dans la boucle pour imprimer la sortie restante.

Tout d'abord, r=[n%k and' 'for n in x]construit la liste des restes de chaque entier n dans x divisé par k . Les restes positifs, c'est-à-dire les restes qui ne correspondent pas à des multiples de k , sont véridiques et sont remplacés par un espace par and' '.

Ensuite, nous construisons m%k*r. Puisque m = (k - 1)! , par le corollaire du théorème de Wilson, ce sera simplement r si k est premier, mais une liste vide sinon. S'il y a au moins un 0 dans le résultat, c'est-à-dire si k est premier et qu'au moins un entier dans x est divisible par k , 0in m%k*rretournera True et sera p(k,*r)appelé, en imprimant k et les indicateurs de divisibilité: 0si divisible, un espace sinon .

Enfin, on multiplie m par et on incrémente k , donc la qualité m = (k - 1)! continue de tenir.

Dennis
la source
1

MATL , 31 octets

pYfu!Gy\~h0GhwvVZ{'(?<!\d)0'0YX

Cela utilise 1au lieu de *, comme le permet le défi.

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication ( obsolète )

p           % Implictly input array of numbers. Push product of array
Yf          % Prime factors as a row vector
u           % Keep only unique values
!           % Transpose into column vector
G           % Push input again
y           % Duplicate column vector of unique prime factors onto top
\           % Modulo, element-wise with broadcast
~           % Negate
h           % Concatenate horizontally
0           % Push 0
G           % Push input again
h           % Concatenate horizontally
w           % Swap
v           % Concatenate vertically
V           % Char array representation
Z{          % Convert to cell array of strings. Each row gives a string
'(?<!\d)0'  % Push this string: match '0' not preceded by a digit
0           % Push this string: '0' will be replaced by char 0
YX          % Regexp replace
            % Implicit inoput. Char 0 is displayed as space
Luis Mendo
la source
0

Raquette 176 octets

(let((p printf))(display"   ")(for((x nl))(p" ~a " x))(displayln"")(for((i '(2 3 7 11)))
(p"~a  " i)(for((j nl))(if(member i(prime-divisors j))(p" * ")(p"   ")))(displayln"")))

Non golfé:

(define (f nl)
  (let ((p printf))

    (display "   ")
    (for ((x nl))
      (p " ~a " x))
    (displayln "")

    (for ((i '(2 3 7 11)))
      (p "~a  " i)
      (for ((j nl))
        (if (member i (prime-divisors j))
            (p " * ")
            (p "   ")))
      (displayln ""))))

Essai:

(f '(6 9 14 22))

Sortie:

    6  9  14  22 
2   *     *  * 
3   *  *       
7         *    
11            * 
rnso
la source