Найближчий продукт із 7-ма чіткими характеристиками


14

(через чат )

Запис OEIS A123321 перераховує послідовність чисел, що є добутком семи різних простих чисел. Для стислості ми назвемо це число 7DP . Перші кілька чисел та їх відповідних дільників нижче:

510510 = 2 * 3 * 5 * 7 * 11 * 13 * 17
570570 = 2 * 3 * 5 * 7 * 11 * 13 * 19
690690 = 2 * 3 * 5 * 7 * 11 * 13 * 23
746130 = 2 * 3 * 5 * 7 * 11 * 17 * 19

Завданням буде знайти найближчий номер 7DP з точки зору абсолютної відстані від заданого входу.

Вхідні дані

Єдине додатне ціле число n у будь-якому зручному форматі .

Вихідні дані

Найближчий до 7DP номер n , знову в будь-якому зручному форматі. Якщо два 7DP-номери пов'язані для найближчих, ви можете вивести або один, або і інший.

Правила

  • Можна вважати, що цифри вписуються у [int]тип даних за замовчуванням (або еквівалент) вашої мови .
  • Прийнятна або повна програма, або функція.
  • Стандартні лазівки заборонені.
  • Це , тому застосовуються всі звичайні правила гольфу, і найкоротший код виграє.

Приклади

5 -> 510510
860782 -> 870870
1425060 -> 1438710 (or 1411410, or both)

Відповіді:


11

Пітон, 89 86 85 байт

f=lambda n,k=0:126^sum(1>>n%i<<7*(n/i%i<1)for i in range(2,n))and f(n+k,k%2*2+~k)or n

Алгоритм спочатку O (страшно), і рекурсія насправді не допомагає, але він працює добре, доки n достатньо близько до числа 7DP.

Дякуємо @xnor за те, що виграли 3 байти!

Перевірте це на repl.it .

Як це працює

У Python немає вбудованих принципів первинності чи факторизації, але ми можемо ідентифікувати 7DP числа за кількістю та характером їх дільників.

За принципом множення кількість дільників цілого числа може бути обчислена як добуток збільшених показників його основної факторизації. Таким чином, σ 0 (n) ( функція дільника ) дорівнює 2 м, коли n - число mDP.

σ 0 (n) = 128 , отже, є необхідною умовою, але вона недостатня; наприклад, σ 0 (2 127 ) = 128 , але 2 127 явно не є числом 7DP. Однак якщо обидва σ 0 (n) = 128 і немає досконалого квадрата ділиться n рівномірно, то n - це число 7DP.

Для введення n алгоритм полягає в огляді цілих чисел n , n - 1 , n + 1 , n - 2 , n + 2 тощо і поверненні першого, що є числом 7DP.

Коли f викликається аргументом n , відбувається таке:

  • Кодекс

    126^sum(1>>n%i<<7*(n/i%i<1)for i in range(2,n))

    тести, якщо n є НЕ число 7DP наступним чином .

    Для всіх цілих чисел i таких, що 1 <i <n ,1>>n%i<<7*(n/i%i<1) отримують оцінку.

    • Якщо n ділиться на i, але не на i 2 , 1>>n%iвиходить 1 і (n/i%i<1)виходить 0 , в результаті чого
      1 · 2 7 · 0 = 1 .

    • Якщо n ділиться на i 2 , 1>>n%iі (n/i%i<1)обидва дають 1 , в результаті чого 1 · 2 7 · 1 = 128 .

    • Якщо n не ділиться на i , 1>>n%iвиходить 0 , в результаті чого 0 · 7 7 x x = 0 .


    Сума отриманих чисел буде 2 м - 2 , якщо п є число MDP (його 2 м подільники, за винятком 1 і п ) і число більше 127 , якщо п має ідеальний квадрат фактор. Таким чином, сума буде 126, якщо і тільки якщо n - це 7DP-число.

  • Для 7DP-чисел сума дорівнює 126 , тож XORing її з 126 приводить до 0 , що є помилковим. Таким чином, лямбда або частина лямбда виконується і f повертає поточне значення n .

  • Якщо n не є числом 7DP, XOR поверне ненульове, триєдне значення. Таким чином, і виконується частина лямбда.

    f(n+k,k%2*2+~k)

    рекурсивно викликає f з оновленими значеннями n (наступне потенційне число 7DP) і k (різниця між новим кандидатом і тим після цього).

    Якщо k - парне, негативне ціле число, то k%2*2виходить 0, а ~kвихід - (k + 1) . Сума обох результатів - (k + 1) , що є непарним, від’ємним цілим числом, що дорівнює 1 більше в абсолютному значенні, ніж k .

    Якщо k - непарне, від’ємне ціле число, k%2*2виходить 2, а ~kвихід - (k + 1) . Сума обох результатів 2 - (k + 1) = - (k - 1) , що є парним, негативним цілим числом, яке дорівнює 1 одиницю більше в абсолютній величині, ніж k .

    Це означає, що k приймає значення 0, -1, 2, -3, 4, ⋯ .

    Коли додається кумулятивно до n 0 (початкове значення n ), отримані цілі числа є

    • n 0 + 0
    • ( n 0 + 0) - 1 = n 0 - 1
    • ( n 0 - 1) + 2 = n 0 + 1
    • ( n 0 + 1) - 3 = n 0 - 2
    • ( n 0 - 2) + 4 = n 0 + 2
    • тощо.


    переконавшись , що перший номер 7DP ми стикаємося як можна ближче до п 0 , як це можливо.


