生成方法
表 E.1 は次の方法で作ることが出来ます。
Python
def make_alignment_table(size):
    return tuple(reversed([(size - d - 1) for d in make_alignment_table_r(size)]))
def make_alignment_table_r(size):
    if size < 25:
        return []
    count = int((size + 12) / 28)
    step = int(((size - 13) + (count >> 1)) / count)
    step += step & 1
    return tuple([(i * step + 6) for i in range(count)] + [size - 7])
# 以下、出力処理
for t in range(1, 41):
    print('%2d: %s' % (t, make_alignment_table(t * 4 + 17)))
実行結果
 1: ()
 2: (6, 18)
 3: (6, 22)
 4: (6, 26)
 5: (6, 30)
 6: (6, 34)
 7: (6, 22, 38)
 8: (6, 24, 42)
 9: (6, 26, 46)
10: (6, 28, 50)
11: (6, 30, 54)
12: (6, 32, 58)
13: (6, 34, 62)
14: (6, 26, 46, 66)
15: (6, 26, 48, 70)
16: (6, 26, 50, 74)
17: (6, 30, 54, 78)
18: (6, 30, 56, 82)
19: (6, 30, 58, 86)
20: (6, 34, 62, 90)
21: (6, 28, 50, 72, 94)
22: (6, 26, 50, 74, 98)
23: (6, 30, 54, 78, 102)
24: (6, 28, 54, 80, 106)
25: (6, 32, 58, 84, 110)
26: (6, 30, 58, 86, 114)
27: (6, 34, 62, 90, 118)
28: (6, 26, 50, 74, 98, 122)
29: (6, 30, 54, 78, 102, 126)
30: (6, 26, 52, 78, 104, 130)
31: (6, 30, 56, 82, 108, 134)
32: (6, 34, 60, 86, 112, 138)
33: (6, 30, 58, 86, 114, 142)
34: (6, 34, 62, 90, 118, 146)
35: (6, 30, 54, 78, 102, 126, 150)
36: (6, 24, 50, 76, 102, 128, 154)
37: (6, 28, 54, 80, 106, 132, 158)
38: (6, 32, 58, 84, 110, 136, 162)
39: (6, 26, 54, 82, 110, 138, 166)
40: (6, 30, 58, 86, 114, 142, 170)
表の規則性
表から、以下の規則性を考えます。
- 位置合わせパターンの数
- 配置間の差分
位置合わせパターンの座標数
型を増やしていって、数が変わるところを抽出します。
| 型 | 数 | 幅 | 差分 | 
|---|---|---|---|
| 1 | 0 | 21 | |
| 2 | 1 | 25 | 4 | 
| 7 | 2 | 45 | 20 | 
| 14 | 3 | 73 | 28 | 
| 21 | 4 | 101 | 28 | 
| 28 | 5 | 129 | 28 | 
| 35 | 6 | 157 | 28 | 
(幅=モジュールの大きさ)
この表から「1型」を例外とすると、幅が 28(型が 7)の単位で変化することが分かります。
配置間の差分
表 E.1 の座標では、2 列目の規則性が分からないので、前列との差分をとります。
| 型 | ||||||
|---|---|---|---|---|---|---|
| 2 | 12 | |||||
| 3 | 16 | |||||
| 4 | 20 | |||||
| 5 | 24 | |||||
| 6 | 28 | |||||
| 7 | 16 | 16 | ||||
| 8 | 18 | 18 | ||||
| 9 | 20 | 20 | ||||
| 10 | 22 | 22 | ||||
| 11 | 24 | 24 | ||||
| 12 | 26 | 26 | ||||
| 13 | 28 | 28 | ||||
| 14 | 20 | 20 | 20 | |||
| 15 | 20 | 22 | 22 | |||
| 16 | 20 | 24 | 24 | |||
| 17 | 24 | 24 | 24 | |||
| 18 | 24 | 26 | 26 | |||
| 19 | 24 | 28 | 28 | |||
| 20 | 28 | 28 | 28 | |||
| 21 | 22 | 22 | 22 | 22 | ||
| 22 | 20 | 24 | 24 | 24 | ||
| 23 | 24 | 24 | 24 | 24 | ||
| 24 | 22 | 26 | 26 | 26 | ||
| 25 | 26 | 26 | 26 | 26 | ||
| 26 | 24 | 28 | 28 | 28 | ||
| 27 | 28 | 28 | 28 | 28 | ||
| 28 | 20 | 24 | 24 | 24 | 24 | |
| 29 | 24 | 24 | 24 | 24 | 24 | |
| 30 | 20 | 26 | 26 | 26 | 26 | |
| 31 | 24 | 26 | 26 | 26 | 26 | |
| 32 | 28 | 26 | 26 | 26 | 26 | |
| 33 | 24 | 28 | 28 | 28 | 28 | |
| 34 | 28 | 28 | 28 | 28 | 28 | |
| 35 | 24 | 24 | 24 | 24 | 24 | 24 | 
| 36 | 18 | 26 | 26 | 26 | 26 | 26 | 
| 37 | 22 | 26 | 26 | 26 | 26 | 26 | 
| 38 | 26 | 26 | 26 | 26 | 26 | 26 | 
| 39 | 20 | 28 | 28 | 28 | 28 | 28 | 
| 40 | 24 | 28 | 28 | 28 | 28 | 28 | 
行の中で値が違うのは、1 列目になりました。これで
- 最後の座標:「モジュールの大きさ - 7」
- 等幅で逆順に配置
- 最初の座標: 6
とするとよさそうです。差分の値は、モジュールの大きさと座標数から求められると考えられます。最初と最後は決められているので、間のモジュール数から座標数の間隔数で均等割(step1a)にしてみます。座標は全て偶数ですが、step1a は奇数があります。そこで、奇数は切り上げて偶数(step1b)にしてみました。それでも幾つか合いません。除算では均等割を四捨五入(step2a)して、奇数を切り上げる(step2b)ことで一致するようになりました。
Python
for qrtype in range(2,40+1):
    modules = (qrtype << 2) + 17
    steps = int((modules + 12) / 28)
    span = modules - 13
    step1a = int(span / steps)                   # 小数部は切り捨て
    step1b = step1a + (step1a & 1)               # 奇数は偶数に切り上げ
    step2a = int((span + (steps >> 1)) / steps)  # 小数部は四捨五入
    step2b = step2a + (step2a & 1)               # 奇数は偶数に切り上げ
    print(['%2d' % qrtype, steps, step1a, step2a, step1b, step2b,
           span, modules, step1a==step2a, step1b==step2b])
