QRコード：JIS X 0510 - 附属書 E（規定）位置合わせパターンの位置 - （計算で求める）

# 生成方法

表 E.1 は次の方法で作ることが出来ます。

```python: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)))
```

```console:実行結果
 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. 位置合わせパターンの数
2. 配置間の差分


## 位置合わせパターンの座標数

型を増やしていって、数が変わるところを抽出します。

| 型 | 数 | 幅 | 差分 |
|:-:|--:|--:|--:|
|  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: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])
```

```console:実行結果
[' 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]
```

---

:::note info
「QRコード」はデンソーウェーブの登録商標です。
:::