"Bit-ödünç" iki sayı


20

Küçük bir sayının daha büyük bir sayıdan bit ödünç alabileceğini biliyor muydunuz ? İşte bir örnek. Diyelim ki iki sayımız 5 ve 14. İlk olarak, bunları ikili olarak yazın:

5       14
000101  001110

Önce en küçük almak üzerine uzakta daha büyük sayıda bit ve biz en küçük ver kapalı diğer numarasına bit. Yani

This bit turns off
            |
            v
000101  001110
    ^
    |
This bit turns on

Şimdi elimizde

000111  001100

ve sayılarımız 7 ve 12'dir. İlk sayı hala daha küçüktür, bu yüzden devam ediyoruz.

000111  001100
001111  001000

Şimdi 15 ve 8 var, böylece durabiliriz. Bu işlem grubuna "bit borçlanma" iki sayı diyoruz. Bir örnek daha yapalım. 20 ve 61.

20        61
010100    111101
010101    111100
010111    111000
111111    100000
63        32

Yani sonuçlarımız 32, 63. Bir tane daha yapalım . 31 ve 12. 31 zaten 12'den büyük, bu yüzden yapacak bir şey yok! 31 ve 12 bit borçlanması 31 ve 12 verir, değişiklik olmaz.

Meydan okuma

Zorluk, iki sayı alan ve bunları ödünç alan bir program veya işlev yazmaktır. İki sayı her zaman pozitif tamsayı olur. Giriş ve çıktınız herhangi bir makul formatta olabilir.

Test G / Ç:

Input: 2, 3
Output: 3, 2

Input: 3, 2
Output: 3, 2

Input: 8, 23
Output: 31, 0

Input: 42, 81
Output: 63, 0

Input: 38, 41
Output: 47, 32

Input: 16, 73
Output: 23, 0

Input: 17, 17
Output: 17, 17

Standart boşluklar uygulanır ve baytlarda en kısa cevap kazanır!

Yanıtlar:


12

Jöle , 11 bayt

~1¦&N$^µ</¿

Çevrimiçi deneyin! veya tüm test senaryolarını doğrulayın .

Arka fon

N tamsayısının son ayarlanan bitini aşağıdaki gibi çıkarabiliriz .

n + 1 , n'nin sondaki set bitlerini ve bitişik ayarlanmamış biti değiştirir. Örneğin, 10011 2 + 1 = 10100 2 .

Yana ~ n = - (n + 1) = -n - 1 , n = ~ n + 1 , bu -n değil bit cinsinden yukarıda geçerlidir n (geçiş yapar tüm bu şekilde son önce tüm bit geçiş, bit) 1 .

Örneğin, -10100 2 = ~ 10100 2 + 1 = 01011 2 + 1 = 01100 2 .

Alarak -n n & Bitwise VE ait n ve -n eşitsiz oldu yana (son ayarlanan bit boşa çıktığı önce tüm bit , n ve n , böylece son grubu bit hasıl) n .

Örneğin, 10100 2 & -10100 2 = 10100 2 & 01100 2 = 00100 2 .

Böylece XORing n ile n & -n unsets son seti biraz n .

Tersine, n'nin son ayarlanan bitini ayarlamak için çözmek için , n ^ (~ n & - ~ n) formülünü türettiğimiz noktadan yukarıdakileri ~ n'ye uygulamak yeterlidir .

Nasıl çalışır

~1¦&N$^µ</¿  Main link. Argument: A (list of pairs)

          ¿  While loop:
        </     Condition: Reduce p by less-than. True iff x < y.
       µ       Body chain:
~1¦              Apply bitwise NOT to the x, first item of the pair.
     $           Convert the two links to the left into a monadic chain.
    N              Negate; multiply [~x, y] by -1, yielding [-~x, -y].
   &               Logical AND. Yields [-~x & ~x, -y & y].
      ^            Vectorized XOR with p. Yields [(-~x & ~x) ^ x, (-y & y) ^ y].

6

J, 31 26 bayt

