บวกไบนารีคนตาบอด


10

ลองนึกภาพคุณมีสองกล่องB(x)และB(y)แต่ละกล่องมีบิตที่ไม่รู้จัก - 0 หรือ 1 และเครื่องFที่สามารถเอ็กซเรย์และสร้างกล่องที่สามสำหรับB(x^y)( xor ) FยังสามารถคำนวณB(x*y)( และ ) ในความเป็นจริงนั้นเป็นเพียงกรณีพิเศษของการดำเนินการเดียวที่เครื่องสามารถดำเนินการได้ - ผลิตภัณฑ์ภายในแต่ละตัวแสดงด้วยF()ด้านล่าง

สำหรับสองอาร์เรย์ที่มีความยาวเท่ากัน

[B(x[0]), B(x[1]), ..., B(x[n-1])]
[B(y[0]), B(y[1]), ..., B(y[n-1])]

ผลิตภัณฑ์ภายในถูกกำหนดให้เป็น

B(x[0]*y[0] ^ x[1]*y[1] ^ ... ^ x[n-1]*y[n-1])

" แต่ละ " หมายถึงF()สามารถประมวลผลหลายคู่x[], y[]ในหนึ่งไป x[]และy[]จากหนึ่งคู่จะต้องมีความยาวเดียวกัน; x[]-s และy[]-s จากคู่ที่แตกต่างกันไม่จำเป็นต้อง

กล่องถูกแสดงด้วยรหัสจำนวนเต็มที่ไม่ซ้ำกัน

การใช้งานผลิตภัณฑ์ภายในแต่ละตัวใน JavaScript อาจดูเหมือน

var H=[0,1];          // hidden values, indexed by boxId
function B(x) {       // seal x in a new box and return the box id
  return H.push(x)-1;
}
function F(pairs) {   // "inner product each"
  return pairs.map(function (pair) {
    var r = 0, x = pair[0], y = pair[1];
    for (var i = 0; i < x.length; i++) r ^= H[x[i]] * H[y[i]];
    return B(r);
  })
}

(โปรดแปลข้างต้นเป็นภาษาที่คุณเลือก)

ให้สิทธิ์ในการF()ใช้งานตามความเหมาะสมสำหรับภาษาของคุณ (แต่ไม่สามารถเข้าถึงHหรือB()) และให้กล่องรหัสสองอาร์เรย์ซึ่งประกอบไปด้วยการแทนเลขฐานสองแบบ 16 บิตของจำนวนเต็มสองตัวaและbงานของคุณคือการผลิตกล่องรหัสสำหรับการเป็นตัวแทนไบนารีแบบ ของa+b(ทิ้งมากF()เกินไป) ด้วยจำนวนการโทรขั้นต่ำ

โซลูชันที่เรียกF()เวลาน้อยที่สุดจะเป็นผู้ชนะ ความสัมพันธ์จะถูกทำลายโดยการนับจำนวนx[],y[]คู่ทั้งหมดที่F()ถูกเรียกด้วย - น้อยกว่าดีกว่า หากยังคงถูกผูกไว้ขนาดของรหัสของคุณ (ไม่รวมการติดตั้งF()และผู้ช่วย) จะเป็นตัวกำหนดผู้ชนะในการตีกอล์ฟแบบดั้งเดิม โปรดใช้ชื่อเช่น "MyLang, 123 สาย, 456 คู่, 789 ไบต์" สำหรับคำตอบของคุณ

เขียนฟังก์ชั่นหรือโปรแกรมที่สมบูรณ์ อินพุต / เอาต์พุต / อาร์กิวเมนต์ / ผลลัพธ์คือ int arrays ในรูปแบบที่เหมาะสม การเป็นตัวแทนแบบไบนารีอาจเป็นแบบเล็กหรือใหญ่ - เลือกอย่างใดอย่างหนึ่ง


