Таблиця головного дільника


28

Вступ

Щось, з чим я бавився в рекреаційній математиці, - це побудова таблиці дільниць для візуального порівняння / порівняння простих дільників набору чисел. Набір вхідних номерів розташований вгорі, як мітки стовпців, ліві роздільники розташовані ліворуч як мітки рядків, а позначка вказує, де два рядки вгору.

Наприклад, для введення буде 6, 9, 14, 22побудована таблиця, подібна до наступних:

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

Це тому, що 6має прості дільники 2і 3, 9має прості дільники 3тощо.

Будівництво

  • Таблиця побудована таким чином, що вхідні номери утворюють мітки стовпців, які розділені пробілами та у порядку зростання (можна припустити, що вони попередньо відсортовані), а прості дільники перелічені зліва у порядку зростання, по одному на рядок, що утворює рядок етикетки.
  • Зауважте, що провідні пробіли на простих дільниках та номерах вводу можуть знадобитися, якщо числа різної довжини, так що всі стовпці однакової ширини та лінійки належним чином.
  • Кожен дільник представлений одним *(або іншим відповідним символом ASCII на ваш вибір, якщо той самий символ використовується для всіх подій).
  • Кілька дільників ігноруються (наприклад, 3 x 3 = 9але *для цього перетину є лише один ).
  • *Можуть бути розміщені в будь-якому місці в горизонтальному положенні в колоні, так довго , як це однозначна ( у мене є всі мої приклади з *вирівнюванням по правому краю).

Вхідні дані

  • Список натуральних чисел у будь-якому зручному форматі , кожен >1.
  • Можна припустити, що вхід попередньо відсортовано.
  • Гарантія має лише унікальні значення.

Вихідні дані

Отримане ASCII художнє зображення таблиці простих дільниць.

Правила

  • Провідні чи кінцеві рядки чи пробіли - це необов’язково, до тих пір, поки самі символи правильно вишикуються.
  • Якщо коротше мати роздільник, що відокремлює заголовки стовпців / рядків від табличних даних, це теж дозволено.
  • Прийнятна або повна програма, або функція. Якщо функція, ви можете повернути вихід, а не надрукувати його.
  • Якщо можливо, додайте посилання на онлайн-тестування, щоб люди могли спробувати ваш код!
  • Стандартні лазівки заборонені.
  • Це тому діють усі звичайні правила гольфу, і найкоротший код (у байтах) виграє.

Приклади

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
Чи можемо ми мати розділові лінії після верхнього ряду та лівого стовпця?
ngenisis

@ngenisis Звичайно, я дозволю це. Точна формулювання таблиці досить відкрита, оскільки це не є точною метою цього завдання.
AdmBorkBork

Відповіді:


5

Математика, 101 90 байт

Завдяки ngenisis за економію 11 байт!

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

Характер близько третини шляху через це U + 2223 (3 байта). Безіменна функція змінної кількості аргументів, кожен з яких є ненульовим цілим числом, яке повертає TableFormоб'єкт (відформатований вихід) так:

Вихід таблиціForm

f=#&@@@FactorInteger[1##]визначає fсукупність усіх простих чисел, що розділяють будь-який із входів (еквівалентно, що ділить їх добуток 1##), тоді gяк список складається з входів. Outer[If[#∣#2,Y,""]&,f,g]складає таблицю Ys і порожніх рядків, що відповідають розділенню (ми використовуємо невизначений маркер Yзамість рядка "Y"або "*"для збереження двох байтів). Потім ми використовуємо TableForm[...,TableHeadings->‌{f,g}]для форматування отриманого масиву з відповідними заголовками рядків і стовпців.

Попереднє подання:

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

Ви можете залишити перший "".
Мартін Ендер

