Mã QR và tất cả những gì Jazz!


18

Đây sẽ là thử thách tương đối khó khăn với môn đánh gôn.

Đầu vào: Bất kỳ URL nào, phải có giao thức được đính kèm, ví dụ: http://codegolf.stackexchange.com (sẽ là trường hợp thử nghiệm của chúng tôi)

Đầu ra: Mã QR được tạo đại diện cho URL này, khi được quét bởi một thiết bị thông minh sẽ đưa bạn đến URL đó trên trình duyệt của thiết bị thông minh.

Luật chơi cho Code-Golf này

  1. Như thường lệ, mã nhỏ nhất sẽ thắng.
  2. Không có tài nguyên web bên ngoài, thư viện hoặc plugin để tạo mã cho bạn. Mã của bạn phải tính toán hình ảnh mã QR.
  3. Đầu ra có thể được trình bày bằng một hình ảnh, được tạo bởi HTML5 / CSS3 hoặc thậm chí sử dụng các khối Unicode thích hợp hoặc nếu ASCII của nền tảng của bạn có sẵn, thông qua các ký tự ASCII có thể tạo thành mã QR (cái cuối cùng này được hướng vào Commodore 64 Basic, Người dùng Amiga QBasic, Amstrad Basic, v.v.), nhưng nó phải tạo ra đầu ra mã QR để tôi có thể quét mã.
  4. Các mục nhập của mã phải được theo sau với đầu ra được tạo, bằng cách chụp màn hình đầu ra sau khi thực thi mã của bạn hoặc bằng một liên kết hiển thị đầu ra (tùy theo tình huống nào phù hợp nhất)
  5. Bạn phải kiểm tra mã của mình bằng URL " http://codegolf.stackexchange.com " và báo cáo đầu ra theo Quy tắc 3 đến 4.
  6. Bạn cũng phải kiểm tra mã của mình bằng một URL bạn chọn và báo cáo đầu ra theo Quy tắc 3 đến 4.

Người giới thiệu:

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.qr ware.com/ để lấy cảm hứng ...;)


4
Đệ

@ace Phát hiện tốt ... điều này đã được sửa
WallyWest

1
Sau khi đọc một số tài liệu, tôi nghĩ rằng "tương đối thách thức" là một cách đánh giá thấp.
Danny

Chúng tôi có thể làm rõ về việc "mã của bạn phải tính toán hình ảnh mã QR" nghĩa là gì không? Tôi đang hiểu điều đó có nghĩa là chúng ta phải thực hiện hai điểm chính trong mã được gửi : 1) Mã hóa RS và 2) bố cục mô-đun .
Nick T

quy tắc 3: vì vậy nghệ thuật ascii được in từ thiết bị đầu cuối tốt, hay nó phải đi vào một tập tin hình ảnh thực tế?

Câu trả lời:


17

Python 3: 974 ký tự [nb]

Đánh bại hơn nữa với cây gậy xấu xí, xem vở trên GH-Gist . Python 3 có mã hóa ASCII-85 tích hợp, giúp cho xúc xích được nén. Các thuật toán nén tích hợp tiên tiến hơn (LZMA) của 3 dường như không hoạt động tốt với những thứ nhỏ như vậy.

Zipping rất hay thay đổi về việc thay đổi các ký tự xung quanh, hầu như rất muốn viết một cái gì đó sẽ ngẫu nhiên thử các tên 1 chữ cái khác nhau cho các biến để giảm thiểu kích thước được nén.

Python 2: 1420 1356 1085 1077 ký tự

nhập mô tả hình ảnh ở đây

Tôi đọc đối số đầu tiên được truyền khi được gọi, có thể là một chuỗi dài tối đa 106 ký tự. Đầu ra luôn là mã QR phiên bản 5-L và mặt nạ 4, có nghĩa là mô-đun 37x37 lớn và chỉ có thể xử lý thiệt hại ~ 5%.

Các phụ thuộc duy nhất của chương trình là numpy(thao tác mảng) và matplotlib(chỉ hiển thị); tất cả mã hóa, đóng gói dữ liệu và bố trí mô-đun của Sậy-Solomon được xử lý trong mã được cung cấp . Đối với RS, về cơ bản tôi đã cướp đi các chức năng Wikiversity ... nó vẫn là một hộp đen đối với tôi. Đã học được một tấn về QR trong bất kỳ sự kiện.

Đây là mã trước khi tôi đánh bại nó bằng cây gậy xấu xí:

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()

Sau:

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()

(dựa vào một tab để tính là 4/8 / số lượng khoảng trắng> = 2., không chắc nó sẽ sao chép tốt như thế nào)

Bởi vì nó quá dài, chúng tôi có thể nén nó (thấy ai đó làm điều này ở nơi khác, quên mất mặc dù :() để lưu thêm một số ký tự, đưa tổng số xuống còn 1085 1077pylabbẩn thỉu:

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='))

nhập mô tả hình ảnh ở đây

Nếu bạn thay thế dòng cuối cùng bằng dòng sau (nó thêm 62 ký tự), bạn sẽ có được đầu ra gần như hoàn hảo, nhưng dòng kia vẫn quét, vì vậy bất cứ điều gì.

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

Mã QR tốt


Bạn đã làm rất tốt! Thật đáng tiếc khi Python không phải là giải pháp chơi gôn tốt nhất, nhưng đây là mã hóa đáng chú ý, @NickT!
WallyWest

Tôi có thể có thể tiết kiệm thêm một số chi tiết nếu tôi bị mất structcuộc gọi và một chút đẩy không cần thiết bằng cách cắt ngắn 'chuỗi chủ' của mình ...
Nick T

FYI cấp độ thụt thứ hai có thể chỉ là hai không gian. Tôi đã nhận thấy rằng bạn sử dụng bốn / tab.
Beta Decay

1
@BetaDecay đáng lẽ chỉ là 1 tab (1 tab> 1 khoảng trống có liên quan đến thụt lề ... Tôi nghĩ SE phá vỡ các tab?)
Nick T

@NickT vâng, đúng vậy.
Rɪᴋᴇʀ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.