ภาคผนวก 1: เพื่อให้การท้าทายง่ายขึ้นเล็กน้อยคุณสามารถสมมติว่ากล่องที่มีรหัส 0 และ 1 มีค่า 0 และ 1 ซึ่งจะช่วยให้คุณมีค่าคงที่มีประโยชน์เช่นการปฏิเสธ ( x^1คือ "ไม่") แน่นอนว่ามีหลายวิธีที่ยังขาดค่าคงที่ แต่ความท้าทายที่เหลือก็ยากพออยู่แล้วดังนั้นเรามากำจัดความฟุ้งซ่านนี้กัน


ภาคผนวก 2: หากต้องการรับรางวัลคุณต้องทำอย่างใดอย่างหนึ่งต่อไปนี้:

  • โพสต์คะแนนของคุณ (โทร, คู่, ไบต์) และรหัสของคุณก่อนกำหนด

  • โพสต์คะแนนของคุณและแฮชของรหัสของคุณก่อนถึงเส้นตาย; จากนั้นโพสต์รหัสจริงภายใน 23 ชั่วโมงหลังจากกำหนด


หากฉันแปลสิ่งนี้เป็นภาษาที่ฉันเลือก (Haskell) ฉันสามารถใช้การเรียกซ้ำค่าและโทรFเพียงครั้งเดียว นั่นคงจะเป็นการโกง แต่ฉันไม่แน่ใจว่ามันจะเป็นการโกงที่ดีหรือการโกงที่ไม่ดี
Christian Sievers

ฉันรู้ว่ารัฐทั่วโลกไม่ได้รับการต้อนรับใน Haskell แต่ให้ฉันถามสิ่งนี้ว่าเป็นการทดลองทางความคิด: ถ้าฉันเพิ่มตัวนับทั่วโลกในการนำ F มาใช้มันจะเติบโตขึ้นมากแค่ไหน? - นั่นคือความเข้าใจของฉัน "จำนวนการโทร"
ngn

ฉันสามารถทำอย่างนั้นได้และมันจะบอกว่า 1 แต่ไม่สามารถแปลกลับไปเป็น JavaScript โดยใช้รหัสของคุณ เป็นหลักผมว่าy=f(x)และให้ขึ้นอยู่กับx y
Christian Sievers

ฉันเกรงว่าฉันจะไม่เข้าใจว่ามันจะทำงานอย่างไร คุณช่วยแสดงรหัสตัวอย่างได้ไหม Haskell ของฉันไม่ดี แต่ฉันแน่ใจว่าฉันสามารถคิดออกว่าฉันสามารถเล่นกับรหัส
ngn

บางทีเราสามารถใช้ประเภทต่อไปนี้เพื่อสร้างปัญหานี้? data Box = B Int deriving (Show); f :: [[[Box]]] -> [Box]ฉันจะต้องใช้เวลามากขึ้นในการหาวิธีการใช้งานf(Haskell บังคับให้ตัวพิมพ์เล็กที่นี่) - ฉันจะลองในวันพรุ่งนี้
NGN

คำตอบ:


6

Python 3 , 5 สาย, 92 คู่, 922 ไบต์

Python 3 , 5 สาย, 134 คู่, 3120 ไบต์

Python 3 , 6 สาย, 106 คู่, 2405 ไบต์

[JavaScript (Node.js)], 9 สาย, 91 คู่, 1405 ไบต์

JavaScript (Node.js), การโทร 16 ครั้ง, 31 คู่, 378 ไบต์

