Raddoppia, XOR e fallo di nuovo


20

Definiamo la funzione g come g (n) = n XOR (n * 2) per qualsiasi numero intero n> 0 .

Dato x> 0 , trova il numero intero più piccolo y> 0 tale che g k (y) = x per qualche k> 0 .

Esempio

x = 549

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

Ciò significa che g 2 (161) = 549 . Non possiamo andare oltre, poiché non esiste n tale che g (n) = 161 . Pertanto, l'output previsto per x = 549 è y = 161 .

Regole

  • Non dovresti supportare voci non valide. Una coppia (y, k) è garantita per il valore di input x .
  • Questo è , quindi vince la risposta più breve in byte!

Casi 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: A048274 che è la sequenzaa(n) = g(n)
Giuseppe

Risposte:


5

Java 8, 68 57 53 52 byte

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

-5 byte grazie a @ OlivierGrégoire .

Provalo online.

Spiegazione:

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 byte). Siamo spiacenti ^^ '
Olivier Grégoire il

@ OlivierGrégoire Ancora più intelligente, grazie!
Kevin Cruijssen,

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

@Titus Temo che non funzionerà in Java (anche se ho usato questo approccio nella mia risposta iterativa JavaScript ). In Java i+i^i^n?non è un valore booleano, quindi non verrà nemmeno compilato. Inoltre, n>i-=...avrà bisogno di parentesi ( n>(i-=...)) e n=inon è consentito nella clausola else del ternary-if, solo nella clausola if (quest'ultima non so perché, ma purtroppo è quello che è in Java ).
Kevin Cruijssen,

1
@KevinCruijssen "e n=inon è consentito nella clausola else del ternary-if". Perché Java lo analizzerebbe come (i-=(i*2^i)!=n?-1:n)=iillegale.
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))

Gè g^-1impostato isu 0se successo, impostato isu 1se fallito.


1
Questo è stato l'approccio che ho cercato di utilizzare, anche se mi è venuta con una versione di 50 byte: f=n=>(g=n=>n<2?0/!n:n%2+2*g(n/2^n%2))(n)?f(g(n)):n. Purtroppo l'approccio noioso è più corto di 12 byte.
Neil,

3

Pyth , 13 12 10 byte

Salvato 1 byte grazie a @MrXcoder e altri 2 byte seguendo il loro suggerimento

fqQ.W<HQxy

Provalo online

Spiegazione:

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
È possibile eliminare il trailing Tper 12 byte.
Mr. Xcoder,

3

R , 73 65 byte

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

Provalo online!

Grazie mille Giuseppe (-8) grazie alle tue modifiche, così semplice ma molto efficace


1
al contrario di una precedente risposta del vostro, perché questa funzione è ricorsiva, si fa necessario il f=dato che le esigenze funzionali di essere vincolato a ffunzionare correttamente. Detto questo, bel lavoro, e prendi un +1 da me!
Giuseppe,

2
puoi anche fare un po 'di ridimensionamento della tua logica e portarlo a 65 byte
Giuseppe

2

JavaScript, 38 36 byte

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

Provalo online : inizia a lanciare errori di overflow da qualche parte tra 9999& 57308.



2

C (gcc) , 57 56 55 51 byte

  • Salvataggio di un byte grazie a ceilingcat ; !=-.
  • Salvato un byte cinque byte grazie alla Rogem ; facendo uso dell'espressione ternaria e delle stranezze di gcc.
X(O,R){for(R=1;R;O=R?R:O)for(R=O;--R&&(R^2*R)-O;);}

Provalo online!


1
+1 perX(O,R)
JayCe

@ceilingcat Ottimo suggerimento, grazie.
Jonathan Frech,

for(R=1;R;O=R?R:O)salva un byte.

R=O;alla fine sembra non essere necessario, risparmiando altri 4 byte.

@Rogem sembra essere, grazie.
Jonathan Frech,

2

Z80Golf , 22 byte

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

Porta della risposta Java di @ KevinCruijssen

Esempio con input di 9-Provalo online!

Esempio con input di 85-Provalo online!

Montaggio:

;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

Esempio di assemblaggio per chiamare la funzione e stampare il risultato:

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

Se si crea ail contatore di loop anziché d, è possibile sostituire le ld d,0istruzioni con xor aentrambe le volte, risparmiando due byte.
Misha Lavrov,


1

JavaScript (Node.js), 48 45 38 byte

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

-7 byte grazie a @Neil creando una versione ricorsiva della mia versione iterativa di seguito. Non funziona per casi di test di grandi dimensioni.