,`(($:~(OR>:))~(AND<:))@.<

Özyineleme ve bitsel hileler kullanarak düz ileri yaklaşım. Bir n değeri için en sağdaki açık ( 1 ) biti kapatmak ( 0'a ayarlanmış ) için , bitsel-ve n ve n -1 arasında gerçekleştirebilir ve en sağdaki ( 1'e ayarlı ) açabilirsiniz n değeri için off ( 0 ) biti , bitsel olarak veya n ve n +1 arasında gerçekleştirebilirsiniz .

kullanım

Giriş, biri LHS'ye, diğeri RHS'ye uygulanan iki tamsayıdan oluşur ve çıktı, bit ödünç alınan değerlerin bir listesidir.

   f =: ,`(($:~(OR>:))~(AND<:))@.<
   2 f 3
3 2
   3 f 2
3 2
   8 f 23
31 0
   42 f 81
63 0
   38 f 41
47 32
   16 f 73
23 0
   17 f 17
17 17

açıklama

,`(($:~(OR>:))~(AND<:))@.<  Input: x on LHS, y on RHS
                            If x < y,
,                             Form a 2-element array [x, y] and return
                            Else
                   <:         Decrement y
                AND           Perform bitwise-and on y and y-1, call it y'
          >:                  Increment x
        OR                    Perform bitwise-or on x and x+1, call it x'
    $:                        Call recursively on x' and y' and return

Güzel cevap! Bir yanıt gönderdikten sonra meydan okumayı değiştirdiğim için üzgünüm, ancak meydan okumayı biraz basitleştirdim. (artık listeyi tekrarlamanız gerekmez). Bu, biraz daha kısaltmanıza izin vermelidir.
DJMcMayhem

@DrGreenEggsandIronMan J aslında iki dizinin arasına fonksiyon öğesini akıllıca açık bir sıralama olmadan uyguluyor, ki bu güzel. Başka bir hile olmadığı sürece, muhtemelen aynı kalacaktır.
mil

4

Python, 42 bayt

f=lambda x,y:x<y and f(x|x+1,y&y-1)or(x,y)

4 bayt golf için @ jimmy23013 için teşekkürler! 2 bayt golf için @LeakyNun için teşekkürler!

Ideone üzerinde test edin .


3

Mathematica, 46 bayt

If[#<#2,BitOr[#,#+1]~#0~BitAnd[#2,#2-1],{##}]&

Benim kullanılan aynı yöntem çözümü J.

@ Martin'e 1 bayt kaydettiği ve infix uygulamasını hatırlattığı için teşekkürler~ .

kullanım

Girdi iki tamsayı bağımsız değişkeninden oluşur ve çıktı bit ödünç alınan değerlerin bir listesidir.

Misal


Komik bir şey denediğimi düşündüm, ama ne yazık ki daha uzun bir bayt: #//.{x_,y_}/;x<y:>{BitOr[x,x+1],BitAnd[y,y-1]}&(belki de nasıl kısaltacağına dair bir fikrin var)
Martin Ender

Bu düzgün bir kural, ama golf kurallarına pek aşina değilim. Genellikle sadece ikame /.ve koşulu kullanırım /;. Keşke Mathematica, ve benzeri argüman türlerini inceleyerek boolean ve bitwise arasında geçiş yapabilir &&.
mil

3

Pyth, 29 27 25 22 21 20 19 18 16 bayt

MXG ^ 2x _! \ 0.BG`HCm.W <FHgVZU2dC 
MXG ^ 2x_ + 0jG2HCm.W <FHgVZU2dC 
Cm.W <FH.bxN ^ 2x_ + 0jN2YZ2dC 
m.W <FH.bxN ^ 2x_ + 0jN2YZ2       <- değiştirilen giriş / çıkış format
 mW <FH.exb ^ 2x_ + 0jb2kZ 
m.W <FH.U ,. | bhb. & ZtZZ 
.W <FH.U ,. | bhb. & ZtZZ          <- giriş / çıkış formatını değiştirdi
 . W <FH.U ,. | bhb. & ZTZ
.W <FH.U ,. |. Bhb & t

Test odası.


Bir yanıt gönderdikten sonra meydan okumayı değiştirdiğim için üzgünüm, ancak meydan okumayı biraz basitleştirdim. (artık listeyi tekrarlamanız gerekmez). Neyse ki bu kısaltmanıza izin verecektir.
DJMcMayhem

@DrGreenEggsandIronMan Yalnızca bir bayt kaydetti. Pyth olan bu verimli.
Sızan Rahibe