def add(F,a,b):r=[];p=lambda x:(x,x);q=lambda u,v,t:([u,v]+t[0],[u,v]+t[1]);s=lambda c,k,n:([e[j][n]for j in range(k,-1,-1)]+[f[n]],[c]+f[n-k:n+1]);t=lambda c,k,n:q(a[n],b[n],s(c,k,n-1));z=F([p([a[i],b[i]])for i in range(16)]+[([a[i]],[b[i]])for i in range(16)]);e=[z[0:16]];f=z[16:32];r+=[e[0][0]];c=f[0];z=F([p([a[1],b[1],c]),([e[0][1],f[1]],[c,f[1]])]+[([e[0][i]],[e[0][i-1]])for i in range(3,16)]);r+=[z[0]];c=z[1];e+=[[0]*3+z[2:15]];z=F([p([a[2],b[2],c]),t(c,0,3),s(c,1,3)]+[([e[j][i]],[e[1][i-j-1]])for j in range(2)for i in range(6+j,16)]);r+=z[0:2];c=z[2];e+=u(2,4,z[3:]);z=F([p([a[4],b[4],c])]+[t(c,i,i+5)for i in range(0,3)]+[s(c,3,7)]+[([e[j][i]],[e[3][i-j-1]])for j in range(4)for i in range(12+j,16)]);r+=z[0:4];c=z[4];e+=u(4,8,z[5:]);z=F([p([a[8],b[8],c])]+[t(c,i,i+9) for i in range(0,7)]);return r+z
def u(b,e,z):
	j=0;w=[0]*(e-b)
	for i in range(b,e):w[i-b]=[0]*(i+e)+z[j:j+16-(i+e)];j+=16-(i+e)
	return w

ลองออนไลน์!

รุ่นแรก โอเคที่ไม่ได้เล่นกอล์ฟ มันเป็นเพียงการปรับเปลี่ยนรหัสของ @ ngn

แนวคิดเดียวที่นี่คือคุณไม่จำเป็นต้องคำนวณการพกพาครั้งสุดท้ายเนื่องจากคุณทิ้งการล้น นอกจากนี้การโทรของFจะถูกจัดกลุ่มโดยสอง บางทีพวกเขาอาจถูกจัดกลุ่มในอีกทางหนึ่ง แต่ฉันสงสัยว่าคุณสามารถลดจำนวนคู่ลงได้อย่างมากเนื่องจากลักษณะของอัลกอริธึมการเพิ่มพื้นฐาน

แก้ไข : ยังไม่ได้เล่นกอล์ฟ จำนวนคู่อาจลดลงอย่างแน่นอนและอาจเป็นจำนวนการโทรด้วย ดูhttps://gist.github.com/jferard/864f4be6e4b63979da176bff380e6c62เพื่อดู"หลักฐาน" ด้วย sympy

แก้ไข 2เปลี่ยนเป็น Python เพราะสามารถอ่านได้มากขึ้นสำหรับฉัน ตอนนี้ฉันมีสูตรทั่วไปแล้วฉันคิดว่าฉันจะโทรถึงขีด จำกัด 5 (อาจจะ 4)

แก้ไข 3 ต่อไปนี้เป็นอิฐพื้นฐาน:

alpha[i] = a[i] ^ b[i]
beta[i] = a[i] * b[i]
c[0] = beta[0]
r[0] = alpha[0]

สูตรทั่วไปคือ:

c[i] = alpha[i]*c[i-1] ^ beta[i]
r[i] = a[i] ^ b[i] ^ c[i-1]

เวอร์ชันขยายคือ:

c[0] = beta[0]
c[1] = alpha[1]*beta[0] ^ beta[1]
c[2] = alpha[2]*alpha[1]*beta[0] ^ alpha[2]*beta[1] ^ beta[2]
c[3] = alpha[3]*alpha[2]*alpha[1]*beta[0] ^ alpha[3]*alpha[2]*beta[1] ^ alpha[3]*beta[2] ^ beta[3]
...
c[i] = alpha[i]*...*alpha[1]*beta[0] ^ alpha[i]*...*alpha[2]*beta[1] ^ .... ^ alpha[i]*beta[i-1] ^ beta[i]

การโทร 5 ครั้งดูเหมือนขีด จำกัด สำหรับฉัน ตอนนี้ฉันมีงานเล็กน้อยที่จะลบคู่และตีกอล์ฟ!

แก้ไข 4ฉันเล่นกอล์ฟคันนี้

เวอร์ชันที่ไม่ถูกปรับแต่ง:

def add(F, a, b):
    r=[]
    # p is a convenient way to express x1^x2^...x^n
    p = lambda x:(x,x)
    # q is a convenient way to express a[i]^b[i]^carry[i-1]
    q = lambda u,v,t:([u,v]+t[0],[u,v]+t[1])

    # step1: the basic bricks
    z=F([p([a[i],b[i]]) for i in range(16)]+[([a[i]],[b[i]]) for i in range(16)])
    alpha=z[0:16];beta=z[16:32]
    r.append(alpha[0])
    c = beta[0]

    # step 2
    z=F([
        p([a[1],b[1],c]),
        ([alpha[1],beta[1]],[c,beta[1]])
        ]+[([alpha[i]],[alpha[i-1]]) for i in range(3,16)])
    r.append(z[0])
    c = z[1] # c[1]
    alpha2=[0]*3+z[2:15]
    assert len(z)==15, len(z)

    # step 3
    t0=([alpha[2],beta[2]],[c,beta[2]])
    t1=([alpha2[3],alpha[3],beta[3]],[c,beta[2],beta[3]])
    z=F([
        p([a[2],b[2],c]),
        q(a[3],b[3],t0),
        t1]+
        [([alpha[i]],[alpha2[i-1]]) for i in range(6,16)]+
        [([alpha2[i]],[alpha2[i-2]]) for i in range(7,16)])
    r.extend(z[0:2])
    c = z[2] # c[3]
    alpha3=[0]*6+z[3:13]
    alpha4=[0]*7+z[13:22]
    assert len(z)==22, len(z)

    # step 4
    t0=([alpha[4],beta[4]],[c,beta[4]])
    t1=([alpha2[5],alpha[5],beta[5]],[c,beta[4],beta[5]])
    t2=([alpha3[6],alpha2[6],alpha[6],beta[6]],[c,beta[4],beta[5],beta[6]])
    t3=([alpha4[7],alpha3[7],alpha2[7],alpha[7],beta[7]],[c,beta[4],beta[5],beta[6],beta[7]])
    z=F([
        p([a[4],b[4],c]),
        q(a[5],b[5],t0),
        q(a[6],b[6],t1),
        q(a[7],b[7],t2),
        t3]+
        [([alpha[i]],[alpha4[i-1]]) for i in range(12,16)]+
        [([alpha2[i]],[alpha4[i-2]]) for i in range(13,16)]+
        [([alpha3[i]],[alpha4[i-3]]) for i in range(14,16)]+
        [([alpha4[i]],[alpha4[i-4]]) for i in range(15,16)])
    r.extend(z[0:4])
    c = z[4] # c[7]
    alpha5 = [0]*12+z[5:9]
    alpha6 = [0]*13+z[9:12]
    alpha7 = [0]*14+z[12:14]
    alpha8 = [0]*15+z[14:15]
    assert len(z) == 15, len(z)

    # step 5
    t0=([alpha[8],beta[8]],[c,beta[8]])
    t1=([alpha2[9],alpha[9],beta[9]],[c,beta[8],beta[9]])
    t2=([alpha3[10],alpha2[10],alpha[10],beta[10]],[c,beta[8],beta[9],beta[10]])
    t3=([alpha4[11],alpha3[11],alpha2[11],alpha[11],beta[11]],[c,beta[8],beta[9],beta[10],beta[11]])
    t4=([alpha5[12],alpha4[12],alpha3[12],alpha2[12],alpha[12],beta[12]],[c,beta[8],beta[9],beta[10],beta[11],beta[12]])
    t5=([alpha6[13],alpha5[13],alpha4[13],alpha3[13],alpha2[13],alpha[13],beta[13]],[c,beta[8],beta[9],beta[10],beta[11],beta[12],beta[13]])
    t6=([alpha7[14],alpha6[14],alpha5[14],alpha4[14],alpha3[14],alpha2[14],alpha[14],beta[14]],[c,beta[8],beta[9],beta[10],beta[11],beta[12],beta[13],beta[14]])
    t7=([alpha8[15],alpha7[15],alpha6[15],alpha5[15],alpha4[15],alpha3[15],alpha2[15],alpha[15],beta[15]],[c,beta[8],beta[9],beta[10],beta[11],beta[12],beta[13],beta[14],beta[15]])

    z=F([
        p([a[8],b[8],c]),
        q(a[9],b[9],t0),
        q(a[10],b[10],t1),
        q(a[11],b[11],t2),
        q(a[12],b[12],t3),
        q(a[13],b[13],t4),
        q(a[14],b[14],t5),
        q(a[15],b[15],t6)
    ])
    r.extend(z)
    return r

