Duplo, XOR e faça novamente

20

Definimos a função g como g (n) = n XOR (n * 2) para qualquer número inteiro n> 0 .

Dado x> 0 , encontre o menor número inteiro y> 0 tal que g k (y) = x para alguns k> 0 .

Exemplo

x = 549

549 = 483 XOR (483 * 2)     (as binary: 1000100101 = 111100011 XOR 1111000110)
483 = 161 XOR (161 * 2)     (as binary:  111100011 =  10100001 XOR  101000010)

O que significa que g 2 (161) = 549 . Não podemos ir mais longe, pois não existe n tal que g (n) = 161 . Portanto, a saída esperada para x = 549 é y = 161 .

Regras

  • Você não deve oferecer suporte a entradas inválidas. É garantido que existe um par (y, k) para o valor de entrada x .
  • Isso é , então a resposta mais curta em bytes vence!

Casos de teste

     3 -->     1
     5 -->     1
     6 -->     2
     9 -->     7
    10 -->     2
    23 -->    13
    85 -->     1
   549 -->   161
   960 -->    64
  1023 -->   341
  1155 -->   213
  1542 -->     2
  9999 -->  2819
 57308 --> 19124
 57311 -->   223
983055 -->     1
Arnauld
fonte
3
OEIS relacionadas: A048274 , que é a seqüênciaa(n) = g(n)
Giuseppe

Respostas:

5

Java 8, 68 57 53 52 bytes

n->{for(int i=0;i<n;)i-=(i*2^i)==n?n=i:-1;return n;}

-5 bytes graças a @ OlivierGrégoire .

Experimente online.

Explicação:

n->{                 // Method with integer as both parameter and return-type
  for(int i=0;i<n;)  //  Loop `i` in the range (1,n)
    i-=(i*2^i)==n?   //   If `i*2` XOR-ed with `i` equals `n`
        n=i          //    Set `n` to `i`, and set `i` to 0 to reset the loop
       :             //   Else:
        -1;          //    Increase `i` by 1 to go to the next iteration
  return n;}         //  Return `n` after the entire loop
Kevin Cruijssen
fonte
1
n->{for(int i=0;i<n;)i-=(i*2^i)==n?n=i:-1;return n;}(52 bytes). Desculpe ^^ '
Olivier Grégoire
@ OlivierGrégoire Ainda mais esperto, obrigado!
Kevin Cruijssen 6/06/19
for(int i=0;n>i-=i+i^i^n?-1:n=i;);?
Titus
@ Titus Receio que isso não funcione em Java (embora eu tenha usado essa abordagem na minha resposta iterativa de JavaScript ). Em Java i+i^i^n?não é um booleano, por isso nem será compilado. Além disso, n>i-=...precisará de parênteses ( n>(i-=...)) e n=inão é permitido na cláusula else do ternary-if, apenas na cláusula if (esta última não sei por que, mas é isso que ocorre em Java infelizmente )
Kevin Cruijssen
1
@KevinCruijssen "e n=inão é permitido na cláusula else do ternary-if". Porque o Java analisaria como (i-=(i*2^i)!=n?-1:n)=iilegal.
Olivier Grégoire
4

Python 2 , 54 53 bytes

f=lambda n:next((f(i)for i in range(n)if n==i^i*2),n)

Experimente online!

TFeld
fonte
3

JavaScript, 53 bytes

f=x=>(i=0,y=(G=x=>x&&(i^=x&1)+2*G(x>>1))(x),i?x:f(y))

Gé g^-1, definido icomo 0se tiver êxito, definido icomo 1se falhar.

tsh
fonte
1
Esta foi a abordagem que eu tentei usar, embora eu vim com uma versão de 50-byte: f=n=>(g=n=>n<2?0/!n:n%2+2*g(n/2^n%2))(n)?f(g(n)):n. Infelizmente, a abordagem chata é 12 bytes mais curta.
Neil
3

Pitão , 13 12 10 bytes

Guardou 1 byte graças a @MrXcoder e mais 2 bytes seguindo a sugestão

