Komşularıyla bitleri değiştirin


26

Görev tanımı

Bir tamsayı verildiğinde, k> 0 tüm tamsayıları için (2k – 1) - ve 2k - en az anlamlı bitlerini değiştirin . Bu, OEIS'deki A057300 dizisidir .

(Sayının “sonsuz sayıda” öncü sıfıra sahip olduğu varsayılır. Pratikte bu, tek bir 0 bit ile tek uzunluklu sayılar hazırlamak anlamına gelir.)

görüntü tanımını buraya girin

Bu , bu yüzden en kısa kod (bayt cinsinden) kazanır.

Test durumları

0 -> 0
1 -> 2
9 -> 6
85 -> 170
220 -> 236
1827 -> 2835
47525 -> 30298

5
Bu sayının bit kayması gibi şeyler için int olarak uygun olduğunu varsayabilir miyiz?
xnor

1
@xnor: Bence bu varsayılan / topluluk fikir birliğidir (aksi halde C vb. cevaplar her zaman yanlış olur)? Çok emin! :)
Lynn

@ Lynn: C unsigned char array_of_bytes[1024]beklediğiniz şekilde çalışmayı gerektirir (örneğin, 1024 * CHAR_BITgirişli bir bitfield olabilir ). İsteğe bağlı uzunluktaki girişleri destekleyen çoğu cevabın CHAR_BIT, baytlar arasında bitlerin kaydırılması zahmetli olduğu için eşit olacağını varsayardım . Bu yüzden kesinlikle k256 gibi sabit bir boyuta, AES için uygun bir şey gibi bir destek koyabilirsiniz ve 256bit tamsayı türü olmayan diller döngü kullanmak zorunda kalır. Bu SIMD vektörlerini x86 asm cevabı için göz önünde bulundurarak değerlendirebilir: P
Peter Cordes

2
@Geobits'i Minibits ile değiştirdim
Optimizer

Yanıtlar:



20

Python 2, 26 bayt

lambda n:2*n-3*(4**n/3&n/2)

Biraz numara!

Say ikilik nbiçiminde ...ghfedcbavardır. Sonra, onu diğer bütün parçalara bölebiliriz.

n   = o + 2*e
n   = ...hgfedcba
o   = ...0g0e0c0a
2*e = ...h0f0d0b0

Ardından, bit anahtarlamalı sonuç solarak ifade edilebilir s=2*o+e.

s   = 2*o + e
s   = ...ghefcdab
2*o = ...g0e0c0a0
e   = ...0h0f0d0b

Biz daha ziyade yalnızca birini hesaplamak istiyorum eve obiz ifade böylece, o=n-2*eve yerine

s=2*(n-2*e)+e = 2*n-3*e

Yani, şimdi eaçısından ifade etmek kalır n. Sayı M=4**n/3, ...10101010101ikili sayılar için maske görevi gören ikili biçimde oluşur . Üs nolmasını sağlar Myeterince uzun olduğunu. Bu değeri bit andyönünde alarak ve istediğiniz gibi n/2verir e.

n/2     = ...hgfedcb
M       = ...1010101
n/2 & M = ...h0f0d0b = e

Onun yerine ifade edebilen eaçısından o e=(n-o)/2veren s=(n+o*3)/2xsot bir optimizasyon bir bayt sayesinde kazandırır,.

lambda n:n+(n&4**n/3)*3>>1

Büyük açıklama ve maskeyi yalnızca bir kez çıkartarak kullanmak için güzel bir numara n. Ancak, ters "tek" vs "çift" bit adlandırma kuralını tercih ederim. LSB bit 0'dır, hatta (ilk bit olsa bile). Karıştırıcıların genellikle bir dizine sahip öğeleri seçtiği SIMD programlamasında, dizinler 0'dan sayılır, bu nedenle düşük öğeyi eşit bir öğe olarak kabul etmek normaldir. örneğin[ 3 2 1 0 ]
Peter Cordes,