ลองออนไลน์!


ดีมาก :) คุณพบว่าการเพิ่มประสิทธิภาพง่าย ๆ สองอย่างที่ฉันตั้งใจทำ "ฉันสงสัยคุณสามารถลดอย่างมีนัยสำคัญจำนวนคู่" - F()ทราบว่าเกณฑ์แรกสำหรับผู้ชนะคือจำนวนของการเรียกไปยัง ฉันรับประกันว่ามีวิธีที่จะลดสิ่งเหล่านั้นอย่างมีนัยสำคัญ (นั่นคือส่วนที่ยากที่สุดของความท้าทายนี้) จากนั้นจะมีที่ว่างสำหรับการเพิ่มประสิทธิภาพของจำนวนคู่และสุดท้ายแน่นอนว่าการเล่นรหัส (แต่นั่นเป็นเกณฑ์ที่สำคัญที่สุด)
ngn

โอเคเข้าใจแล้ว! ... + x * y * z + ...ไม่ช้าก็เร็วคุณได้สิ่งที่ต้องการ: เราไม่สามารถใช้Fประเมินมันได้ แต่ถ้าเราคำนวณx * yด้วยการFโทรก่อนหน้านี้เราก็ต้องทำ: ... + (x * y) * z + ...(มันตรงกับรูปแบบของF) ฉันจัดการกับการโทรด้วย sympy (ขั้นที่ 1: คำนวณ r0, c0, r1; step2: คำนวณ c1 และค่า aux บางอย่างขั้นตอนที่ 3: คำนวณ r2, c2, r3, c3) และตอนนี้ฉันกำลังดูทั่วไป สารละลาย.
jferard

ใช่อีกนัยหนึ่ง: บิตเอาท์พุทเป็นพหุนามมีระดับสูงกว่า 2 ในอินพุตบิต ผลิตภัณฑ์ชั้นในสามารถรวมพหุนาม m-degree และ n-degree เข้าใน (m + n) - พหุนามองศาได้มากที่สุด อย่ารีบเร่ง - ภายในไม่กี่ชั่วโมงฉันจะสามารถตั้งค่าความโปรดปรานได้ :)
ngn

คุณอาจต้องการใช้ประโยชน์จากภาคผนวก 2 ด้านบน หรืออย่างอื่น: หากมีคนคัดลอกรหัสของคุณลบช่องว่างและโพสต์ใหม่ในทางเทคนิคฉันจะต้องให้รางวัลโบนัสแก่พวกเขา
ngn

2
สำหรับเร็กคอร์ดเป็นไปไม่ได้ที่จะใช้การเรียกน้อยกว่าห้ารายการเนื่องจากโซลูชันต้องใช้พหุนาม 32 องศา (พหุนามตรงกับฟังก์ชันใด ๆ ของบิตอินพุตไม่ซ้ำกัน)
Nitrodon

2

Haskell, 1 call (cheat ???), 32 pairs (ควรปรับปรุง), 283 bytes (เดียวกัน)

โปรดอย่าโกรธฉันฉันไม่ต้องการชนะด้วยสิ่งนี้ แต่ฉันได้รับการสนับสนุนในคำพูดถึงความท้าทายเพื่ออธิบายสิ่งที่ฉันพูดถึง

