Prime Divisor Table

28

Introdução

Algo com o qual eu brinquei em matemática recreativa foi a construção de uma tabela divisória para comparar / contrastar visualmente os divisores primos de um conjunto de números. O conjunto de números de entrada está na parte superior como rótulos de coluna, os divisores principais estão à esquerda como rótulos de linha e uma marca indica onde os dois estão alinhados.

Por exemplo, para entrada, 6, 9, 14, 22uma tabela semelhante à seguinte seria construída:

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

Isso ocorre porque 6possui divisores primários de 2e 3, 9possui divisores primários de 3e assim por diante.

Construção

  • A tabela é construída de forma que os números de entrada formem rótulos de colunas separados por espaços e em ordem crescente (você pode assumir que eles são pré-classificados) e os divisores principais são listados à esquerda em ordem crescente, um por linha que forma a linha etiquetas.
  • Observe que os espaços iniciais nos divisores primos e nos números de entrada podem ser necessários se os números tiverem comprimentos diferentes, para que todas as colunas tenham a mesma largura e se alinhem adequadamente.
  • Cada divisor é representado por um único *(ou outro caractere ASCII adequado de sua escolha, desde que o mesmo caractere seja usado para todas as ocorrências).
  • Vários divisores são ignorados (por exemplo, 3 x 3 = 9mas há apenas um *para essa interseção).
  • Ele *pode ser colocado em qualquer lugar horizontalmente na coluna, desde que não seja ambíguo (tenho todos os meus exemplos com o *alinhado à direita).

Entrada

  • Uma lista de números inteiros positivos em qualquer formato conveniente , cada um >1.
  • Você pode assumir que a entrada é pré-classificada.
  • A entrada é garantida para ter apenas valores exclusivos.

Saída

A representação artística ASCII resultante da tabela do divisor principal.

Regras

  • Novas linhas à esquerda ou à direita ou espaços em branco são opcionais, desde que os próprios caracteres estejam alinhados corretamente.
  • Se for mais curto ter uma linha divisória que separa os títulos das colunas / linhas dos dados tabulares, isso também é permitido.
  • Um programa completo ou uma função são aceitáveis. Se uma função, você pode retornar a saída em vez de imprimi-la.
  • Se possível, inclua um link para um ambiente de teste on-line para que as pessoas possam experimentar seu código!
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.

Exemplos

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
fonte
1
Podemos ter linhas divisórias após a linha superior e a coluna esquerda?
Ngenisis
@ngenisis Claro, eu vou permitir isso. A formulação exata da tabela é bastante aberta, já que esse não é o objetivo exato desse desafio.
AdmBorkBork

Respostas:

5

Mathematica, 101 90 bytes

Obrigado a ngenisis por salvar 11 bytes!

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

O caractere cerca de um terço do caminho é U + 2223 (3 bytes). Função sem nome de um número variável de argumentos, cada um dos quais é um número inteiro diferente de zero, que retorna um TableFormobjeto (saída formatada) da seguinte forma:

Saída de TableForm

f=#&@@@FactorInteger[1##]define fcomo o conjunto de todos os números primos que dividem qualquer uma das entradas (equivalentemente, dividindo seu produto 1##), enquanto gé a lista que consiste nas entradas. Outer[If[#∣#2,Y,""]&,f,g]cria uma tabela de Ys e cadeias vazias correspondentes à divisibilidade (usamos o token indefinido em Yvez de uma cadeia "Y"ou "*"para salvar dois bytes). Em seguida, usamos o TableForm[...,TableHeadings->‌{f,g}]formato da matriz resultante com os títulos de linha e coluna apropriados.

Submissão anterior:

Grid[p=Prepend;Thread[q[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}]~p~g,f~p~""]]/.q->p]&
Greg Martin
fonte
Você pode deixar de fora o primeiro "".
Martin Ender
2
TableForm[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}],TableHeadings->{f,g}]&se divisores são permitidos
ngenisis
E o segundo também, se você mudar para p[f,].
Martin Ender
Linhas de grade para separar os cabeçalhos são permitidas.
AdmBorkBork
1
TableFormé legal, espero que fique na minha caixa de ferramentas!
Greg Martin
3

Gelatina , 18 bytes

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

Usa em 1vez de *, conforme permitido pelas regras.

Experimente online!

Como funciona

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
fonte
2

Geléia , 25 23 bytes

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

Experimente online!

Quão?

Pode ser mais curto usar ÆEe filtrar linhas vazias.

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
fonte
2

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

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

Eu acho que essa abordagem agora excedeu permanentemente a recursiva (atualmente 178 bytes):

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):''

Usa 0no lugar de *, o que é permitido pelo desafio.

Snippet de teste

ETHproductions
fonte
Se não me engano, você pode usar o |operador na instrução if, já que você está comparando 2 booleans ...
Lucas
@ Lucas Ei, você está certo. Não sei como eu perdi isso
ETHproductions
Não é mais curto mover a i<2verificação dentro da .mapfunção?
10247 Luke
@ Lucas Se você quer dizer mudar ...i<2?a:a.map(x=>x%i&&c)para ...a.map(x=>i<2?x:x%i&&c), não é mais curto. Se você quer dizer movê-lo para o outro .map , talvez ...
ETHproductions
2