fqQ.W<HQxy

Experimente online

Explicação:

fqQ.W<HQxyZZT   Implicit: Q=eval(input()), trailing ZZT inferred

f               Return the first T in [1,2,3...] where the following is truthy
   .W       T     Functional while - loop until condition is true, starting value T
     <HQ            Condition: continue while iteration value (H) less than input
        xyZZ        Body: xor iteration value (Z) with double (y) iteration value (Z)
 qQ               Is the result of the above equal to input?
Sok
fonte
1
Você pode soltar o final Tde 12 bytes.
Mr. Xcoder
3

R , 73 65 bytes

f=function(x){for(i in 1:x)if(x==bitwXor(i,i*2)){i=f(i);break};i}

Experimente online!

Muito obrigado Giuseppe (-8) devido aos seus ajustes, tão simples, mas muito eficaz

DS_UNI
fonte
1
em oposição a uma resposta anterior de vocês, porque esta função é recursiva, você não precisa do f=desde as necessidades de função a ser obrigado a ftrabalhar corretamente. Dito isto, bom trabalho, e tire um +1 de mim!
Giuseppe
2
você também pode fazer alguns re-jiggering de sua lógica e chegar a este 65 bytes
Giuseppe
2

JavaScript, 38 36 bytes

f=(n,x=n)=>x?x^x+x^n?f(n,--x):f(x):n

Experimente online - Começa a lançar erros de estouro algures entre 9999& 57308.

Shaggy
fonte
2

Geléia , 8 7 bytes

Use ⁺¿para retornar o último elemento diferente de zero (obrigado Dennis por -1 byte)

^Ḥ)i$⁺¿

Experimente online!

A força bruta vence novamente :(

user202729
fonte
1
^Ḥ)i$⁺¿salva um byte.
Dennis
E é 2x mais lento.
user202729
2

C (gcc) , 57 56 55 51 bytes

  • Salvou um byte graças ao ceilingcat ; !=-.
  • Salvou um byte de cinco bytes graças a Rogem ; fazendo uso da expressão ternária e das peculiaridades do gcc.
X(O,R){for(R=1;R;O=R?R:O)for(R=O;--R&&(R^2*R)-O;);}

Experimente online!

Jonathan Frech
fonte
1
+1 paraX(O,R)
JayCe 07/06
@ceilingcat Boa sugestão, obrigado.
Jonathan Frech
for(R=1;R;O=R?R:O)salva um byte.
R=O;no final, parece desnecessário, poupando mais 4 bytes.
@ Roger Parece ser, obrigado.
Jonathan Frech
2

Z80Golf , 22 bytes

