รหัส QR ... และแจ๊สทั้งหมดนั้น!


18

นี่จะเป็นความท้าทายที่ท้าทายสำหรับนักกอล์ฟ

อินพุต: URL ใด ๆ จะต้องมีโปรโตคอลที่แนบมาเช่นhttp://codegolf.stackexchange.com (ซึ่งจะเป็นกรณีทดสอบของเรา)

ผลลัพธ์:รหัส QR ที่สร้างขึ้นซึ่งแสดงถึง URL นี้ซึ่งเมื่อสแกนโดยอุปกรณ์สมาร์ทจะนำคุณไปยัง URL นั้นบนเบราว์เซอร์ของอุปกรณ์สมาร์ทโฟน

กฎสำหรับ Code-Golf นี้

  1. ตามปกติรหัสที่เล็กที่สุดจะเป็นผู้ชนะ
  2. ไม่มีแหล่งข้อมูลภายนอกเว็บไลบรารีหรือปลั๊กอินเพื่อสร้างรหัสให้คุณ รหัสของคุณจะต้องคำนวณภาพรหัส QR
  3. สามารถนำเสนอผลลัพธ์โดยรูปภาพสร้างโดย HTML5 / CSS3 หรือแม้กระทั่งการใช้บล็อก Unicode ที่เหมาะสมหรือถ้า ASCII ของแพลตฟอร์มของคุณมีพร้อมใช้งานผ่านอักขระ ASCII ที่สามารถสร้างรหัส QR (อันสุดท้ายนี้ถูกกำกับที่ Commodore 64 Basic, Amiga QBasic, Amstrad Basic, ฯลฯ ผู้ใช้) แต่มันจะต้องสร้างเอาท์พุทรหัส QR เพื่อที่ฉันจะสามารถสแกนรหัสได้
  4. รายการของโค้ดจะต้องตามด้วยเอาต์พุตที่สร้างขึ้นโดยภาพหน้าจอของเอาต์พุตหลังจากรันโค้ดของคุณหรือมีลิงก์แสดงเอาต์พุต (แล้วแต่ว่าสถานการณ์จะเหมาะสมที่สุด)
  5. คุณต้องทดสอบรหัสของคุณด้วย URL " http://codegolf.stackexchange.com " และรายงานผลลัพธ์ตามกฎ 3 ถึง 4
  6. คุณต้องทดสอบรหัสด้วย URL ที่คุณเลือกและรายงานผลลัพธ์ตามกฎ 3 ถึง 4

อ้างอิง:

1) http://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders

2) http://www.pclviewer.com/rs2/calculator.html

3) http://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction

4) http://en.wikipedia.org/wiki/QR_code

5) http://www.qrstuff.com/สำหรับแรงบันดาลใจ ... ;)


4
การเรียกซ้ำแบบไม่สิ้นสุดที่กฎ 5
12205

@ace ด่างดี ... สิ่งนี้ได้รับการแก้ไขแล้ว
WallyWest

1
หลังจากอ่านเอกสารบางอย่างแล้วฉันคิดว่า "ค่อนข้างท้าทาย" คือการพูดน้อย
แดนนี่

เราสามารถขอความกระจ่างเกี่ยวกับ "รหัสของคุณจะต้องคำนวณภาพรหัส QR" หมายความว่าอะไร? ฉันใช้มันจะหมายความว่าเราจะต้องทำทั้งสองจุดสำคัญในรหัสส่ง : 1) การเข้ารหัสอาร์เอสและ 2) รูปแบบโมดูล
Nick T

กฎข้อที่ 3: พิมพ์ ascii art จากเทอร์มินัล fine หรือต้องเข้าไปในไฟล์ภาพจริงหรือไม่

คำตอบ:


17

Python 3: 974 ตัวอักษร[nb]

จังหวะต่อกับติดน่าเกลียดดูโน๊ตบุ๊คบน GH-สรุปสาระสำคัญ Python 3 มีการเข้ารหัส ASCII-85 ในตัวซึ่งช่วยในการบีบอัดไส้กรอก อัลกอริธึมการบีบอัดในตัว (LZMA) ขั้นสูงกว่า 3 ดูเหมือนจะทำงานได้ไม่ดีกับสิ่งเล็ก ๆ น้อย ๆ

การซิปเป็นสิ่งที่ไม่แน่นอนมากเกี่ยวกับการเปลี่ยนตัวอักษรรอบ ๆ ถูกล่อลวงให้เขียนสิ่งที่จะลองชื่อ 1 ตัวอักษรที่แตกต่างกันสำหรับตัวแปรเพื่อลดขนาดซิป

