Tavolo Prime Divisor


28

Intro

Qualcosa con cui ho giocato in matematica ricreativa è stata la costruzione di un tavolo divisore per confrontare visivamente / contrastare i primi divisori di un insieme di numeri. L'insieme dei numeri di input si trova nella parte superiore come etichette di colonna, i divisori primi sono a sinistra come etichette di riga e un segno indica la posizione delle due linee.

Ad esempio, per l'input 6, 9, 14, 22verrebbe costruita una tabella simile alla seguente:

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

Questo perché 6ha divisori primi di 2e 3, 9ha divisori primi di 3e così via.

Costruzione

  • La tabella è costruita in modo tale che i numeri di input formino etichette di colonne separate da spazi e in ordine crescente (si può presumere che siano preordinate) e che i divisori primi siano elencati a sinistra in ordine crescente uno per riga formando la riga etichette.
  • Si noti che potrebbero essere richiesti spazi iniziali sui divisori primi e numeri di input se i numeri hanno lunghezze diverse, in modo che tutte le colonne abbiano la stessa larghezza e siano allineate in modo appropriato.
  • Ogni divisore è rappresentato da un singolo *(o altro carattere ASCII adatto di tua scelta, purché lo stesso carattere venga utilizzato per tutte le occorrenze).
  • I divisori multipli vengono ignorati (ad esempio, 3 x 3 = 9ma ce n'è solo uno *per quell'intersezione).
  • È *possibile posizionarlo ovunque orizzontalmente nella colonna, a condizione che sia inequivocabile (ho tutti i miei esempi con *allineato a destra).

Ingresso

  • Un elenco di numeri interi positivi in qualsiasi formato conveniente , ciascuno >1.
  • Si può presumere che l'input sia preordinato.
  • È garantito che l'input abbia solo valori univoci.

Produzione

La risultante rappresentazione artistica ASCII della tabella dei divisori primi.

Regole

  • Le nuove linee iniziali o finali o gli spazi bianchi sono tutti opzionali, purché i personaggi stessi si allineino correttamente.
  • Se è più breve avere una linea di divisione che separa le intestazioni di colonna / riga dai dati tabulari, anche questo è permesso.
  • È accettabile un programma completo o una funzione. Se una funzione, è possibile restituire l'output anziché stamparlo.
  • Se possibile, includi un collegamento a un ambiente di test online in modo che le persone possano provare il tuo codice!
  • Sono vietate le scappatoie standard .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

Esempi

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           *

1
Possiamo avere linee divisorie dopo la riga superiore e la colonna di sinistra?
ngenesi,

@ngenisis Certo, lo permetterò. La formulazione esatta del tavolo è piuttosto aperta, dal momento che non è l'esatta spinta di questa sfida.
AdmBorkBork,

Risposte:


5

Matematica, 101 90 byte

Grazie a ngenisis per aver salvato 11 byte!

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

Il personaggio a circa un terzo del percorso è U + 2223 (3 byte). Funzione senza nome di un numero variabile di argomenti, ognuno dei quali è un numero intero diverso da zero, che restituisce un TableFormoggetto (output formattato) in questo modo:

Output TableForm

f=#&@@@FactorInteger[1##]definisce fcome l'insieme di tutti i numeri primi che dividono gli input (equivalentemente, dividendo il loro prodotto 1##), mentre gl'elenco è costituito dagli input. Outer[If[#∣#2,Y,""]&,f,g]crea una tabella di se Ystringhe vuote corrispondenti alla divisibilità (usiamo il token indefinito Yinvece di una stringa "Y"o "*"per salvare due byte). Quindi usiamo TableForm[...,TableHeadings->‌{f,g}]per formattare l'array risultante con le intestazioni di riga e colonna appropriate.

Presentazione precedente:

Grid[p=Prepend;Thread[q[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}]~p~g,f~p~""]]/.q->p]&

Puoi tralasciare il primo "".
Martin Ender,

2
TableForm[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}],TableHeadings->{f,g}]&se i divisori sono ammessi
ngenisi

E anche il secondo se lo cambi p[f,].
Martin Ender,

Sono consentite linee di griglia per separare le intestazioni.
AdmBorkBork,

1
TableFormè bello, speriamo che rimanga nella mia cassetta degli attrezzi!
Greg Martin,

3

Gelatina , 18 byte

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

Utilizza 1invece di* , come consentito dalle regole.

Provalo online!

Come funziona

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.

2

Gelatina , 25 23 byte

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

Provalo online!

Come?

Potrebbe essere più breve utilizzare ÆEe filtrare le righe vuote.

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

2

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

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

Penso che questo approccio abbia superato definitivamente quello ricorsivo (attualmente 178 byte):

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

Utilizza 0al posto di *, che è consentito dalla sfida.

Test snippet


Se non sbaglio, puoi usare l' |operatore nell'istruzione if, dato che stai confrontando 2 booleani ...
Luca

@Luke Ehi, hai ragione. Non sono sicuro di come mi sia perso
ETHproductions

Non è più breve spostare il i<2segno di spunta all'interno della .mapfunzione?
Luca,

@Luke Se intendi cambiare ...i<2?a:a.map(x=>x%i&&c)in ...a.map(x=>i<2?x:x%i&&c), non è più breve. Se vuoi dire spostalo nell'altro .map , forse ...
ETHproductions

