ใช้ adder 8 บิต


12

ความท้าทาย

ใช้ฟังก์ชั่นที่รับจำนวนเต็มสองจำนวนซึ่งมีค่าอยู่ในช่วงตั้งแต่ 0 - 255 และส่งคืนผลรวมของจำนวนเต็ม mod 256 เหล่านั้นคุณสามารถใช้การปฏิเสธ bitwise (~), bitwise หรือ (|), ตัวดำเนินการเปลี่ยนบิต (>>, <<) และและการมอบหมาย (=)

สิ่งที่คุณไม่สามารถใช้รวมถึง (แต่ไม่ จำกัด เฉพาะ)

  • การบวกการลบการคูณและการหาร
  • ลูป
  • คำสั่งแบบมีเงื่อนไข
  • ฟังก์ชั่นการโทร

ใช้น้อยที่สุดของไบนารีหรือปฏิเสธไบนารีและกะบิตชนะการดำเนินงาน ในกรณีที่เสมอกันโซลูชันที่ได้รับความนิยมมากที่สุดจะเป็นผู้ชนะ เช่นเคยใช้ช่องโหว่มาตรฐาน

นี่คือตัวอย่างของแอดเดอร์ 2 บิตที่เรียบง่าย มันใช้การปฏิเสธไบนารี 77 รายการไบนารี ORS 28 รายการและ 2 บิตกะเป็นคะแนนรวม 107 (สามารถดูได้จากการรัน C preprocessor ด้วยgcc -E) มันสามารถทำให้มีประสิทธิภาพมากขึ้นโดยการลบ#defines และลดความซับซ้อนของการแสดงออกที่เกิดขึ้น แต่ฉันได้ทิ้งไว้เพื่อความชัดเจน

#include <stdio.h>

#define and(a, b) (~((~a)|(~b)))
#define xor(a, b) (and(~a,b) | and(a,~b))

int adder(int a, int b)
{
    int x, carry;
    x = xor(and(a, 1), and(b, 1));
    carry = and(and(a, 1), and(b, 1));
    carry = xor(xor(and(a, 2), and(b, 2)), (carry << 1));
    x = x | carry;
    return x;
}

int main(int argc, char **argv)
{
    int i, j;
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            if (adder(i, j) != (i + j) % 4) {
                printf("Failed on %d + %d = %d\n", i, j, adder(i, j));
            }
        }
    }
}

อัปเดต: เพิ่มตัวอย่างและเปลี่ยนเกณฑ์การให้คะแนนแล้ว


2
ทำไมไม่ bitwise "และ"?
rdans

@Ryan คนส่วนใหญ่คุ้นเคยกับประตู NAND มากกว่าประตู NOR :)
Orby

1
การเรียกซ้ำนับเป็นลูปหรือไม่
rdans

@ Ryan Recursion นับเป็นลูป แต่ฉันไม่แน่ใจว่าคุณจะใช้งานได้อย่างไรโดยไม่ต้องมีเงื่อนไข
Orby

มีการกำหนดโอเวอร์โฟลว์หรือสามารถส่งเอาต์พุตอะไรก็ได้หากโอเวอร์โฟลว์?
องค์การคอมมิวนิสต์สากล

คำตอบ:


8

Python 36 การดำเนินงาน

วิธีการที่เป็นลอการิทึมในพารามิเตอร์ "8"!

def add(a,b):
    H = a&b   #4 for AND
    L = a|b   #1 
    NX = H | (~L) #2
    K = NX 

    H = H | ~(K | ~(H<<1)) #5
    K = K | (K<<1) #2

    H = H | ~(K | ~(H<<2)) #5
    K = K | (K<<2) #2

    H = H | ~(K | ~(H<<4)) #5

    carry = H<<1 #1

    neg_res = NX ^ carry  #7 for XOR
    res_mod_256 = ~(neg_res|-256) #2
    return res_mod_256

ความคิดคือการคิดออกว่าดัชนีใดล้นและสาเหตุการดำเนินการ ในขั้นต้นนี้เป็นเพียงสถานที่ที่ทั้งสองaANDD มีb 1แต่เนื่องจากบิตที่ถูกบรรทุกอาจทำให้เกิดโอเวอร์โฟลว์ต่อไปจึงจำเป็นต้องพิจารณาซ้ำ

