クソアプリアドベントカレンダー2024の技術ネタ:サロゲートペア・ハフマン符号化・頻出ひらがな
公開 2024/12/05 05:59
最終更新 -
クソアプリアドベントカレンダー2024作品【真名を示す暗黒ツール『‡虚空叡智の変換機‡』】の技術ネタです。
https://simblo.net/u/WKZXBT/post/150175


NGな変換ルール #

今回のような変換では、「単一換字式暗号」や「シーザー暗号」的な変換は使えませんでした。
それらの方式だと、変換後の文字が以下のようになってしまうためです。
(前提として、変換元として指定可能な文字は、ひらがなと「、」「。」「ー」です。)

・あり得ない文字から始まる「ュパセーチ」「、ピリスカ」「ーエグオイ」「ンミコソザ」
・あり得ない小文字のつながり「アョンテスル」「キュォテン」
・あり得ない文字の連続「ヤ。ーラブ」

こういうのが発生するためです。


サロゲートペア的変換ルールにする #

「全ての文字に対して、対応する言葉」を1つずつ当てていきます。

「の→ア」
「に→サ」
・・・

ただ、これだと「単一換字式暗号」になってしまうので工夫が必要です。
全ての「変換後」の言葉を、小文字や記号や[ン]で始まらないようにします。

そのために、一部の文字については「変換後の文字を2〜3文字」にします。

具体的には、「ツ」「リ」「ウ」「ネ」など、一部の文字を上位サロゲートにして、これらの文字の場合は必ず「変換後2〜3文字の言葉」で定義します。

「の→ア」
「に→サ」
・・・
「ゆ→ウラ」
「ふ→ウル」
・・・

こうすることで、必ず「変換後の言葉が読める状態のもの」になります。


ただここで問題なのが、「変換したらやたら長い文字になった」だとちょっとイケてない感じがすることです。


ハフマン符号化的アプローチ #

そこで、「頻出文字はなるべく1文字」で、「出現頻度が低い文字は2~3文字」にすることで、変換前と変換後の文字数の増加量を抑えるようにします。

ただ、じゃあ実際どの文字の出現頻度が高いのか?ですが、
ネットにある頻出ひらがなの情報だと全てのひらがなを網羅していない感じだったので、自分で調べてみます。


頻出ひらがなの調査 #

ということで、自分で集計してみます。
今回はWikipediaのデータを使わせていただきます。

手前味噌ですが、
https://github.com/hoku/splitWikipediaPerPage
こちらのツールで1記事1xmlファイルに分割。

各ファイルをパースして、ひたすら出現数をカウントします。

本当はMediawikiの記法に則ってちゃんと処理してからカウントした方がより良いですし、そもそも「Wikiの場合の出現頻度」という前提になるわけですが、今回はざっくり頻度が分かれば良いのであまり気にせずカウントします。

実際のカウント処理はこんな感じです。

<?php
// https://github.com/hoku/splitWikipediaPerPage.git
// で分割したxmlファイルから、[ひらがな]を文字毎にカウントする。

define('WIKI_FILES_DIR', './out');
define('OUT_FILE', './result.json');

echo 'Start!('.date('Y/m/d H:i:s').")\n";

$countsPerChara = [];

foreach (glob(WIKI_FILES_DIR . '/*') as $outDir) {
    if (!is_dir($outDir)) { continue; }
    foreach (glob($outDir . '/*.xml') as $pageXml) {
        if (!is_file($pageXml)) { continue; }

        // 本文のひらがなを文字毎にカウントする
        $xml = simplexml_load_file($pageXml);
        $bodyText = trim($xml->page->revision->text);
        preg_match_all('/[ぁ-ゖー、。]/u', $bodyText, $matches);
        foreach ($matches[0] as $chara) {
            if (array_key_exists($chara, $countsPerChara)) {
                $countsPerChara[$chara]++;
            } else {
                $countsPerChara[$chara] = 1;
            }
        }
    }

    echo $outDir." -> Done\n";
}

// 多い順に並び替えて出力
arsort($countsPerChara);
file_put_contents(OUT_FILE, json_encode($countsPerChara));

echo 'Finish!('.date('Y/m/d H:i:s').")\n";