ฉันพยายามใช้ state monad เพื่อจัดการเพิ่มกล่องและนับจำนวนการโทรและคู่และมันใช้งานได้ แต่ฉันไม่ได้จัดการเพื่อให้โซลูชันของฉันทำงานในการตั้งค่านั้น ดังนั้นฉันจึงทำสิ่งที่แนะนำในความคิดเห็น: เพียงซ่อนข้อมูลไว้ด้านหลังตัวสร้างข้อมูลและไม่ต้องมอง (วิธีใหม่ทั้งหมดคือการใช้โมดูลแยกและไม่เอ็กซ์พอร์ตคอนสตรัคเตอร์) เวอร์ชั่นนี้มีข้อได้เปรียบที่ง่ายกว่ามาก

เนื่องจากเรากำลังพูดถึงกล่องบิตฉันจึงใส่Boolค่าลงไป ฉันกำหนดzeroเป็นกล่องที่กำหนดโดยมีบิตเป็นศูนย์ - oneไม่จำเป็นต้องใช้

import Debug.Trace

data B = B { unB :: Bool }

zero :: B
zero = B False

f :: [([B],[B])] -> [B]
f pairs =  trace ("f was called with " ++ show (length pairs) ++ " pairs") $
           let (B i) &&& (B j) = i && j
           in map (\(x,y) ->  B ( foldl1 (/=) (zipWith (&&&) x y))) pairs

เรากำลังใช้ฟังก์ชั่นการตรวจแก้จุดบกพร่องtraceเพื่อดูความถี่ที่fถูกเรียกและจำนวนคู่ &&&รูปลักษณ์ที่ลงในกล่องโดยจับคู่รูปแบบที่ไม่สมดุลกัน/= ใช้ในค่าคือBoolxor

bits :: Int -> [Bool]
bits n = bitsh n 16
  where bitsh _ 0 = []
        bitsh n k = odd n : bitsh (n `div` 2) (k-1)

test :: ( [B] -> [B] -> [B] ) -> Int -> Int -> Bool
test bba n m = let x = map B (bits n)
                   y = map B (bits m)
                   r = bba x y
                   res = map unB r
               in res==bits(n+m)

testฟังก์ชั่นใช้งูตาบอดไบนารีเป็นอาร์กิวเมนต์แรกและจากนั้นตัวเลขสองซึ่งนอกจากจะมีการทดสอบ ส่งคืนการBoolบ่งชี้ว่าการทดสอบสำเร็จหรือไม่ ก่อนอื่นจะสร้างกล่องป้อนข้อมูลจากนั้นจึงเรียกใช้ตัวบวกผลลัพธ์ที่ไม่ได้ทำกล่อง (กับunB) และเปรียบเทียบกับผลลัพธ์ที่คาดไว้

ผมดำเนินการสองงูทางออกตัวอย่างเพื่อที่ว่าเราจะเห็นว่าการส่งออกการแก้ปัญหาได้อย่างถูกต้องและวิธีการแก้ปัญหาของฉันโดยใช้การเรียกซ้ำค่าsimplevalrec

simple a b = let [r0] = f [([a!!0,b!!0],[a!!0,b!!0])]
                 [c]  = f [([a!!0],[b!!0])]
             in loop 1 [r0] c
             where loop 16 rs _ = rs
                   loop i  rs c = let [ri] = f [([a!!i,b!!i,c],[a!!i,b!!i,c])]
                                      [c'] = f [([a!!i,b!!i,c],[b!!i,c,a!!i])]
                                  in loop (i+1) (rs++[ri]) c'

valrec a b =
    let res = f (pairs res a b)
    in [ res!!i | i<-[0,2..30] ]
  where pairs res a b =
           let ts = zipWith3 (\x y z -> [x,y,z])
                             a b (zero : [ res!!i | i<-[1,3..29] ]) in
           [ p | t@(h:r) <- ts, p <- [ (t,t), (t,r++[h]) ] ]

มาดูกันว่าฉันกำหนดresในแง่ของตัวเองอย่างไร ที่ยังเป็นที่รู้จักกันผูกปม

ตอนนี้เราสามารถเห็นวิธีการfเรียกเพียงครั้งเดียว:

*Main> test valrec 123 456
f was called with 32 pairs
True

หรือแทนที่valrecด้วยsimpleเพื่อดูfว่าถูกเรียก 32 ครั้ง

ลองออนไลน์! (ผลลัพธ์การสืบค้นกลับปรากฏใต้ "Debug")


ไม่มีความโกรธที่นี่ :) ดังนั้นถ้าฉันเข้าใจอย่างถูกต้องการโต้เถียงfเป็นรายการที่ขี้เกียจและไม่มีที่สิ้นสุดที่อาจเกิดขึ้นเมื่อคุณวนซ้ำมัน? ฉันกลัวว่าขัดกับจิตวิญญาณของความท้าทาย - มันช่วยให้คุณสามารถที่จะเลื่อนการตัดสินใจเกี่ยวกับสิ่งที่ผ่านเป็นที่i+1โต้แย้ง -st til หลังจากที่คุณได้รับผลที่สอดคล้องกับi-th เป็นเรื่องที่น่าสนใจมากขึ้นที่จะทราบว่าfคุณต้องใช้สายที่มีข้อโต้แย้งที่ไม่เปลี่ยนรูปแบบและมีการเรียกจำนวนมากแค่ไหน:)
ngn

