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

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.

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!


¹Ñ¦¨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.


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


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.


2

Mathematica, 83 bytes

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

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.


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.


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/},^∞}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.