İfadenizi kullanarak bir C cevabı ekledim. Dijital Travma'nın C cevabı - byte tasarrufları için tüm krediler buna bağlıdır.
Peter Cordes,

2
26:lambda n:n+(n&4**n/3)*3>>1
xsot

@PeterCordes C kodunuz benim için gcc 4.8.3 ve varsayılan ayarlarla çalışıyor. giriş 2 için 1f(x){return x+((x&~0U/3)*3)>>1;} değerini döndürür .
Dennis,

@Dennis: Evet, benim için çalışıyor C, benim hatam. Aslında ifadeyi calc(aka apcalc) olarak test ediyordum, aslında C'yi değil. 32bit veya ikisinin tamamlayıcısını kesmeye ihtiyacım olmadığı için iyi olacağımı düşündüm. İfadenin doğru göründüğünü düşünmedim, bu yüzden yanlış testlerime inanmaya istekliydim. Ama yine de, sürtükler geliştirmek için daha iyi bir REPL'e ihtiyacım var. Baska öneri? (İdeal olarak Linux komut satırı, bc -lya da gibi calc, ama aslında int32_t/ / uint32_tveya bir şeyi
Peter Cordes,

10

C işlevi, 38

Bit-Raketi çevirmek:

f(x){return(x&~0U/3*2)/2+(x&~0U/3)*2;}

Ideone.


Veya eğlencesi için:

C özyinelemeli işlevi, 43

Uyarınca OEIS formül ,a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

f(x){return x>3?4*f(x/4)+f(x%4):x%3?3-x:x;}

veya

f(x){return x>3?4*f(x/4)+f(x%4):x%2*2+x/2;}

Ideone.


1
xnor'ın ifadenin zekice dönüşümü, bunu C'deki 32 bayta indirdi. Ben, ayrı bir cevap olarak gönderdim, çünkü oldukça farklı bir yaklaşım.
Peter Cordes,

8

CJam, 16 14 13 bayt

ri4b4e!2=f=4b

Burada test et.

açıklama

ri  e# Read input and convert to integer.
4b  e# Get base-4 digits.
4e! e# Push all permutations of [0 1 2 3].
2=  e# Select the third one which happens to be [0 2 1 3].
f=  e# For each base-4 digit select the value at that position in the previous
    e# list, which swaps 1s and 2s.
4b  e# Convert back from base 4.

Permütasyonlarla ilgili bu numara çok iyi!
Luis Mendo

7

Pyth, 9 bayt

iXjQ4S2)4

Pyth Compiler'da deneyin .

Nasıl çalışır

  jQ4      Convert the input (Q) to base 4.
 X   S2)   Translate [1, 2] to [2, 1].
i       4  COnvert from base 4 to integer.

5

JavaScript (ES6), 32 30 bayt

(n,m=0x55555555)=>n*2&~m|n/2&m

JavaScript tam sayılarının sınırlamaları nedeniyle yalnızca 1073741823’e kadar çalışır. 38 36 bayt 4294967295'e kadar çalışıyor:

(n,m=0x55555555)=>(n*2&~m|n/2&m)>>>0

Düzenleme: @ user81655 sayesinde 2 bayt kaydedildi.

51 byte 4503599627370495 kadar çalışır:

n=>parseInt(n.toString(4).replace(/1|2/g,n=>3-n),4)

Could n<<1olmak n*2?
user81655 14

@ user81655 Ve ben de kullanabilirim n/2! Bunları neden daha önce düşünmediğimi bilmiyorum.
Neil

Hiç görmedim >>>... bu nedir?
Titus

@Titus Bu gibi >>>ama imzasız bir vardiya yapıyor. >>>0temel olarak 32 bit işaretsiz tam sayıya dönüştürür.
Neil

5

x86 asm işlevi: 14 bayt makine kodu

uint64_t versiyonu: 24 bayt