00000000: 1600 1803 4216 007a b830 097a 82aa b828  ....B..z.0.z...(
00000010: f314 18f3 78c9                           ....x.

Porto da resposta Java de @ KevinCruijssen

Exemplo com entrada de 9-Experimente online!

Exemplo com entrada de 85-Experimente online!

Montagem:

;d=loop counter
;b=input and output
f:
	ld d,0
	jr loop
	begin:
	ld b,d
	ld d,0
	loop:
		ld a,d
		cp b
		jr nc,end	; if d==b end
		ld a,d
		add d		; mul by 2
		xor d
		cp b
		jr z,begin	; if (d*2)^d==b set b to d
		inc d
		jr loop
	end:
	ld a,b
	ret

Exemplo de montagem para chamar a função e imprimir o resultado:

ld b,9 ; input to the function, in this case 9
call f
add 30h ; ASCII char '0'
call 8000h ; putchar
halt
Logern
fonte
Se você criar ao contador de loop em vez de d, poderá substituir as ld d,0instruções pelas xor aduas vezes, o que salva dois bytes.
Misha Lavrov #
1

Java (JDK 10) , 78 bytes

int g(int n){return f(n)%2<1?g(f(n)/2):n;}int f(int x){return 1>x?0:x^f(x/2);}

Experimente online!

user202729
fonte
1

JavaScript (Node.js), 48 45 38 bytes

f=(n,i=0)=>i<n?i*2^i^n?f(n,i+1):f(i):n

-7 bytes graças a @Neil criando uma versão recursiva da minha versão iterativa abaixo. Não funciona para casos de teste grandes.

Experimente online.


Versão iterativa de 45 bytes que funciona para todos os casos de teste:

n=>{for(i=0;i<n;)i-=i*2^i^n?-1:n=i;return n;}

Porta da minha resposta Java.
-3 bytes graças a @Arnauld .

Experimente online.

Kevin Cruijssen
fonte
1
Você pode fazer i-=i*2^i^n?-1:n=i(mas infelizmente não em Java).
Arnauld
@ Arnauld Achei que era possível para o booleano em Java apenas 1em JS. Obrigado!
Kevin Cruijssen 6/06/19
1
38 bytes escritos de forma recursiva (não funciona para entradas maiores):f=(n,i=0)=>i<n?i*2^i^n?f(n,i+1):f(i):n
Neil
1

Ruby , 39 bytes

f=->x,y=x{y<1?x:x==y^y*2?f[y]:f[x,y-1]}

Experimente online!

Como esperado para a versão recursiva, reclama sobre o "nível de pilha muito profundo" nos últimos casos de teste.

Kirill L.
fonte
1

Geléia , 11 9 bytes

BÄḂṛḄß$Ṫ?

Experimente online!

Dicas: Use a função recursiva em vez de loops.


Muito rápido, infelizmente perde para a abordagem da força bruta.

Observe que:

  • Para x> 0 , f (x)> x .
  • popcount (f (x)) é par, onde popcount (n) é o número de bits definido em n .
  • Se n tiver contagem de números pares, existe x tal que f (x) = n .
  • Seja B (x) a representação binária de x e Ṗ (l) seja a lista l com o último elemento removido. Então B (x) é o XOR acumulado de Ṗ (B (f (x))) .

Então, repetidamente:

  • Calcular sua representação binária ( B)
  • então pegue o XOR acumulado (use ^\ou ÄḂ, eles têm o mesmo efeito).
  • Verifique se ( ?) a cauda (último elemento) ( ) do XOR acumulado é diferente de zero (popcount ímpar)
    • Nesse caso, converta a lista binária de volta para decimal e recorra.
    • Caso contrário, retorna a entrada ( ).
user202729
fonte
9 bytes:B^\⁸Ḅß$Ṫ?
Leaky Nun
1

Quarto (gforth) , 71 bytes

: f 0 begin 2dup dup 2* xor = if nip 0 else 1+ then 2dup < until drop ;

Experimente online!

Explicação

0                 \ add an index variable to the top of the stack
begin             \ start an indefinite loop
  2dup            \ duplicate the top two stack items (n and i)
  dup 2* xor =    \ calculate i xor 2i and check if equal to n
  if nip 0        \ if equal, drop n (making i the new n) and use 0 as the new i
  else 1+         \ otherwise just increment i by 1
  then            \ end the if-statement
  2dup <          \ duplicate the top two stack items and check if n < i
until             \ if previous statement is true, end the loop
drop              \ drop i, leaving n on top of the stack
reffu
fonte
1

Perl 6 , 44 bytes

{({first {($^a+^2*$a)==$_},^$_}...^!*).tail}

Tente

Expandido:

{  # bare block lambda with implicit parameter $_

  (
    # generate a sequence

    # no need to seed the sequence with $_, as the following block will
    # default to using the outer $_
    # $_, 

    { # parameter $_

      first
        {  # block with placeholder parameter $a

          ( $^a +^ 2 * $a ) # double (numeric) xor
          == $_             # is it equal to the previous value
        },

        ^$_  # Range up to and excluding the previous value ( 0..^$_ )
    }

    ...^  # keep doing that until: (and throw away last value)

    !*    # it doesn't return a trueish value

  ).tail  # return the last generated value
}
Brad Gilbert b2gills
fonte
1

PHP, 49 bytes

Com base nas respostas de Kevin Cruijssen.

for($x=$argn;$x>$i-=$i*2^$i^$x?-1:$x=$i;);echo$x;

Execute como pipe -nrou experimente online .

Titus
fonte
1

F #, 92 bytes

let rec o i=
 let r=Seq.tryFind(fun x->x^^^x*2=i){1..i-1}
 if r.IsNone then i else o r.Value

Experimente online!

Verifica recursivamente os números de 1 a i-1. Se houver uma correspondência, verifique se há uma menor para esse número. Se não houver correspondência, retorne o número de entrada.

Ciaran_McCarthy
fonte
1

JavaScript (Node.js) , 40 bytes

f=n=>g(n)%2?n:f(g(n)/2)
g=x=>x&&x^g(x/2)

Experimente online!

Obrigado Shaggy por -1 bytes.

Porto da minha resposta Jelly .

Finalmente, há uma linguagem em que essa abordagem é mais curta ( oops ). (Eu tentei Python e Java , não funciona)

Alguém pode explicar por que eu posso usar em /2vez de >>1?

user202729
fonte
1
x/2funciona por causa do fluxo aritmético. Qualquer número IEEE 754 será avaliado como 0 quando dividido por 2 vezes suficientes. (E a parte decimal é simplesmente ignorada quando XOR, assim que esta não afeta o resultado.)
Arnauld
40 bytes
Shaggy
@ Shaggy Surpreso que funcione. Eu sei que funciona para Python e Lua etc., mas não Javascript.
user202729
O falseretorno na última iteração é implicitamente convertido para 0o operador XOR bit a bit.
Shaggy
@ Shagy Na verdade, não falseestá envolvido . O JS &&se comporta quase de forma idêntica ao Python / Lua and.
user202729
1

K (ngn / k) , 32 26 bytes

{$[*|a:2!+\2\x;x;2/-1_a]}/

Experimente online!

{ } é uma função com argumento x

/ aplica até convergência

$[ ; ; ] if-then-else

2\xdígitos binários de x(isto é específico para ngn / k)

+\ somas parciais

2! mod 2

a: atribuir a a

*|last - reverse ( |) e obtenha first ( *)

se o acima for 1, xserá retornado

de outra forma:

-1_a solte o último elemento de a

2/ decodificar binário

ngn
fonte
0

C, 62 bytes

Baseado no Java de Kevin Cruijssen:

int n(int j){for(int i=0;i<j;)i-=(i*2^i)==j?j=i:-1;return j;}

Testar:

#include <stdio.h>
int n(int j);
#define p(i) printf("%6d --> %5d\n", i, n(i))
int main(void)
{
    p(3);
    p(5);
    p(6);
    p(9);
    p(10);
    p(23);
    p(85);
    p(549);
    p(960);
    p(1023);
    p(1155);
    p(1542);
    p(9999);
    p(57308);
    p(57311);
    p(983055);
}

Quando executado, o programa de teste gera:

     3 -->     1
     5 -->     1
     6 -->     2
     9 -->     7
    10 -->     2
    23 -->    13
    85 -->     1
   549 -->   161
   960 -->    64
  1023 -->   341
  1155 -->   213
  1542 -->     2
  9999 -->  2819
 57308 --> 19124
 57311 -->   223
983055 -->     1

C, 54 bytes

Funciona apenas com C89 ou K&R C:

n(j){for(i=0;i<j;)i-=(i*2^i)==j?j=i:-1;return j;}

JustinCB
fonte
int n(int j){for(int i=0;j>i-=i*2^i^j?-1:j=i;);return j;}Esses 57 bytes funcionam?
Titus
0

Wolfram Language (Mathematica) , 58 bytes

Min[{#}//.x_:>Select[Range@#,MemberQ[x,#|BitXor[#,2#]]&]]&

Experimente online!

Começa com uma lista contendo apenas a entrada. Substitui iterativamente a lista por todos os números inteiros que já estão nela ou mapeiam nela pela operação double-e-xor. Então //.diz para fazer isso até chegar a um ponto fixo. A resposta é o menor elemento do resultado.

Misha Lavrov
fonte