Soma ou diferença de duas potências de duas


27

Seu desafio, caso você aceite aceitá-lo, é que, dado um número inteiro K >= 1, encontre números inteiros não negativos Ae de B modo que pelo menos uma das duas condições a seguir seja mantida:

  1. K = 2^A + 2^B
  2. K = 2^A - 2^B

Se não existe tal Ae B, seu programa pode se comportar de qualquer forma. (Para esclarecer Ae Bpode ser igual.)

Casos de teste

Muitas vezes, existem várias soluções para um número, mas aqui estão algumas:

K => A, B
1 => 1, 0
15 => 4, 0                      ; 16 - 1 = 15
16 => 5, 4                      ; 32 - 16 = 16; also 3, 3: 8 + 8 = 16
40 => 5, 3                      ; 2^5 + 2^3 = 40
264 => 8, 3
17179867136 => 34, 11           ; 17179869184 - 2048 = 17179867136 

O último caso de teste 17179867136, deve ser executado em menos de 10 segundos em qualquer máquina relativamente moderna. Como é um código de golfe, o programa mais curto em bytes vence. Você pode usar um programa completo ou uma função.


5
A pode B igual ?
Dennis

2
@ Dennis Não vejo por que não.
Conor O'Brien

... e para 16, ambos 5,4e 3,3são válidos.
Titus

Na verdade, agora que penso nisso, pode A, Bser negativo? (por exemplo, -1, -1para 1)
Sp3000

@ Sp3000 Não, bom ponto.
Conor O'Brien

Respostas:


3

Geléia , 11 10 bytes

;0+N&$BL€’

Aplicando o truque de twiddling da resposta Python por @xnor

Teste em TryItOnline
Todos os casos de teste também estão em TryItOnline

Quão?

;0+N&$BL€’ - main link takes an argument, k, e.g 15
;0         - concatenate k with 0, e.g. [15, 0]
     $     - last two links as a monad
   N       - negate, e.g. -15
    &      - bitwise and, e.g. -15&15=1 since these two are called as a monad (one input)
  +        - add, vectorises, e.g. [16,1]
      B    - convert to binary, vectorises, e.g. [[1,0,0,0,0],[1]]
       L€  - length for each, e.g. [5,1]
         ’ - decrement, vectorises, e.g. [4,0]

15

Python 2, 43 bytes

lambda n:[len(bin((n&-n)+k))-3for k in n,0]

Diga isso n==2^a ± 2^bcom a>b. Então, o maior fator de potência-2 de né 2^be podemos encontrá-lo usando o truque de bits 2^b = n&-n. Isso permite calcular 2^b + n, o que é igual 2^a + 2 * 2^bou justo 2^a. Qualquer um tem o mesmo comprimento de bit que a*. Então, produzimos os comprimentos de bits de n&-ne (n&-n)+ncalculados a partir dos comprimentos de suas representações binárias. O Python 3 é um byte mais longo para parênteses no for k in(n,0)].

* Exceto que 2^a + 2^bwith a==b+1tem um comprimento de bit mais longo, mas tudo bem, porque podemos interpretar isso como 2^(a+1)-2^b.


Maravilhoso - procurei um pouco de violino, mas não consegui resolver, apenas portado para Jelly.
Jonathan Allan

Tente n=4ou 8ou 16por favor.
Titus

@Titus f(2**n)retorna (n+1,n)e, 2**(n+1)-2**n=2**nportanto, não há problema.
Jonathan Allan

ah ... Qual é o formato do bin()Python?
Titus

@ Titus é uma string com um líder 0b, daí o -3.
Jonathan Allan

8

JavaScript (ES6), 73 bytes

(n,[s,f,z]=/^1+(.*1)?(0*)$/.exec(n.toString(2)))=>[s.length-!!f,z.length]

Para o caso de subtração, o primeiro número é o número de dígitos na representação binária e o segundo número é o número de zeros à direita. Para o caso de adição, subtraímos 1 do primeiro número. Se a representação binária for todos os 1s seguidos por alguns 0s, o caso de adição será assumido, caso contrário, o caso de subtração será assumido. Porta de 36 bytes da versão do @ xnor que funciona apenas para B≤30 em JavaScript:

n=>[(l=Math.log2)(n+(n&=-n))|0,l(n)]

2
@ETHproductions Claro, mas eu golfed-lo para baixo a 36.
Neil

Meu mal, pensei que a versão de 36 bytes não funcionasse para o caso de teste de 17 bilhões.
ETHproductions 10/09/16

@ETHproductions Não funciona, mas sua porta também não, como eu me lembro (comentário desde excluído, suspiro), já que ele usava operações bit a bit.
Neil

Desculpe, aqui está novamente: n=>[n,0].map(k=>((n&-n)+k).toString(2).length-1)E ambas as versões retornam [34,11]no último caso de teste (estou usando o FF 48).
ETHproductions 10/09/16

