Псевдофакторний


39

Є досить цікаве число, яке іноді виявляється в математичних задачах або загадках. Псевдофакторний (N) є найменшим (тобто найнижчим) загальним кратним чисел від 1 до N; Іншими словами, це найменше число, яке містить усі числа від 1 до N в якості факторів.

Наприклад, псевдофакторний (7) = 3 * 4 * 5 * 7, що таке саме, як 7! за винятком того, що 2 та 6 видалено, оскільки вони містяться в інших термінах.

Напишіть програму для обчислення псевдофакторних (N) і, як завжди, виграє найкоротший код.

Ось короткий список для вашого використання. Більше тестових випадків можна знайти в OEIS під A003418 .

Фактор:

  1. 1
  2. 2
  3. 6
  4. 24
  5. 120
  6. 720
  7. 5040

Псевдофактор:

  1. 1
  2. 2
  3. 6
  4. 12
  5. 60
  6. 60
  7. 420

6
Я не впевнений, що розумію, чому 2і 6були вилучені зі списку кратних. Можете, будь ласка, уточнити правила?
Малтісен

2
@Mattysen, psuedofactorial (N) - найменше число, яке має числа від 1 до N в якості факторів (найменше загальне кратне число цих чисел). Це технічне визначення, але те, як я його написав, дещо підказувало, що воно схоже на факторіальне.
Тоні Рут


4
Ласкаво просимо до головоломки програмування та коду для гольфу! Це приємний перший виклик!
Алекс А.

1
Ваш перший виклик потрапив на вершину HNQ. Приємно!
Даніель М.

Відповіді:




8

C (з x86), 52 байти

d(n,k,b,t){for(b=k=1;b;++k)for(t=n,b=0;t;b+=k%t--);}

Перевіряє числа від 1 вгору. Кожне число ділить його на всі числа від n вниз до 1 і підсумовує залишки. Зупиняється, коли сума дорівнює 0.

Використання:

main()
{
    printf("%d\n", d(7)); // outputs 420
}

Не очевидно, як він повертає значення (немає returnтвердження).

Конвенція виклику для x86 говорить, що функція повинна повернути своє значення в eaxрегістрі. Зручно, що інструкція поділу idivочікує його введення eaxі виводить результат у eax(коефіцієнт) та edx(залишок). Остання ітерація ділиться kна 1, тому eaxбуде містити правильне значення, коли функція закінчується.

Це працює лише з увімкненими оптимізаціями (у режимі налагодження він виводить 421).


Як уникнути того, що ви не декларуєте тип n, k, b і t?
Тоні Рут

У C є правило за замовчуванням - всі опущені типи intза замовчуванням (включаючи повернене значення). Він працює для аргументів функції, якщо вони оголошені за допомогою так званого синтаксису "старого стилю". Декларація з чітко визначеними типами будеint d(n,k,b,t) int n,k,b,t; {...}
anatolyg

якщо ви скористаєтесь умовою виклику, тоді це дійсно має бути позначене "C (cdecl)", а не просто "C"
Стів Кокс

@SteveCox Обидва cdeclі stdcallвикористовують один і той же метод для повернення значення, тому я думаю x86, що достатньо
anatolyg

7

Haskell, 20 байт

f x=foldr1 lcm[1..x]

Приклад використання: map f [1..7]-> [1,2,6,12,60,60,420].

lcmТрик в Haskell.


6

Python + SymPy, 45 байт

import sympy
lambda n:sympy.lcm(range(1,n+1))

Досить зрозуміло.


Python 2, 57 54 байт

i=r=input();exec't=r\nwhile r%i:r+=t\ni-=1;'*r;print r

Перевірте це на Ideone .

Як це працює

Вхід зберігається у змінних i та r .

execвиконує наступний код r разів.

t=r
while r%i:r+=t
i-=1

Хоча я змінюється від r до 1 , ми додаємо початкове значення r (зберігається в t ) стільки разів, скільки потрібно, щоб r себе створити кратне i . Результат, очевидно, кратний t .

Кінцеве значення r , таким чином, кратне всіх цілих чисел у діапазоні [1, ..., n] , де n - вхід.


1
Без використання сторонніх бібліотек чи execхитрощів є рішення, що має 78 байт: from fractions import*;lambda n:reduce(lambda x,y:x*y/gcd(x,y),range(1,n+1),1) Використовує той факт lcm(x,y) = x*y/gcd(x,y).
Бакуріу

6

Пітон, 46 байт

g=lambda n,c=0:n<1or(c%n<1)*c or g(n,c+g(n-1))