実際にカウントした結果が以下になります。

{
  "の": 94902446,
  "ー": 81016486,
  "、": 66910764,
  "に": 51726769,
  "。": 47943741,
  "る": 42211681,
  "た": 41790080,
  "と": 38184105,
  "し": 38069515,
  "い": 36859625,
  "は": 36486516,
  "を": 35373531,
  "で": 33231624,
  "て": 32818337,
  "が": 30182278,
  "な": 25583329,
  "れ": 23126747,
  "か": 17814469,
  "ら": 16294210,
  "さ": 16263151,
  "す": 15852872,
  "り": 15692655,
  "っ": 15446688,
  "あ": 14236256,
  "も": 13267461,
  "こ": 12879166,
  "う": 12304974,
  "ま": 12244326,
  "よ": 9937923,
  "く": 9554993,
  "き": 8564425,
  "ん": 7985015,
  "お": 7052682,
  "め": 6844567,
  "け": 6493180,
  "つ": 6162208,
  "そ": 5940536,
  "だ": 5271260,
  "え": 5187000,
  "や": 5090813,
  "ち": 4742223,
  "わ": 4613303,
  "ど": 4538246,
  "み": 4429072,
  "せ": 3597357,
  "へ": 2740176,
  "じ": 2658185,
  "ば": 2564891,
  "び": 2307353,
  "ず": 1969986,
  "ろ": 1792898,
  "ほ": 1695347,
  "げ": 1331530,
  "む": 1311501,
  "ひ": 1263080,
  "べ": 1208729,
  "ゆ": 1199121,
  "ふ": 1177456,
  "ご": 1025260,
  "ょ": 1008229,
  "ぶ": 975894,
  "ね": 881724,
  "ゃ": 871815,
  "ぐ": 703633,
  "ぎ": 672675,
  "ぼ": 479487,
  "づ": 466282,
  "ざ": 429467,
  "ゅ": 419541,
  "ぞ": 398791,
  "ぬ": 220262,
  "ぜ": 198194,
  "ぱ": 184610,
  "ぽ": 154691,
  "ぷ": 145419,
  "ぴ": 96578,
  "ぃ": 68134,
  "ぁ": 53970,
  "ぇ": 44578,
  "ぺ": 41156,
  "ぉ": 13145,
  "ぅ": 12573,
  "ゐ": 11960,
  "ぢ": 11897,
  "ゑ": 7373,
  "ゔ": 4298,
  "ゎ": 610,
  "ゕ": 36,
  "ゖ": 20
}

ちゃんとカウントできていますね!

