Найменший множник, який виявляє коефіцієнт напівпринципу


16

З огляду на напівпримір N , знайдіть найменше додатне ціле число m таке, що двійкове представлення одного з двох факторів N можна знайти у двійковому поданні N * m .

Приклад

Розглянемо напівпервідність N = 9799 .

Спробуємо різні значення m , починаючи з 1:

 m |  N * m |   N * m in binary
---+--------+------------------
 1 |   9799 |    10011001000111
 2 |  19598 |   100110010001110
 3 |  29397 |   111001011010101
 4 |  39196 |  1001100100011100
 5 |  48995 |  1011111101100011
 6 |  58794 |  1110010110101010
 7 |  68593 | 10000101111110001
 8 |  78392 | 10011001000111000
 9 |  88191 | 10101100001111111
10 |  97990 | 10111111011000110
11 | 107789 | 11010010100001101

Ми зупиняємось тут, тому що бінарне представлення останнього продукту містить, 101001яке є двійковим поданням 41 , один з двох факторів 9799 (інший - 239 ).

приклад

Тож відповідь буде 11 .

Правила та примітки

  • Пробувати рівні значення m безглуздо. Вони були показані у наведеному вище прикладі заради повноти.
  • Ваша програма повинна підтримувати будь-який N, для якого N * m знаходиться в межах обчислювальних можливостей вашої мови.
  • Вам дозволяється факторізовать N заздалегідь , а не намагатися кожен можливий подстроку двійкового представлення Н * м , щоб побачити , якщо вона виявляється чинником N .
  • Як підтвердив MitchellSpector , m завжди існує.
  • Це код-гольф, тому найкоротша відповідь у байтах виграє. Стандартні лазівки заборонені.

Тестові справи

Перший стовпець - це вхід. Другий стовпець - очікуваний вихід.

         N |    m |         N * m |                              N * m in binary | Factor
-----------+------+---------------+----------------------------------------------+-------
         9 |    3 |            27 |                                      [11]011 |      3
        15 |    1 |            15 |                                       [11]11 |      3
        49 |    5 |           245 |                                   [111]10101 |      7
        91 |    1 |            91 |                                    10[1101]1 |     13
       961 |   17 |         16337 |                             [11111]111010001 |     31
      1829 |    5 |          9145 |                             1000[111011]1001 |     59
      9799 |   11 |        107789 |                          1[101001]0100001101 |     41
     19951 |   41 |        817991 |                       1[1000111]101101000111 |     71
    120797 |   27 |       3261519 |                     11000[1110001]0001001111 |    113
   1720861 |  121 |     208224181 |               11000110100[100111111101]10101 |   2557
 444309323 |  743 |  330121826989 |    100110011011100110010[1101010010101011]01 |  54443
 840000701 | 4515 | 3792603165015 | 11011100110000[1000110000111011]000101010111 |  35899
1468255967 |   55 |   80754078185 |      1001011001101010100010[1110001111]01001 |    911

Гм, я відчуваю запах алгоритму, аналогічного тому, який ми використовували у вашій задачі щодо послідовності Блекджека ...
ETHproductions,

@ETHproductions Хм, справді? Вони, чесно кажучи, абсолютно не пов'язані між собою.
Арнольд

Ну, вони в основному схожі тим, що вам потрібно перевірити кожну суміжну підрядку на предмет певного властивості. Крім того, що вони насправді є дуже спорідненими.
ETHproductions

"і, мабуть, заохочується" - мені шкода. Нас не хвилює швидкість нашого коду.
Джон Дворак

@JanDvorak Справедливо. Вилучено.
Арнольд

Відповіді:


6

Pyth, 13 байт

ff}.BY.B*TQPQ

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

Пояснення:

ff}.BY.B*TQPQ
f                Find the first integer >= to 1 where the following is true
 f         PQ    Filter the prime factors of the input
        *TQ      Multiply the input by the outer integer
      .B         Convert to a binary string
   .BY           Convert the prime factor to a binary string
  }              Check whether the factor string is in the multiple string.

6

05AB1E , 18 16 15 байт

-2 байти завдяки Райлі!

-1 байт дякую Еміньї!

