QR 코드… 그리고 그 모든 재즈!


18

이것은 상대적으로 어려운 코드 골프 과제입니다.

입력 : 모든 URL에는 프로토콜이 첨부되어 있어야합니다 ( 예 : http://codegolf.stackexchange.com (테스트 사례)).

출력 : 이 URL을 나타내는 생성 된 QR 코드는 스마트 장치에서 스캔 할 때 스마트 장치의 브라우저에서 해당 URL로 이동합니다.

이 코드 골프에 대한 규칙

  1. 평소와 같이 가장 작은 코드가 승리합니다.
  2. 코드를 생성하는 외부 웹 리소스, 라이브러리 또는 플러그인이 없습니다. 코드는 QR 코드 이미지를 계산해야합니다.
  3. HTML5 / CSS3에 의해 생성 된 이미지 나 적절한 유니 코드 블록을 사용하거나 QR 코드를 구성 할 수있는 ASCII 문자를 통해 플랫폼의 ASCII를 사용할 수있는 경우 이미지로 출력을 표시 할 수 있습니다 (마지막은 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에서 무한 재귀
user12205

@ace 잘 발견 ...이 해결되었습니다
WallyWest

1
몇 가지 문서를 읽은 후 "상대적으로 어려운"내용은 과소 평가라고 생각합니다.
Danny

"코드가 QR 코드 이미지를 계산해야 함"이 무엇을 의미하는지에 대한 설명을 얻을 수 있습니까? 제출 된 코드에서 1) RS 인코딩 과 2) 모듈 레이아웃 의 두 가지 주요 사항 수행 해야 함을 의미합니다 .
Nick T

규칙 3 : 아스키 아트가 터미널에서 잘 인쇄됩니까? 아니면 실제 이미지 파일로 이동해야합니까?

답변:


17

파이썬 3 : 974 자 [nb]

추악한 막대기 로 더 뛰십시오 .GH-Gist의 노트북을 참조하십시오 . Python 3에는 내장 ASCII-85 인코딩이있어 압축 된 saus에 도움이됩니다. 3의 고급 내장 압축 알고리즘 (LZMA)은 이러한 작은 것들과 잘 작동하지 않는 것 같습니다.

압축은 문자를 바꾸는 데 매우 까다 롭고 압축 된 크기를 최소화하기 위해 변수에 대해 다른 1 문자 이름을 임의로 시도하는 무언가를 작성하려고 거의 유혹했습니다.

Python 2 : 1420 1356 1085 1077 자

여기에 이미지 설명을 입력하십시오

호출 할 때 전달 된 첫 번째 인수를 읽습니다.이 문자열은 최대 106 자 길이의 문자열 일 수 있습니다. 출력은 항상 버전 5L QR 코드 및 마스크 4입니다. 즉, 37x37 모듈이며 최대 5 %의 손상 만 처리 할 수 ​​있습니다.

프로그램의 종속성은 numpy(배열 조작) 및 matplotlib(표시 만)입니다. 모든 Reed-Solomon 인코딩, 데이터 패킹 및 모듈 레이아웃은 제공된 코드 내에서 처리됩니다 . RS의 경우 기본적으로 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로 계산, 얼마나 잘 복사하는지 확실하지 않음)

그것은 너무 오래이기 때문에, 우리는 그것을에 총 낮추기, 좀 더 문자를 저장 (톱 다른 사람이 곳은, 비록 :( 누구 잊었 않음) 압축 할 수 있습니다 1085 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 코드


잘 했어! 파이썬이 골프 솔루션에서 최고가 아니라는 것은 유감이지만, 이것은 @NickT라는 놀라운 코딩입니다!
WallyWest

struct전화를 잃고 '마스터 스트링'을 잘라서 불필요한 비트를 밀면 더 많은 비용을 절약 할 수 있습니다 .
Nick T

참고로 두 번째 들여 쓰기 수준은 두 칸이 될 수 있습니다. 네 / 탭을 사용하는 것으로 나타났습니다.
Beta Decay

1
@BetaDecay 그것은 단지 1 탭이어야합니다 (들여 쓰기에 관한 한 1 탭> 1 공간 ... SE는 탭을 깰 것 같아요?)
Nick T

@NickT 예, 그렇습니다.
Rɪᴋᴇʀ
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.