แทนที่จะทำการโอเวอร์โฟลว์แต่ละดัชนีลงในอันถัดไปเราจะเร่งกระบวนการโดยการย้าย 1 ดัชนีจากนั้น 2 ดัชนีจากนั้น 4 ดัชนีเพื่อให้แน่ใจว่าได้จดจำสถานที่ที่มีการล้น (H) และการล้นไม่สามารถเกิดขึ้นได้อีก (K) )


โซลูชันวนซ้ำง่ายขึ้นด้วยการทำงาน47 รายการ :

def add(a,b):
    H = a&b   #4 for AND
    L = a|b   #1 
    NX = H | (~L) #2

    c=H<<1  #1

    for _ in range(6): #6*5
        d = (~c)|NX
        e = ~d
        c = c|(e<<1)

    res = c ^ NX  #7 for XOR

    res_mod_256 = ~(res|-256) #2
    return res_mod_256

อุปกรณ์ทดสอบสำหรับผู้ที่ต้องการคัดลอก

errors=[]
for a in range(256):
    for b in range(256):
        res = add(a,b)
        if res!=(a+b)%256: errors+=[(a,b,res)]

print(len(errors),errors[:10])

9

C - 0

มันใช้โอเปอเรเตอร์นอก ~, |, >>, <<, และ = แต่ฉันเห็นวิธีแก้ปัญหาโดยใช้ตัวดำเนินการแคสติ้งและคอมม่าดังนั้นฉันเดาว่ากฎไม่เข้มงวดเกินไปหากไม่ใช้โอเปอเรเตอร์ต้องห้าม

unsigned char sum(unsigned char x, unsigned char y)
{
    static unsigned char z[] = {
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
        32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
        48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
        64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
        80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
        96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
        112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
        128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
        144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
        160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
        176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
        192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
        208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
        224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
        240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
        0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
        16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
        32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
        48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
        64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
        80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
        96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
        112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
        128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
        144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
        160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
        176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
        192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
        208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
        224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
        240,241,242,243,244,245,246,247,248,249,250,251,252,253,254
    };

    return (&z[x])[y];
}

เห็นได้ชัดว่านี่เป็นช่องโหว่ แต่ +1 สำหรับการชี้ให้เห็น
Orby

7

หลาม, คะแนน = 83 80

def g(x,y):
    for i in xrange(7):
        nx = ~x
        ny = ~y
        x,y = ~(x|ny)|~(nx|y), (~(nx|ny))<<1
    x = ~(x|~y)|~(~x|y)
    return ~(~x|256)

คลี่วง มันคือ 10 ops ต่อ loop คูณ 7 loops, 7 สำหรับ xor สุดท้ายและ 3 เพื่อ squash บิต 9 ที่ส่วนท้าย

ใช้สมการx+y = x^y + 2*(x&y)โดยทำซ้ำ 8 ครั้ง yแต่ละครั้งที่มีอีกหนึ่งศูนย์บิตที่ด้านล่างของ


7

C, คะแนน: 77 60

มีไว้สำหรับขุมนรก206 169 131 ไบต์:

#define F c=((~(~c|~m))|n)<<1;
a(x,y){int m=(~(x|~y))|~(~x|y),n=~(~x|~y),c;F F F F F F F return (unsigned char)(~(m|~c))|~(~m|c);}

ขยาย:

int add(x,y)
{
    int m=(~(x|~y))|~(~x|y);
    int n=~(~x|~y);
    int c = 0;
    c=((~(~c|~m))|n)<<1; 
    c=((~(~c|~m))|n)<<1; 
    c=((~(~c|~m))|n)<<1; 
    c=((~(~c|~m))|n)<<1; 
    c=((~(~c|~m))|n)<<1;    
    c=((~(~c|~m))|n)<<1; 
    c=((~(~c|~m))|n)<<1; 
    return (int)((unsigned char)(~(m|~c))|~(~m|c));
}

โดยพื้นฐานแล้วเป็นวิธีแก้ปัญหาเดียวกัน (ทางคณิตศาสตร์) ที่@KeithRandall @JuanICarrano เกิดขึ้น แต่ใช้ประโยชน์จากความสามารถของ C ในการเล่นอย่างรวดเร็วและหลวมกับตัวแปรและพอยน์เตอร์เพื่อล้างทุกอย่างหลังจาก 8 บิตแรกโดยไม่ต้องใช้ตัวดำเนินการเพิ่มเติม

