परीक्षण यदि एक संख्या एक वर्ग है


16

एक लिखें गोल्फ़ विधानसभा प्रोग्राम है जो रजिस्टर में एक 64-बिट अहस्ताक्षरित पूर्णांक दिया nडालता रजिस्टर में एक गैर शून्य मान sअगर nएक वर्ग, अन्यथा है 0में s

आपका GOLF बाइनरी (कोडांतरण के बाद) 4096 बाइट्स में फिट होना चाहिए।


आपका कार्यक्रम निम्नलिखित पायथन 3 प्रोग्राम (जो GOLF निर्देशिका के अंदर रखा जाना चाहिए ) का उपयोग करके बनाया जाएगा :

import random, sys, assemble, golf, decimal

def is_square(n):
    nd = decimal.Decimal(n)
    with decimal.localcontext() as ctx:
        ctx.prec = n.bit_length() + 1
        i = int(nd.sqrt())
        return i*i == n

with open(sys.argv[1]) as in_file:
    binary, debug = assemble.assemble(in_file)

score = 0
random.seed(0)
for i in range(1000):
    cpu = golf.GolfCPU(binary)

    if random.randrange(16) == 0: n = random.randrange(2**32)**2
    else:                         n = random.randrange(2**64)

    cpu.regs["n"] = n
    cpu.run()
    if bool(cpu.regs["s"]) != is_square(n):
        raise RuntimeError("Incorrect result for: {}".format(n))
    score += cpu.cycle_count
    print("Score so far ({}/1000): {}".format(i+1, score))

print("Score: ", score)

GOLF को नवीनतम संस्करण के साथ अपडेट करना सुनिश्चित करें git pull। रन प्रोग्राम स्कोर का उपयोग करें python3 score.py your_source.golf

यह संख्या का एक सेट उत्पन्न करने के लिए एक स्थिर बीज का उपयोग करता है जिसमें से लगभग 1/16 वर्ग है। इस संख्या के सेट के प्रति अनुकूलन प्रश्न की भावना के खिलाफ है, मैं किसी भी बिंदु पर बीज को बदल सकता हूं। आपका कार्यक्रम किसी भी गैर-नकारात्मक 64-बिट इनपुट नंबर के लिए काम करना चाहिए, न कि केवल इन।

सबसे कम स्कोर जीतता है।


क्योंकि GOLF बहुत नया है, मैं यहाँ कुछ संकेत शामिल करूँगा। आप पढ़ना चाहिए गोल्फ़ सभी निर्देशों और चक्र लागत के साथ विनिर्देश । Github रिपॉजिटरी में उदाहरण कार्यक्रम मिल सकते हैं।

मैन्युअल परीक्षण के लिए, अपने प्रोग्राम को चलाकर बाइनरी में संकलित करें python3 assemble.py your_source.golf। फिर अपने प्रोग्राम का उपयोग करके चलाएं python3 golf.py -p s your_source.bin n=42, यह प्रोग्राम nको 42 के सेट के साथ शुरू करना चाहिए , और प्रिंट्स रजिस्टर sऔर बाहर निकलने के बाद साइकिल की गिनती। -dझंडे के साथ कार्यक्रम से बाहर निकलने पर रजिस्टर सामग्री के सभी मूल्यों --helpको देखें - सभी झंडे को देखने के लिए उपयोग करें।


मैंने प्रति परीक्षण ~ 64 संचालन को बचाने के लिए एक 32-पुनरावृति लूप को अनियंत्रित किया। वह शायद चुनौती की भावना से बाहर है। शायद यह बेहतर होगा क्योंकि कोड द्वारा विभाजित गति?
स्पर्स

@ शेपर लूप को अनियंत्रित करने की अनुमति है, जब तक कि आपका बाइनरी 4096 बाइट्स में फिट बैठता है। क्या आपको लगता है कि यह सीमा बहुत अधिक है? मैं इसे कम करने को तैयार हूं।
orlp