x86-64 SysV arama kuralı ( xin edi), ancak bu aynı makine kodu 32bit modunda da çalışacaktır. ( leaİrade çözülürken lea eax, [edi + eax*2], hangi aynı sonuçları verir ).

0000000000000040 <onemask_even>:
  40:   89 f8                   mov    eax,edi
  42:   25 55 55 55 55          and    eax,0x55555555
  47:   29 c7                   sub    edi,eax
  49:   d1 ef                   shr    edi,1
  4b:   8d 04 47                lea    eax,[rdi+rax*2]
  4e:   c3                      ret    
4f: <end>

0x4f - 0x40 = 14 bayt

Bu, xnor'ın mükemmel maske-bir kez fikrini ters yönde kullanmaktan derleyici çıktısıdır . (Ve zıt terminoloji: düşük bit, garip olmayan, bit 0'dır.)

unsigned onemask_even(unsigned x) {
  unsigned emask = ~0U/3;
  unsigned e = (x & emask);
  return e*2 + ((x - e) >> 1);
}

Derleyicinin yaptığı hakkında herhangi bir gelişme bulamadım. mov eax, 0x555.../ Olarak yazmış olabilirim and eax, edi, ama bu aynı uzunluk.


64bit tamsayılar için aynı işlev 24 bayt alır (godbolt bağlantısına bakın). movabs rax, 0x55...Maskeyi bir kayıt defterinde oluşturmak için 10 bayttan daha kısa bir yol görmüyorum . (x86'nın divtalimatı clunky, bu yüzden herkesin 3'e göre imzasız bölümü yardımcı olmuyor.)

Maskeyi rax'ta üretmek için bir döngü oluşturdum, ancak 10 byte (tam olarak aynı uzunluk mov imm64).

# since 0x55 has its low bit set, shifting it out the top of RAX will set CF
0000000000000000 <swap_bitpairs64>:
   0:   31 c0                   xor    eax,eax      ; old garbage in rax could end the loop early
0000000000000002 <swap_bitpairs64.loop>:
   2:   48 c1 e0 08             shl    rax,0x8
   6:   b0 55                   mov    al,0x55      ; set the low byte
   8:   73 f8                   jnc    2 <swap_bitpairs64.loop>  ; loop until CF is set
000000000000000a <swap_bitpairs64.rest_of_function_as_normal>:
 # 10 bytes, same as   mov  rax, 0x5555555555555555
 # rax = 0x5555...
   a:   48 21 f8                and    rax,rdi
   ...

Var olan baytların hiçbirinin raxdüşük bit kümesine sahip olmadığını bilseydik, bunu atlayabiliriz xorve bu 8 bayt uzunluğunda olur.

Bu cevabın önceki bir sürümü loopinsn'i kullanan 10 baytlık bir döngüye sahipti, fakat 0xFFFFFFFFFFFFFF08sadece belirlediğim için en kötü durumdaki yineleme çalışma süresine sahipti cl.


5

Oasis , 17 bayt (rakipsiz)

n4÷axxn4÷xxe+3120

Çevrimiçi deneyin!

Oasis, dizilerde uzmanlaşmış, Adnan tarafından tasarlanan bir dildir .

Şu anda, bu dil özyineleme ve kapalı formu yapabilir.

Bu formülü kullanıyoruz: a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

Temel durumu belirlemek basittir: 3120Sonunda sadece bu anlamına gelir a(0)=0, a(1)=2, a(2)=1, a(3)=3.

n4÷axxn4÷xxe+3120
                0  a(0) = 0
               2   a(1) = 2
              1    a(2) = 1
             3     a(3) = 3

n                  push n (input)
 4÷                integer-divide by 4
   a               a(n/4)
    xx             double twice; multiply by 4
                   now we have 4a(n/4)
      n            push n (input)
       4÷xx        integer-divide by 4 and then multiply by 4
                   since there is no modulo currently, n%4
                   is built as n-(n/4*4)
           e       we should have done a(n-(n/4*4)), but this
                   is a shortcut for a(n-x) where x is the top
                   of stack. Therefore, we now have a(n-n/4*4)
                   which is a(n%4).
            +      add.