Python 2: 1420 1356 1085 1077 ตัวอักษร

ป้อนคำอธิบายรูปภาพที่นี่

ฉันอ่านอาร์กิวเมนต์แรกที่ส่งผ่านเมื่อมีการเรียกซึ่งอาจเป็นสตริงที่ยาวได้ถึง 106 ตัวอักษร ผลลัพธ์จะเป็นรหัส QR รุ่น 5-L และมาสก์ 4 ซึ่งหมายความว่าเป็นโมดูลขนาดใหญ่ 37x37 และสามารถจัดการความเสียหายได้ ~ 5% เท่านั้น

การพึ่งพาของโปรแกรมเท่านั้นคือnumpy(การเปลี่ยนแปลงอาร์เรย์) และmatplotlib(แสดงผลเท่านั้น); การเข้ารหัส Reed-Solomon ทั้งหมดการจัดเก็บข้อมูลและโครงร่างโมดูลได้รับการจัดการภายในรหัสที่ให้ไว้ สำหรับอาร์เอสโดยทั่วไปฉันปล้นฟังก์ชั่น Wikiversity ... มันยังคงเป็นกล่องดำสำหรับฉัน เรียนรู้เกี่ยวกับ QR ในทุกกรณี

นี่คือรหัสก่อนที่ฉันจะเอาชนะด้วยแท่งน่าเกลียด:

import sys
import numpy as np
import matplotlib.pyplot as plt
# version 5-L ! = 108 data code words (bytes), 106 after metadata/packing

### RS code stolen from https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#RS_generator_polynomial
gf_exp = [1] + [0] * 511
gf_log = [0] * 256
x = 1
for i in range(1,255):
    x <<= 1
    if x & 0x100:
        x ^= 0x11d
    gf_exp[i] = x
    gf_log[x] = i
for i in range(255,512):
    gf_exp[i] = gf_exp[i-255]

def gf_mul(x,y):
    if x==0 or y==0:
        return 0
    return gf_exp[gf_log[x] + gf_log[y]]