@ शेपियर अभी आपका बाइनरी 1.3k है, लेकिन मुझे लगता है कि 32-इटरेशन लूप अनरोलिंग थोड़ा ज्यादा है। 1024 बाइट्स ध्वनि की एक द्विआधारी सीमा कैसे होती है?
orlp

सभी प्रतियोगियों को चेतावनी! अपने GOLF दुभाषिया से अपडेट करें git pull। मुझे लेफ़्टशफ्ट ऑपरेंड में एक बग मिला जहां यह ठीक से नहीं लिपटा था।
orlp

मुझे यकीन नहीं है। 1024 मुझे केवल एक बार लूप की आवश्यकता होगी; मैं अभी भी ~ 62 ops प्रति परीक्षण बचा सकता हूँ unrolling द्वारा। मुझे संदेह है कि किसी व्यक्ति को लुकअप टेबल के रूप में उपयोग करने के लिए इतनी जगह मिल सकती है। मैंने कुछ एल्गोरिदम देखे हैं जो 32 बिट वर्ग जड़ों के लिए 2-8k लुकअप टेबल चाहते हैं।
शुक्राणु

जवाबों:


2

स्कोर: 22120 (3414 बाइट्स)

मेरा समाधान न्यूटन की विधि को हल करने के लिए 3kB लुकअप टेबल का उपयोग करता है जो परिणाम के आकार के आधार पर शून्य से तीन पुनरावृत्तियों के लिए चलता है।

    lookup_table = bytes(int((16*n)**0.5) for n in range(2**10, 2**12))

    # use orlp's mod-64 trick
    and b, n, 0b111111
    shl v, 0xc840c04048404040, b
    le q, v, 0
    jz not_square, q
    jz is_square, n

    # x will be a shifted copy of n used to index the lookup table.
    # We want it shifted (by a multiple of two) so that the two most 
    # significant bits are not both zero and no overflow occurs.
    # The size of n in bit *pairs* (minus 8) is stored in b.
    mov b, 24
    mov x, n 
    and c, x, 0xFFFFFFFF00000000
    jnz skip32, c
    shl x, x, 32
    sub b, b, 16
skip32:
    and c, x, 0xFFFF000000000000
    jnz skip16, c
    shl x, x, 16
    sub b, b, 8
skip16:
    and c, x, 0xFF00000000000000
    jnz skip8, c
    shl x, x, 8
    sub b, b, 4
skip8:
    and c, x, 0xF000000000000000
    jnz skip4, c
    shl x, x, 4
    sub b, b, 2
skip4:
    and c, x, 0xC000000000000000
    jnz skip2, c
    shl x, x, 2
    sub b, b, 1
skip2:

    # now we shift x so it's only 12 bits long (the size of our lookup table)
    shr x, x, 52

    # and we store the lookup table value in x
    add x, x, data(lookup_table)
    sub x, x, 2**10
    lbu x, x

    # now we shift x back to the proper size
    shl x, x, b

    # x is now an intial estimate for Newton's method.
    # Since our lookup table is 12 bits, x has at least 6 bits of accuracy
    # So if b <= -2, we're done; else do an iteration of newton
    leq c, b, -2
    jnz end_newton, c
    divu q, r, n, x
    add x, x, q
    shr x, x, 1

    # We now have 12 bits of accuracy; compare b <= 4
    leq c, b, 4
    jnz end_newton, c
    divu q, r, n, x
    add x, x, q
    shr x, x, 1

    # 24 bits, b <= 16
    leq c, b, 16
    jnz end_newton, c
    divu q, r, n, x
    add x, x, q
    shr x, x, 1

    # 48 bits, we're done!

end_newton:

    # x is the (integer) square root of n: test x*x == n
    mulu x, h, x, x
    cmp s, n, x
    halt 0

is_square:
    mov s, 1

not_square:
    halt 0

10

स्कोर: 27462