Чудова ідея з підрахунком дільника! Я думаю, що ви можете пограти в гольф по черзі, пройшовши оновлення kбезпосередньо f(n+k,k%2*2+~k), починаючи з k=0.
xnor

Велике поліпшення. Спасибі!
Денніс

9

Брахілог , 44 40 16 байт

Закреслений 44 все ще є регулярним 44; (

:I=+.>0,.$pPdPl7

Приклад:

?- run_from_atom(':I=+.>0,.$pPdPl7',1425060,Z).
Z = 1438710 .

Чи може бути, що ця мова не завжди смокче? Я бив Jelly і MATL!

Тестовий випадок с 5 найдовший і займає близько 10 секунд на моїй машині.

Це було б 12 байтів, якби $pне помилка (нам це не потрібно>0,. частина )

Пояснення

Брахілог використовує логічне програмування обмежень за замовчуванням для всіх арифметичних цілих чисел. Більше того, маркування вбудоване= працює на можливо нескінченних областях.

Він послідовно об'єднує змінну без обмежень (тобто в (-inf, inf)) як таку:0, 1, -1, 2, -2, 3, … .

Таким чином, ми можемо отримати найближчий номер 7DP, шукаючи перше число, Iуніфіковане (-inf, inf)(використовуючи автоматичне зворотне відстеження), для якого Input + Iє 7DP-номер.

:I=                Label variables in [Input, I]. I has no constraints and Input is known
   +.              Unify Output with Input + I
     >0,           Output > 0 (wouldn't be needed if $p failed for numbers less than 1)
        .$pP       Unify P with the list of prime factors of Output
            dP     Check that P with duplicates removed is still P
              l7   Check that the length of P is 7

1
Я бив Jelly і MATL! Але лише на 0 байт :-P
Луїс Мендо

1
@LuisMendo Якщо я виправляю помилку, це буде 13 байт $p. Теоретично мені це не потрібно >0,, але моя реалізація баггі: P
Fatalize

1
@DavidC Так, оскільки він починається на вході, а потім пробує всі числа як такі: Input+1, Input-1, Input+2, Input-2, Input+3, ...тому перший 7DP, знайдений цим методом, буде найближчим.
Фаталізувати

1
@mat Виправлення помилок після опублікування виклику робить відповідь неконкурентоспроможною, тому я залишу її в 16, хоча зараз це може бути 12 байт ( >0,.не потрібно)
Fatalize

1
codegolf.stackexchange.com/a/111998/59995 Закреслений 444 все ще 444. Я буду вражений, коли побачимо перекреслений
4444.

7

Желе, 17 байт

Pµạ³,
×⁹ÆRœc7Ç€ṂṪ

Теоретично працює, але на це потрібно багато років.


Ось версія, яка фактично працює для заданих входів, але теоретично не працює для великих входів:

Pµạ³,
50ÆRœc7Ç€ṂṪ

Спробуйте тут.Це генерує всі праймери до 50, потім знаходить усі 7-комбінації праймерів у цьому списку, а потім усі їхні продукти. Нарешті, він просто знаходить найближчий елемент із цього списку до заданого аргументу.

Звичайно, як тільки наші 7DP будуть містити праймери вище 50, це не вдасться. Теоретична версія генерує всі праймери до 256n для введення n , але в іншому випадку працює так само.

Доказ

Нехай p(x)позначають наступний простір після x. (Вкрай вільна) верхня межа для найближчого продукту 7DP до x:

p(x) * p(p(x)) * p(p(p(x))) * ... * p(p(p(p(p(p(p(x)))))))

Тому нам потрібно лише перевірити праймери в [2… p (p (p (p (p (p (p (p (x))))) ”) . Постулат Бертрана говорить, що p (x) ≤ 2x , тому достатньо перевірити всі праймери до 128x .


×⁹ÆRœc7P€µạ³ỤḢịабо ×⁹ÆRœc7P€µạ³NMị(друк масиву всіх рішень) зберігає пару байтів. Крім того, ×⁹можна змінити +⁴для підвищення ефективності.
Денніс

5

MATL , 21 17 16 14 13 байт

Дякуємо Деннісу за пропозицію, яка видалила 4 байти, та ще один, який врятував ще 1 байт!

t17*Zq7XN!pYk

Це працює в теорії, але не вистачає пам'яті для вхідних даних вище 6(онлайн-компілятор).

Більш ефективна версія використовує 21 байт і обчислює всі тестові випадки приблизно за одну секунду:

t3e4/k16+_YqZq7XN!pYk

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

Пояснення

Ефективна для пам'яті версія

Візьмемо приклад N = 860782як приклад. Досить розглянути прості числа до М = 29, який є першим прем'єром , який множиться на 2*3*5*7*11*13перевищуєте N . У цьому прикладі 2*3*5*7*11*13*29 = 870870. Наступний прем'єр - це 31. Будь-який продукт з участю прем'єр , що більше або буде , по крайней мере 2*3*5*7*11*13*31 = 930930, і тому він гарантовано НЕ буде рішенням, оскільки воно перевищує 870870яких перевищує N .

M обчислюється як перший прайм більше, ніж max(N/(2*3*5*7*11*13), 16). maxФункція використовується для забезпечення того , щоб , щонайменше 17визначена. Щоб зберегти кілька байтів, код замінюється 2*3*5*7*11*13 = 30030на 30000, а функція maxдодається. Ці зміни є дійсними, оскільки вони дають більше значення.

t      % Take input implicitly. Duplicate
3e4/k  % Divide input by 30000 and round down (rounding here is only needed
       % due to a bug in the "next prime" function)
16+    % Add 16
_Yq    % Next prime
Zq     % Prime numbers up to that value
7XN    % Combinations of those primes taken 7 at a time. Gives a 2D array
       % with each combination on a different row
!p     % Product of each row
Yk     % Output product that is closest to the input. Implicitly display

Неефективна пам'ять версія

Для подальшого зменшення кількості байтів поділ можна видалити; насправді достатньо помножити на 17(спасибі, @Dennis). Це гарантує включення наступного розквіту (за постулатом Бертранда ) і того, що принаймні результат 17. Це працює в теорії, але не вистачає пам'яті для входів, більших, ніж приблизно 6.

У коді розділ

3e4/k  % Divide input by 30000 and round down (rounding here is only needed
       % due to a bug in the "next prime" function)
16+    % Add 16
_Yq    % Next prime

замінюється на

17*    % Multiply by 17

3

Пайк, 32 байти

#PDl 7q.ID}lRlqi*(#)DF-X,)R],She

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

Зверніть увагу, що це не працює в Інтернеті - воно вичерпується. Ця версія перевіряє лише два різних праймера і повинна працювати швидше. Коли від мети знаходяться 2 числа на однаковій відстані, вона вибирає нижнє.

Це проходить через усі числа, поки не знайде той, який більший за вхідний і не становить 7DP. Кожне число позбавляється від нього, якщо це не 7DP. Потім у ньому є список 7DP на вхід, з тим, який більший. Потім вибирається той, який знаходиться найближче до входу.


3

Джулія, 59 байт

!n=sort(map(prod,combinations(17n|>primes,7))-n,by=abs)[]+n

Це дуже неефективно, але це працює для першого тестового випадку на практиці та для інших в теорії.

Ціною на ще 5 байт - загалом 64 байти - ефективність може бути значно покращена.

!n=sort(map(prod,combinations(n>>14+17|>primes,7))-n,by=abs)[]+n

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

Фон

Як згадується у відповіді @ LuisMendo , набір простих ліній, які ми повинні врахувати для найближчого 7DP-номера, досить малий. Набір достатньо, щоб він містив число 7DP, яке перевищує вхідний n , що буде істинним, якщо і лише тоді, коли він містить простою p ≥ 17, так що 30300p = 2 · 3 · 5 · 7 · 11 · 13 · p ≥ п .

В Про інтервал, що містить щонайменше одне просте число, доводиться, що інтервал [x, 1,5x) містить щонайменше одне просте число, коли x ≥ 8 . Оскільки 30030/16384 ≈ 1,83 , це означає , що має бути головним р в (n / 30030, n / 16384), коли n> 8 · 30300 = 242400 .

Нарешті, коли n <510510 , p = 17 явно достатньо, тому нам потрібно розглянути лише прості рівні до n / 16384 + 17 .

Ціною ефективності ми можемо вважати праймери до 17n . Це працює, коли n = 1 і значно більше n / 16384 + 17 для більших значень n .

Як це працює

17n|>primesі n>>14+17|>primes(біт зміщення еквівалентно діленню на 2 14 = 16384 ) обчислити прості діапазони, згадані в попередньому абзаці. Потім combinations(...,7)обчислює всі масиви із семи різних простих чисел у цьому діапазоні і prod, зіставляючи ті, обчислює їхні продукти, тобто 7DP числа, з яких ми виберемо відповідь.

Далі -nвіднімаємо n prom кожне число 7DP, а потім сортуємо sort(...,by=abs)ці відмінності за їх абсолютними значеннями. Нарешті, ми вибираємо першу різницю за допомогою []та обчислюємо відповідне число 7DP, додаючи n с +n.


2

Pyth, 30 байт

L&{IPbq7lPby#.W!syMH,hhZa0teZ,

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

Тестовий набір.

(5 запускається занадто довго)

Пояснення

L&{IPbq7lPby#.W!syMH,hhZa0teZ,

L&{IPbq7lPb     Defines a function y, whose argument is b:
 &                  Return if both the following are true:
  {IPb                  the prime factorization contains no duplicate; and:
      q7lPb             the number of prime factors is 7

           y#.W!syMH,hhZa0teZ,   The main programme. Input as Q.
                             ,QQ Implicit arguments, yield [Q,Q].
             .W                  While
               !syMH                   both numbers do not satisfy y:
                    ,hhZ             increment the first number
                          teZ        and decrement the second number
                        a0           while making it non-negative.

1

Mathematica 136 80 75 байт

Це прямий підхід, який працює назовні n.

nце найвищий добуток продукту, якщо кількість простих факторів становить 7 ( PrimeNu@#==7), і жоден з цих факторів не з’являється більше одного разу ( SquareFreeQ@#&).

g@n_:=(k=1;While[!(PrimeNu@#==7&&SquareFreeQ@#&)⌊z=n-⌊k/2](-1)^k⌋,k++];z)

Моє попереднє подання (136 байт) знайшло перший продукт із 7-мальованими найвищими показниками вище, nі, якщо він існує, перший перший продукт із 7-мальованими простими властивостями нижче n. Потім він просто визначив, який був ближче n. Якщо продукти були на однаковій відстані, він повертав обидва.

Поточна версія перевіряє n-1, n + 1, n-2, n + 2 ... до тих пір, поки вона не досягне першого продукту, що відрізняється від 7-ти рівнів. Ця більш ефективна версія використовує підхід, який взяв Денніс.

Ключовий заздалегідь був у використанні ⌊k/2](-1)^k⌋для повернення серії, 0, 1, -1, 2, -2 ... Нуль використовується для перевірки того, чи nє сам по собі продукт із 7-ма головними чіткостями. З цієї причини Floor(тобто ⌊...⌋) використовується замість Ceiling.


g[5]
g[860782]
g[1425060]

510510

870870

1438710


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