Çift, XOR ve tekrar yap


20

Herhangi bir n> 0 tamsayısı için g fonksiyonunu g (n) = n XOR (n * 2) olarak tanımlarız .

Verilen x> 0 , en küçük tam sayı bulmak y> 0 öyle ki g K (y) = x bazı k> 0 .

Misal

x = 549

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

Olan anlamına gelir g 2 (161), 549 = . Hiçbir olarak biz, herhangi daha ileri gidemez n öyle ki g (n) 161 = . Yani, beklenen çıkışı x = 549 ise y 161 = .

kurallar

  • Geçersiz girişleri desteklememeniz gerekiyor. X giriş değeri için bir çift (y, k) bulunması garanti edilir .
  • Bu , bu yüzden bayt en kısa cevap kazanır!

Test senaryoları

     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
İlgili OEIS : A048274 olan dizia(n) = g(n)
Giuseppe

Yanıtlar:


5

Java 8, 68 57 53 52 bayt

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

@ OlivierGrégoire sayesinde -5 bayt .

Çevrimiçi deneyin.

Açıklama:

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 bayt). Üzgünüz ^^ '
Olivier Grégoire

@ OlivierGrégoire Daha akıllı, teşekkürler!
Kevin Cruijssen

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

@Titus, Java'da işe yaramayacağından korkuyorum ( bu yaklaşımı JavaScript yinelemesinde kullandığım halde ). Java'da i+i^i^n?bir boolean değildir, bu yüzden derlenmeyecektir. Buna ek olarak, n>i-=...parantez ( n>(i-=...)) gerekir n=ive üçlünün başka yan tümcesinde izin verilmez-if, yalnızca if yan tümcesinde (bu sonuncusu neden bilmiyorum, ama maalesef Java'da olan budur ).
Kevin Cruijssen

1
@KevinCruijssen "ve n=iüçlü- if'in başka yan tümcesinde izin verilmez". Çünkü Java onu (i-=(i*2^i)!=n?-1:n)=iyasadışı olarak ayrıştırırdı .
Olivier Grégoire


3

JavaScript, 53 bayt

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

Golduğu g^-1belirlenen hangi iüzere 0ayarlanmış, eğer başarı iiçin 1başarısız olursa.


1
Bu ben 50 bayt sürümü ile geldi rağmen kullanım çalıştı yaklaşım oldu: f=n=>(g=n=>n<2?0/!n:n%2+2*g(n/2^n%2))(n)?f(g(n)):n. Ne yazık ki sıkıcı yaklaşım 12 bayt daha kısadır.
Neil

3

Pyth , 13 12 10 bayt

@MrXcoder sayesinde 1 bayt ve önerilerini takiben 2 bayt tasarruf edildi

fqQ.W<HQxy

Çevrimiçi deneyin

Açıklama:

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
İzlemeyi T12 bayt için bırakabilirsiniz .
Bay Xcoder

3

R , 73 65 bayt

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

Çevrimiçi deneyin!

Tweaks'iniz sayesinde çok teşekkürler Giuseppe (-8), çok basit ama çok etkili


1
senin bir önceki cevabı aksine bu işlev özyinelemeli olduğundan, sen do ihtiyaç f=fonksiyon ihtiyaçları için bağlayıcı olduğunu beri fdüzgün çalışması için. Olduğu söyleniyor, iyi iş çıkardın ve benden +1 alın!
Giuseppe

2
ayrıca mantığınızın yeniden jiggeringini yapabilir ve bunu 65 bayta alabilirsiniz
Giuseppe



2

C (gcc) , 57 56 55 51 bayt

  • Tavan kedisi sayesinde bir bayt kurtardı ; !=-.
  • Kaydedilen bir bayt beş sayesinde bayt Rogem ; üçlü ifade ve gcc tuhaflıklarından yararlanma.
X(O,R){for(R=1;R;O=R?R:O)for(R=O;--R&&(R^2*R)-O;);}

Çevrimiçi deneyin!


1
+1 içinX(O,R)
JayCe

@ ceilingcat İyi öneri, teşekkürler.
Jonathan Frech

for(R=1;R;O=R?R:O)bir bayt kaydeder.

R=O;sonunda gereksiz görünüyor, size 4 bayt tasarruf.

@Rogem Öyle görünüyor, teşekkürler.
Jonathan Frech

2

Z80Golf , 22 bayt

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

Bağlantı noktası @ KevinCruijssen'in Java yanıtı

9-girişli örnek Çevrimiçi deneyin!

85 girişli örnek-Çevrimiçi deneyin!

Montaj:

;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

İşlevi çağırmak ve sonucu yazdırmak için montaj örneği:

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

Eğer yaparsanız ayerine döngü sayacını d, o zaman yerine ld d,0göre talimatları xor aiki bayt kaydeder iki kere.
Misha Lavrov


1

JavaScript (Node.js), 48 45 38 bayt

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

@Neil, aşağıdaki yinelemeli sürümümün özyinelemeli bir sürümünü oluşturması sayesinde -7 bayt. Büyük test durumlarında çalışmaz.

Çevrimiçi deneyin.


Tüm test senaryoları için çalışan itteratif 45 bayt versiyonu:

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

Java yanıtımın bağlantı noktası. @Arnauld
sayesinde -3 bayt .

Çevrimiçi deneyin.


1
Yapabilirsiniz i-=i*2^i^n?-1:n=i(ama ne yazık ki Java'da değil).
Arnauld

@Arnauld Java'daki boole için sadece 1JS'de bir şeyin mümkün olduğunu düşündüm . Teşekkürler!
Kevin Cruijssen

1
Tekrarlayan bir şekilde yazılan 38 bayt (daha büyük girdiler için çalışmaz):f=(n,i=0)=>i<n?i*2^i^n?f(n,i+1):f(i):n
Neil

1

Ruby , 39 bayt

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

Çevrimiçi deneyin!

Özyinelemeli versiyondan beklendiği gibi, ikinci test durumlarında "yığın seviyesi çok derin" den şikayet eder.


1

Jöle , 11 9 bayt

BÄḂṛḄß$Ṫ?

Çevrimiçi deneyin!

İpuçları: Döngüler yerine özyinelemeli işlev kullanın.


Çok hızlı, maalesef kaba kuvvet yaklaşımını kaybediyor.

Bunu not et:

  • İçin x> 0 , f (x) X " .
  • popcount (f (x)) burada çift sayıdır, popcount (n) olarak belirlenen bit sayısıdır n .
  • Eğer n, daha popcount vardır, o zaman var olan X bu şekilde F (x) = n .
  • Let B (x) bir ikili gösterimini olmak x ve P (L) listesi olabilir l çıkarılan son elemanı. O zaman B (x) Ṗ (B (f (x))) birikmiş XOR'sidir .

Yani, tekrar tekrar:

  • İkili gösterimini hesapla ( B)
  • daha sonra biriken XOR'u alın ( ^\veya kullanın ÄḂ, aynı etkiye sahiptirler).
  • (Kontrol edin ?) kuyruk (son öğe) ( ) birikmiş XOR sıfırdan farklı olduğu (tek popcount)
    • Öyleyse, ikili listeyi ondalık sayıya ve tekrarlamaya dönüştürün.
    • Değilse, girişi ( ) döndürür .


1

İleri (gforth) , 71 bayt

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

Çevrimiçi deneyin!

açıklama

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 bayt

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

Dene

Expanded:

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

Kevin Cruijssen'in cevaplarına dayanarak.

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

Pipo ile çalıştırın -nrveya çevrimiçi deneyin .


1

F #, 92 bayt

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

Çevrimiçi deneyin!

1'den 1'e kadar olan sayıları tekrar tekrar kontrol eder i-1. Bir eşleşme varsa, bu sayı için daha küçük olup olmadığını kontrol edin. Eşleşme yoksa giriş numarasını döndürün.


1

JavaScript (Node.js) , 40 bayt

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

Çevrimiçi deneyin!

-1 bayt için Shaggy teşekkürler.

Jelly cevabımın limanı .

Son olarak bu yaklaşımın daha kısa olduğu bir dil vardır ( ayy ). (Python ve Java'yı denedim , çalışmıyor)

Herkes /2bunun yerine neden kullanabileceğimi açıklayabilir >>1mi?


1
x/2aritmetik taşma nedeniyle çalışır. Herhangi bir IEEE 754 numarası, yeterli 2'ye bölündüğünde sonunda 0 olarak değerlendirilecektir . (Ve ondalık kısım XOR'd olduğunda göz ardı edilir, bu nedenle sonucu etkilemez.)
Arnauld


@Shaggy Çalışması şaşırttı. Python ve Lua vb için çalıştığını biliyorum, ancak Javascript için değil.
user202729

falseGeçen yineleme iade örtülü artığını 0bitsel XOR operatörü tarafından.
Shaggy

@Shaggy Aslında, hiçbir falseilgili değildir . JS &&neredeyse Python / Lua ile aynı şekilde davranır and.
user202729

1

K (ngn / k) , 32 26 bayt

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

Çevrimiçi deneyin!

{ } argümanlı bir işlevdir x

/ yakınsamaya kadar uygular

$[ ; ; ] if-then-else

2\xikili basamak x(bu ngn / k'ye özgüdür)

+\ kısmi toplamlar

2! mod 2

a: atamak a

*|last - reverse ( |) ve get get ( *)

yukarıdaki 1 ise, xiade edilecektir

aksi takdirde:

-1_a son elemanını bırakmak a

2/ ikili kod çözme


0

C, 62 bayt

Kevin Cruijssen'in Java'sına dayanarak:

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

Test etmek için:

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

Çalıştırıldığında, test programı çıktı verir:

     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 bayt

Sadece C89 veya K&R C ile çalışır:

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;}Bu 57 bayt çalışıyor mu?
Titus

0

Wolfram Dili (Mathematica) , 58 bayt

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

Çevrimiçi deneyin!

Yalnızca girişi içeren bir listeyle başlar. Listeyi, içinde zaten bulunan tüm tamsayılarla veya çift ve xor işlemiyle eşleştirerek yineleyerek değiştirir. Sonra //.bunu sabit bir noktaya ulaşana kadar yapmayı söylüyor. Cevap, sonucun en az unsurudur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.