Akılsız bit işlemleri


16

Golf oynamaktan hoşlanıyorum dc, ama bazen sinirli oluyorum çünkü dcbitsel operasyonları yok.

Meydan okuma

C bitsel operasyonların eşdeğer uygulamak dört adlandırılmış işlevleri sağlayın &, |, ~ve ^(ikilik VE, VEYA, DEĞİL ve XOR). Her işlev ~, en az 32 bit işaretsiz tam sayı olan iki işlenen alır ( yalnızca bir tane alır). Her işlev, işlenenlerle aynı bit genişliğinde işaretsiz bir tamsayı döndürür.

kısıtlama

Yalnızca tarafından desteklenen işlemleri kullanabilirsiniz dc. Bunlar:

  • + - * / Aritmetik toplama, çıkarma, çarpma ve bölme
  • ~ modulo (veya diliniz destekliyorsa divmod)
  • ^ üstalma
  • | modüler üs alma
  • v kare kök
  • > >= == != <= < standart eşitlik / eşitsizlik operatörleri
  • >> <<bit kaydırma operatörleri. dcbunlara sahip değil, ama önemsiz bir şekilde 2 güç ile bölünme / çarpma açısından uygulandığından, bunlara izin vereceğim.

Kontrol yapıları dc(özyinelemeli) makrolar ve (in) eşitlik işlemleri kullanılarak beceriksizce inşa edilebilir. Dilinizin sahip olduğu yerleşik kontrol yapılarını kullanabilirsiniz.

Sen de mantıksal operatörler kullanabilir && || ! bu doğrudan kullanılamaz halde dc.

Sen bitsel operatörleri kullanmamalıdır & , |, ~ve ^ya trivially bunları uygulamak herhangi bir işlev.

Ayrıca, dize işleçlerinin veya işlevlerinin yerleşik temel dönüşümünü kullanmamalısınız.


Lütfen yanıtınızı doğrulamaya yardımcı olması için bir test programı veya çevrimiçi derleyici snippet'i (golf skoruna dahil değildir) sağlamayı düşünün.


İstenen işlemi parametre olarak alan bir fonksiyon uygulayabilir miyiz? Ayrıca, bit kaydırma için bir stand-2 olarak tamsayıya bölebilir miyiz?
xnor

@xnor Dört operatörün her birini uygulayan 4 ortak işlev sağlamalısınız. Ayrıca, dört genel işlev tarafından çağrılan ortak / yardımcı özel yöntemlere / işlevlere sahip olabilirsiniz, ancak bunların hepsinin golf skoruna dahil edilmesi gerekecektir.
Dijital Travma

7
@xnor Siz ve sadece xnor operatörünü de uygulamalısınız ;-)
Dijital Travma

Dört anonim işlevin bir listesini oluşturabilir miyim?
xnor

@MariaTidalTug Dört işlev listesinin döndürülmesi ile el ile seçilmesi ve uygulanması (xnor'ın önerdiği gibi) ile seçim parametresini kabul eden ve seçimi kendisi yapan (wolfhammer'ın yanıtladığı gibi) bir işleve sahip olmak arasındaki etkili fark nedir? Her ikisi de, kod boyutunu kullanıcı koduna yükledikleri için, adlandırılmış dört işleve sahip olma noktasını zayıflatır gibi görünüyor. Hatta bu durumda kullanıcı kodu muhtemelen ikinci durumda olduğundan daha karmaşık olduğu için, eski kodun daha fazla zayıflattığını iddia ediyorum.
Runer112

Yanıtlar:


4

C, 134

C önişlemcisi kötüye kullanımı oldukça eğlencelidir. Temel olarak, bu makro 3 işlevlerini tanımlar a, ove x, için and, orve xorsırasıyla. Bu işlemler için algoritmada tek fark, sonuçtaki biti ayarlama ölçütleridir.

notfonksiyonudur n.

#define f(n,c)n(a,b){for(r=0,i=31;i+1;--i)if(((a>>i)%2+(b>>i)%2)c)r+=1<<i;return r;}
i,r;n(a){return 0xffffffff-a;}f(a,/2)f(o,)f(x,%2)

Test programı (uzun zaman alıyor, hiç optimize etmedim, ancak MAX_INT ile ilgili olanların yanında mümkün olan her test durumunu test ediyor):