[N¹*b¹Ñ¦¨båOiNq

Пояснення:

[                   # Infinite loop start
 N                  # Push the amount of times we have iterated
  ¹*               # Multiplied by input
    b              # Convert to binary
     ¹Ñ¦¨b         # Calculate the proper divisors of the input in binary excluding one
          åO       # Check if a substring of N * m in binary is in the divisors
            iNq    # If so, print how many times we have iterated and terminate the program

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


¹Ñ¦¨båOмає працювати замість перевірки кожної підрядки.
Райлі

@Riley дякую, що помітили це!
Okx

2
Ви можете зберегти інші байти заміни ¼і ¾з N.
Емінья

@Emigna Я не знав про цей трюк, дякую!
Okx

4

JavaScript (ES6), 96 95 80 байт

n=>F=m=>(k=p=>p&&(q=1,g=x=>1<x&&x<n&n%x<1|g(x>>1,q*=2))(p)|k(p-q))(n*m)?m:F(-~m)

Функція, яка повертає рекурсивну функцію, яка використовує рекурсивну функцію, яка використовує рекурсивну функцію. Я справді починаю цікавитись, чи буде .toString(2)маршрут коротшим ...

Привласнити змінній , наприклад , f=n=>...і виклик з додатковою парою дужок, f(9)(). Якщо це заборонено ( мета-повідомлення знаходиться на рівні + 6 / -2), ви можете використовувати цю 83-байтну версію зі стандартним викликом:

f=(n,m)=>(k=p=>p&&(q=1,g=x=>1<x&&x<n&n%x<1|g(x>>1,q*=2))(p)|k(p-q))(n*m)?m:f(n,-~m)

Обидві версії працюють для всіх, крім останніх трьох тестових випадків. Ви можете спробувати ці тестові випадки, перейшовши x>>1на (x-x%2)/2.


Не впевнений, чи дійсно існує консенсусу з цього приводу (ми знаходимось на рівні 6 / -2 на момент публікації), але, що стосується мене, перший формат введення добре.
Арнольд

3

Утиліти Bash + Unix, 85 84 байт

for((;;m++)){ dc -e2o$[$1*m]n|egrep -q $(dc "-e2o`factor $1`nBEPn")&&break;}
echo $m

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


Я також зазначу, що m завжди існує для будь-якого напівпервинного n. Ось чому:

Запишіть n = pq, де p і q прості та p <= q.

Нехай b - кількість цифр у двійковому поданні n-1. Тоді для будь-якого k між 0 і n-1 включно, p * (2 ^ b) + k у двійковій формі складається з двійкового подання p, а потім b додаткових бітів, що представляють k.

Тож числа p * (2 ^ b) + k при 0 <= k <= n-1, коли вони записуються двійковими, усі починаються з двійкового подання p. Але це n послідовних чисел, тому одне з них повинно бути кратним n.

Звідси випливає, що ми маємо кратне mn з n, двійкове подання якого починається з двійкового подання p.

Виходячи з цього, можна придумати верхню межу для m 2 sqrt (n). (Можливо, можна отримати набагато більш жорстку верхню межу, ніж ця.)


2

Haskell, 161 байт

import Data.List
(!)=mod
a#b|a!b==0=b|0<1=a#(b+1)
g 0=[]
g n=g(n`div`2)++show(n!2)
(a%b)c|g b`isInfixOf`g(a*c)=c|0<1=a%b$c+1
f n=min(n%(n#2)$1)$n%(n`div`(n#2))$1

Пряма перевірка. Спершу скористайтеся фактором, потім шукайте лінійно, починаючи з 1, і беруть мінімум значення для обох факторів.

Займає кілька секунд для останньої проби ( 1468255967), ghciповідомляє (15.34 secs, 18,610,214,160 bytes)на моєму ноутбуці.



2

Брахілог (2), 14 байт

ḋḃᵐD∧?:.×ḃs∈D∧

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

Існує не один спосіб записати це в 14 байт у Брахілог, тому я пішов на найефективніший. Як це властиво для подань Брахілогів, це подання функції; його вхід - напівпринцип, його вихід - мультиплікатор.

Пояснення

ḋḃᵐD∧?:.×ḃs∈D∧
ḋ               Prime decomposition (finds the two prime factors)
 ḃᵐ             Convert each factor to binary
   D            Name this value as D
    ∧?          Restart with the user input
      :.×       The output is something that can be multiplied by it
         ḃ      to produce a number which, when expressed in binary
          s     has a substring
           ∈D   that is an element of D
             ∧  (suppress an implicit constraint that D is the output; it isn't)

Порядок оцінювання Пролога та Брахілога встановлюється першим обмеженням, яке неможливо одразу вивести із вхідних даних. У цій програмі це обмеження на результат множення, тому інтерпретатор має на меті підтримувати операнди множення якомога ближче до 0. Ми знаємо один з операндів, а інший - вихід, тому ми знаходимо найменший вихід, який ми можемо, і саме це ми хочемо.


1

PowerShell , 136 байт

param($n)$a=2..($n-1)|?{!($n%$_)}|%{[convert]::ToString($_,2)};for(){$b=[convert]::toString(++$m*$n,2);if($a|?{$b-like"*$_*"}){$m;exit}}

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

Дуже тривалий завдяки тому, як працює в PowerShell перехід до бінарних. : - /

Здійснює введення $n, перебирає 2на $n-1та вилучає фактори !($n%$_). Надсилає їх у цикл |%{...}і convertкожен із них переходить у двійковий (базовий)2 ) рядок. Зберігає ці двійкові рядки $a.

Потім вводимо нескінченну for(){...}петлю. Кожну ітерацію ми збільшуємо ++$m, помножуючи це на $nта convertбінарний рядок, що зберігається в $b. Тоді, в ifцій рядку повторно виражаються -likeбудь-які рядки $a, ми виводимо $mі exit.


0

Perl 6 , 66 байт

->\n{first {(n*$_).base(2)~~/@(grep(n%%*,2..^n)».base(2))/},^∞}

На основі Regex

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

Обчислення коефіцієнтів лише один раз покращує продуктивність, але робить його 72 байти:

->\n{my @f=grep(n%%*,2..^n)».base(2);first {(n*$_).base(2)~~/@f/},^∞}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.