@ETHproductions Aha, com mais precisão eles funcionam quando o segundo resultado é 30 ou menos.
Neil

6

Perl, 52 49 32 bytes

Solução antiga (49 bytes)

Inclui +1 para -p

Dê entrada no STDIN:

pow2.pl <<< 17179867136

pow2.pl

#!/usr/bin/perl -p
$_=reverse sprintf"%b",$_;/()1(?:1+|0*)/;$_="@+"

No entanto, o uso do algoritmo do xnor e a adição de um twist fornecem 32 bytes:

perl -nE 'say 13/9*log|0for$;=$_&-$_,$_+$'

Apenas o código:

say 13/9*log|0for$;=$_&-$_,$_+$

Isso sofre um erro grave de arredondamento porque 13/9 = 1.444...está um pouco acima 1/log 2 = 1.44269...( logele também tem um erro de arredondamento, mas é muito menor que podemos envolvê-lo na análise de 13/9). Mas como qualquer 2**big - 2** smallcorreção é corrigida 2** bigantes do log, isso não é importante e o cálculo para 2**big + 2 * 2**smalltruncado também é seguro. E no outro lado da faixa 2**n+2**(n-1)não há aumento suficiente na faixa [0,64](não posso corretamente de qualquer forma, suporte mais do que o intervalo inteiro devido ao uso de &) para levar a um resultado errado ( 1.5no entanto, o multiplicador seria muito distante para números grandes).


5

Braquilog , 23 bytes

,A:B#+.:2rz:^a{+|-}?,.=

Experimente online!

Isso é muito mais rápido do que o necessário, por exemplo, ainda é inferior a 10 segundos no TIO .

Explicação

Esta é basicamente uma transcrição direta da fórmula sem otimização:

,A:B     The list [A, B]
#+       Both A and B are greater than or equal to 0
.        Output = [A, B]
:2rz     The list [[2, A], [2, B]]
:^a      The list [2^A, 2^B]
{+|-}?   2^A + 2^B = Input OR 2^A - 2^B = Input
,.=      Assign a value to A and B which satisfy those constraints

2
Parece que este desafio foi feito para o idioma: D
Conor O'Brien

4

Python, 69 bytes

def f(k):b=bin(k)[::-1];return len(b)-2-(b.count('1')==2),b.find('1')

Os testes estão em ideone

Como a entrada não válida pode fazer qualquer coisa, sabemos que se a entrada tiver exatamente 2 bits configurados, será a soma desses 2 poderes de 2 e, caso contrário (se válido), será executado um número de bits (incluindo a possibilidade de apenas 1 bit) e será a diferença entre a próxima potência mais alta de 2 do que o conjunto MSB e LSB.


4

JAVA 7,142 ,140, 134 BYTES

Este é o meu primeiro post no PPCG! Eu realmente gostaria de receber feedback sobre dicas de golfe
Graças a congelado por salvar 2 bytes

void f(long n){for(int i=-1,j;i++<31;)for(j=0;j++<34;){long a=1,x=a<<i,y=a<<j;if(x+y==n|y-x==n){System.out.println(j+" "+i);return;}}}

UNGOLF

void f(long n){
    for(int i=-1,j;i++<31;)
         for(j=0;j++<34;){
          long a=1,x=a<<i,y=a<<j;
            if(x+y==n|y-x==n){
            System.out.println(j+" "+i);
        return;
        }
            }
    }

ideona


1
Oi numberknot! Outro andarilho de intrigante, eu vejo. Parece não funcionar 40=2**3+2**5, por exemplo. Olhando para ele, eu não posso ver por que não, talvez eu tenha cometido um erro de transcrição ...
Jonathan Allan

1
@JonathanAllan Agora funciona bem. Na verdade, os colchetes estavam ausentes nessa linha se ((a << i) + (a << j) == n | (a << j) - (a << i) == n ) e obrigado.
Numberknot

Você não pode usar um literal em 1vez de declarar uma variável para ele?
Titus

1
@ ITtus se eu usar o literal 1, então este testcase (17179867136) não seria possível porque se você usar o literal 1, o java automaticamente atribuiria um espaço de memória INT.
Numberknot

