QR Kodları… ve tüm bu Caz!


18

Bu nispeten zor bir kod-golf meydan okuma olacak.

Girdi: Herhangi bir URL, protokol eklenmiş olmalıdır, örneğin http://codegolf.stackexchange.com (test durumumuz olacak)

Çıktı: Akıllı bir cihaz tarafından tarandığında sizi akıllı cihazın tarayıcısında bu URL'ye götürecek olan bu URL'yi temsil eden oluşturulmuş bir QR Kodu.

Bu Code-Golf Kuralları

  1. Her zamanki gibi en küçük kod kazanır.
  2. Kodu oluşturmak için harici web kaynakları, kütüphaneler veya eklentiler yok. Kodunuz QR kodu görüntüsünü hesaplamalıdır.
  3. Çıktı, HTML5 / CSS3 tarafından oluşturulan bir görüntü ile veya uygun Unicode blokları kullanılarak veya hatta platformunuzun ASCII'sinde mevcutsa, QR kodunu oluşturabilen ASCII karakterleri aracılığıyla sunulabilir (bu sonuncusu Commodore 64 Basic'te yönlendirilir, Amiga QBasic, Amstrad Basic, vb kullanıcılar), ancak kodu tarayabilmem için bir QR kod çıkışı oluşturmalıdır.
  4. Kod girişlerini, kodunuzu yürüttükten sonra çıktının ekran görüntüsü ya da çıktıyı gösteren bir bağlantı (hangisi duruma en uygunsa) oluşturulan çıktıyla takip etmelisiniz.
  5. Kodunuzu " http://codegolf.stackexchange.com " URL'si ile test edip çıktıyı Kural 3 ila 4'e göre bildirmeniz gerekir.
  6. Ayrıca, kodunuzu seçtiğiniz bir URL ile test etmeniz ve çıktıyı Kural 3 ila 4'e göre bildirmeniz gerekir.

Referanslar:

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) İlham için http://www.qrstuff.com/ ...;)


4
Kural 5'de sonsuz özyineleme
user12205

@ace İyi tespit edildi ... bu giderildi
WallyWest

1
Bazı belgeleri okuduktan sonra, "nispeten zorlayıcı" bir eksiklik olduğunu düşünüyorum.
Danny

"Kodunuzun QR kod görüntüsünü hesaplaması gerekir" ne anlama geldiğini açıklayabilir miyiz? Sunulan kodda iki önemli noktayı yapmamız gerektiği anlamına geliyorum : 1) RS kodlaması ve 2) modül düzeni .
Nick T

kural 3: ASCII resmi bir terminal para cezasından yazdırılıyor mu, yoksa gerçek bir görüntü dosyasına mı girmesi gerekiyor?

Yanıtlar:


17

Python 3: 974 karakter [nb]

Çirkin sopa ile daha fazla dövün , GH-Gist'teki not defterine bakın . Python 3, sıkıştırılmış sosis ile yardımcı olan dahili ASCII-85 kodlamasına sahiptir. 3'ün daha gelişmiş yerleşik sıkıştırma algoritmaları (LZMA) böyle küçük şeylerle iyi çalışmıyor gibi görünüyor.

Zipping, karakterleri değiştirme konusunda çok kararsız, neredeyse sıkıştırılmış boyutu en aza indirgemek için değişkenler için farklı 1 harfli adları rastgele deneyecek bir şey yazmaya cazip geldi.

Python 2: 1420 1356 1085 1077 karakter

resim açıklamasını buraya girin

Arandığında, 106-ish karakter uzunluğunda bir dize olabilecek ilk argümanı okudum. Çıktı her zaman sürüm 5-L QR kodu ve maske 4'tür, yani 37x37 modülleri büyüktür ve sadece ~% 5 hasar verebilir.

Programın tek bağımlılıkları numpy(dizi manipülasyonları) ve matplotlib(yalnızca görüntüleme); tüm Reed-Solomon kodlama, veri paketleme ve modül yerleşimi verilen kod içinde işlenir . RS için temel olarak Wikiversity işlevlerini soydum ... bu benim için hala bir kara kutu. Her durumda QR hakkında bir ton öğrendim.

Çirkin sopa ile dövmeden önce kod İşte:

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

Sonra:

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 / boşluk sayısı = = 2 olarak saymak için bir sekmeye dayanarak, ne kadar iyi kopyalayacağından emin değilim)

Bu kadar uzun olduğundan, onu toplam aşağı getirerek, bazı daha fazla karakter kaydetmek için (testere başkasının bu yerde olsa :( kim unuttum do) zip 1085 1077 çünkü pylabpis:

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

resim açıklamasını buraya girin

Son satırı aşağıdaki ile değiştirirseniz (62 karakter ekler), neredeyse mükemmel çıktı elde edersiniz, ancak diğeri hala tarar, her neyse.

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

İyi QR kodu


İyi iş! Python'un golf çözümlerinde en iyisi olmaması üzücü, ancak bu dikkat çekici bir kodlama @NickT!
WallyWest

structÇağrıyı kaybedersem biraz daha kurtarabilirim ve sadece 'ana telimi' keserek gereksiz yere biraz iterim ...
Nick T

İkinci girinti seviyesi sadece iki boşluk olabilir. Dört / sekme kullandığınızı fark ettim.
Beta Çürümesi

1
@BetaDecay sadece 1 sekme olması gerekiyordu (girinti söz konusu olduğunda 1 sekme> 1 boşluk ... Sanırım SE sekmeleri kırıyor mu?)
Nick T

@NickT evet, öyle.
Rɪᴋᴇʀ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.