Doublez, XOR et recommencez


20

Nous définissons la fonction g comme g (n) = n XOR (n * 2) pour tout entier n> 0 .

Étant donné x> 0 , trouvez le plus petit entier y> 0 tel que g k (y) = x pour certains k> 0 .

Exemple

x = 549

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

Ce qui signifie que g 2 (161) = 549 . On ne peut pas aller plus loin, car il n'y a pas de n tel que g (n) = 161 . Ainsi, la sortie attendue pour x = 549 est y = 161 .

Règles

  • Vous n'êtes pas censé prendre en charge les entrées non valides. Il est garanti qu'une paire (y, k) existe pour la valeur d'entrée x .
  • C'est le , donc la réponse la plus courte en octets l'emporte!

Cas de test

     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

3
OEIS connexe: A048274 qui est la séquencea(n) = g(n)
Giuseppe

Réponses:


5

Java 8, 68 57 53 52 octets

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

-5 octets grâce à @ OlivierGrégoire .

Essayez-le en ligne.

Explication:

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

1
n->{for(int i=0;i<n;)i-=(i*2^i)==n?n=i:-1;return n;}(52 octets). Désolé ^^ '
Olivier Grégoire

@ OlivierGrégoire Encore plus intelligent, merci!
Kevin Cruijssen

for(int i=0;n>i-=i+i^i^n?-1:n=i;);?
Titus