ฉันเห็นด้วย. @ jferard ได้ทำงานที่น่าอัศจรรย์ซึ่งไม่น่าจะเป็นโมฆะหากใช้กลอุบาย ในขณะที่fสามารถรับอินพุตไม่สิ้นสุด (เพิ่มสตรีมบิตที่ไม่มีที่สิ้นสุดใช่!) นั่นไม่ใช่จุด โอ้และที่จริงแล้วtraceข้อความยืนยันได้ว่าความยาวนั้น จำกัด และเป็นที่รู้จักตั้งแต่แรก นอกจากนี้ฉันจะไม่พูดว่ามีการตัดสินใจรอการตัดบัญชี: ทุกอย่างถูกวางแผนล่วงหน้าเวลาตามที่ต้องการฉันเพียงแค่สับกล่องสุ่มสี่สุ่มห้า และทราบว่ามันไม่เกี่ยวกับลำดับของการขัดแย้ง: ฉันสามารถเปลี่ยนมันเพื่อให้resมีผลก่อนแล้วจึงพกบิต
Christian Sievers

"ผมเพียงสุ่มสี่สุ่มห้าสับกล่อง" - สมมติว่าคุณได้รับกล่องจากการเรียกf; คุณป้อนกลับกล่องนั้นเป็นอาร์กิวเมนต์อื่นในการโทรเดียวกันfหรือไม่
ngn

ใช่ฉันทำ. นั่นคือสิ่งที่การเรียกคืนค่าเป็นเรื่องเกี่ยวกับ คุณมีสิทธิ์นั้น: มันใช้ความขี้เกียจและความจริงที่ว่าฉันสามารถใช้การโต้เถียงที่ไม่ได้เกิดขึ้นอย่างสมบูรณ์ (ฉันชอบคำอธิบายนั้น) ด้วยจิตวิญญาณที่ชัดเจนของความท้าทายนั่นคือ - ตามที่ได้ประกาศไว้ - การโกงอย่างชัดเจน หากใครคิดว่ามันสร้างสรรค์หรือน่าจดจำใคร ๆ ก็อาจเถียงว่าเป็นการโกงที่ดี
Christian Sievers

แน่นอนว่าเป็นคนดี - แน่นอนว่าคุณไม่มีเจตนาลวงที่นี่ ความเกียจคร้านในการเขียนโปรแกรมฟังก์ชั่นเป็นแนวคิดที่สวยงามและมีการใช้งานที่ถูกต้อง เมื่อฉันพยายามที่จะเรียนรู้ Haskell เมื่อไม่กี่ปีที่ผ่านมาฉันจำได้ว่าประทับใจมากกับสายการบินเดียวที่ "ผูกปม" กับตัวเลขฟีโบนักชี
ngn

0

JavaScript, การโทร 32 ครั้ง, 32 คู่, 388 ไบต์

Dyalog APL การโทร 32 ครั้ง 32 คู่ 270 ไบต์

