Menor multiplicador que revela um fator de semiprime

16

Dado um N semiprime , encontre o menor número inteiro positivo m, de modo que a representação binária de um dos dois fatores de N possa ser encontrada na representação binária de N * m .

Exemplo

Vamos considerar o semiprime N = 9799 .

Tentamos diferentes valores de m , começando em 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

Paramos aqui porque a representação binária do último produto contém 101001qual é a representação binária de 41 , um dos dois fatores de 9799 (o outro sendo 239 ).

exemplo

Então a resposta seria 11 .

Regras e notas

  • Tentar valores iguais de m não faz sentido. Eles foram mostrados no exemplo acima por uma questão de integridade.
  • Seu programa deve suportar qualquer N para o qual N * m esteja dentro dos recursos de computação do seu idioma.
  • Você está autorizado a fatorar N antemão ao invés de tentar cada possível substring da representação binária de N * m para ver se ele acaba por ser um fator de N .
  • Conforme comprovado pelo MitchellSpector , m sempre existe.
  • Isso é código-golfe, então a resposta mais curta em bytes vence. As brechas padrão são proibidas.

Casos de teste

A primeira coluna é a entrada. A segunda coluna é a saída esperada.

         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
Arnauld
fonte
Hmm, eu cheiro um algoritmo semelhante ao que usamos em seu desafio seqüência Blackjack ...
ETHproductions
@ETHproductions Hmm, sério? Eles honestamente deveriam ser completamente independentes.
Arnauld
Bem, eles são principalmente semelhantes, pois você precisa verificar cada substring contíguo para uma propriedade específica. Fora isso, eles realmente não têm nenhuma relação.
ETHproductions
"e provavelmente encorajado" - me desculpe. Não nos importamos com a velocidade do nosso código.
John Dvorak
@JanDvorak Fair suficiente. Removido.
Arnauld

Respostas:

6

Pitão, 13 bytes

ff}.BY.B*TQPQ

Demonstração

Explicação:

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.
isaacg
fonte
6

05AB1E , 18 16 15 bytes

-2 bytes graças a Riley!

-1 byte graças a Emigna!

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

Explicação:

[                   # 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

Experimente online!

Okx
fonte
¹Ñ¦¨båOdeve funcionar em vez de verificar cada substring.
Riley
@Riley obrigado por descobrir isso!
Okx
2
Você pode salvar outro byte substituindo ¼e ¾por N.
Emigna
@ Emigna Eu não sabia sobre esse truque, obrigado!
Okx
4

JavaScript (ES6), 96 95 80 bytes

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)

Uma função que retorna uma função recursiva que usa uma função recursiva que usa uma função recursiva. Estou realmente começando a me perguntar se a .toString(2)rota seria mais curta ...

Atribua a uma variável, por exemplo, f=n=>...e chame com um par extra de parênteses f(9)(),. Se isso não for permitido (a meta postagem está em + 6 / -2), você pode usar esta versão de 83 bytes com invocação padrão:

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)

Ambas as versões funcionam para todos, exceto os três últimos casos de teste. Você também pode tentar esses casos de teste, alterando x>>1para (x-x%2)/2.

ETHproductions
fonte
Não tenho certeza se existe realmente um consenso sobre isso (estamos em + 6 / -2 no momento da publicação), mas, no que me diz respeito, o primeiro formato de entrada é bom.
Arnauld 21/02
3

Utilitários Bash + Unix, 85 84 bytes

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

Experimente online!


Vou apontar também que m sempre existe para qualquer n semiprime. Aqui está o porquê:

Escreva n = pq, onde p e q são primos ep <= q.

Seja b o número de dígitos na representação binária de n-1. Então, para qualquer k entre 0 e n-1 inclusive, p * (2 ^ b) + k em binário consiste na representação binária de p seguida de b bits adicionais representando k.

Portanto, os números p * (2 ^ b) + k para 0 <= k <= n-1, quando escritos em binário, todos começam com a representação binária de p. Mas esses são n números consecutivos, portanto, um deles deve ser um múltiplo de n.

Segue-se que temos um mn múltiplo de n cuja representação binária começa com a representação binária de p.

Com base nisso, pode-se chegar a um limite superior para m de 2 sqrt (n). (Pode-se provavelmente obter um limite superior muito mais apertado do que isso.)

Mitchell Spector
fonte
2

Haskell, 161 bytes

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

Verificação direta. Fatore primeiro, depois pesquise linearmente começando em 1 e use o mínimo do valor para os dois fatores.

Leva alguns segundos para o último testcase ( 1468255967), ghcirelata (15.34 secs, 18,610,214,160 bytes)no meu laptop.

ThreeFx
fonte
2

Mathematica, 83 bytes

1//.x_/;FreeQ[Fold[#+##&]/@Subsequences@IntegerDigits[x#,2],d_/;1<d<#&&d∣#]:>x+1&
Martin Ender
fonte
2

Braquilog (2), 14 bytes

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

Experimente online!

Há mais de uma maneira de escrever isso em 14 bytes no Brachylog, então eu fui o mais eficiente. Como é comum para envios de Brachylog, este é um envio de função; sua entrada é a semiprime, sua saída é o multiplicador.

Explicação

ḋḃᵐ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)

A ordem de avaliação de Prolog e Brachylog é definida pela primeira restrição que não pode ser deduzida imediatamente da entrada. Neste programa, isso é uma restrição ao resultado de uma multiplicação; portanto, o intérprete procurará manter os operandos da multiplicação o mais próximo possível de 0. Conhecemos um dos operandos e o outro é a saída; portanto, encontramos a menor saída possível, que é exatamente o que queremos.


fonte
1

PowerShell , 136 bytes

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

Experimente online!

Muito demorado devido ao funcionamento da conversão em binário no PowerShell. : - /

Recebe entrada $n, passa 2para $n-1e retira os fatores !($n%$_). Envia aqueles para um loop |%{...}e converts cada um deles para uma 2string binária (base ). Armazena essas cadeias binárias em $a.

Então entramos em um for(){...}loop infinito . Cada iteração, incrementamos ++$m, multiplica isso por $ne convertpara uma string binária, armazenada em $b. Então, ifessa string é regex em -likequalquer string $a, produzimos $me exit.

AdmBorkBork
fonte
0

Perl 6 , 66 bytes

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

Baseado em Regex.

Super lento, porque força brutal os fatores de n novamente em cada posição de correspondência de expressão regular de cada número que é tentado.

O cálculo dos fatores apenas uma vez melhora o desempenho, mas aumenta 72 bytes:

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