4

MATL , 10 bayt

BP2eP1ePXB

Çevrimiçi deneyin!

Dizinin ilk terimlerini üretmek için değiştirilmiş sürüm ( OEIS A057300 ).

açıklama

B     % Take input implicitly. Convert to binary array
P     % Flip
2e    % Convert to two-row 2D array, padding with a trailing zero if needed. 
      % Because of the previous flip, this really corresponds to a leading zero
P     % Flip each column. This corresponds to swapping the bits
1e    % Reshape into a row
P     % Flip, to undo the initial flipping
XB    % Convert from binary array to number. Display implicitly

3

zsh, 28 bayt

<<<$[`tr 12 21<<<$[[#4]$1]`]

Bir komut satırı argümanı olarak girdi alır, STDOUT'da çıktı verir.

Bash uyumlu değildir çünkü zsh'ye özgü temel dönüştürme sözdizimini kullanır.

                       $1     input (first command line argument)
                 $[      ]    arithmetic expansion
                   [#4]       output in base 4
              <<<             pass the result of this to...
      tr                      the `tr' command
         12 21                and replace 1s with 2s, 2s with 1s
     `                    `   evaluate the result...
   $[                      ]  in another arithmetic expansion, to convert back
                                to base 10
<<<                           output the result on STDOUT

3

Retina, 70 bayt

. +
, $ *
+ `(1 +) \ 1
$ 1x
x1
1
^
x
r` (). ().
$ 2 $ 1
1
x '
+ `X @
x @@
X * ( '*)
$ 0,1
0 $

Test odası. (Hafifçe değiştirilmiş.)

Eh, sadece eğlence için: 7 bayt

T`12`21

4 numaralı girişi girdi olarak alır ve 4 numaralı girişi çıkar.

Çevrimiçi deneyin!


4
Ben çatışıyorum. Cevabınızın alt yarısını, üst yarısını ise düşürmek istiyorum.
Dennis

1
@Dennis Şimdi bu bitlerin var.
Sızdıran Rahibe,

3

05AB1E, 8 bayt

4B12‡4ö

-5 baytlık @Adnan'a teşekkürler!

CP-1252 kodlamasını kullanır.

Çevrimiçi Deneyin!

Açıklama:

4B       - Take input and convert to base 4.
  12Â    - Push 12 bifurcated.
     ‡   - Transliterate [1, 2] to [2, 1].
      4ö - Convert to base 10.

2
Güzel, ancak 8 bayt 1 2‚2 1‚ile değiştirebilirsiniz 12Â.
Adnan

Güzel cevap! İşte 8 baytlık bir alternatif:4в2‰íJJC
Kevin Cruijssen

3

C, 32 30 29 bayt

f(x){return(x&~0U/3)*3+x>>1;}                // 30 bit version, see below

// less golfed:
f(x){return ((x & 0x55555555)*3 + x) >>1;}   //  >> is lower precedence than +

Algoritma , xsot'un xnor'ın Python cevabı hakkındaki yorumundan kopyalanmıştır. . Her iki yolu da maskelemek yerine, bir yolu maskeleyin ve birleştirin.

Bu , test ettiğim son sürümle aynıdır ve çalışır (çalışır. (X'e kadar 0x3FFFFFFFve x 30 için ayarlanmadığı sürece x için aşağıya bakın). Makine kodunda, mevcut asm cevabım ile aynı uzunlukta.


Yukarıdaki sürüm her zaman sonucun yüksek bitini temizler . En iyi güvenli sürüm 32 bayttır:

g(x){return 2*x-3*(x/2U&~0U/3);}   // safe 32bit version, works for all x

Python sürümünde bu sorun yoktur, çünkü python, sabit bir üst sınıra kesmek yerine, gerektiğinde isteğe bağlı bir tamsayı türü kullanır .


@Dennis: Argh, evet, teşekkürler. Testten sonra bu son değişikliği yaptım ve asm çıktısındaki farkı kaçırdım. Merak etme, yanlış göründüğünü düşünüyordum; Bunun >>düşük öncelikli olduğunu unutmuştum . Kuralların ne olduğunu tam olarak hatırlayacak kadar golf oynamıyorum, çünkü derleyici tehlikeli durumlarda ebeveynlerin önerdiği uyarıları beni gerçek kodla koruyor. : P
Peter Cordes

2
İfadedeki terimleri yeniden düzenleyerek bu boşluğu bırakabilirsiniz.
xsot

2

Javascript (ES6), 113 109 bayt

Upgoat sayesinde 4 bayt kurtarıldı

n=>+('0b'+/(..)+$/.exec('0'+n.toString`2`)[0].split``.reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])[0],2)

Nasıl çalışır

n=>+('0b'+                              //parse as binary literal
    /(..)+$/.exec('0'+n.toString`2`)[0] //convert to binary string with an even number of digits
        .split``                        //convert to array
        .reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])
                                        //swap all numbers
)