นี่เป็นโซลูชันตัวอย่างไร้เดียงสาที่สามารถทำหน้าที่เป็นแม่แบบ

โปรดทราบว่าจำนวนไบต์ต้องรวมเฉพาะส่วนที่ล้อมรอบด้วย "BEGIN / END SOLUTION"

คำอธิบาย:

ฉันเลือกลำดับบิตน้อยสุด ( x[0]เป็นบิตสำคัญน้อยที่สุด)

สังเกตที่เดียวบิตนอกจาก mod 2 สามารถรับรู้เป็นF([[[x,y],[x,y]]])(นั่นคือ: x*x ^ y*y- คูณ mod 2 เป็น idempotent) F([[[x],[y]]])และการคูณเลขฐานสองเป็น

เราสำรวจบิตจากนัยสำคัญน้อยที่สุดไปเป็นสำคัญที่สุดและในแต่ละขั้นตอนคำนวณบิตผลลัพธ์และการกระทำ

#!/usr/bin/env node
'use strict'
let H=[0,1]
,B=x=>H.push(x)-1
,nCalls=0
,nPairs=0
,F=pairs=>{
  nCalls++;nPairs+=pairs.length
  return pairs.map(([x,y])=>{let s=0;for(let i=0;i<x.length;i++)s^=H[x[i]]*H[y[i]];return B(s)})
}

// -----BEGIN SOLUTION-----
var f=(a,b)=>{
  var r=[], c // r:result bits (as box ids), c:carry (as a box id)
  r[0]=F([[[a[0],b[0]],[a[0],b[0]]]])          // r0 = a0 ^ b0
  c=F([[[a[0]],[b[0]]]])                       // c = a0*b0
  for(var i=1;i<16;i++){
    r.push(F([[[a[i],b[i],c],[a[i],b[i],c]]])) // ri = ai ^ bi ^ c
    c=F([[[a[i],b[i],c],[b[i],c,a[i]]]])       // c = ai*bi ^ bi*c ^ c*ai
  }
  return r
}
// -----END SOLUTION-----

// tests
let bits=x=>{let r=[];for(let i=0;i<16;i++){r.push(x&1);x>>=1}return r}
,test=(a,b)=>{
  console.info(bits(a))
  console.info(bits(b))
  nCalls=nPairs=0
  let r=f(bits(a).map(B),bits(b).map(B))
  console.info(r.map(x=>H[x]))
  console.info('calls:'+nCalls+',pairs:'+nPairs)
  console.assert(bits(a+b).every((x,i)=>x===H[r[i]]))
}

test(12345,6789)
test(12,3)
test(35342,36789)

เหมือนกันใน Dyalog APL (แต่ใช้รหัสกล่องสุ่ม):

⎕io←0⋄K←(V←⍳2),2+?⍨1e6⋄B←{(V,←⍵)⊢K[≢V]}⋄S←0⋄F←{S+←1,≢⍵⋄B¨2|+/×/V[K⍳↑⍉∘↑¨⍵]}
⍝ -----BEGIN SOLUTION-----
f←{
  r←F,⊂2⍴⊂⊃¨⍺⍵        ⍝ r0 = a0 ^ b0
  c←⊃F,⊂,¨⊃¨⍺⍵        ⍝ c = a0*b0
  r,⊃{
    ri←⊃F,⊂2⍴⊂⍺⍵c     ⍝ ri = ai ^ bi ^ c
    c⊢←⊃F,⊂(⍺⍵c)(⍵c⍺) ⍝ c = ai*bi ^ bi*c ^ c*ai
    ri
  }¨/1↓¨⍺⍵
}
⍝ -----END SOLUTION-----
bits←{⌽(16⍴2)⊤⍵}
test←{S⊢←0⋄r←⊃f/B¨¨bits¨⍺⍵
      ⎕←(↑bits¨⍺⍵)⍪V[K⍳r]⋄⎕←'calls:' 'pairs:',¨S
      (bits⍺+⍵)≢V[K⍳r]:⎕←'wrong!'}
test/¨(12345 6789)(12 3)(35342 36789)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.