Verdopple, XOR und mach es noch einmal


20

Wir definieren die Funktion g als g (n) = n XOR (n * 2) für eine beliebige ganze Zahl n> 0 .

Wenn x> 0 ist , finde die kleinste ganze Zahl y> 0, so dass g k (y) = x für einige k> 0 ist .

Beispiel

x = 549

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

Was bedeutet, dass g 2 (161) = 549 ist . Wir können nicht weiter gehen, da es keine n , so dass g (n) 161 = . Die erwartete Ausgabe für x = 549 ist also y = 161 .

Regeln

  • Sie dürfen keine ungültigen Einträge unterstützen. Für den Eingabewert x ist garantiert ein Paar (y, k) vorhanden .
  • Das ist , also gewinnt die kürzeste Antwort in Bytes!

Testfälle

     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
Verwandte OEIS: A048274, die die Sequenz ista(n) = g(n)
Giuseppe

Antworten:


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 dank @ OlivierGrégoire .

Probieren Sie es online aus.

Erläuterung:

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 Bytes). Sorry ^^ '
Olivier Grégoire

@ OlivierGrégoire Noch schlauer, danke!
Kevin Cruijssen

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

@Titus Ich fürchte, das wird in Java nicht funktionieren (obwohl ich diesen Ansatz in meiner iterativen JavaScript-Antwort verwendet habe ). In Java i+i^i^n?ist es kein Boolescher Wert, daher wird es nicht einmal kompiliert. Außerdem n>i-=...wird parenthesis ( n>(i-=...)) benötigt und n=iist in der else-Klausel des ternary-if nicht erlaubt, nur in der if-Klausel (diese letzte weiß ich nicht warum, aber das ist es leider in Java ).
Kevin Cruijssen

1
@KevinCruijssen "und n=iist in der else-Klausel des ternary-if nicht erlaubt". Weil Java es als (i-=(i*2^i)!=n?-1:n)=iillegal analysieren würde .
Olivier Grégoire


3

JavaScript, 53 Byte

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

Gist g^-1, die festgelegt iauf , 0wenn der Erfolg, setzen Sie iauf , 1wenn fehlgeschlagen.


1
Dies war der Ansatz , den ich zu verwenden versucht , obwohl ich mit einer 50-Bit - Version kam: f=n=>(g=n=>n<2?0/!n:n%2+2*g(n/2^n%2))(n)?f(g(n)):n. Leider ist der langweilige Ansatz 12 Bytes kürzer.
Neil

3

Pyth , 13 12 10 Bytes

1 Byte dank @MrXcoder und 2 weitere Bytes nach ihrem Vorschlag gespeichert

fqQ.W<HQxy

Probieren Sie es online aus

Erläuterung:

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
Sie können das Trailing Tfür 12 Bytes löschen.
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}

Probieren Sie es online!

Vielen Dank, Giuseppe (-8), aufgrund deiner Optimierungen, so einfach und doch sehr effektiv


1
wie zu einer früheren Antwort von Ihnen gegenüber , da diese Funktion rekursiv ist, Sie tun müssen , die f=da die Funktion Bedürfnisse gebunden sein , um frichtig zu funktionieren. Davon abgesehen, gute Arbeit, und nimm eine +1 von mir!
Giuseppe

2
Sie können auch Ihre Logik neu triggern und dies auf 65 Bytes bringen
Giuseppe

2

JavaScript, 38 36 Bytes

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

Online testen - Startet das Auslösen von Überlauffehlern zwischen 9999& 57308.



2

C (gcc) , 57 56 55 51 Bytes

X(O,R){for(R=1;R;O=R?R:O)for(R=O;--R&&(R^2*R)-O;);}

Probieren Sie es online!


1
+1 fürX(O,R)
JayCe

@ceilingcat Guter Vorschlag, danke.
Jonathan Frech

for(R=1;R;O=R?R:O)Speichert ein Byte.

R=O;am ende scheint das unnötig zu sein und erspart euch weitere 4 bytes.

@Rogem Scheint zu sein, danke.
Jonathan Frech

2

Z80Golf , 22 Bytes

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

Portierung der Java-Antwort von @ KevinCruijssen

Beispiel mit Eingabe von 9-Online ausprobieren!

Beispiel mit Eingabe von 85-Online ausprobieren!

Versammlung:

;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

Assembly-Beispiel zum Aufrufen der Funktion und zum Drucken des Ergebnisses:

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

Wenn Sie astattdessen den Schleifenzähler erstellen d, können Sie die ld d,0Anweisungen durch xor abeide Male ersetzen , wodurch zwei Bytes eingespart werden.
Mischa Lawrow


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 dank @Neil, der unten eine rekursive Version meiner iterativen Version erstellt. Funktioniert nicht für große Testfälle.

Probieren Sie es online aus.


Iterative 45-Byte- Version, die für alle Testfälle funktioniert:

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