Дивлячись на декількох cз g(n-1)безпосередньо. Я мав, хоча раніше, цей метод помилково знайде 0 як кратне що-небудь, але orкоротке замикання або (c%n<1)*cпропустить c==0також, тому що 0 - це Falsey.


50 байт:

g=lambda n,i=1:n<1or(i*n%g(n-1)<1)*i*n or g(n,i+1)

Як рішення Денніса , але як рекурсивна функція. Обчисливши g(n-1), шукає найменшого кратного i*nз nщо також кратно g(n-1). Дійсно повільно.

Завдяки Деннісу за 4 байти, переглянувши кратні nзамість, а не g(n-1).


5

J, 9 байт

[:*./1+i.

Прямий підхід. Створює діапазон чисел [0, ..., n-1], потім додає по одній до кожної та зменшує її за допомогою LCM.

Використання

   f =: [:*./1+i.
   f 7
420


4

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

LCM@@Range@#&

це не еквівалент просто композиції LCMта Rangeз @*?
Мальтісен

1
LCMоперує елементом у списку, який би переданий Range, тобто це просто поверне lcm ( x ) для x від 1 до n . Крім того, є відсутність, &який закривав би анонімну функцію. Щось на кшталт LCM@@Range@#&13 байт спрацювало б.
миль



3

Октава, 27 байт

@(x)lcm(1,num2cell(1:x){:})

Створює анонімну функцію, яку можна викликати як ans(N).

Демонстрація в Інтернеті

Пояснення

Це рішення створює список усіх чисел між 1і x( 1:x), перетворює їх у масив комірок num2cell. Тоді {:}індексація створює список, розділений комами, який передається lcmяк декілька вхідних аргументів для обчислення найменшого загального множини. 1 завжди передається як перший аргумент, lcmтому що lcmзавжди потрібні принаймні два вхідні аргументи.


1
Так що lcmв Octave приймається більше 2-х входів! Цікаво
Луїс Мендо

@LuisMendo Yup 2+
Suever


3

Perl 6 , 13 байт

{[lcm] 1..$_}

Блок анонімного коду, який створює діапазон від 1 до входу (включно), а потім зменшує цей показник на &infix:<lcm>.

Приклад:

#! /usr/bin/env perl6
use v6.c;

my &postfix:<p!> = {[lcm] 1..$_}

say 1p!; # 1
say 2p!; # 2
say 3p!; # 6
say 4p!; # 12
say 5p!; # 60
say 6p!; # 60
say 7p!; # 420

say 10000p!; # 5793339670287642968692270879...
# the result from this is 4349 digits long


2

JavaScript (ES6), 92 88 80 74 69 байт:

Дякую @ConorOBrien та @Neil

y=>(g=(a,b)=>b?g(b,a%b):a,[...Array(y)].map((_,i)=>y=y*++i/g(y,i)),y)

b?g(b,a%b):aзберігає байт.
Ніл

y*++i/g(y,i)економить ще кілька байт.
Ніл

1

05AB1E, 20 байт

Lpvyi¹LÒN>¢àN>*ˆ}}¯P

Пояснення

Lpv                    # for each item in isprime(range(1,N)): N=7 -> [0,1,1,0,1,0,1]
   yi                  # if prime
     ¹LÒN>¢            # count occurrences of the prime 
                         in the prime-factorization of range(1,N):
                         p=2 -> [0,1,0,2,0,1,0]
           àN>*ˆ       # add max occurrence of that prime multiplied by the prime 
                         to global array: N=7 -> [4,3,5,7]
                }}     # end if/loop
                  ¯P   # get product of global array

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


1

Мінколанг 0,15 , 12 байт

У мене є два 12-байтові рішення, і я включив їх обидва.

1n[i1+4$M]N.

Спробуйте тут!

Пояснення

1               Push 1
 n              Take number from input
  [             For loop that repeats n times
   i1+          Push loop counter + 1
      4$M       Pop b, a and push lcm(a,b)
         ]      Close for loop
          N.    Output as number and stop.

Приблизно так само просто.


11nLd[4$M]N.

Спробуйте тут!

Пояснення

11              Push two 1s
  n             Take number from input
   L            Pop b, a and push range from a to b, inclusive
    d           Duplicate top of stack (n)
     [4$M]      Pop b, a and push lcm(a,b), n times
          N.    Output as number and stop.