2

Python 2 - 197 byte

Passato a Python 2 per una più facile gestione dell'input e consentendo `` per la conversione di stringhe. Utilizza gmpy2per generare il prossimo primo. Il formato di output si basa ancora sulla precedente presentazione di Python 3 (vedi sotto), vale a dire riempire un elenco gcon simboli e formattarlo.

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

Provalo online!

Spiegazione

Per coloro che non vogliono decodificarlo da soli.

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
)


Precedente

Python 3 - 251 byte

Abbastanza sicuro che qualcuno possa fare di meglio. Sulla base di questa risposta per generare i numeri primi < 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',' '))

Seguiranno la versione non scritta e la spiegazione.


4
Benvenuti in PPCG!
AdmBorkBork,

1
Invece di i=list(map(int,input().split(','))), potresti semplicemente fare i=input()e prendere input nel modulo [1, 2, 3, 4].
nedla2004,

Grazie, non lo sapevo. Ma lo rivedrò più tardi comunque :).
PidgeyUsedFust

È possibile salvare 2 byte con p=gmpy2.next_prime(p);t=['*'[m%p:]for m in i]e rimuovere lo spazio in if"*" in.
Trelzevir,

1

Mathematica, 165 byte

Piuttosto dettagliato - forse qualcuno può farci qualcosa:

(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}]]]])&

1

Utilità Bash + GNU, 134 133 132 125 123 byte

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
}

Provalo online!


1

Python 2 , 181 179 byte

-2 byte grazie a 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'input deve essere una tupla.
Provalo online!


Funziona all(i%j for j in p)invece di usare map?
FlipTack

@ FlipTack sì, era meglio, ma ho cambiato qualcosa e ho dimenticato l'aggiornamento questo
Rod

1

Lotto, 451 byte

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

Spiegazione: Inizia calcolando la larghezza del campo wtramite il massimo dei valori di input m. Genera la prima riga di output riempiendo una stringa vuota e i numeri di input fino alla larghezzaw usando la subroutine t. Quindi scorre gli interi a partire da 2, generando la linea di output riempiendo il numero intero e quindi chiamando la subroutinec per riempire una stringa vuota o un asterisco come appropriato per ciascun valore, tuttavia la linea generata viene quindi saltata se non contiene asterischi. Man mano che viene generato l'output, ogni valore viene diviso per l'intero fino a quando non lascia un resto, quindi il ciclo termina quando nessun valore è maggiore di 1.

Si noti che set v=viene eseguito dopo che il %v%viene sostituito nel forloop sulla stessa riga.


1

Python 2 , 157 148 146 145 143 byte

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]

Utilizza 0invece di* , come consentito dalle regole.

Provalo online!

sfondo

Per identificare i numeri primi, usiamo un corollario del teorema di Wilson :

corollario del teorema di Wilson

Come funziona

La prima riga definisce una funzione di supporto.

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

p accetta un numero variabile di argomenti che memorizza nella tupla t .

Il '%%%ds '%len(`x[-1]`)utilizza una stringa di formato per costruire una stringa di formato; %%è un segno di percentuale letterale, %dè un segnaposto per l'intero che len(`x[-1]`)restituisce, ovvero il numero di cifre dell'ultimo elemento in x (l'input, non ancora definito) ed è letterale.

Se, ad esempio, l'ultimo elemento di x ha tre cifre, questo produce %3s , che si *len(t)ripete una volta per ogni elemento di x . Infine, %tapplica quella stringa di formato alla tupla t , costruendo una stringa di elementi t , separati da spazio e giustificati a destra per una certa lunghezza.

La seconda riga definisce l'invio effettivo: una funzione f che accetta un elenco x come input. Dopo aver sostituito l' execistruzione, che esegue la stringa che precede x[-1]volte, con un forciclo, otteniamo il seguente codice.

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

Innanzitutto, f inizializza k e m su 1 . Nota che (k - 1)! = 0! = 1 = m .

Quindi, p(' ',*x)stampa uno spazio e gli interi in x , utilizzando la funzione p .

Ora, entriamo nel loop per stampare l'output rimanente.

In primo luogo, r=[n%k and' 'for n in x]costruisce l'elenco dei resti di ogni intero n in x diviso per k . I resti positivi, cioè i resti che non corrispondono ai multipli di k , sono veritieri e vengono sostituiti da uno spazio con and' '.

Successivamente, costruiamo m%k*r. Poiché m = (k - 1)! , secondo il corollario del teorema di Wilson, questo sarà semplicemente r se k è primo, ma in caso contrario una lista vuota. Se nel risultato c'è almeno uno 0 , ovvero se k è primo e almeno un numero intero in x è divisibile per k , 0in m%k*rrestituirà True e p(k,*r)verrà chiamato, stampando k e gli indicatori di divisibilità:0 se divisibile, uno spazio in caso contrario .

Infine, moltiplichiamo m per e incrementiamo k , quindi la qualità m = (k - 1)! continua a trattenere.


1

MATL , 31 byte

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

Questo utilizza 1invece di* , come consentito dalla sfida.

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione ( obsoleta )

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

0

Racchetta 176 byte

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

test:

(f '(6 9 14 22))

Produzione:

    6  9  14  22 
2   *     *  * 
3   *  *       
7         *    
11            * 
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.