Provalo online.


Versione iterativa a 45 byte che funziona per tutti i casi di test:

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

Porta della mia risposta Java.
-3 byte grazie a @Arnauld .

Provalo online.


1
Puoi farlo i-=i*2^i^n?-1:n=i(ma sfortunatamente non in Java).
Arnauld,

@Arnauld immaginava che fosse possibile per il booleano in Java solo 1in JS. Grazie!
Kevin Cruijssen,

1
38 byte scritti in modo ricorsivo (non funziona per input più grandi):f=(n,i=0)=>i<n?i*2^i^n?f(n,i+1):f(i):n
Neil

1

Rubino , 39 byte

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

Provalo online!

Come previsto per la versione ricorsiva, si lamenta del "livello di stack troppo profondo" su questi ultimi casi di test.


1

Gelatina , 11 9 byte

BÄḂṛḄß$Ṫ?

Provalo online!

Suggerimenti: utilizzare la funzione ricorsiva anziché i loop.


Molto veloce, purtroppo perde l'approccio della forza bruta.

Nota che:

  • Per x> 0 , f (x)> x .
  • popcount (f (x)) è pari, dove popcount (n) è il numero di bit impostati in n .
  • Se n ha un numero pari pari, allora esiste x tale che f (x) = n .
  • Sia B (x) la rappresentazione binaria di x , e Ṗ (l) sia la lista l con l'ultimo elemento rimosso. Quindi B (x) è lo XOR accumulato di Ṗ (B (f (x))) .

Quindi ripetutamente:

  • Calcola la sua rappresentazione binaria ( B)
  • quindi prendi lo XOR accumulato (usa ^\o ÄḂ, hanno lo stesso effetto).
  • Controlla se ( ?) la coda (ultimo elemento) ( ) dello XOR accumulato è diversa da zero (dispari popcount)
    • In tal caso, riconvertire l'elenco binario in decimale e ricorrere.
    • In caso contrario, restituisce input ( ).


1

Forth (gforth) , 71 byte

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

Provalo online!

Spiegazione

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 byte

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

Provalo

Allargato:

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

Basato sulle risposte di Kevin Cruijssen.

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

Esegui come pipe -nro provalo online .


1

F #, 92 byte

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

Provalo online!

Controlla ricorsivamente i numeri da 1 a i-1. Se c'è una corrispondenza, verificane una più piccola per quel numero. Se non c'è corrispondenza, restituisce il numero di input.


1

JavaScript (Node.js) , 40 byte

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

Provalo online!

Grazie Shaggy per -1 byte.

Risposta Port of my Jelly .

Infine c'è una lingua in cui questo approccio è più breve ( oops ). (Ho provato Python e Java , non funziona)

Qualcuno può spiegare perché posso usare /2invece di >>1?


1
x/2funziona a causa del underflow aritmetico. Qualsiasi numero IEEE 754 verrà infine valutato come 0 se diviso per 2 volte sufficienti. (E la parte decimale viene semplicemente ignorata quando XOR'd, quindi questo non influisce sul risultato.)
Arnauld


@Shaggy Sorpreso che funzioni. So che funziona per Python e Lua ecc., Ma non Javascript.
user202729

Il falseritorno sull'ultima iterazione viene implicitamente eseguito il cast 0dall'operatore XOR bit a bit.
Shaggy,

@Shaggy In effetti, no falseè coinvolto . JS si &&comporta in modo quasi identico a Python / Lua and.
user202729

1

K (ngn / k) , 32 26 byte

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

Provalo online!

{ } è una funzione con argomento x

/ lo applica fino alla convergenza

$[ ; ; ] if-then-else

2\xcifre binarie di x(questo è specifico di ngn / k)

+\ somme parziali

2! mod 2

a: assegnato a a

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

se quanto sopra è 1, xverrà restituito

altrimenti:

-1_a rilasciare l'ultimo elemento di a

2/ decodifica binaria


0

C, 62 byte

Basato su Java di Kevin Cruijssen:

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

Testare:

#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 eseguito, il programma di test genera:

     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 byte

Funziona solo con C89 o 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;}Questi 57 byte funzionano?
Tito

0

Wolfram Language (Mathematica) , 58 byte

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

Provalo online!

Inizia con un elenco contenente solo l'input. Sostituisce in modo iterativo l'elenco con tutti i numeri interi che sono già in esso o mappati in esso mediante l'operazione double-and-xor. Quindi //.dice di farlo fino a raggiungere un punto fisso. La risposta è il minimo elemento del risultato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.