एक 8 बिट योजक को लागू करें


12

चुनौती

एक फ़ंक्शन को लागू करें जो दो पूर्णांकों को स्वीकार करता है जिनके मान 0 से 255 तक होते हैं और उन पूर्णांकों के योग को 256 प्रतिफल देता है। आप केवल बिटवाइज़ निगेटिव (~), बिटवाइज़ या (!), बिट शिफ्टिंग ऑपरेटर (>>, <<) का उपयोग कर सकते हैं। , और असाइनमेंट (=)।

जिन चीजों का आप उपयोग नहीं कर सकते हैं (लेकिन वे सीमित नहीं हैं)

  • जोड़, घटाव, गुणा और भाग
  • लूप्स
  • सशर्त बयान
  • फंक्शन कॉल

द्विआधारी या बाइनरी नकार का सबसे अच्छा उपयोग करता है, और बिट शिफ्ट ऑपरेशन जीतता है । एक टाई की स्थिति में, सबसे लोकप्रिय समाधान जीतता है। हमेशा की तरह, मानक खामियां लागू होती हैं।

यहाँ एक सरल 2-बिट योजक का एक उदाहरण है। यह 77 द्विआधारी नकारात्मक, 28 द्विआधारी अयस्कों, और 107 के कुल स्कोर के लिए 2 बिट-शिफ्ट का उपयोग करता है (इसे सी प्रीप्रोसेसर के साथ चलाकर देखा जा सकता है gcc -E)। यह #defineएस को हटाकर और परिणामी अभिव्यक्तियों को सरल करके बहुत अधिक कुशल बनाया जा सकता है , लेकिन मैंने उन्हें स्पष्टता के लिए छोड़ दिया है।

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

अद्यतन: उदाहरण और जोड़ा स्कोरिंग critera बदल दिया है


2
क्यों ठीक नहीं "और"?
rdans

@ रियान ज्यादातर लोग NOR गेट्स की तुलना में NAND गेट्स से ज्यादा परिचित हैं :)
Orby

1
क्या लूप के रूप में रिकर्सन की गिनती होती है?
rdans

@ रेयान रिकर्सियन एक लूप के रूप में गिना जाता है, हालांकि मुझे यकीन नहीं है कि आप इसे सशर्त विवरण के बिना कैसे लागू करेंगे।
ऑर्बी

अतिप्रवाह परिभाषित है या क्या मैं कुछ भी आउटपुट कर सकता हूं यदि यह ओवरफ्लो होता है?
कॉमिनटेन

जवाबों:


8

पायथन, 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में a है 1। लेकिन चूँकि बिट्स आगे चलकर अधिक फैलाव का कारण बन सकते हैं, इसलिए इसे पुनरावृत्त रूप से निर्धारित करने की आवश्यकता है।

प्रत्येक इंडेक्स को अगले एक में ओवरफ्लो करने के बजाय, हम 1 इंडेक्स, फिर 2 इंडेक्स, फिर 4 इंडेक्स को आगे बढ़ाते हुए प्रक्रिया को तेज करते हैं, यह सुनिश्चित करने के लिए कि उन जगहों को याद रखना है जहां ओवरफ्लो हुआ (एच) और जहां ओवरफ्लो किसी भी अधिक नहीं हो सकता है (के। )।


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

सी - ०

यह ~,।, >>, <<, और = के बाहर के ऑपरेटरों का उपयोग करता है, लेकिन मैं कास्टिंग और अल्पविराम ऑपरेटरों का उपयोग करके समाधान देखता हूं, इसलिए मुझे लगता है कि नियम बहुत सख्त नहीं है बशर्ते कि यह निषिद्ध ऑपरेटरों का उपयोग नहीं कर रहा है।

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।
ओर्बी

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 ऑप्स प्रति लूप समय 7 छोरों, 7 अंतिम एक्सोर के लिए, और 3 अंत में 9 वीं बिट स्क्वैश करने के लिए है।

x+y = x^y + 2*(x&y)इसे 8 बार दोहराकर समीकरण को लागू करता है । हर बार नीचे एक और शून्य बिट होता है y


7

सी, स्कोर: 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 के साथ आया था, लेकिन किसी भी अधिक ऑपरेटर का उपयोग करके पहले 8 बिट्स के बाद सब कुछ मिटा देने के लिए चर प्रकार और संकेत के साथ तेज और ढीली खेलने की सी की क्षमता का लाभ उठाता है।

मशीन के एंडियन-नेस पर निर्भर करता है और आकार () एक इंट और एक चार, लेकिन उचित पॉइंटर गणित के साथ अधिकांश मशीन विशिष्ट अनुप्रयोगों में पोर्ट किए जाने में सक्षम होना चाहिए।

EDIT: यह एक चुनौती है कि C (या अन्य निम्न स्तर की भाषाओं) में एक अलग ऊपरी हाथ होगा - जब तक कि कोई ऐसा एल्गोरिथम नहीं आता है जिसे ले जाने की आवश्यकता नहीं है।


यदि आप उस तरह से चारों ओर लपेट को संभालने के लिए जा रहे हैं, तो आप बस डाल सकते हैं unsigned char। यह क्लीनर और अधिक पोर्टेबल है।
ऑर्बी

@ ओबी - मुझे लगता है कि unsignedकोड गोल्फ में मेरे लिए टाइपिंग स्वाभाविक रूप से नहीं आती है। आप बिल्कुल सही हैं - अद्यतन।
कॉमिंटर

4

पायथन - स्कोर 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

यह एक तरंग योजक के लिए समीकरण है। सी कैरी है। यह एक समय में एक बिट की गणना की जाती है: प्रत्येक पुनरावृत्ति में लेफ्ट को प्रचारित किया जाता है। जैसा कि @Orby द्वारा बताया गया है, मूल संस्करण ने एक मॉड्यूलर जोड़ नहीं बनाया। मैंने इसे ठीक किया और पुनरावृति में एक चक्र भी बचाया, क्योंकि पहला कैरी-इन हमेशा शून्य होता है।


3
अच्छा काम है, लेकिन आपका कोड ठीक से नहीं लिपटता है (यानी s(255,2)रिटर्न के 257बजाय 1)। आप अपनी अंतिम पंक्ति को बदलकर इसे ठीक कर सकते return ~(~xxor(axb,C)|256) हैं जिसमें 3 अंक हैं।
ऑर्बी

2

सी ++ - स्कोर: 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 वापसी कर रहा है, @ रेयान।
ऑर्बी

@ इसके द्वारा अभी तय है
rdans

%अनुमति दी ऑपरेटरों, अर्थात् की सूची में नहीं है ~, |, >>, और <<। शायद इसके साथ बदलें ands(x8|y8, 255)>>1?
ऑर्बी

दरअसल, ~(~x8 | y8 | 0xFFFFFF00)आपके स्कोर को केवल 4+ के साथ अच्छी तरह से कर देगा।
ऑर्बी

2
लेकिन byteइसके बजाय प्रकार नहीं बना intयह स्वचालित रूप से अतिप्रवाह होगा?
गर्वित हैकेलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.