30560


<https://ja.wikipedia.org/wiki/Punycode> を見ていました。

基本的に、任意の utf 文字列を Punycode へ変換する際には、

  1. ASCII文字のみ をそのままコピー
  2. 非ASCII文字たち をエンコードしながら、 1. の末尾に `-` の後ろにくっつける

と、理解したのですが、特に複数個、非ASCII文字が存在した場合のエンコードないしデコードの方法がいまいち理解できていないです。

１文字だけ非ASCII文字を含んでいる `bücher`は、エンコードした結果は `bcher-
kva`ですが、これは次の処理でもってデコードできるのだと理解しました。

  1. `kva` は 10,21,0 なので、 `10 + 21*35 = 745`, 特に、 a は 0 なので、数値の終わりとして取り扱われている。
  2. `length('bcher') + 1` で 6 を取得する
  3. `745/6` で 124 を取得するので、 `124 + 128 == 252` なので、 `ü` を挿入するべきだとわかる
  4. `745 % 6` で 1 を取得したので、 １文字の直後に`ü`を挿入する

のですが、複数文字のデコードが一体どのように実現されているのかがよくわかっていないです。特に、 `büücher` は `bcher-kvaa`
とエンコードされ、 `bücüher` は `bcher-kvab`, `ýbücher` は `bcher-kvaf`
らしいですが、これは一体どういうロジックでデコードされているのでしょうか。


CC BY-SA 3.0
2016-11-20T08:24:27.510
30551
2018-05-12T17:56:09.547
2018-05-12T17:56:09.547
19769
754
question
unicode url
複数個 非ASCII 文字があった場合の Punycode のデコード処理が理解できない


Punycodeのデコード処理は次のような流れをイメージするとよいかと思います。

[code]

    for (n = 128; ; n++) {
      for (i = 0; i <= len(output);  i++) {
        if(/* このタイミングで挿入を行うか？ */) {
          output = insert(output, i, n);
          i++;
        }
      }
    }
    
[/code]

挿入する文字と位置を順番に変化させながら、文字を挿入するというループです。

可変長数値としてエンコードされた値は、内側のループで行っている **挿入処理を行わない回数** を表します。値が745であれば745回スキップした後、
n=252 i=1 の状態で挿入が行われます。

さて、`büücher` のうち最初の `ü`
を挿入しました。続けてもう一度同じ文字を挿入するには…次の周ですぐさま挿入処理を行えばいいですね。ですからスキップする回数は0です。これを可変長数値にエンコードすると
`a` になり、bcher-kva **a** となります。

一方 `bücüher` の場合、次の `ü` まで1文字飛ばさなければいけません。スキップする回数は1、可変長数値でいうと `b` ですから、bcher-
kva **b** となります。

* * *

`ýbücher` では非ASCII文字が増えました。

処理の流れ上、コードポイントの小さい文字から順に挿入しますから、まずは `bcher` に対して`ü` を挿入します。これは先ほどと同じですから
745=`kva` とエンコードされます。

挿入後の状態は output=`bücher` n=252 i=2 です。

次は `ý` を `bücher` の先頭に挿入したいので、 n=253 i=0 になるまで挿入処理を **5回**
スキップします。5を可変長数値にエンコードすると `f` ですから、bcher-kva **f** となります。


CC BY-SA 3.0
2016-11-20T16:10:26.790
30560
2016-11-20T16:10:26.790
8000
30551
answer