Python 2 - 197 bytes

Alterado para Python 2 para facilitar o manuseio de entrada e permitir `` a conversão de strings. Usa gmpy2para gerar o próximo prime. Formato de saída ainda baseado no envio anterior do Python 3 (veja abaixo), ou seja, preenchendo uma lista gcom símbolos e formatando-a.

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

Experimente online!

Explicação

Para aqueles que não querem decodificar eles mesmos.

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
)


Anterior

Python 3-251 bytes

Tenho certeza que alguém pode fazer melhor. Com base nesta resposta para gerar os números primos < 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',' '))

A versão não-gasta e explicação seguirão.

PidgeyUsedGust
fonte
4
Bem-vindo ao PPCG!
AdmBorkBork
1
Em vez de i=list(map(int,input().split(','))), você pode simplesmente fazer i=input()e receber informações no formulário [1, 2, 3, 4].
precisa saber é o seguinte
Obrigado, eu não sabia disso. Mas vou retrabalhá-lo mais tarde de qualquer maneira :).
precisa saber é o seguinte
Você pode salvar 2 bytes com p=gmpy2.next_prime(p);t=['*'[m%p:]for m in i]e removendo o espaço if"*" in.
Trelzevir
1

Mathematica, 165 bytes

Bastante detalhado - talvez alguém possa fazer algo com isso:

(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
fonte
1

Utilitários Bash + GNU, 134 133 132 125 123 bytes

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
}

Experimente online!

Mitchell Spector
fonte
1

Python 2 , 181 179 bytes

-2 bytes graças ao 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

A entrada deve ser uma tupla.
Experimente online!

Cajado
fonte
Funciona em all(i%j for j in p)vez de usar map?
21417 FlipTack
@FlipTack Sim, era melhor, mas eu mudei alguma coisa e esqueceu a atualização esta
Rod
1

Lote, 451 bytes

@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%%%

Explicação: Inicia calculando a largura do campo watravés do máximo dos valores de entrada m. Gera a primeira linha de saída preenchendo uma string vazia e os números de entrada na largura wusando a sub-rotina t. Em seguida, percorre os números inteiros começando em 2, gerando a linha de saída preenchendo o número inteiro e chamando a sub c- rotina para preencher uma sequência vazia ou um asterisco conforme apropriado para cada valor, no entanto, a linha gerada é ignorada se não contiver asteriscos. À medida que a saída é gerada, cada valor é dividido pelo número inteiro até deixar um restante, portanto o loop termina quando nenhum valor é maior que 1.

Observe que os set v=executados após o %v%são substituídos no forloop na mesma linha.

Neil
fonte
1

Python 2 , 157 148 146 145 145 143 bytes

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]

Usa em 0vez de *, conforme permitido pelas regras.

Experimente online!

fundo

Para identificar números primos, usamos um corolário do teorema de Wilson :

corolário do teorema de Wilson

Como funciona

A primeira linha define uma função auxiliar.

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

p recebe um número variável de argumentos que armazena na tupla t .

O '%%%ds '%len(`x[-1]`)usa uma string de formato para construir uma string de formato; %%é um sinal de porcentagem literal, %dé um espaço reservado para o número inteiro que len(`x[-1]`)retorna, ou seja, o número de dígitos do último elemento em x (a entrada, ainda não definida) e é literal.

Se, por exemplo, o último elemento de x tiver três dígitos, isso produzirá %3s , que se *len(t)repete uma vez para cada elemento de x . Por fim, %taplica essa sequência de formatação à tupla t , construindo uma sequência de elementos de t , separados por espaço e todos justificados à direita para um determinado comprimento.

A segunda linha define a submissão real: uma função f que recebe uma lista x como entrada. Depois de substituir a execinstrução, que executa a string que antecede os x[-1]tempos, com um forloop, obtemos o código a seguir.

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

Primeiro, f inicializa k e m para 1 . Note que (k - 1)! = 0! = 1 = m .

Em seguida, p(' ',*x)imprime um espaço e os números inteiros em x , usando a função p .

Agora, entramos no loop para imprimir a saída restante.

Primeiro, r=[n%k and' 'for n in x]constrói a lista dos restantes de cada número inteiro n em x dividido por k . Restos positivos, isto é, restos que não correspondem a múltiplos de k , são verdadeiros e são substituídos por um espaço por and' '.

A seguir, construímos m%k*r. Como m = (k - 1)! , pelo corolário do teorema de Wilson, este será simplesmente r se k for primo, mas uma lista vazia se não. Se houver pelo menos um 0 no resultado, ou seja, se k for primo e pelo menos um número inteiro em x for divisível por k , 0in m%k*rretornará True e será p(k,*r)chamado, imprimindo k e os indicadores de divisibilidade: 0se divisível, um espaço se não .

Finalmente, multiplicamos m por e incrementamos k , para que a qualidade m = (k - 1)! continua a segurar.

Dennis
fonte
1

MATL , 31 bytes

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

Isso usa em 1vez de *, conforme permitido pelo desafio.

Experimente online! Ou verifique todos os casos de teste .

Explicação ( desatualizada )

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
fonte
0

Raquete 176 bytes

(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"")))

Ungolfed:

(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 ""))))

Teste:

(f '(6 9 14 22))

Saída:

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