Port meiner Java-Antwort.
-3 Bytes dank @Arnauld .

Probieren Sie es online aus.


1
Das kannst du i-=i*2^i^n?-1:n=i(aber leider nicht in Java).
Arnauld

@Arnauld Es stellte sich heraus, dass etwas für den Booleschen in Java möglich war, nur 1in JS. Vielen Dank!
Kevin Cruijssen

1
38 Bytes rekursiv geschrieben (funktioniert bei größeren Eingaben nicht):f=(n,i=0)=>i<n?i*2^i^n?f(n,i+1):f(i):n
Neil


1

Jelly , 11 9 Bytes

BÄḂṛḄß$Ṫ?

Probieren Sie es online!

Tipps: Verwenden Sie rekursive Funktionen anstelle von Schleifen.


Sehr schnell, verliert leider an der Brute-Force-Annäherung.

Beachten Sie, dass:

  • Für x> 0 gilt f (x)> x .
  • popcount (f (x)) ist gerade, wobei popcount (n) die Anzahl der in n gesetzten Bits ist .
  • Wenn n auch PopCount hat, dann gibt es x , so dass f (x) = n .
  • Sei B (x) die Binärdarstellung von x und Ṗ (l) die Liste l ohne letztes Element. Dann ist B (x) das akkumulierte XOR von Ṗ (B (f (x))) .

Also haben wir wiederholt:

  • Berechne seine Binärdarstellung ( B)
  • dann nimm das akkumulierte XOR (benutze ^\oder ÄḂ, sie haben den gleichen Effekt).
  • Überprüfen Sie, ob ( ?) das Ende (letztes Element) ( ) des akkumulierten XOR ungleich Null ist (ungerade Popcount).
    • Wenn ja, konvertieren Sie die Binärliste zurück in dezimal und rekursiv.
    • Wenn nicht, wird die Eingabe ( ) zurückgegeben.


1

Viertens (gviertens) , 71 Bytes

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

Probieren Sie es online!

Erläuterung

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 Bytes

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

Versuch es

Erweitert:

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

Basierend auf den Antworten von Kevin Cruijssen.

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

Laufen Sie als Pipe mit -nroder versuchen Sie es online .


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

Probieren Sie es online!

Überprüft rekursiv die Zahlen von 1 bis i-1. Wenn eine Übereinstimmung vorliegt, suchen Sie nach einer kleineren für diese Nummer. Wenn es keine Übereinstimmung gibt, geben Sie die eingegebene Nummer zurück.


1

JavaScript (Node.js) , 40 Byte

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

Probieren Sie es online!

Danke Shaggy für -1 Bytes.

Port meiner Gelee Antwort .

Schließlich gibt es eine Sprache, in der dieser Ansatz kürzer ist ( oops ). (Ich habe versucht, Python und Java , es funktioniert nicht)

Kann mir jemand erklären, warum ich /2anstelle von verwenden kann >>1?


1
x/2funktioniert wegen arithmetischem Unterlauf. Jede IEEE 754-Nummer wird schließlich als 0 gewertet, wenn sie zweimal geteilt wird. (Und der Dezimalteil wird beim XOR einfach ignoriert, daher hat dies keinen Einfluss auf das Ergebnis.)
Arnauld


@ Shaggy Überrascht, dass es funktioniert. Ich weiß, dass es für Python und Lua usw. funktioniert, aber nicht für Javascript.
user202729

Der falsebei der letzten Iteration zurückgegebene Wert wird implizit 0vom bitweisen XOR-Operator umgewandelt.
Shaggy

@ Shaggy In der Tat ist kein falsebeteiligt . JS &&verhält sich fast identisch zu Python / Lua and.
user202729

1

K (ngn / k) , 32 26 Bytes

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

Probieren Sie es online!

{ } ist eine Funktion mit Argument x

/ wendet es bis zur Konvergenz an

$[ ; ; ] wenn-dann-sonst

2\xBinärziffern von x(dies ist spezifisch für ngn / k)

+\ Teilsummen

2! mod 2

a: zuweisen a

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

Wenn der obige Wert 1 ist, xwird er zurückgegeben

Andernfalls:

-1_a Lasse das letzte Element von fallen a

2/ binär dekodieren


0

C 62 Bytes

Basierend auf Kevin Cruijssens Java:

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

Zu testen:

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

Beim Ausführen gibt das Testprogramm Folgendes aus:

     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

Funktioniert nur mit C89 oder 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;}Funktionieren diese 57 Bytes?
Titus

0

Wolfram Language (Mathematica) , 58 Byte

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

Probieren Sie es online!

Beginnt mit einer Liste, die nur die Eingabe enthält. Ersetzt die Liste iterativ durch alle bereits enthaltenen Ganzzahlen oder ordnet sie durch die Operation double-and-xor zu. Dann //.sagt man dies bis zum Erreichen eines festen Punktes. Die Antwort ist das kleinste Element des Ergebnisses.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.