Третє рішення може бути отримане з цього: видаліть a 1та додайте a dпісля струму d. В обох випадках додаткова кількість потрібно , тому що цикл працює занадто багато разів, і зробити його запустити один менше часу займає два байти ( як 1-раз перед [).


1

Рубін, 25 байт

g=->n{(1..n).reduce :lcm}

Рубін, 25 байт

g=->n{n<1?1:a[n-1].lcm n}

1
Привіт, і ласкаво просимо до PPCG! Чудовий перший пост! Не потрібно називати свою функцію, тому ви можете її видалити g=.
NoOneIsHere

Анонімні функції дозволені.
Ерік Аутгольфер

1

Мова GameMaker, 60 байт

for(b=k=1;b;++k){b=0for(t=argument0;t;b+=k mod t--)}return k

Виходячи з логіки відповіді анатоліга.


1

PHP, 61 52 48 байт

збережено 9 байт завдяки @ user59178, 4 байти об’єднанням циклів.

Рекурсія в PHP об’ємна завдяки functionключовому слову; тому я використовую ітерацію.
І маючи "маленькі" трюки, я зараз навіть обіграв JS Arnauld's .

while(++$k%++$i?$i>$argv[1]?0:$i=1:$k--);echo$k;

приймає дані з аргументу командного рядка. Бігайте з -r.

зламатися

while(++$k%++$i?    # loop $i up; if it does not divide $k
    $i>$argv[1]?0       # break if $i (smallest non-divisor of $k) is larger than input
    :$i=1               # while not, reset $i and continue loop with incremented $k
    :$k--);         # undo increment while $i divides $k
echo$k;         # print $k

неозорий

Це фактично дві петлі в одній:

while($i<=$argv[1]) # loop while $i (smallest non-divisor of $k) is not larger than input
    for($k++,       # loop $k up from 1
        $i=0;$k%++$i<1;);   # loop $i up from 1 while it divides $k
echo$k;             # print $k

Примітка: скопійовано з моєї відповіді на дублікат




0

Хун , 67 байт

|*
*
(roll (gulf 1 +<) |=({a/@ b/_1} (div (mul a b) d:(egcd a b))))

Створіть список [1..n], складіть його через lcm. На жаль, у Hoon stdlib немає попередньо побудованого, який я можу використовувати: /



0

AWK, 42 байти

{for(x=n=1;n<=$1;)if(x%n++){x++;n=1}$0=x}1

Використання командного рядка:

awk '{for(x=n=2;n<=$1;)if(x%n++){x++;n=2}$0=x}1' <<< NUM

Я не побачив AWKрішення та дубліката питання, щойно опублікованого вчора, тож я подумав, що зроблю це разом. На 19моєму боксі це досить повільне рішення , але воно працює.


0

QBIC , 35 32 байти

Це привело мене сюди.

:{p=0[a|~q%b|p=1]]~p=0|_Xq\q=q+1

Пояснення:

:        Get cmd line param as number 'a'
{        Start an infinite DO loop
p=0      Sets a flag that shows if divisions failed
[a|      FOR (b=1; b<=a; b++)
~q%b     IF 'q' (which starts at 1 in QBIC) is not cleanly divisible by 'b'
|p=1     THEN Set the flag
]]   Close the FOR loop and the IF, leave the DO open
~p=0     IF 'q' didn't get flagged
|_Xq     THEN quit, printing 'q'
\q=q+1   ELSE raise 'q', redo
         [DO Loop implicitly closed by QBIC]

Ось версія, яка зупиняє тестування, qколи bне розділяє її чисто. Крім того , порядок перевірки b«проти s qвідновлюється в припущенні , що більш високі b» s буде важче розділити на (взяти 2, 3, 4наприклад: якщо %2=0, %4може бути !0. І навпаки , не так багато ...).

:{p=0[a,2,-1|~q%b|p=1┘b=2]]~p=0|_Xq\q=q+1

0

Аксіома, 35 байт

f(x)==reduce(lcm,[i for i in 1..x])

код тесту та результати

(25) -> [[i,f(i)] for i in [1,6,19,22,30]]
   (25)  [[1,1],[6,60],[19,232792560],[22,232792560],[30,2329089562800]]
                                                  Type: List List Integer

я просто прийняв рішення знайти найменше додатне ціле число, яке має всі цілі числа від 1 до n як фактори, тому що ви говорите, що це подвійне, я розміщую його тут



0

8-й , 23 байти

Код

1 ' lcm rot 2 swap loop

Цей код залишає отриманий псевдофакторний TOS

Використання та приклад

ok> 7 1 ' lcm rot 2 swap loop .
420

Або більш чітко

ok> : pseudofact 1 ' n:lcm rot 2 swap loop ;

ok> 7 pseudofact .
420
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.