समय के बारे में मैं एक GOLF चुनौती में प्रतिस्पर्धा करूँगा : D

    # First we look at the last 6 bits of the number. These bits must be
    # one of the following:
    #
    #     0x00, 0x01, 0x04, 0x09, 0x10, 0x11,
    #     0x19, 0x21, 0x24, 0x29, 0x31, 0x39
    #
    # That's 12/64, or a ~80% reduction in composites!
    #
    # Conveniently, a 64 bit number can hold 2**6 binary values. So we can
    # use a single integer as a lookup table, by shifting. After shifting
    # we check if the top bit is set by doing a signed comparison to 0.

    and b, n, 0b111111
    shl v, 0xc840c04048404040, b
    le q, v, 0
    jz no, q
    jz yes, n

    # Hacker's Delight algorithm - Newton-Raphson.
    mov c, 1
    sub x, n, 1
    geu q, x, 2**32-1
    jz skip32, q
    add c, c, 16
    shr x, x, 32
skip32:
    geu q, x, 2**16-1
    jz skip16, q
    add c, c, 8
    shr x, x, 16
skip16:
    geu q, x, 2**8-1
    jz skip8, q
    add c, c, 4
    shr x, x, 8
skip8:
    geu q, x, 2**4-1
    jz skip4, q
    add c, c, 2
    shr x, x, 4
skip4:
    geu q, x, 2**2-1
    add c, c, q

    shl g, 1, c
    shr t, n, c
    add t, t, g
    shr h, t, 1

    leu q, h, g
    jz newton_loop_done, q
newton_loop:
    mov g, h
    divu t, r, n, g
    add t, t, g
    shr h, t, 1
    leu q, h, g
    jnz newton_loop, q
newton_loop_done:

    mulu u, h, g, g
    cmp s, u, n 
    halt 0
yes:
    mov s, 1
no:
    halt 0

अगर मैं आपका लुकअप आइडिया चुराता हूं तो मेरा स्कोर 161558 से 47289 हो जाता है। आपका एल्गोरिथ्म अभी भी जीतता है।
शुक्राणु

क्या आपने न्यूटन लूप को अनियंत्रित करने की कोशिश की है? सबसे खराब स्थिति के लिए इसे कितने पुनरावृत्तियों की आवश्यकता है?
Sparr

@ शेपर हां, यह अनियंत्रित होने के लिए तेज़ नहीं है क्योंकि पुनरावृत्तियों की संख्या में उच्च विचरण है।
orlp

क्या यह कभी शून्य या एक पुनरावृत्तियों में पूरा होता है? अधिकतम क्या है?
स्पर्म

लुकअप टेबल विचार भी उत्तर stackoverflow.com/a/18686659/4339987 में था
14 सितंबर को lirtosiast

5

स्कोर: 161558 227038 259038 260038 263068

मैंने सबसे तेज़ पूर्णांक वर्ग रूट एल्गोरिथ्म लिया, जो मुझे मिल सकता है और वापस लौट सकता है या नहीं, इसका शेष शून्य है।

# based on http://www.cc.utah.edu/~nahaj/factoring/isqrt.c.html
# converted to GOLF assembly for http://codegolf.stackexchange.com/questions/49356/testing-if-a-number-is-a-square