#define m_assert(expected, condition, actual)\
    if(!((expected) condition (actual)))\
        printf("assert fail @ line %i, expected: %x, actual %x, condition "#condition"\n", __LINE__, expected, actual);

int main()  {
    unsigned int j,k;
    for(j=0; j<0xffff; ++j)    {
        m_assert(~j, ==, n(j));
        for(k=0; k<0xffff; ++k)    {
            m_assert(j & k, ==, a(j,k));
            m_assert(j | k, ==, o(j,k));
            m_assert(j ^ k, ==, x(j,k));
        }
    }

1
ayy. bunu unuttum. Şimdi düzeltti.
pseudonym117

4

76 baytlık

Genellikle sinir bozucu, ama biz gerçekten çünkü şimdi, hoşgeldin - ised da bitsel faaliyeti bulunmamaktadır gerek bunları uygulamaktır.

İşlevler numaralı bellek yuvalarında saklanır (ayrıntılı adlar olmadan).

İkili dosyaya ve ikili dosyaya dönüştürme:

@5{:x/2^[32]%2:};
@6{:x@:2^[32]:};

DEĞİL olabilir @1{:$6::{1-$5::x}:}ama sadece çıkarmak daha kolaydır:

@1{:2^32-x-1:};

VEYA:

@2{:$6::{$5::{x_0}:+$5::{x_1}>0}:};

VE:

@3{:$6::{$5::{x_0}:*$5::{x_1}}:};

XOR:

@4{:$6::{$5::{x_0}:<>$5::{x_1}}:};

Bu bizi 156 bayta (satırsonu ve noktalı virgülle) getirir. Bir test kodu yalnızca ($ 1, 2 $, 3 $, 4 $ adları altında bulunan art arda DEĞİL, OR, AND, XOR) olacaktır:

> $1::{6}
4294967289
> $2::{12 11}
15
> $3::{12 11}
8
> $4::{12 11}
7

Ama elbette OR ve NOT gerçekten ihtiyacımız olan şeyler ve işler basitleştirilebilir:

@1{:2^32-x-1:};
@2{:@+{2^U{?{$5::x}%32}}:};
@3{:${1 2 1}::x:};
@4{:$3::{$2::x${1 2}::x}:};
@5{:x/2^[32]%2:};

Bu 109 karakter. Yeni satırlar ve noktalı virgüller atlandığında ve biraz daha fazla golf ile 76 karakterimiz var:

@3{@1{:2^32-x-1:}@2{:@+{2^U{?{x/2^[32]%2}%32}}:}$1}@4{{:$2::x${1 2}::x:}$3};

1

Nim (537) (490)

Nim Derleyici 0.10.2

Ben nim öğrenmek için bir sebep arıyordum, işte başlıyoruz.

Kod golf için, değişken parametreleri ve örtük getirileri kaldıraç var. Belgelere göre değişken parametreler daha az yığın verimlidir. Şahsen, örtük getirileri okumakta zorlanıyorum ve muhtemelen sadece önemsiz prosedürlerde kullanacağım.

Algoritmalara gelince, bunlar yeterince basittir. NOT hariç tüm işlemler için, her bir biti karşılaştırır ve bunları manuel olarak beklenen doğruluk tablomuzla karşılaştırırız. Her bir biti çıkış değişkenimizde yol boyunca gerektiği şekilde ayarlayın. Nim'de sonuç, örtük dönüş değeridir.

Not: OR prosedürünü kullanmamıza izin verilip verilmediğini bilmiyordum, böylece iki boolean koşulunu iddia etmek için notZero prosedürü yerine koyuldu.

proc s(x, y, b: var int)=
  x = x div 2
  y = y div 2
  b *= 2

proc n(x: var int): int =
  return -(x+1)

proc a(x, y: var int): int =
  var b = 1
  while x > 0 and y > 0:
    if (x mod 2  + y mod 2) == 2:
      result += b

    s(x,y,b)

proc o(x, y: var int): int =
  var b = 1
  while x + y > 0:
    if (x mod 2 + y mod 2) >= 1:
      result += b

    s(x,y,b)

proc r(x, y: var int): int =
  var b = 1
  while x + y > 0:
    if (x mod 2 + y mod 2) == 1:
      result += b

    s(x,y,b)

Hala daha iyi bir yöntem arıyoruz ...

İşte fışkırmamış versiyon artı kendi makinenizde çalıştırmak için tam test koşum takımı.
Sadece birkaç giriş çalıştırmak istiyorsanız, test senaryosu lite .


@MariaTidalTug Açıkladığınız için teşekkürler!
cory.todd

Bunu yeniden üretemem. Hesap makineniz temel 16 modunda mı?
cory.todd

Sahte171'e benzer bir test takımı ekledim.
cory.todd

1

CJam, 71 bayt

{:F;0{:R;2md@2md@+F~!2I#*R+}64fI\;\;}:B{"2-"B}:A{'!B}:O{0SB}:N{'(B}:X];

açıklama

"B : UInt64 UInt64 String -> UInt64
 Computes a bitwise operation on the two given unsigned integers. The operation
 is defined by the logical inverse of the result of evaluating the given string
 given the sum of two input bits.";
{
  :F;             "Save the operation string.";
  0               "Initialize the result to 0.";
  {               "For I from 0 through 63:";
    :R;             "Save the result.";
    2md@2md@        "Divide each input by 2 and collect the remainders as the
                     next pair of bits to process.";
    +F~!            "Compute the logical inverse of the result of evaluating
                     the operation string given the sum of the two bits.";
    2I#*            "Adjust the resulting bit to be in the correct output
                     position by multiplying it by 2^I.";
    R+              "Add the location-adjusted bit to the result.";
  }64fI
  \;\;            "Clean up.";
}:B

"A : UInt64 UInt64 -> UInt64
 Computes the bitwise AND of the two given unsigned integers.
 This is done by passing the inputs along to B with an operation such that:
   bit_out = !((bit_in_1 + bit_in_2) - 2)";
{"2-"B}:A

"O : UInt64 UInt64 -> UInt64
 Computes the bitwise OR of the two given unsigned integers.
 This is done by passing the inputs along to B with an operation such that:
   bit_out = !(!(bit_in_1 + bit_in_2))";
{'!B}:O

"N : UInt64 -> UInt64
 Computes the bitwise NOT of the given unsigned integer.
 This is done by passing the input and 0 along to B with an operation such that:
   bit_out = !((bit_in + 0))";
{0SB}:N

"X : UInt64 UInt64 -> UInt64
 Computes the bitwise XOR of the two given unsigned integers.
 This is done by passing the inputs along to B with an operation such that:
   bit_out = !((bit_in_1 + bit_in_2) - 1)";
{'(B}:X

];              "Clean up.";

Test odası

Bu kod, eşit dağıtılmış 64-bit imzasız girişlerle ve xor işlevlerimin ve xor işlevlerinin her birinin çalışmasını test eder ve sonucu yerleşik işleç tarafından üretilenle karşılaştırır. Değerlendirme operatörünün gereksiz kullanımı nedeniyle, oldukça yavaştır ve çevrimiçi tercümanla yaklaşık bir dakika sürebilir. Ancak her şey yolunda giderse, yürütme çıktı olmadan sona ermelidir, çünkü bulunan tutarsızlıklar yazdırılır.

N:L;
{:F;0{:R;2md@2md@+F~!2I#*R+}64fI\;\;}:B{"2-"B}:A{'!B}:O{0SB}:N{'(B}:X];
{;Y32#__mr*\mr+}2e2%2/{~:U;:V;"A&O|X^"2/{[{US@SV" = "UV5$~L}/9$2$={];}{]oLo}?}/"N~"[{U" = "U3$~Y64#(&L}/6$2$={];}{]oLo}?}/

0

JavaScript 294 267

@ AlexA. ve @ kennytm'in önerileriyle birkaç bayt daha tıraş edebildim.

Fonksiyonlar:

B=(n,m,t)=>{for(var p=4294967296,y=0;p>=1;p/=2)y+=t=='x'&&(n>=p||m>=p)&& !(n>=p&&m>=p)?p:0,y+=t=='a'&&n>=p&&m>=p?p:0,y+=t=='o'&&(n>=p||m>=p)?p:0,n-=n>=p?p:0,m-=m>=p?p:0
return y}
N=(n)=>{return 4294967295-n}
A=(n,m)=>B(n,m,'a')
O=(n,m)=>B(n,m,'o')
X=(n,m)=>B(n,m,'x')

misal:

var n = 300;
var m = 256;
console.log(X(n,m) + ", " + (n ^ m));
console.log(O(n,m) + ", " + (n | m));
console.log(A(n,m) + ", " + (n & m));
console.log(N(n) + ", " + (~n>>>0));
console.log(N(m) + ", " + (~m>>>0));

çıktı:

44, 44
300, 300
256, 256
4294966995, 4294966995
4294967039, 4294967039

2
Dört genel işlev sağlamanız gerekir - her biri AND, OR için. DEĞİL ve XOR. (Ayrıca, dört genel işlev tarafından çağrılan ortak / yardımcı özel yöntemlere / işlevlere sahip olabilirsiniz). Ayrıca, NOT eksik - muhtemelen tüm bunların en kolayı
Digital Trauma

Teşekkürler @AlexA. Baytları ekledim ve biraz daha golf oynadım.
wolfhammer

Sen sonra boşluk kaybedebilir forve değiştirme function B(n,m,t)ile B=(n,m,t)=>. Aynı şekilde diğer işlevler için.
Alex

42 4*(1<<30)4294967296 ve -1>>>04294967295 için kullanabilirsiniz . ② varBurada gerçekten gerekli mi? ③ (n,m)=>B(n,m,'a')yerine yazabilirsiniz(n,m)=>{return B(n,m,'a')}
kennytm
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.