+('0b"+binary_string_here)`parseInt (..., 2) yerine kullanın
Downgoat

1

J, 20 bayt

4#.0 2 1 3{~4#.^:_1]

kullanım

>> f =: 4#.0 2 1 3{~4#.^:_1]
>> f 85
<< 170

Nerede >>STDIN ve <<STDOUT ise.

Ungolfed

to_base   =: 4 #.^:_1 ]
transpose =: 0 2 1 3 {~ to_base
from_base =: 4 #. transpose

Üç çatal.

Kenar notu

Resmi tercüman ^:_1tarafından değiştirilebilirinv 1 bayt tasarrufu .

Ancak, çevrimiçi tercümanların hiçbiri bunu uygulamıyor.



1

INTERCAL , 60 bayt

DOWRITEIN.1PLEASE.1<-!1~#21845'$.1~#43690DOREADOUT.1DOGIVEUP

Çevrimiçi deneyin!

INTERCAL için en doğal biçimde yapılan G / Ç ile 16 bitlik tamsayılar için çalışır: giriş, birkaç doğal veya yapılı dilden birinde yazılan ondalık basamağı dizisidir ve çıktı "kasaplı Romen rakamları" dır.

Bu, INTERCAL'in ikili operatörlerinin gerçekte sezgisel olarak kullanılabildiği nadir zorluklardan biridir, çünkü bitleri yeniden konumlandırmak onların hakkında bir şeydir. ( ) Öğesini seçin ve bunları ters sırayla tekrar birleştirin. Neyse ki bayt sayısı için, INTERCAL'in operatörleri tanımlanmış bir önceliğe sahip olmasa da (dilin hedefi önceliğe sahip olmadığı için), TIO'daki C-INTERCAL'in bu özel ifade için çok fazla gruplama gerektirmediği, ancak şu andan beri sadece bir bayt maliyeti olduğu ortaya çıktı. kısaltılabilir~ ) bitleri ikinci argümanındakilere karşılık gelen ilk argümanından alır ve sıfırla ve sağa (mingle ( ile doldurur ve .$ ), argümanlarının bitlerini ilk argümanın bitleri daha anlamlı olacak şekilde artar. Bu nedenle basit çözüm, daha az önemli alternatif bitleri ( .1~#21845) seçmek , daha önemli alternatif bitleri ( ) seçmek.1~#43690'.!

32 bit tam sayı desteği ile:

INTERCAL , 67 bayt

DOWRITEIN:1PLEASE:1<-':1~#0$#65535'$:1~#65535$#0DOREADOUT:1DOGIVEUP

Çevrimiçi deneyin!

INTERCAL, 32-bit değişmezlere izin vermez, bu aslında okumayı biraz daha kolaylaştırır , çünkü alternatif bitlerin seçilmesi için sihirli sabitlerin, biri 16-bit değişmezleri birbirine karıştırmak suretiyle inşa edilmeleri gerekir; hepsi (Aslında, 32-bit değişmezler olsa bile, bu daha kısa olacaktır. #0$#65535İki bayt kapalı #1431655765, ve diğeri için de geçerlidir.) Bu, tüm süreci INTERCAL için doğal olarak iyi bir şekilde iletir.

Operand aşırı yüklenmesinin sakar kullanımı ile alternatif bir yaklaşım :

INTERCAL , 71 bayt

DO:1<-:1/.2$.3PLEASEWRITEIN:2DO:1<-:2PLEASE:2<-.3$.2DOREADOUT:2DOGIVEUP

Çevrimiçi deneyin!

Bu, bununla karıştırıldığını bildirerek , girdiye ayarlayarak , sonra karıştırılarak çıkartarak tamamen seçim :1yapmaktan .2kaçınır . Yana olarak aşırı oldu , atar değerleri ve bu şekilde değerini elde ile sonuçlanır daha fazla önemli alternatif bit içeren ve daha az önemli değişken bit ihtiva etmektedir. Aşırı yüklenmiş durumla değiştirilebilseydi , bu iki 32 bit çözümün dört bayt kısalması olurdu , ancak.3:1.3.2:1.2$.3DO :1 <- :2.2.3:1:2.2:2.3PLEASE WRITE IN :1PLEASE WRITE IN :2 DO :1 <- :2:1CALCULATINGaşırı yükleme kullanmak için gerekli olduğu ortaya çıktı. Ayrıca, aşırı yüklenmenin kendisini programın başlatılmasından daha kısa bir yoldan DO:1<-:1/.2$.3yürütmenin daha kısa bir yolu olabileceğini hissediyorum , ancak bu INTERCAL olduğu için olamayacağımı da hissediyorum.


0

Mathematica, 44 bayt

Fold[3#+##&,#~IntegerDigits~4/.{1->2,2->1}]&

CJam cevabımdakilerle aynı yaklaşım: base-4'e dönüştürün, 1s ve 2s'i değiştirin, geri dönüştürün. Ayrıca, bir bayttan tasarruf etmek için FromDigitsbir Foldişlemle değiştirmek için alephalpha hilesini kullanır .


0

Aslında, 16 bayt

4@¡"21""12"(t4@¿

Çevrimiçi deneyin!

Açıklama:

4@¡"21""12"(t4@¿
4@¡               base 4 representation of n
   "21""12"(t     translate (swap 1s and 2s)
             4@¿  base 4 to decimal

0

J, 22 bayt

([:,_2|.\,&0)&.(|.@#:)

Temel 4 numarası yerine dizi manipülasyonuna dayalı alternatif yaklaşım.

kullanım

   f =: ([:,_2|.\,&0)&.(|.@#:)
   (,.f"0) 0 1 9 85 220 1827 47525
    0     0
    1     2
    9     6
   85   170
  220   236
 1827  2835
47525 30298

açıklama

([:,_2|.\,&0)&.(|.@#:)  Input: n
                   #:   Get the value as a list of base 2 digits
                |.@     Reverse it
(           )&.         Apply to the list of base 2 digits
         ,&0            Append a zero to the end of the list
    _2  \               Split the list into nonoverlapping sublists of size 2
      |.                Reverse each sublist
 [:,                    Flatten the list of sublists into a list
             &.(    )   Apply the inverse of (reversed base 2 digits)
                        to convert back to a number and return it

0

REXX, 88 bayt

n=x2b(d2x(arg(1)))
o=0
do while n>''
  parse var n a+1 b+1 n
  o=o||b||a
  end
say x2d(b2x(o))
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.