Prime Divisor Table


28

Intro

In der Freizeitmathematik habe ich mit der Konstruktion einer Divisortabelle gespielt, um die Primteiler einer Reihe von Zahlen visuell zu vergleichen / gegenüberzustellen. Die eingegebenen Zahlen stehen oben als Spaltenbezeichnungen, die Primteiler links als Zeilenbezeichnungen und eine Markierung gibt an, wo sich die beiden in einer Reihe befinden.

Für die Eingabe wird beispielsweise 6, 9, 14, 22eine Tabelle ähnlich der folgenden erstellt:

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

Dies liegt daran, dass 6es Hauptteiler von 2und 3, 9Hauptteiler von 3und so weiter gibt.

Konstruktion

  • Die Tabelle ist so aufgebaut, dass die Eingabenummern Spaltenbezeichnungen bilden, die durch Leerzeichen und in aufsteigender Reihenfolge voneinander getrennt sind (Sie können davon ausgehen, dass sie vorsortiert sind), und die Primteiler links in aufsteigender Reihenfolge für jede Zeile aufgelistet sind, die die Zeile bildet Etiketten.
  • Beachten Sie, dass führende Leerzeichen in den Primteilern und Eingabezahlen erforderlich sein können, wenn die Zahlen unterschiedlich lang sind, damit alle Spalten die gleiche Breite haben und entsprechend ausgerichtet sind.
  • Jeder Teiler wird durch ein einzelnes *(oder ein anderes geeignetes ASCII-Zeichen Ihrer Wahl dargestellt, sofern für alle Vorkommen dasselbe Zeichen verwendet wird).
  • Mehrere Teiler werden ignoriert (z. B. 3 x 3 = 9gibt es nur einen *für diese Schnittmenge).
  • Das *kann überall horizontal in der Spalte platziert werden, solange es eindeutig ist (ich habe alle meine Beispiele *rechtsbündig).

Eingang

  • Jeweils eine Liste positiver Ganzzahlen in einem beliebigen Format>1 .
  • Sie können davon ausgehen, dass die Eingabe vorsortiert ist.
  • Die Eingabe hat garantiert nur eindeutige Werte.

Ausgabe

Die resultierende ASCII-Grafikdarstellung der Primteilertabelle.

Regeln

  • Führende oder nachfolgende Zeilenumbrüche oder Leerzeichen sind optional, sofern die Zeichen selbst korrekt ausgerichtet sind.
  • Wenn eine Trennlinie zwischen den Spalten- / Zeilenüberschriften und den Tabellendaten kürzer ist, ist dies ebenfalls zulässig.
  • Es ist entweder ein vollständiges Programm oder eine Funktion zulässig. Bei einer Funktion können Sie die Ausgabe zurückgeben, anstatt sie zu drucken.
  • Fügen Sie nach Möglichkeit einen Link zu einer Online-Testumgebung hinzu, damit die Benutzer Ihren Code ausprobieren können!
  • Standardlücken sind verboten.
  • Dies ist daher gelten alle üblichen Golfregeln, und der kürzeste Code (in Byte) gewinnt.

Beispiele

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
Können wir Trennlinien nach der oberen Reihe und der linken Spalte haben?
Genisis

@ngenisis Klar, das werde ich zulassen. Die genaue Formulierung des Tisches ist ziemlich offen, da dies nicht der genaue Grund für diese Herausforderung ist.
AdmBorkBork

Antworten:


5

Mathematica, 101-90 Bytes

Danke an ngenisis für das Speichern von 11 Bytes!

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

Das Zeichen ungefähr ein Drittel des Durchgangs ist U + 2223 (3 Bytes). Unbenannte Funktion einer variablen Anzahl von Argumenten, von denen jedes eine Ganzzahl ungleich Null ist, die ein TableFormObjekt (formatierte Ausgabe) wie folgt zurückgibt :

TableForm-Ausgabe