1
Você pode declarar j junto com i:for(int i=-1,j;[...]
Frozn 10/09

4

Mathematica, 57 54 bytes

Economizou 3 bytes graças a LegionMammal978!

Do[Abs[2^a-#]==2^b&&Print@{a,b},{a,2Log@#+1},{b,0,a}]&

Na verdade, imprime todos os 1 pares apropriados {a, b}. 2Log@#+1é um limite superior para o maior aque pode aparecer ao representar a entrada #(o limite superior restrito é Log [2 #] / Log [2] = 1,44 ... Log [#] + 1). É executado quase instantaneamente na entrada de teste e em menos de um quarto de segundo (no meu computador novo, mas pronto para uso) em entradas de 100 dígitos.

1 Deixar ainiciar no valor padrão de 1 em vez de 0 salva dois bytes; faz com que a saída {0,0} seja perdida quando a entrada é 2, mas localiza a saída {2,1} nesse caso, o que é bom o suficiente.


Todos * pares apropriados? (Além disso, If[Abs[2^a-#]==2^b,Print@{a,b}]pode ser substituída com Abs[2^a-#]==2^b&&Print@{a,b}a economizar 3 bytes.)
LegionMammal978

Boa observação, entendi! "All *" era uma nota de rodapé, mas agora está mais clara.
Greg Martin

3

MATL , 23 22 bytes

BnQ:qWtG-|ym)1)tG-|hZl

Experimente online! Ou verifique todos os casos de teste .

Explicação

B      % Implicit input. Convert to binary. Gives n digits
nQ:q   % Range [1 ... n+1]
W      % 2 raised to that, element-wise: gives [1 2 4 ... 2^(n+1)] (*)
tG-|   % Duplicate. Absolute difference with input, element-wise (**)
y      % Push a copy of (*)
m      % True for elements of (**) that are members of (*)
)      % Use as logical index to select elements from (*)
1)     % Take the first element. Gives power of the first result
tG-|   % Duplicate. Absolute difference with input. Gives power of the second result
hZl    % Concatenate. Take binary logarithm. Implicit display

3

Perl 6 , 41 bytes

{.base(2).flip~~/1[1+|0*]/;$/.to,$/.from}

(Algoritmo copiado descaradamente da resposta Perl 5 )

Explicação:

# bare block lambda with implicit parameter 「$_」
{
  # turn into binary
  # ( implicit method call on 「$_」 )
  .base(2)

  # flip the binary representation
  .flip

  ~~ # smartmatch that against:

  /
    1      # a 「1」
    [
      | 1+ # at least one 「1」
      | 0* # or any number of 「0」
    ]
  /;

  # returns a list comprised of

  # the position of the end of the match (larger of the two)
  $/.to,
  # the position of the beginning of the match
  $/.from
}

Uso:

# give it a lexical name for clarity
my &bin-sum-diff = {.base(2).flip~~/1[1+|0*]/;$/.to,$/.from}

say bin-sum-diff 15; # (4 0)
say bin-sum-diff 16; # (5 4)

say bin-sum-diff 20; # (4 2)
# 2**4==16, 2**2==4; 16+4 == 20

say bin-sum-diff 40; # (5 3)
say bin-sum-diff 264; # (8 3)
say bin-sum-diff 17179867136; # (34 11)

1

PHP, 73 bytes

Eu poderia ter copiado a solução Pyhton 2 de Jonathan por 54 bytes (+13 em cima),
mas queria criar algo diferente.

salve no arquivo e execute com phpou php-cgi.

<?=strlen($n=decbin($argv[1]))-!!strpos($n,'01')._.strpos(strrev($n),49);

imprime ae bseparado por um sublinhado, qualquer coisa sem solução.

solução distinta, 96 bytes

<?=preg_match('#^(10*1|(1+))(0*)$#',decbin($argv[1]),$m)?strlen($m[0])-!$m[2]._.strlen($m[3]):_;

imprime ae bseparado por um sublinhado; um único sublinhado para nenhuma solução.

Ele ainda informa a operação por mais 11 bytes:
basta substituir o primeiro sublinhado no código por '-+'[!$m[2]].


Se eu tentar 67 em echo strlen ($ n = decbin ($ argv [1])) - !! strpos ($ n, '01 ') .'- +' [! $ N [2]]. Strpos (strrev ( $ n), 49); dá-me de volta 6 + 0, que é de 65
Jörg Hülsermann 10/10

@ JörgHülsermann: 67 não tem solução; comportamento para nenhuma solução é indefinido; de modo que não importa o que ele imprime para 67.
Titus

0

PHP, 117 bytes

if(preg_match("#^(1+|(10*1))0*$#",$b=decbin($k=$argv[1]),$t))echo($l=strlen($b))-($t[2]?1:0).",",$l+~strrpos($b,"1");

Versão estendida 4 Cases

$l=strlen($b=decbin($k=$argv[1]));
// Case 1: n=2(n-1)=n+n or n=n*(2-1)=2n-n 
if(preg_match('#^100*$#',$b))echo($l-2).'a+'.($l-2).':'.$l.'a-'.($l-1);
// Case 2: n-m
elseif(preg_match('#^1+0*$#',$b)){echo $l.'b-',strpos($b,"0")?$l-strpos($b,"0"):0;}
// Case 3: n+m 
elseif(preg_match('#^10*10*$#',$b))echo ($l-1).'c+',$l-strrpos($b,"1")-1;
else echo "Nothing";

a versão curta une os casos 1 e 3 e faz diferença no caso 3 e, nas duas versões, o caso 4 não fornece saída.

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.