実行結果
[' 2', 1, 12, 12, 12, 12, 12, 25, True, True]
[' 3', 1, 16, 16, 16, 16, 16, 29, True, True]
[' 4', 1, 20, 20, 20, 20, 20, 33, True, True]
[' 5', 1, 24, 24, 24, 24, 24, 37, True, True]
[' 6', 1, 28, 28, 28, 28, 28, 41, True, True]
[' 7', 2, 16, 16, 16, 16, 32, 45, True, True]
[' 8', 2, 18, 18, 18, 18, 36, 49, True, True]
[' 9', 2, 20, 20, 20, 20, 40, 53, True, True]
['10', 2, 22, 22, 22, 22, 44, 57, True, True]
['11', 2, 24, 24, 24, 24, 48, 61, True, True]
['12', 2, 26, 26, 26, 26, 52, 65, True, True]
['13', 2, 28, 28, 28, 28, 56, 69, True, True]
['14', 3, 20, 20, 20, 20, 60, 73, True, True]
['15', 3, 21, 21, 22, 22, 64, 77, True, True]
['16', 3, 22, 23, 22, 24, 68, 81, False, False]
['17', 3, 24, 24, 24, 24, 72, 85, True, True]
['18', 3, 25, 25, 26, 26, 76, 89, True, True]
['19', 3, 26, 27, 26, 28, 80, 93, False, False]
['20', 3, 28, 28, 28, 28, 84, 97, True, True]
['21', 4, 22, 22, 22, 22, 88, 101, True, True]
['22', 4, 23, 23, 24, 24, 92, 105, True, True]
['23', 4, 24, 24, 24, 24, 96, 109, True, True]
['24', 4, 25, 25, 26, 26, 100, 113, True, True]
['25', 4, 26, 26, 26, 26, 104, 117, True, True]
['26', 4, 27, 27, 28, 28, 108, 121, True, True]
['27', 4, 28, 28, 28, 28, 112, 125, True, True]
['28', 5, 23, 23, 24, 24, 116, 129, True, True]
['29', 5, 24, 24, 24, 24, 120, 133, True, True]
['30', 5, 24, 25, 24, 26, 124, 137, False, False]
['31', 5, 25, 26, 26, 26, 128, 141, False, True]
['32', 5, 26, 26, 26, 26, 132, 145, True, True]
['33', 5, 27, 27, 28, 28, 136, 149, True, True]
['34', 5, 28, 28, 28, 28, 140, 153, True, True]
['35', 6, 24, 24, 24, 24, 144, 157, True, True]
['36', 6, 24, 25, 24, 26, 148, 161, False, False]
['37', 6, 25, 25, 26, 26, 152, 165, True, True]
['38', 6, 26, 26, 26, 26, 156, 169, True, True]
['39', 6, 26, 27, 26, 28, 160, 173, False, False]
['40', 6, 27, 27, 28, 28, 164, 177, True, True]
「QRコード」はデンソーウェーブの登録商標です。