f=#&@@@FactorInteger[1##]Definiert fdie Menge aller Primzahlen, die eine der Eingaben aufteilen (gleichbedeutend mit der Aufteilung ihres Produkts 1##), während gdie Liste aus den Eingaben besteht. Outer[If[#∣#2,Y,""]&,f,g]erstellt eine Tabelle mit Ys und leeren Strings entsprechend der Teilbarkeit (wir verwenden das undefinierte Token Yanstelle eines Strings "Y"oder "*"um zwei Bytes zu speichern). Anschließend TableForm[...,TableHeadings->‌{f,g}]formatieren wir das resultierende Array mit den entsprechenden Zeilen- und Spaltenüberschriften.

Vorherige Einreichung:

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

Sie können den ersten weglassen "".
Martin Ender

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

Und das zweite auch, wenn Sie es ändern p[f,].
Martin Ender

Rasterlinien zum Trennen der Überschriften sind zulässig.
AdmBorkBork

1
TableFormist cool, hoffentlich bleibt das in meiner toolbox!
Greg Martin

3

Jelly , 18 Bytes

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

Verwendet 1statt *, wie es die Regeln erlauben.

Probieren Sie es online!

Wie es funktioniert

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

Jelly , 25 23 Bytes

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

Probieren Sie es online!

Wie?

Es kann durchaus kürzer sein ÆE, leere Zeilen zu verwenden und herauszufiltern.

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

Ich denke, dieser Ansatz hat jetzt den rekursiven (derzeit 178 Bytes) dauerhaft überschritten:

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

Verwendet 0anstelle von *, was durch die Herausforderung erlaubt ist.

Testschnipsel


Wenn ich mich nicht irre, können Sie den |Operator in der if-Anweisung verwenden, da Sie 2 Boolesche Werte vergleichen ...
Luke

@ Luke Hey, du hast recht. Nicht sicher, wie ich das verpasst habe
ETHproductions

Ist es nicht kürzer, den i<2Scheck innerhalb der .mapFunktion zu verschieben?
Luke

@Luke Wenn du Wechsel ...i<2?a:a.map(x=>x%i&&c)zu meinst , ...a.map(x=>i<2?x:x%i&&c)ist das nicht kürzer. Wenn Sie meinen, verschieben Sie es in die andere .map , vielleicht ...
ETHproductions

2

Python 2 - 197 Bytes

Zu Python 2 gewechselt, um die Eingabe zu vereinfachen und die Konvertierung von Zeichenfolgen zu ermöglichen. Verwendet gmpy2zur Erzeugung der nächsten Primzahl. Das Ausgabeformat basiert immer noch auf der vorherigen Python 3-Übermittlung (siehe unten), dh, es wird eine Liste gmit Symbolen gefüllt und formatiert.

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

Probieren Sie es online!

Erläuterung

Für diejenigen, die es nicht selbst entschlüsseln wollen.

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
)


Bisherige

Python 3 - 251 Bytes

Ich bin mir ziemlich sicher, dass es jemand besser machen kann. Basierend auf dieser Antwort zur Generierung der Primzahlen < 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',' '))

Ungolfed-Version und Erklärung folgen.


4
Willkommen bei PPCG!
AdmBorkBork

1
Stattdessen i=list(map(int,input().split(',')))können Sie einfach i=input()eine Eingabe in das Formular vornehmen [1, 2, 3, 4].
nedla2004

Danke, das wusste ich nicht. Aber ich werde es trotzdem später überarbeiten :).
PidgeyUsedGust

Sie können mit 2 Byte speichern p=gmpy2.next_prime(p);t=['*'[m%p:]for m in i]und den Speicherplatz in entfernen if"*" in.
Trelzevir

1

Mathematica, 165 Bytes

Ziemlich ausführlich - vielleicht kann jemand etwas damit anfangen:

(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

Python 2 , 181 179 Bytes

-2 Bytes dank 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

Die Eingabe muss ein Tupel sein.
Probieren Sie es online!


Funktioniert all(i%j for j in p)anstatt zu verwenden map?
FlipTack

@FlipTack ja, es war besser, aber ich habe etwas geändert und das Update vergessen
Rod

1

Batch, 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%%%

Erläuterung: Beginnt mit der Berechnung der Feldbreite wüber das Maximum der Eingabewerte m. Erzeugt die erste Ausgabezeile, indem eine leere Zeichenfolge und die eingegebenen Zahlen wmit der Unterroutine auf die Breite aufgefüllt werden t. Durchlaufen Sie dann die Ganzzahlen ab 2, erzeugen Sie die Ausgabezeile, indem Sie die Ganzzahl auffüllen und dann die Unterroutine aufrufen, cum je nach Wert eine leere Zeichenfolge oder ein Sternchen aufzufüllen. Die erzeugte Zeile wird jedoch übersprungen, wenn sie keine Sternchen enthält. Bei der Generierung der Ausgabe wird jeder Wert durch die Ganzzahl geteilt, bis ein Rest übrig bleibt. Die Schleife wird beendet, wenn kein Wert größer als 1 ist.

Beachten Sie, dass das set v=ausgeführt wird, nachdem das %v%in die forSchleife in derselben Zeile eingesetzt wurde.


1

Python 2 , 157 148 146 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]

Verwendet 0statt *, wie es die Regeln erlauben.

Probieren Sie es online!

Hintergrund

Um Primzahlen zu identifizieren, verwenden wir eine Folgerung aus Wilsons Theorem :

Folgerung aus Wilsons Satz

Wie es funktioniert

Die erste Zeile definiert eine Hilfsfunktion.

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

p akzeptiert eine variable Anzahl von Argumenten, die es im Tupel t speichert .

Das '%%%ds '%len(`x[-1]`)verwendet eine Formatzeichenfolge, um eine Formatzeichenfolge zu erstellen; %%ist ein literales Prozentzeichen, %dein Platzhalter für die zurückgegebene Ganzzahl len(`x[-1]`), dh die Anzahl der Stellen des letzten Elements in x (der Eingabe, die noch nicht definiert ist), und ist literal.

Wenn zum Beispiel das letzte Element von x drei Ziffern hat, ergibt dies %3s , was sich *len(t)einmal für jedes Element von x wiederholt . Schließlich %tgilt , dass die Format - String auf das Tupel t , eine Reihe von Konstruktion t ‚s Elemente, durch Leerzeichen getrennte und alle rechtsbündig auf eine bestimmte Länge.

Die zweite Zeile definiert die tatsächliche Einreichung: eine Funktion f , die eine Liste x als Eingabe nimmt. Nachdem Sie die execAnweisung, die den vorangestellten String ausführt x[-1], durch eine forSchleife ersetzt haben, erhalten Sie den folgenden Code.

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

Zunächst initialisiert f k und m auf 1 . Beachte, dass (k - 1)! = 0! = 1 = m .

Mit der Funktion p werden dann p(' ',*x)ein Leerzeichen und die ganzen Zahlen in x gedruckt .

Nun betreten wir die Schleife, um die verbleibende Ausgabe zu drucken.

Erstellt zunächst r=[n%k and' 'for n in x]die Liste der Reste jeder ganzen Zahl n in x geteilt durch k . Positive Reste, dh Reste, die nicht Vielfachen von k entsprechen , sind wahr und werden durch ein Leerzeichen ersetzt and' '.

Als nächstes konstruieren wir m%k*r. Da m = (k - 1)! In der Folge von Wilsons Theorem ist dies einfach r, wenn k Primzahl ist, aber eine leere Liste, wenn nicht. Wenn das Ergebnis mindestens eine 0 enthält , dh wenn k eine Primzahl ist und mindestens eine Ganzzahl in x durch k teilbar ist , 0in m%k*rwird True zurückgegeben und p(k,*r)aufgerufen, wobei k und die Teilbarkeitsindikatoren ausgegeben werden: 0Wenn teilbar, ein Leerzeichen, wenn nicht .

Schließlich multiplizieren wir m mit und erhöhen k , so dass die Qualität m = (k - 1) ist! hält weiter an.


1

MATL , 31 Bytes

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

Dies wird 1stattdessen verwendet *, wie es die Herausforderung zulässt.

Probieren Sie es online! Oder überprüfen Sie alle Testfälle .

Erklärung ( veraltet )

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

Schläger 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 ""))))

Testen:

(f '(6 9 14 22))

Ausgabe:

    6  9  14  22 
2   *     *  * 
3   *  *       
7         *    
11            * 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.