ขึ้นอยู่กับ endian-ness ของเครื่องและ sizeof () int และ char แต่ควรสามารถจัดพอร์ตไปยังแอพพลิเคชั่นเฉพาะเครื่องจักรส่วนใหญ่ด้วยตัวชี้คณิตศาสตร์ที่เหมาะสม

แก้ไข:นี่คือความท้าทายที่ C (หรือภาษาระดับต่ำอื่น ๆ ) จะมีความแตกต่างที่โดดเด่นที่ - ถ้ามีคนมากับอัลกอริทึมที่ไม่ต้องดำเนินการ


unsigned charหากคุณกำลังจะจัดการห่อรอบวิธีการที่คุณก็สามารถโยนไป มันสะอาดและพกพาได้มากกว่า
Orby

@Orby - ฉันเดาว่าการพิมพ์ออกunsignedมาไม่เป็นธรรมชาติสำหรับฉันในการตีกอล์ฟ แน่นอนคุณ - อัปเดต
องค์การคอมมิวนิสต์สากล

4

Python - คะแนน66 64

def xand(a,b):
    return ~(~a|~b) #4

def xxor(a,b):
    return (~(a|~b))|~(~a|b) #7

def s(a,b):
    axb = xxor(a,b)   #7
    ayb = xand(a,b)   #4

    C = 0
    for i in range(1,8):
        C = ((xand(C,axb))|ayb)<<1    #(1+1+4)x7=6x7=42

    return xxor(axb,xand(C,255))    #7 + 4 = 11
    #total: 7+4+42+11 = 64

มันเป็นสมการสำหรับ adder ระลอก C คือการพกพา คำนวณได้ครั้งละหนึ่งบิต: ในการทำซ้ำแต่ละครั้งการทำซ้ำจะถูกปล่อยไปทางซ้าย ตามที่ระบุโดย @Orby เวอร์ชันดั้งเดิมไม่ได้ทำการเพิ่มเติมแบบแยกส่วน ฉันแก้ไขและยังบันทึกวงจรในการวนซ้ำเนื่องจากการพกพาครั้งแรกจะเป็นศูนย์เสมอ


3
ทำได้ดี แต่รหัสของคุณไม่ถูกต้อง (เช่นs(255,2)ส่งคืน257มากกว่า1) คุณสามารถแก้ไขได้โดยเปลี่ยนบรรทัดสุดท้ายreturn ~(~xxor(axb,C)|256) ที่เพิ่ม 3 คะแนน
Orby

2

C ++ - คะแนน: 113

#define ands(x, y) ~(~x | ~y) << 1
#define xorm(x, y) ~(y | ~(x | y)) | ~(x | ~(x | y))

int add(int x, int y)
{
int x1 = xorm(x, y);
int y1 = ands(x, y);

int x2 = xorm(x1, y1);
int y2 = ands(x1, y1);

int x3 = xorm(x2, y2);
int y3 = ands(x2, y2);

int x4 = xorm(x3, y3);
int y4 = ands(x3, y3);

int x5 = xorm(x4, y4);
int y5 = ands(x4, y4);

int x6 = xorm(x5, y5);
int y6 = ands(x5, y5);

int x7 = xorm(x6, y6);
int y7 = ands(x6, y6);

int x8 = xorm(x7, y7);
int y8 = ands(x7, y7);

return (x8 | y8) % 256;
}

add(1, 255)กำลังส่งคืน 128 สำหรับฉัน @Ryan
Orby

@ หรือแก้ไขแล้วตอนนี้
rdans

%ไม่ได้อยู่ในรายชื่อของผู้ประกอบการที่ได้รับอนุญาตคือ~, |, และ>> <<อาจจะแทนที่ด้วยands(x8|y8, 255)>>1?
Orby

ที่จริงแล้ว~(~x8 | y8 | 0xFFFFFF00)จะทำเคล็ดลับอย่างดีโดยมีเพียง 4 คะแนนของคุณ
Orby

2
แต่จะไม่สร้างแบบbyteแทนที่จะintทำให้มันล้นโดยอัตโนมัติ?
ภูมิใจ haskeller
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.