あとはこの出現数順を考慮して、頻度が高い文字は変換後1文字に、頻度が低い文字は変換後2〜3文字にしていった感じです。
hoku@個人開発
プロフィールページ
シンプルブログの運営者です。
色々作ってます。タイッツーも運営しています。
https://taittsuu.com/
よろしくお願いします〜🙇✨
最近の記事
Nginxのアクセスログからページ毎のアクセス数をざっくり調べる方法
Nginxのアクセスログの内容から、ページ毎の行数をカウントして出力する。 具体的なコマンド # 以下で、ページ毎のアクセス…
2025/01/23 11:01
クソアプリアドベントカレンダー2024の技術ネタ:サロゲートペア・ハフマン符号化・頻出ひらがな
クソアプリアドベントカレンダー2024作品【真名を示す暗黒ツール『‡虚空叡智の変換機‡』】の技術ネタです。 https://simblo.ne…
2024/12/05 05:59
真名を告げる顕現装置『‡虚空叡智の変換機‡』
※「クソアプリアドベントカレンダー2024(カレンダー1)」5日目の記事です。 【クソアプリアドベントカレンダー2024】 http…
2024/12/05 05:59
git push でエラーになった際の対応
結論 # # 現在の設定を確認 git config --show-origin --get-all http.postBuffer # 2Mに変更 git config --global http.po…
2024/08/30 17:01
【シンプルブログ】プロフィールでURLを設定できるようにしました!
今までは、Twitter連携している場合に自分のTwitterアカウントへのリンクアイコンを表示させる機能がありましたが、それを廃止…
2024/01/16 13:33
【タイッツー】リプライ機能の仕様について(2023/12/13時点)
リプライ機能は相手に対して直接声が届く機能となりますので、インターネットは公共の場であることを意識しつつ、いつも以上に…
2023/12/13 01:22
気管支炎
やっと風邪が治まってきた。 風邪をひくと咳が残ってしまいがちな体質なんだけど、どうやら今回は気管支炎とのことで色々処…
2023/12/10 15:43
究極で完全なSNS『Nekodake』
※「クソアプリアドベントカレンダー2023(カレンダー2)」4日目の記事です。 【クソアプリアドベントカレンダー2023】 http…
2023/12/04 07:31
AlmaLinux 9.3 で Wifi を使えるようにする手順
はじめに # AlmaLinux 9.3 のisoファイルを落としてきて、自宅のPCにインストールした場合のお話。(なので、VPSとかでAlmaLin…
2023/11/27 22:45
【タイッツー】政治と宗教に関わる投稿について
タイッツーではユーザーの投稿について利用規約で、 宗教的行為、宗教団体、政治的活動、政治団体の宣伝又は広告に関する情…
2023/09/21 10:44
【★タイッツーに限らず★】SNS等に投稿する内容と著作権について
先日タイーツした著作権等のお話について、 https://taittsuu.com/users/hoku/status/7172808 https://taittsuu.com/users/ho…
2023/09/13 14:06
ミルクボーイ風「好きなSNS」
★「どうもデニールブラザーズですー」 ★◎「お願いしますー ありがとうございますー」 ★「あっ いま チンジャオロースーの…
2023/08/31 23:42
【タイッツー】メンション機能の仕様(2023/8/23時点)
【3行でポイントだけまとめると】 ・メンションはフォロワー相手じゃないと通知が行かない! ・メンションありタイーツはPTL…
2023/08/23 00:36
シンプルブログ、タイッツーにシェアするボタンを追加した!
記事本文の上下にあるシェアボタンに、タイッツーへのシェアボタンも追加!!!! これで簡単にタイッツーにもシェアできる✨
2023/08/02 16:26
【タイッツー】最初期版APIの使い方
現時点では、認証不要の参照系APIのみの公開となります。 認証APIについては最初期版APIに追って追加される可能性がありますが…
2023/07/22 00:31
自分でも予想していなかった流れに
今までずっとtoC向けサービスを作ってたから、今年はtoB向けしか作らないぞ!!!!! と思ってたんだけどね。 …気づいたら…
2023/07/14 07:34
自サービス開発に明け暮れる日々
ここのところ、自身のプロダクト開発に明け暮れている。 去年まではtoC向けの無料サービスばかり作っていたが、そろそろしっ…
2023/05/16 11:49
一発系ネタサービスのバズらせ方について書いてみる
(大層なタイトルですが、私のネタサービスの作り方を公開しているだけのクソしょーもない内容を、少し真面目に書いた記事です…
2023/04/18 18:26
シンプルブログのTwitter認証をOAuth2.0に変更!
シンプルブログをTwitterと連携する機能で、今までは「OAuth 1.0a」というものを使っていた。 ただ、昨今のTwitterAPIの絡みで…
2023/04/11 12:34
シンプルブログの見出し機能をパワーアップ!!
独自タグの見出し機能をパワーアップしたのでご紹介いたします✨ 独自タグの見出し機能をパワーアップしました! # 「見出…
2023/04/06 03:17
もっと見る
タグ
シンプルブログ(15)
タイッツー(8)
個人開発(8)
新機能(7)
アドベントカレンダー(6)
Webサービス(5)
クソアプリ(5)
独自タグ(4)
SNS(3)
AI(2)
API(2)
MacBook(2)
OGP(2)
Twitter(2)
ChatGPT(1)
Chrome(1)
git(1)
Google(1)
Linux(1)
Nginx(1)
TwitterAPI(1)
Webツール(1)
あるある(1)
エンジニア(1)
ガスストーブ(1)
クイズ(1)
グランドオープン(1)
コロナワクチン(1)
サービス開発(1)
サイゼリヤ(1)
もっと見る
ブログランキング
ブログランキング・にほんブログ村へ