2

Labirent , 37 34 bayt

?"
}
|=:{:
)   }
: :;-{
=&( {!;\!@

Çevrimiçi deneyin!

açıklama

Hızlı Labirent Astarı:

  • Labirent , başlangıçta (kapalı) sonsuz miktarda sıfırla doldurulmuş , ana ve yardımcı olmak üzere , keyfi hassasiyetli tamsayılar yığını üzerinde çalışır .
  • Kaynak kodu, bir labirente benziyor, burada yönerge işaretçisi (IP) koridorları takip ediyor. Tüm ilginç kontrol akışı kavşaklarda olur: IP'nin gidecek birden fazla hücresi olduğunda, ana yığının üst kısmı denetlenir. Değer negatifse, IP sola döner, eğer pozitifse, IP sağa döner, aksi takdirde doğrudan ilerler. Seçilen yön bir duvar (yani boşluk) tarafından engellenirse, IP bunun yerine ters yönde hareket eder.

Program diğer cevaplar ile aynı algoritmayı kullanır: biz sürece (a, b)ile değiştirin . Biraz daha golf oynamayı denedikten sonra tam bir açıklama ekleyeceğim.(a | a+1, b & b-1)a < b

IP sol üst köşeden başlar, sağa gider. ?bir tamsayıyı okur a. O zaman "bir işlem yok, ancak IP'nin hemen aşağıya inmesini önlemek gerekiyor. Bu da bir çıkmaz sokak, bu yüzden IP geri dönüyor ve ?okumak için tekrar çalışıyor b. }Daha sonra hamle bgelen ana kadar aux şimdi elimizdeki:

Main [ ... 0 a | b 0 ...] Aux

|O bit benzeri OR alır çünkü o zaman, hiçbir şey yapmaz ave 0. aHer zaman pozitif olduğunu bildiğimiz için IP doğuya döner (çünkü batıya dönemez). Bu, programın ana döngüsünü başlatır. Karşılaştırmak için kısa bir doğrusal bölümle başlıyoruz ave b:

=   Swap tops of stacks, i.e. swap a and b.
:   Duplicate b.
{   Pull a over to main.
:   Duplicate a.
}   Push one copy back to aux.
-   Compute b-a.

IP şimdi başka bir kavşakta. İlk olarak, sonucun olumlu olduğu durumu ele alalım. Bu demektir b > aki bir tekrar daha yapmamız gerekiyor. Bu yineleme de tamamen doğrusaldır. Yığınların şu anda olduğuna dikkat edin:

Main [ ... 0 b (b-a) | a 0 ...] Aux

;   Discard b-a.
:   Duplicate b.
(   Decrement.
&   Bitwise AND with b, clearing the least-significant 1.
=   Swap new b with old a.
:   Duplicate a.
)   Increment.
|   Bitwise OR with a, setting the least-significant 0.

Ve sonra döngünün başlangıcına geri döndük ( atekrar pozitif olduğu için IP tekrar doğuya dönüyor).

Bir noktada b-aartık pozitif değilse , IP diğer iki yoldan birini alacaktır. Her iki durumda da biz getirme Not aile {daha sonra IP kavisi takip köşe çarptı ve sonra baskı aile !. Şimdi yığının üst kısmı yine b-aher iki durumda da IP'nin doğuya doğru hareket edeceği anlamına geliyor. Geriye kalan tek şey şimdi kısa bir doğrusal bit:

;   Discard b-a.
\   Print a linefeed.
!   Print b.
@   Terminate the program.

1

Java 7, 73 bayt

void d(int x,int y){while(x<y){x|=x+1;y&=y-1;}System.out.print(x+","+y);}

Test edilmemiş ve test durumları:

Burada deneyin.

public class Main{
  static void d(int x, int y){
    while(x < y){
      x |= x + 1;
      y &= y - 1;
    }
    System.out.print(x + "," + y);
  }

  public static void main(String[] a){
    print(2, 3);
    print(3, 2);
    print(8, 23);
    print(42, 81);
    print(38, 41);
    print(16, 73);
    print(17, 17);
  }

  public static void print(int a, int b){
    d(a, b);
    System.out.println();
  }
}

Çıktı:

3,2
3,2
31,0
63,0
47,32
23,0
17,17

Eski meydan kuralları [ 126 125 123 bayt]:

NOT: Eski sınama kuralları girdi olarak iki gevşek tamsayı yerine iki tamsayı dizisi kullanmıştır.

void d(int[]a,int[]b){int i=-1,x,y;while(++i<a.length){x=a[i];y=b[i];for(;x<y;x|=x+1,y&=y-1);System.out.println(x+","+y);}}

Bir yanıt gönderdikten sonra meydan okumayı değiştirdiğim için üzgünüm, ancak meydan okumayı biraz basitleştirdim. (artık listeyi tekrarlamanız gerekmez). Neyse ki bu kısaltmanıza izin verecektir.
DJMcMayhem

@DrGreenEggsandIronMan Düzenlendi. Ftw, insanlar cevaplarını gönderdikten sonra kuralları değiştirmek genellikle kötü bir uygulamadır. (PS: Yukarıda herkesin cevabı hakkında yorum
yapmadınız

1
whileDöngününüzü böyle yeniden yazabilirsinizfor(;x<y;x|=x+1,y&=y-1);
cliffroot

O olduğunu biliyorum. -_-Keşke baştan daha iyi yazsaydım. Neyse ki bu mantıksız veya sert bir değişiklik değil. Ayrıca, evet her cevap hakkında yorum yapmadım, ama her kullanıcıyı bilgilendirdim. Aynı kullanıcıyı birden çok kez bilgilendirmek istemiyordum. Dennis'in gönderisi hakkında yorum yapmadım, ancak bunun nedeni beni başlangıçta değiştirmem için teşvik eden kullanıcılardan biriydi.
DJMcMayhem

1

JavaScript (ES6), 33 bayt

f=(n,m)=>n<m?f(n|n+1,m&m-1):[n,m]

Miles tarafından cevap basit bağlantı noktası.


f=Başlangıcı unuttun : P
Mama Fun Roll

1
"Tekrar" ;-) unuttun
Neil

1

Julia, 27 bayt

x<|y=x<y?x|-~x<|y&~-y:[x,y]

Çevrimiçi deneyin!

Nasıl çalışır

İkili operatörü <|amacımız için tanımlarız . Julia'nın son sürümlerinde tanımlanmamıştır, ancak yine de ayrıştırıcı tarafından operatör olarak tanınır. İken \(açıkça tamsayılar için tanımlanmadı) bir byte kısadır, yüksek öncelik değiştirerek gerektirecektir x|-~x<|y&~-yile (x|-~x)\(y&~-y)böylece bayt sayısını artırarak,.

<|ilk argümanının ikincisinden kesinlikle daha az olup olmadığını kontrol eder. Öyleyse, kendini x | - ~ x = x | (x + 1) ve y & ~ -y = y & (y - 1) .

İlave yana 1 için X geçiş yapar tüm arka grubu bitleri ve en sertleşmemiş bit x | (x + 1) en düşük ayarlanmamış biti değiştirir (ve başka bit yok). Benzer şekilde, çıkarma yana 1 den y tüm arka sertleşmemiş bit ve düşük bit set geçiş yapar, y (y + 1) en grubu bit geçiş yapar.

Son olarak, x <y eşitsizliği artık kalmazsa, [x, y]<| çiftini döndürür .


0

MATLAB, 67 66 bayt

loop:

function[]=f(x,y)
while x<y
x=bitor(x,x+1);y=bitand(y,y-1);end
x,y

özyinelemeli (67 bayt):

function[]=f(x,y)
if x<y
f(bitor(x,x+1),bitand(y,y-1))
else
x,y
end

Diğer anwers gibi bitleri değiştirmek için aynı yaklaşım.


0

Clojure, 63 bayt

#(if(< % %2)(recur(bit-or %(inc %))(bit-and %2(dec %2)))[% %2])

Benim kullandığım yöntemle aynı çözeltisi J.

kullanım

=> (def f #(if(< % %2)(recur(bit-or %(inc %))(bit-and %2(dec %2)))[% %2]))
=> (f 38 41)
[47 32]
=> (map (partial apply f) [[2 3] [3 2] [8 23] [42 81] [38 41] [16 73] [17 17]])
([3 2] [3 2] [31 0] [63 0] [47 32] [23 0] [17 17])
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.