def main():
    s = sys.argv[1]

    version = 5
    mode = 4 # byte mode
    dim = 17 + 4 * version
    datamatrix = 0.5 * np.ones((dim, dim))
    nsym = 26

    # PACK
    msg = [mode * 16, len(s) * 16] + [ord(c) << 4 for c in s]
    for i in range(1, len(msg)):
        msg[i-1] += msg[i] // 256
        msg[i] = msg[i] % 256

    pad = [236, 17]
    msg = (msg + pad * 54)[:108]

    # MAGIC (encoding)
    gen = [1]
    for i in range(0, nsym):
        q = [1, gf_exp[i]]
        r = [0] * (len(gen)+len(q)-1)
        for j in range(0, len(q)):
            for i in range(0, len(gen)):
                r[i+j] ^= gf_mul(gen[i], q[j])
        gen = r
    msg_enc = [0] * (len(msg) + nsym)
    for i in range(0, len(msg)):
        msg_enc[i] = msg[i]
    for i in range(0, len(msg)):
        coef = msg_enc[i]
        if coef != 0:
            for j in range(0, len(gen)):
                msg_enc[i+j] ^= gf_mul(gen[j], coef)
    for i in range(0, len(msg)):
        msg_enc[i] = msg[i]


    # PATTERN
    # position marks
    for _ in range(3):
        datamatrix = np.rot90(datamatrix)
        for i in range(4):
            datamatrix[max(0, i-1):8-i, max(0, i-1):8-i] = i%2
    datamatrix = np.rot90(datamatrix.T)

    # alignment
    for i in range(3):
        datamatrix[28+i:33-i, 28+i:33-i] = (i+1)%2

    # timing
    for i in range(7, dim-7):
        datamatrix[i, 6] = datamatrix[6, i] = (i+1)%2

    # the "dark module"
    datamatrix[dim-8, 8] = 1

    # FORMAT INFO
    L4 = '110011000101111' # Low/Mask4
    ptr_ul = np.array([8, -1])
    steps_ul = [0, 1] * 8 + [-1, 0] * 7
    steps_ul[13] = 2 # hop over vertical timing
    steps_ul[18] = -2 # then horizontal

    ptr_x = np.array([dim, 8])
    steps_x = [-1, 0] * 7 + [15-dim, dim-16] + [0, 1] * 7

    for bit, step_ul, step_x in zip(L4, np.array(steps_ul).reshape(-1,2), np.array(steps_x).reshape(-1,2)):
        ptr_ul += step_ul
        ptr_x += step_x
        datamatrix[tuple(ptr_ul)] = int(bit)
        datamatrix[tuple(ptr_x)] = int(bit)

    # FILL
    dmask = datamatrix == 0.5

    cols = (dim-1)/2
    cursor = np.array([dim-1, dim]) # starting off the matrix
    up_col = [-1, 1, 0, -1] * dim
    down_col = [1, 1, 0, -1] * dim
    steps = ([0, -1] + up_col[2:] + [0, -1] + down_col[2:]) * (cols/2)
    steps = np.array(steps).reshape(-1, 2)
    steps = iter(steps)

    # bit-ify everything
    msg_enc = ''.join('{:08b}'.format(x) for x in msg_enc) + '0' * 7 # 7 0's are for padding
    for bit in msg_enc:
        collision = 'maybe'
        while collision:
            cursor += steps.next()
            # skip vertical timing
            if cursor[1] == 6:
                cursor[1] = 5
            collision = not dmask[tuple(cursor)]
        datamatrix[tuple(cursor)] = int(bit)

    # COOK
    mask4 = lambda i, j: (i//2 + j//3)%2 == 0
    for i in range(dim):
        for j in range(dim):
            if dmask[i, j]:
                datamatrix[i, j] = int(datamatrix[i, j]) ^ (1 if mask4(i, j) else 0)

    # THE PRESTIGE
    plt.figure(facecolor='white')
    plt.imshow(datamatrix, cmap=plt.cm.gray_r, interpolation='nearest')
    plt.axis('off')
    plt.show()

if __name__ == '__main__':
    main()

หลังจาก:

import sys
from pylab import*
n=range
l=len
E=[1]+[0]*511
L=[0]*256
x=1
for i in n(1,255):
 x<<=1
 if x&256:x^=285
 E[i]=x;L[x]=i
for i in n(255,512):E[i]=E[i-255]
def f(x,y):
 if x*y==0:return 0
 return E[L[x]+L[y]]
m=sys.argv[1]
m=[ord(c)*16 for c in'\4'+chr(l(m))+m]
for i in n(1,l(m)):m[i-1]+=m[i]/256;m[i]=m[i]%256
m=(m+[236,17]*54)[:108]
g=[1]
for i in n(26):
 q=[1,E[i]]
 r=[0]*(l(g)+l(q)-1)
 for j in n(l(q)):
    for i in n(l(g)):r[i+j]^=f(g[i],q[j])
 g=r
e=[0]*134
for i in n(108):
 e[i]=m[i]
for i in n(108):
 c=e[i]
 if c: 
    for j in n(l(g)):e[i+j]^=f(g[j],c)
for i in n(108):e[i]=m[i]
m=.1*ones((37,)*2)
for _ in n(3):
 m=rot90(m)
 for i in n(4):m[max(0,i-1):8-i,max(0,i-1):8-i]=i%2
m=rot90(m.T)
for i in n(3):m[28+i:33-i,28+i:33-i]=(i+1)%2
for i in n(7,30):m[i,6]=m[6,i]=(i+1)%2
m[29,8]=1
a=array
t=tuple
g=int
r=lambda x:iter(a(x).reshape(-1,2))
p=a([8,-1])
s=[0,1]*8+[-1,0]*7
s[13]=2
s[18]=-2
P=a([37,8])
S=[-1,0]*7+[-22,21]+[0,1]*7
for b,q,Q in zip(bin(32170)[2:],r(s),r(S)):p+=q;P+=Q;m[t(p)]=g(b);m[t(P)]=g(b)
D=m==0.1
c=a([36,37])
s=r(([0,-1]+([-1,1,0,-1]*37)[2:]+[0,-1]+([1,1,0,-1]*37)[2:])*9)
for b in ''.join('{:08b}'.format(x) for x in e):
 k=3
 while k:
    c+=s.next()
    if c[1]==6:c[1]=5
    k=not D[t(c)]
 m[t(c)]=g(b)
a=n(37)
for i in a:
 for j in a:
    if D[i,j]:m[i,j]=g(m[i,j])^(j%3==0)
imshow(m,cmap=cm.gray_r);show()

(พึ่งพาแท็บเพื่อนับเป็น 4/8 / จำนวนช่องว่าง> = 2. ไม่แน่ใจว่ามันจะคัดลอกได้ดีแค่ไหน)

เพราะมันยาวมากเราสามารถซิปมันได้ (เห็นมีคนทำนี่ที่อื่นลืมว่า :() เพื่อบันทึกตัวละครเพิ่มอีกทำให้มีจำนวนถึง1,085 1077เพราะpylabมันสกปรก:

import zlib,base64
exec zlib.decompress(base64.b64decode('eJxtU0tzmzAQvvSkX6FLaglkyiM2hHRvyS2HZNobo3QwwY6IBVjQFrfT/96V3KR4Wg5I+/6+3ZXSfWdGOhwHsjWdpv1xX26oclqPtGDKdleTPezrltxCEUm/CKW3iiJyB/YWr9ZkgohsO0MVVS1tWSTi1YrnhE4fP6KFqi2d3qNfPj1CnK0IvS2UhOn6rpgkqHkkxolVFPPceeBviRpJnuot3bJJHG1Sm807AoS5qcevpqUhoX9ut4VN6d8VRymJBuQUlGb3DUGjVHTmiVXci9bUVqyw4uLdwq+eDdszzbmv5TkJp801gkDSgKf8gCSu7cVJF5a6Bqb9Ik7WIkqxLZe8yKMwk2RnW3VGbW3BH1AtLDmJoF3/sPiO+3t24MuIEwetOUVYnY3Bb5bHuvPcFMpv5CNs2Q6TiUPRSAzegSG1yxoll2dkwsxmql+h/8dWgbW69lY5favazKvWs6qNFBX/J8/fChqCyOvaemAsSQX34pPzl5NzYktqMN14FWKbyZzhpW26LicWCmw9z7OlEucibs1FTN7Cg89nQBIbH2e+ypMEQ99uEpjyI46RM+dUJKEbslhb4Gsxc8MsVyKTuMIllMaURzLC+LXf1zhd1Y7EwL7Um6eSTrkaa8NKNvHA1MNz2ddsia+Ac9JDyYpM4ApxMuBoRCS9zC/QilNKyVBEiYTYnlhoGZN7648Ny9D/E7z6YUAci9g9PpshdRQ24iAeLI0fqmcbhczjKA15EedSGDZw/H3CqfU+HK7vfXjA1R1ZzyXs2IY74f6PQG5A44sKIlK5+muRpA6wYQwr2gfALBZEYwUvSV0V/832j4l7V6ehbCzAxSJoOgS4+JmH2ebXIkCLLkfslxv8ZH1quxIvkBD6/Vnta/pyWv3KhyFo62lk3Ml2P/FpAaxzd66c9gXabqQ3SKniuMT6dDlxKwE7k85WpMxn76zMX9Pe4BI00u1CY0NPF/7ImosEm8OJ0sNz951pUemyh0oHO9yJL4ZfOzX/DQ2mdSs='))

ป้อนคำอธิบายรูปภาพที่นี่

หากคุณแทนที่บรรทัดสุดท้ายด้วยสิ่งต่อไปนี้ (เพิ่ม 62 ตัวอักษร) คุณจะได้ผลลัพธ์ที่เกือบสมบูรณ์แบบ แต่อีกอันหนึ่งยังคงสแกนดังนั้นอะไรก็ตาม

figure(facecolor='white');imshow(m,cmap=cm.gray_r,interpolation='nearest');axis('off');show()

รหัส QR ที่ดี


เยี่ยมมาก! เป็นที่น่าเสียดายที่ Python ไม่ได้ดีที่สุดในการตีกอล์ฟ แต่นี่เป็นการเข้ารหัสที่น่าทึ่ง @NickT!
WallyWest

ฉันสามารถอาจจะประหยัดมากขึ้นบางถ้าผมสูญเสียstructการโทรและบางบิตที่ไม่จำเป็นผลักดันโดยเพียงแค่การตัดทอน 'สตริงโทของฉัน ...
นิค T

FYI ระดับการเยื้องที่สองสามารถเป็นแค่สองช่องว่าง ฉันสังเกตเห็นว่าคุณใช้สี่ / แท็บ
Beta Decay

1
@BetaDecay มันควรจะเป็นเพียง 1 แท็บ (1 แท็บ> 1 ช่องว่างเท่าที่เยื้องเป็นห่วง ... ฉันคิดว่า SE แบ่งแท็บ?)
นิค T

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