QRコード…そしてすべてのジャズ!


18

これは、比較的難しいコードゴルフの挑戦になるでしょう。

入力:任意のURL、たとえばhttp://codegolf.stackexchange.com(テストケースになります)が添付されたプロトコルが必要です

出力:このURLを表す生成されたQRコード。スマートデバイスによってスキャンされると、スマートデバイスのブラウザーでそのURLに移動します。

このCode-Golfのルール

  1. いつものように、最小のコードが勝ちます。
  2. コードを生成するための外部Webリソース、ライブラリ、またはプラグインはありません。コードでQRコード画像を計算する必要があります。
  3. 出力は、HTML5 / CSS3によって生成された画像、または適切なUnicodeブロックを使用して、またはプラットフォームのASCIIで使用可能な場合、QRコードを形成できる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
いくつかのドキュメントを読んだ後、「比較的やりがいのある」は控えめな表現だと思います。
ダニー14

「コードでQRコード画像を計算する必要があります」が何を意味するのかを明確にできますか?私は、提出されたコードの 2つの主要なポイントを実行しなければならないことを意味している:1)RSエンコーディング、および2)モジュールレイアウト
ニックT 14

ルール3:端末から印刷されたアスキーアートは正常ですか、それとも実際の画像ファイルに入力する必要がありますか?

回答:


17

Python 3:974文字[nb]

い棒でさらにbeat ります。GH-Gistのノートを参照してください。Python 3にはASCII-85エンコードが組み込まれており、zip圧縮されたソースを支援します。3のより高度な組み込み圧縮アルゴリズム(LZMA)は、このような小さなものではうまく機能しないようです。

zipは、文字を変更することについて非常に気まぐれであり、zipされたサイズを最小化するために、変数に異なる1文字の名前をランダムに試してみようとするようなものを書きたくなりました。

Python 2:1420 1356 1085 1077文字

ここに画像の説明を入力してください

呼び出されたときに渡される最初の引数を読み取ります。これは最大106文字の文字列です。出力は常にバージョン5 LのQRコードとマスク4で、これは37x37モジュールの大きさであり、最大5%の損傷しか処理できないことを意味します。

プログラムの唯一の依存関係は、numpy(配列操作)とmatplotlib(表示のみ)です。すべてのリードソロモンエンコーディング、データパッキング、およびモジュールレイアウトは、提供されたコード内で処理されます。RSの場合、基本的にウィキバーシティの機能を奪いました。それでも、私にとってはブラックボックスのようなものです。あらゆるイベントでQRについて多くのことを学びました。

Hereい棒で打つ前のコードは次のとおりです。

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ちょうど私の「マスターstring」を切り捨てることによりプッシュコールといくつかの不要なビット...
ニック・T

参考までに、2番目のインデントレベルは2スペースだけです。あなたは4つ/タブを使用していることに気づきました。
ベータ崩壊14年

1
@BetaDecayそれはちょうど1つのタブであるはずです(インデントに関する限り1タブ> 1スペースです...私はSEがタブを壊すと思いますか?)
ニックT 14年

@NickTはい、そうです。
Rɪᴋᴇʀ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.