2
TableForm[Outer[If[#∣#2,Y,""]&,f=#&@@@FactorInteger[1##],g={##}],TableHeadings->{f,g}]&якщо роздільники дозволені
ngenisis

І друге також, якщо ви його змінили p[f,].
Мартін Ендер

Для розділення заголовків дозволено сітки рядків.
AdmBorkBork

1
TableFormкласно, сподіваюсь, що залишиться в моїй панелі інструментів!
Грег Мартін

3

Желе , 18 байт

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

Використовується 1замість *, як це дозволено правилами.

Спробуйте в Інтернеті!

Як це працює

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

Желе , 25 23 байт

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

Спробуйте в Інтернеті!

Як?

Використання ÆEта фільтрування порожніх рядків може бути коротшим .

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 байт

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

Я думаю, що зараз цей підхід назавжди перевищив рекурсивний (зараз 178 байт):

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

Використовує 0замість цього *, що дозволено викликом.

Фрагмент тесту


Якщо я не помиляюся, ви можете використовувати |оператора в операторі if, оскільки ви порівнюєте 2 булевих ...
Лука

@Luke Гей, ти маєш рацію. Не впевнений, як я пропустив це
ETHproductions

Чи не коротше переміщення i<2чека всередині .mapфункції?
Лука

@Luke Якщо ви маєте в виду зміни ...i<2?a:a.map(x=>x%i&&c)в ...a.map(x=>i<2?x:x%i&&c), це не коротше. Якщо ви хочете сказати, перенесіть його в інше .map , можливо ...
ETHproductions

2

Python 2 - 197 байт

Переключено на Python 2 для легшого керування введенням і дозволяє `` для перетворення рядків. Використовує gmpy2для створення наступного простого. Формат виводу все ще заснований на попередньому поданні Python 3 (див. Нижче), а саме заповнення списку gсимволами та форматування його.

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

Спробуйте в Інтернеті!

Пояснення

Для тих, хто не хоче сам їх розшифрувати.

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
)


Попередній

Python 3 - 251 байт

Досить впевнений, що хтось може зробити краще. Виходячи з цієї відповіді для генерації праймес < 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',' '))

Невикористана версія та пояснення будуть наступними.


4
Ласкаво просимо до PPCG!
AdmBorkBork

1
Замість цього i=list(map(int,input().split(',')))можна просто зробити i=input()та взяти вклад у форму [1, 2, 3, 4].
nedla2004

Спасибі, я цього не знав. Але я все одно перероблю це пізніше :).
PidgeyUsedGust

Ви можете зберегти 2 байти за допомогою p=gmpy2.next_prime(p);t=['*'[m%p:]for m in i]та видалити пробіл у if"*" in.
Trelzevir

1

Математика, 165 байт

Швидше багатослівний - можливо, хтось може щось з цим зробити:

(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

Пітон 2 , 181 179 байт

-2 байти завдяки 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

Вхід повинен бути кортежем.
Спробуйте в Інтернеті!


Чи all(i%j for j in p)працює замість використання map?
FlipTack

@FlipTack так, було краще, але я щось змінив і забув оновити це
пд

1

Пакетна, 451 байт

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

Пояснення: Починається з обчислення ширини поля wчерез максимум вхідних значень m. Створює перший рядок виводу шляхом додавання порожнього рядка та вхідних чисел на ширину wза допомогою підпрограми t. Потім прокручуємо цілі числа, починаючи з 2, генеруючи рядок виведення, додаючи ціле число, а потім викликаючи підпрограму, cщоб ввести порожній рядок або зірочку відповідно до кожного значення, проте згенерований рядок потім пропускається, якщо він не містить зірочок. Коли генерується вихід, кожне значення ділиться на ціле число, поки воно не залишить залишок, тому цикл закінчується, коли жодне значення не перевищує 1.

Зверніть увагу , що set v=запускається на виконання після%v% підставляється в forпетлю на одній і тій же лінії.


1

Пітон 2 , 157 148 146 145 143 байт

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]

Використовується 0замість *, як це дозволено правилами.

Спробуйте в Інтернеті!

Фон

Для ідентифікації простих чисел ми використовуємо суперечку теореми Вілсона :

наслідок теореми Вілсона

Як це працює

Перший рядок визначає функцію помічника.

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

p приймає змінну кількість аргументів, які він зберігає в кортежі t .

'%%%ds '%len(`x[-1]`)Використовує формат рядка , щоб побудувати рядок формату; %%- буквальний знак відсотка, %dє заповнювачем для цілого числа, яке len(`x[-1]`)повертається, тобто кількість цифр останнього елемента в x (вхід, ще не визначений), і є буквальним.

Якщо, наприклад, останній елемент x має три цифри, це виходить %3s , що *len(t)повторюється один раз для кожного елемента x . Нарешті, %tзастосовує цей рядок формату до кортежу t , будуючи рядок з елементів t , розділених пробілом і все правильно виправданих до певної довжини.

Другий рядок визначає фактичне подання: функцію f, яка приймає список x як вхідний. Після заміни execоператора, який виконує рядок, який він передує x[-1]разів, forциклом, ми отримуємо наступний код.

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

По-перше, f ініціалізує k і m до 1 . Зауважимо, що (k - 1)! = 0! = 1 = m .

Потім p(' ',*x)друкує пробіл та цілі числа у x , використовуючи функцію p .

Тепер ми вводимо цикл для друку решти результатів.

По-перше, r=[n%k and' 'for n in x]будує список залишків кожного цілого числа n у x, поділене на k . Позитивні залишки, тобто залишки, які не відповідають кратним k , є truthy та їх замінюють пробілом на and' '.

Далі будуємо m%k*r. Оскільки m = (k - 1)! , за наслідком теореми Вілсона, це буде просто r, якщо k є простим, але порожній список, якщо ні. Якщо в результаті є щонайменше один 0 , тобто, якщо k є простим і хоча б одне ціле число в x ділиться на k , 0in m%k*rповернеться True і p(k,*r)отримає виклик, друкуючи k та індикатори поділу: 0якщо ділиться, пробіл, якщо ні .

Нарешті, множимо m на і приріст k , тому якість m = (k - 1)! продовжує триматися.


1

MATL , 31 байт

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

Для цього використовується 1замість *дозволеного викликом.

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення ( застаріле )

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

Ракетка 176 байт

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

Безголівки:

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

Тестування:

(f '(6 9 14 22))

Вихід:

    6  9  14  22 
2   *     *  * 
3   *  *       
7         *    
11            * 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.