@Titus Je crains que cela ne fonctionne pas en Java (même si j'ai utilisé cette approche dans ma réponse JavaScript itérative ). En Java i+i^i^n?n'est pas un booléen, donc il ne compilera même pas. De plus, n>i-=...aura besoin de parenthèses ( n>(i-=...)), et n=in'est pas autorisé dans la clause else du ternary-if, uniquement dans la clause if (cette dernière, je ne sais pas pourquoi, mais c'est ce que c'est malheureusement en Java ).
Kevin Cruijssen

1
@KevinCruijssen "et n=in'est pas autorisé dans la clause else du ternary-if". Parce que Java l'analyserait comme (i-=(i*2^i)!=n?-1:n)=iillégal.
Olivier Grégoire


3

JavaScript, 53 octets

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

Gest g^-1, qui est défini isur 0if success, défini isur 1if failed.


1
Ce fut l'approche que j'essayé d'utiliser , bien que je suis venu avec une version 50 octets: f=n=>(g=n=>n<2?0/!n:n%2+2*g(n/2^n%2))(n)?f(g(n)):n. Malheureusement, l'approche ennuyeuse est de 12 octets plus courte.
Neil

3

Pyth , 13 12 10 octets

1 octet enregistré grâce à @MrXcoder, et 2 octets supplémentaires suite à leur suggestion

fqQ.W<HQxy

Essayez-le en ligne

Explication:

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?

1
Vous pouvez supprimer la fin Tpour 12 octets.
M. Xcoder

3

R , 73 65 octets

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

Essayez-le en ligne!

Merci beaucoup Giuseppe (-8) à cause de vos réglages, si simples mais très efficaces


1
par opposition à une réponse précédente de la vôtre, parce que cette fonction est récursive, vous avez besoin du f=étant donné que les besoins de la fonction d'être lié à ftravailler correctement. Cela étant dit, beau travail, et prenez-moi un +1!
Giuseppe

2
vous pouvez également faire un peu de re-jiggering de votre logique et obtenir ceci à 65 octets
Giuseppe

2

JavaScript, 38 36 octets

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

Essayez-le en ligne - commence à lancer des erreurs de débordement quelque part entre 9999& 57308.



2

C (gcc) , 57 56 55 51 octets

  • Enregistré un octet grâce à plafondcat ; !=-.
  • Un octet enregistré cinq octets grâce à Rogem ; en utilisant l'expression ternaire et les caprices de gcc.
X(O,R){for(R=1;R;O=R?R:O)for(R=O;--R&&(R^2*R)-O;);}

Essayez-le en ligne!


1
+1 pourX(O,R)
JayCe

@ceilingcat Bonne suggestion, merci.
Jonathan Frech

for(R=1;R;O=R?R:O)enregistre un octet.

R=O;à la fin, cela ne semble pas nécessaire, ce qui vous fait économiser encore 4 octets.

@Rogem semble l'être, merci.
Jonathan Frech

2

Z80Golf , 22 octets

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

Port de la réponse Java de @ KevinCruijssen

Exemple avec entrée de 9-Essayez-le en ligne!

Exemple avec entrée de 85-Essayez-le en ligne!

Assemblée:

;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

Exemple d'assemblage pour appeler la fonction et imprimer le résultat:

ld b,9 ; input to the function, in this case 9
call f
add 30h ; ASCII char '0'
call 8000h ; putchar
halt

Si vous effectuez ale compteur de boucles au lieu de d, vous pouvez remplacer les ld d,0instructions par les xor adeux fois, ce qui économise deux octets.
Misha Lavrov


1

JavaScript (Node.js), 48 45 38 octets

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

-7 octets grâce à @Neil créant une version récursive de ma version itérative ci-dessous. Ne fonctionne pas pour les grands cas de test.

Essayez-le en ligne.


Version itérative de 45 octets qui fonctionne pour tous les cas de test:

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

Port de ma réponse Java.
-3 octets grâce à @Arnauld .

Essayez-le en ligne.


1
Vous pouvez le faire i-=i*2^i^n?-1:n=i(mais malheureusement pas en Java).
Arnauld

@Arnauld a compris que quelque chose était possible pour le booléen en Java juste 1en JS. Merci!
Kevin Cruijssen

1
38 octets écrits récursivement (ne fonctionne pas pour les entrées plus importantes):f=(n,i=0)=>i<n?i*2^i^n?f(n,i+1):f(i):n
Neil

1

Rubis , 39 octets

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

Essayez-le en ligne!

Comme prévu pour la version récursive, se plaint de "niveau de pile trop profond" sur ces derniers cas de test.


1

Gelée , 11 9 octets

BÄḂṛḄß$Ṫ?

Essayez-le en ligne!

Conseils: utilisez la fonction récursive au lieu des boucles.


Très rapide, perd malheureusement à l'approche de la force brute.

Notez que:

  • Pour x> 0 , f (x)> x .
  • popcount (f (x)) est pair, où popcount (n) est le nombre de bits défini dans n .
  • Si n a même un popcount, alors il existe x tel que f (x) = n .
  • Soit B (x) la représentation binaire de x , et Ṗ (l) la liste l avec le dernier élément supprimé. Alors B (x) est le XOR accumulé de Ṗ (B (f (x))) .

Donc, nous répétons:

  • Calculer sa représentation binaire (B )
  • puis prenez le XOR accumulé (utilisez ^\ouÄḂ , ils ont le même effet).
  • Vérifiez si ( ?) la queue (dernier élément) ( ) du XOR accumulé est différente de zéro (popcount impair)
    • Si tel est le cas, reconvertissez la liste binaire en décimale et répétez.
    • Sinon, retourne l'entrée ( ).


1

Forth (gforth) , 71 octets

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

Essayez-le en ligne!

Explication

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

1

Perl 6 , 44 octets

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

Essayez-le

Étendu:

{  # 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
}


1

PHP, 49 octets

Basé sur les réponses de Kevin Cruijssen.

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

Exécuter en tant que pipe avec -nrou l' essayer en ligne .


1

F #, 92 octets

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

Essayez-le en ligne!

Vérifie récursivement les nombres de 1 à i-1. S'il y a une correspondance, recherchez un plus petit pour ce nombre. S'il n'y a pas de correspondance, renvoyez le numéro saisi.


1

JavaScript (Node.js) , 40 octets

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

Essayez-le en ligne!

Merci Shaggy pour -1 octets.

Port de ma réponse Jelly .

Enfin, il existe un langage où cette approche est plus courte ( oups ). (J'ai essayé Python et Java , ça ne marche pas)

Quelqu'un peut-il expliquer pourquoi je peux utiliser à la /2place >>1?


1
x/2fonctionne à cause du sous-dépassement arithmétique. Tout numéro IEEE 754 sera finalement évalué à 0 lorsqu'il sera divisé par 2 fois suffisamment. (Et la partie décimale est simplement ignorée lors de la XOR, donc cela n'affecte pas le résultat.)
Arnauld


@Shaggy Surpris que cela fonctionne. Je sais que cela fonctionne pour Python et Lua etc., mais pas Javascript.
user202729

Le résultat falsede la dernière itération est implicitement converti en 0par l'opérateur XOR au niveau du bit.
Shaggy

@Shaggy En fait, aucun falsen'est impliqué . JS &&se comporte presque de manière identique à Python / Lua and.
user202729

1

K (ngn / k) , 32 26 octets

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

Essayez-le en ligne!

{ } est une fonction avec argument x

/ l'applique jusqu'à la convergence

$[ ; ; ] si-alors-sinon

2\xchiffres binaires de x(ceci est spécifique à ngn / k)

+\ sommes partielles

2! mod 2

a: affecter à a

*|last - reverse ( |) et get first ( *)

si ce qui précède est 1, xsera retourné

autrement:

-1_a déposer le dernier élément de a

2/ décoder le binaire


0

C, 62 octets

Basé sur Java de Kevin Cruijssen:

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

Tester:

#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);
}

Lorsqu'il est exécuté, le programme de test génère:

     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 octets

Fonctionne uniquement avec C89 ou K&R C:

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


int n(int j){for(int i=0;j>i-=i*2^i^j?-1:j=i;);return j;}Ces 57 octets fonctionnent-ils?
Titus

0

Wolfram Language (Mathematica) , 58 octets

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

Essayez-le en ligne!

Commence par une liste contenant uniquement l'entrée. Remplace de manière itérative la liste par tous les entiers qui s'y trouvent déjà ou qui y sont mappés par l'opération double et xor. Dit ensuite //.de le faire jusqu'à atteindre un point fixe. La réponse est le moindre élément du résultat.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.