# unrolled for speed, original source commented out at bottom
start:
    or u, t, 1 << 62
    shr t, t, 1
    gequ v, n, u
    jz nope62, v
    sub n, n, u
    or t, t, 1 << 62
    nope62:

    or u, t, 1 << 60
    shr t, t, 1
    gequ v, n, u
    jz nope60, v
    sub n, n, u
    or t, t, 1 << 60
    nope60:

    or u, t, 1 << 58
    shr t, t, 1
    gequ v, n, u
    jz nope58, v
    sub n, n, u
    or t, t, 1 << 58
    nope58:

    or u, t, 1 << 56
    shr t, t, 1
    gequ v, n, u
    jz nope56, v
    sub n, n, u
    or t, t, 1 << 56
    nope56:

    or u, t, 1 << 54
    shr t, t, 1
    gequ v, n, u
    jz nope54, v
    sub n, n, u
    or t, t, 1 << 54
    nope54:

    or u, t, 1 << 52
    shr t, t, 1
    gequ v, n, u
    jz nope52, v
    sub n, n, u
    or t, t, 1 << 52
    nope52:

    or u, t, 1 << 50
    shr t, t, 1
    gequ v, n, u
    jz nope50, v
    sub n, n, u
    or t, t, 1 << 50
    nope50:

    or u, t, 1 << 48
    shr t, t, 1
    gequ v, n, u
    jz nope48, v
    sub n, n, u
    or t, t, 1 << 48
    nope48:

    or u, t, 1 << 46
    shr t, t, 1
    gequ v, n, u
    jz nope46, v
    sub n, n, u
    or t, t, 1 << 46
    nope46:

    or u, t, 1 << 44
    shr t, t, 1
    gequ v, n, u
    jz nope44, v
    sub n, n, u
    or t, t, 1 << 44
    nope44:

    or u, t, 1 << 42
    shr t, t, 1
    gequ v, n, u
    jz nope42, v
    sub n, n, u
    or t, t, 1 << 42
    nope42:

    or u, t, 1 << 40
    shr t, t, 1
    gequ v, n, u
    jz nope40, v
    sub n, n, u
    or t, t, 1 << 40
    nope40:

    or u, t, 1 << 38
    shr t, t, 1
    gequ v, n, u
    jz nope38, v
    sub n, n, u
    or t, t, 1 << 38
    nope38:

    or u, t, 1 << 36
    shr t, t, 1
    gequ v, n, u
    jz nope36, v
    sub n, n, u
    or t, t, 1 << 36
    nope36:

    or u, t, 1 << 34
    shr t, t, 1
    gequ v, n, u
    jz nope34, v
    sub n, n, u
    or t, t, 1 << 34
    nope34:

    or u, t, 1 << 32
    shr t, t, 1
    gequ v, n, u
    jz nope32, v
    sub n, n, u
    or t, t, 1 << 32
    nope32:

    or u, t, 1 << 30
    shr t, t, 1
    gequ v, n, u
    jz nope30, v
    sub n, n, u
    or t, t, 1 << 30
    nope30:

    or u, t, 1 << 28
    shr t, t, 1
    gequ v, n, u
    jz nope28, v
    sub n, n, u
    or t, t, 1 << 28
    nope28:

    or u, t, 1 << 26
    shr t, t, 1
    gequ v, n, u
    jz nope26, v
    sub n, n, u
    or t, t, 1 << 26
    nope26:

    or u, t, 1 << 24
    shr t, t, 1
    gequ v, n, u
    jz nope24, v
    sub n, n, u
    or t, t, 1 << 24
    nope24:

    or u, t, 1 << 22
    shr t, t, 1
    gequ v, n, u
    jz nope22, v
    sub n, n, u
    or t, t, 1 << 22
    nope22:

    or u, t, 1 << 20
    shr t, t, 1
    gequ v, n, u
    jz nope20, v
    sub n, n, u
    or t, t, 1 << 20
    nope20:

    or u, t, 1 << 18
    shr t, t, 1
    gequ v, n, u
    jz nope18, v
    sub n, n, u
    or t, t, 1 << 18
    nope18:

    or u, t, 1 << 16
    shr t, t, 1
    gequ v, n, u
    jz nope16, v
    sub n, n, u
    or t, t, 1 << 16
    nope16:

    or u, t, 1 << 14
    shr t, t, 1
    gequ v, n, u
    jz nope14, v
    sub n, n, u
    or t, t, 1 << 14
    nope14:

    or u, t, 1 << 12
    shr t, t, 1
    gequ v, n, u
    jz nope12, v
    sub n, n, u
    or t, t, 1 << 12
    nope12:

    or u, t, 1 << 10
    shr t, t, 1
    gequ v, n, u
    jz nope10, v
    sub n, n, u
    or t, t, 1 << 10
    nope10:

    or u, t, 1 << 8
    shr t, t, 1
    gequ v, n, u
    jz nope8, v
    sub n, n, u
    or t, t, 1 << 8
    nope8:

    or u, t, 1 << 6
    shr t, t, 1
    gequ v, n, u
    jz nope6, v
    sub n, n, u
    or t, t, 1 << 6
    nope6:

    or u, t, 1 << 4
    shr t, t, 1
    gequ v, n, u
    jz nope4, v
    sub n, n, u
    or t, t, 1 << 4
    nope4:

    or u, t, 1 << 2
    shr t, t, 1
    gequ v, n, u
    jz nope2, v
    sub n, n, u
    or t, t, 1 << 2
    nope2:

    or u, t, 1 << 0
    shr t, t, 1
    gequ v, n, u
    jz nope0, v
    sub n, n, u
    nope0:

end:
    not s, n        # return !remainder
    halt 0


# before unrolling...
#
# start:
#     mov b, 1 << 62  # squaredbit = 01000000...
# loop:               # do {
#     or u, b, t      #   u = squaredbit | root
#     shr t, t, 1     #   root >>= 1
#     gequ v, n, u    #   if remainder >= u:
#     jz nope, v
#     sub n, n, u     #       remainder = remainder - u
#     or t, t, b      #       root = root | squaredbit
# nope:
#     shr b, b, 2     #   squaredbit >>= 2
#     jnz loop, b      # } while (squaredbit > 0)
# end:
#     not s, n        # return !remainder
#     halt 0

EDIT 1: स्क्वेरिंग टेस्ट हटा दिया गया, शेष! सीधे परीक्षा में 3 ऑप्स बचाएं

EDIT 2: n को सीधे शेष के रूप में उपयोग करें, प्रति परीक्षण 1 सेशन बचाएं

EDIT 3: लूप की स्थिति को सरल बनाया, प्रति परीक्षण 32 ऑप्स बचाए

EDIT 4: लूप को अनियंत्रित किया, प्रति परीक्षण लगभग 65 ऑप्स बचाए


1
तुम्हें पता है, निर्देशों में पूर्ण अजगर एक्सप्रेशन का उपयोग कर सकते हैं ताकि आप लिख सकते हैं 0x4000000000000000के रूप में 1 << 62:)
orlp

3

स्कोर: 344493

अंतराल के भीतर एक सरल द्विआधारी खोज करता है [1, 4294967296)अनुमानित करने के लिए sqrt(n), फिर जाँचता है कि nक्या एक पूर्ण वर्ग है।

mov b, 4294967296
mov c, -1

lesser:
    add a, c, 1

start:
    leu k, a, b
    jz end, k

    add c, a, b
    shr c, c, 1

    mulu d, e, c, c

    leu e, d, n
    jnz lesser, e
    mov b, c
    jmp start

end:
    mulu d, e, b, b
    cmp s, d, n

    halt 0

अच्छा शुरुआत! आप में प्रोग्रामिंग पर कोई प्रतिक्रिया है गोल्फ़ विधानसभा, उपकरण मैं के लिए बने गोल्फ़ , या चुनौती? इस प्रकार की चुनौती बहुत नई है, और मैं प्रतिक्रिया सुनने के लिए उत्सुक हूं :)
orlp

आपका उत्तर n = 0 दुख की बात है, 0 0 चुकता है :)
orlp

@orlp को n = 0. के लिए तय किया गया है। इसके अलावा, मैं एक रजिस्टर के मूल्य के मध्य-निष्पादन को प्रिंट करने के लिए एक निर्देश जोड़ने का सुझाव दूंगा, जो GOLF कार्यक्रमों को डीबग करना आसान बना सकता है।
es1024

मैं इस तरह के एक निर्देश को जोड़ने नहीं जा रहा हूं (इसका मतलब है कि चुनौतियों को अस्वीकृत डिबगिंग निर्देशों के बारे में अतिरिक्त नियम जोड़ना होगा), इसके बजाय मेरे पास इंटरैक्टिव डिबगिंग की योजना है, ब्रेकप्वाइंट और सभी रजिस्टर सामग्री को देखने के साथ।
orlp

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