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.
user12205

@ace Добре помічений ... це було виправлено
WallyWest

1
Прочитавши деяку документацію, я думаю, що "відносно складне" - заниження.
Денні

Чи можемо ми роз’яснити, що означає «ваш код повинен обчислювати зображення QR-коду»? Я вважаю, що ми повинні виконати два основні моменти у поданому коді : 1) кодування RS та 2) компонування модуля .
Нік Т

правило 3: так друкується мистецтво ascii з терміналу штрафу, чи воно повинно переходити у фактичний файл зображення?

Відповіді:


17

Пітон 3: 974 знаків [nb]

Далі бийте потворною палицею, див. Зошит на GH-Gist . У Python 3 є вбудована кодування ASCII-85, яка допомагає при блискавці Saus. Більш просунуті вбудовані алгоритми стиснення 3 (LZMA) 3, схоже, не справляються з такими дрібними речами.

Zipping дуже невдалий щодо зміни символів навколо, майже спокусився написати щось, що випадково спробує різні назви 1 літер для змінних, щоб мінімізувати розмір блискавки.

Пітон 2: 1420 1356 1085 1077 символів

введіть тут опис зображення

Я читаю перший аргумент, переданий при виклику, який може бути рядком до 106-ish символів. Вихід - це завжди QR-код версії 5-L та маска 4, що означає, що він має великі модулі 37x37 і може обробляти лише ~ 5% шкоди.

Єдиними залежностями програми є numpy(маніпуляції з масивом) та matplotlib(лише відображення); все кодування Reed-Solomon, упаковка даних та компонування модулів обробляються в рамках наданого коду . Що стосується РС, я в основному пограбував функції Wikipedia ... це все ще для мене чорна скринька. Дізнався тонну про 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-код


Чудова робота! Шкода, що Python не найкращий в гольф-рішеннях, але це чудове кодування, @NickT!
WallyWest

Можливо, я міг би врятувати ще трохи, якщо втрачу structдзвінок і якийсь непотрібний біт, натиснувши просто обрізанням моєї "головної струни" ...
Nick T

Другий рівень відступу може бути лише двома пробілами. Я помітив, що ви використовуєте чотири / табл.
Бета-розпад

1
@BetaDecay це має бути просто 1 вкладка (1 вкладка> 1 пробіл, що стосується відступу ... Я думаю, що SE розбиває вкладки?)
Нік T,

@NickT Так, це так.
Rɪᴋᴇʀ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.