Стол первичного делителя


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

Mathematica, 101 90 байт

Спасибо ngenisis за сохранение 11 байтов!

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

Символ около трети пути - это U + 2223 (3 байта). Безымянная функция переменного числа аргументов, каждый из которых представляет собой ненулевое целое число, которое возвращает TableFormобъект (форматированный вывод) следующим образом:

Табличная форма вывода

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 логических значения ...
Лука,

@ Люк Эй, ты прав. Не уверен, как я пропустил это
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.
Трелзевир

1

Mathematica, 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

Python 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 да, это было лучше, но я кое-что изменил и забыл обновить это
Rod

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

Python 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 = т .

Затем p(' ',*x)печатает пробел и целые числа в x , используя функцию p .

Теперь мы входим в цикл для печати оставшегося вывода.

Сначала составляется r=[n%k and' 'for n in x]список остатков каждого целого числа n в x, разделенный на k . Положительные остатки, то есть остатки, которые не соответствуют кратным k , являются правдивыми и заменяются пробелом на 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"")))

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

Тестирование:

(f '(6 9 14 22))

Выход:

    6  9  14  22 
2   *     *  * 
3   *  *       
7         *    
11            * 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.