文字の出現頻度

**文字の出現頻度**（もじのしゅつげんひんど、）とは、書記言語においてアルファベット（ひらがな、漢字）などの文字が出現する回数の平均をまとめたものを指す。文字の頻度分析はアラブ人数学者のアル＝キンディー（801–873）が暗号解読を行うために確立したことから始まる。またヨーロッパにおいては文字の頻度分析は1450年に活字が発明され、活字に必要な各字形の量を推定するために重要性を増した。一方言語学者の間では未知の表記体系に対する言語同定の技法として文字の頻度分析を行っている。

文字の出現頻度や頻度分析は暗号文やハングマン、スクラブル、Wordleのような単語パズルゲームにおいて利用されており、米国のテレビ番組『ホイール・オブ・フォーチュン』においても利用されている。エドガー・アラン・ポーの小説『黄金虫』では英文字の出現頻度の知見を活かして暗号文の解読を行った記述がある古い文献の一つであり、キャプテン・キッド秘蔵の財宝のありかを示すメッセージを頻度分析により解読している。

ハーバード・ジムは暗号学入門著書『Codes and Secret Writing』において英語の出現頻度は "ETAON RISHD LFCMU GYPWB VKJXZQ" の順序で出現頻度が高いとし、2文字（連接文字）に関しては "TH HE AN RE ER IN ON AT ND ST ES EN OF TE ED OR TI HI AS TO"、同じ文字が連続して出現する順序は "LL EE SS OO TT FF RR NN PP CC" である。なお、出現頻度の加算方法の違いによって数値は多少変動する場合がある。

文字の出現頻度は一部のキーボード配列のデザインにも影響を与えている。ブリッケンデルファー型タイプライターやDvorak配列、Colemak配列などは出現頻度の高い文字をホームポジションに配置している。

## 背景

文書中における文字の出現頻度は暗号解読において研究され、特にアラブ人数学者のアル＝キンディー（801–873）が頻度分析の手法を確立したことで広まったとされる（頻度分析を用いて解読できる暗号は頻度分析の前から存在するガイウス・ユリウス・カエサルが発明したシーザー暗号が挙げられ、頻度分析自体はより以前から研究されていた可能性がある。）。1450年にはヨーロッパにおいて活版印刷が発明され、活字ケースの区画スペースの大きさがそれぞれ違うことからも読み取れるように、活版印刷に必要な各文字の字形の量を推定する必要が生じたことで文字の出現頻度分析の重要性が増した。

すべての言語において厳密な文字の出現頻度の分布は文字の書き手によって使用する文法や単語が異なるため、求めることが不可能である。しかしながら、ほとんどの言語において一定量の文書内での文字の出現頻度は特有の分布が現れる。例として、（互いに理解することが困難とされ、）極端な言語の変遷を経た古英語と現代英語それぞれの文字の出現頻度においても類似した特徴を持つことがある。聖書のある一節における両者の文字の出現頻度は高い順に、古英語: ***'、現代英語: ***' となり、違いとしては第一にそれぞれでのみ使用されている文字が存在することが挙げられるが、両者とも  が最も出現頻度の高い文字である。

英語圏でのライノタイプを使用していた職人の長年の経験と習慣から文字の出現頻度の高い順から低い順に ***' であると考えられており、フランス語圏においては ***' の出現頻度であると考えられていた。

各アルファベットのモールス符号を通信にかかる時間が短いまとまり順に並べると ***' となる。文字の出現頻度は[[Baudot Code#ITA No.2|Murray Code]]のような他の電信システムにおいても考慮されている。

文字の出現頻度における同様の利用例としては[[ハフマン符号]]のような現代の[[データ圧縮]]などが挙げられる。

文字の出現頻度はと同様に書き手や記述されている内容によって異なった出現頻度となる。フィクション小説を例としてみると、文章の時制が過去形で書かれることが多くなることから、 の出現頻度が高くなるとされている。また[[X線]]に関するエッセイの文字の出現頻度は  が異様に高くなることが考えられる。加えて、執筆者の言葉の言い回しからも文字の出現頻度は影響を受けるとされる。例として、[[芥川龍之介]]の文体と[[菊池寛]]の文体は文字の頻度分析によって明確に区別することが可能であると検証されている。単文字、[[バイグラム]]、[[トライグラム]]、単語の出現頻度、[[#単語の長さ|単語の長さ]]、文章の長さを求めることで文章の表現方法が類似している著者の作品に対して、識別することが可能となる。

より厳密な文字の出現頻度は大規模な文書データを分析することで求めることができる。大規模な文書データに対する分析は現代のコンピュータと大規模な[[コーパス言語学|テキストコーパス]]を使用することで容易に行うことができる。より具体的には（出版記事、宗教文書、学術文書、フィクション小説など）さまざまな資料をもとに出現頻度を求めることができる。

また同じ言語を使用する地域ごとにも文字の出現頻度はそれぞれ違いがある。例として、米国では "analyze"、"apologize"、"recognize" のように  が含まれた単語を用いているが、英国においてはこれらの単語がそれぞれ "analyse"、"apologise"、"recognise" のように異なった綴りで書かれている。このことから米国における  の出現頻度は英国とは異なった出現頻度とされる。

アルファベットにおいて出現頻度の高い上位十二文字の割合は約 80% にも達する。また上位八文字のみについても出現頻度は 65% に達する。文字の出現頻度はいくつかのランク関数によく適合し、中でも2つパラメータを持つ[[ベータ関数|ベータランク関数]]が最も適合する。パラメータを持たないランク関数も文字の出現頻度の分布に適合される（これらのランク関数はタンパク質構造におけるアミノ塩基の出現頻度を表す際にも使用されている）。やに基づいた暗号を使用するスパイは通常 "a sin to err"（2つ目の "r" を省略） や "at one sir" といった[[語呂合わせ]]を用いて出現頻度の高い八文字を記憶する。

== 日本語における文字の出現頻度 ==
=== 平仮名 ===
[[平仮名]]の出現頻度は以下の表の通りである。分析に使用したデータにおける平仮名の総数は 20,711,361文字である。



=== 片仮名 ===
[[片仮名]]の出現頻度は以下の表の通りである。分析に使用したデータにおける片仮名の総数は 3,608,288文字である。



=== 漢字 ===
[[文化庁]]によりまとめられた日本語における[[漢字]]の出現頻度上位50文字は以下の表の通りである。分析に使用されたデータは総数177,276,398文字であり、そのうち漢字は51,258,216文字であった。出現頻度の高い上位100文字はすべて[[常用漢字]]である。



1993年の調査では、日本において使用される字体の異なる漢字の総数（異なり字）は計4476文字であり、出現頻度の高い漢字の上位500文字で出現頻度は約8割に達する。また、出現頻度の高い漢字上位1600文字での出現頻度は約99%を占め、残りの約3000文字においては全体の1%程度の出現頻度となっている。

=== 文字種別の出現頻度 ===
日本語における記号、数字、平仮名、片仮名、漢字、アルファベットの文字の種類別の出現頻度は以下の通りとなる。



== 英語における文字の出現頻度 ==

=== 文字の相対出現頻度 ===

文字の出現頻度を算出する方法は大きく三種類存在し、各方法によって文字の出現頻度の分布は大きく異なってくる。一つ目は辞書の見出し語として書かれているごとに文字の出現頻度を加算する方法である。以下の節ではこの方法により文字の出現頻度を求めている。二つ目は基本語の "abstract" を "abstracts"、"abstracted"、"abstracting" のように語形変化の単語ごとに文字の出現頻度を加算する方法である。この方法では、インターネット上で頻出する英単語のリストから文字の出現頻度を求める場合に、 のような文字の出現頻度がより現れるとされる。すなわち、 は複数形や三人称単数現在形の動詞中に付け加えられる文字であるため、非基本語の単語中に普遍的に現れる文字となっている。三つ目は実際の文書中に使用されている単語そのままを文字の出現頻度として加算する方法であり、これにより "the"、"then"、"both"、"this" のような単語の頻出により  の出現頻度がより現れるとされる。そして、絶対的な文字の出現頻度が求められるこの方法ではキーボードのレイアウトや古来の印刷機における文字の頻出度合いについて求めることができる。

[[英英辞典]]『Concise Oxford dictionary』を辞典内における単語の頻出度合を無視して文字の出現頻度を分析すると、順番は "EARIOTNSLCUDPMHGBFYWKVXZJQ" であった。

この出現頻度順はロベルト・ルワンド著『Cryptological Mathematics』を引用したパベル・ミツカ氏のウェブサイトにまとめられていたものである。

ルワンドによると、文字の出現頻度の高い順から並べると、'''etaoinshrdlcumwfgypbvkjxqz''' となることが言及されている。このルワンドの出現頻度順は[[コーネル大学]]の「Math Explorer's Project」による40000文字に対する文字の出現頻度順とは異なった並びとなっている。

英語における[[空白記号]]の出現頻度は英文字の出現頻度が最も高い  の約2倍となっており、非アルファベット文字（数字、句読点など）総計の出現頻度は  と  の間となる4番目（空白記号も含めた順位）に位置している。


=== 単語の頭文字・末尾の文字の相対出現頻度 ===


単語の頭文字の出現頻度を分析することは物理的空間におけるファイルや索引の量を割り当てるために重要視されている。アルファベット 26 文字に対応したの引き出しを準備する場合に、各文字ごとに一つの引き出し、つまり 1:1 の割当を行うのではなく、頭文字の出現頻度に沿った引き出しの割当を行うことが合理的であると考えられる。すなわち、出現頻度の低い VWXYZ をまとめて一つの引き出しに割り当てる、出現頻度の高い  では Aa-An、Ao-Az、Ca-Cj、Ck-Cz、Sa-Si、Sj-Sz のように複数の引き出しを割り当てることが考えられる。同様の事例としては複数の巻に分かれた[[百科事典]]の構成や図書館において書籍の識別の名前の頭文字の分布を均等にするための [[:en:Cutter Expansive Classification#Cutter numbers (Cutter codes)|Cutter number]] が挙げられる。

英単語全体および頭文字の出現頻度の分布は両者ともに[[ジップ分布]]に従い、またにも十分従うことが知られている。

一般的に数字の最初の桁の出現頻度の分布は数字全体の分布と比べて有意に差があるとされており、これは[[ベンフォードの法則]]として知られている（[[#ベンフォードの法則|ベンフォードの法則]]節を参照）。

[[ピーター・ノーヴィグ]]は[[光学文字認識]]（OCR）を用いて[[Google Books Ngram Viewer|Google Books]]のデータにおける100,000単語以上出現する単語を対象にした英単語の頭文字の出現頻度が分析された。


== ラテン文字を使用する言語における文字の相対出現頻度 ==


: [[İ]] および [[点のないI|ı]] を参照。

下記の図はいくつかの国における[[ラテン文字]]26文字の出現頻度を可視化したものである。各国はいずれも英語と同様に25文字程度のアルファベットを使用している。



=== 出現頻度のランキング ===
以下の表はいくつかの言語において出現頻度の高い10文字を並べたものである。



== キリル文字を使用する言語における相対出現頻度 ==
以下の表は[[キリル文字]]を使用する言語における文字の出現頻度を表している。

[[ロシア語]]は [http://www.stefantrost.com/contact Stefan Trost] の分析結果をまとめたものである。分析には "WordCreator" の機能 Unicode Counter を使用した。分析にあたって利用したコーパスは 1,351,370文字（210,844単語）のもので、そのうち 1,086,255文字を集計している。ただし、分析するコーパスによっては相対出現頻度は多少異なることがある。

[[ロシア語]]における出現頻度の高い文字（[[ロシア語アルファベット|アルファベット]]）は 、、 となる。



== アラビア文字を使用する言語における相対出現頻度 ==

[[アラビア文字]]における文字の出現頻度は以下の表の通りとなる。[[アラビア語]]の分析において使用したデータにおける語の総数は 1,297,259語、文字の総数は 5,122,132文字である。



[[ペルシア語]]に関しては[[ペルシア文字]]を、[[ウルドゥー語]]に関しては[[ウルドゥー文字]]を、[[マレー語]]に関しては[[ジャウィ文字]]を参照。

== ブラーフミー系文字を使用する言語における文字の相対出現頻度 ==
以下では主に[[南アジア]]、[[東南アジア]]の言語で使用されている[[ブラーフミー系文字]]（インド系文字）における文字の相対出現頻度についてまとめる。

=== デーヴァナーガリーを使用する言語 ===
==== ヒンディー語 ====
以下の表は [http://www.stefantrost.com/contact Stefan Trost] の分析結果をまとめたものである。分析には "WordCreator" の機能 Unicode Counter を使用した。分析にあたって利用したコーパスは 978,430文字（238,604単語）のもので、そのうち 736,216文字を集計している。ただし、分析するコーパスによっては相対出現頻度は多少異なることがある。

[[ヒンディー語]]における出現頻度の高い文字（[[デーヴァナーガリー]]）は 、、 となる。



==== ガルワーリー語 ====
[[ガルワーリー語]]における文字（[[デーヴァナーガリー]]）の出現頻度は以下の表の通りである。



また、ガルワーリー語の[[母音]]のみの出現頻度は以下の通りとなる。



==== マラーティー語 ====
[[マラーティー語]]における文字（[[デーヴァナーガリー]]）の出現頻度上位100文字は以下の表の通りである。



=== ベンガル語 ===
[[ベンガル語]]で使用される[[ベンガル文字]]における文字の出現頻度は以下の表の通りである。



またベンガル語の辞書の見出し語における文字の出現頻度は ***' の順である。

### タイ語
タイ語のタイ文字における文字の出現頻度は以下の表の通りとなる。分析に使用したデータにおける文字の総数は 354,221,260文字である。

タイ文字の子音における文字の出現頻度は高い順に  である。またタイ文字の母音、記号、数字における文字の出現頻度は高い順に  である。

### ビルマ語
ビルマ語で使用されるビルマ文字の基本字母における文字の出現頻度は以下の表の通りである。ビルマ文字では 33 の文字が基本字母として存在している。

また、ビルマ語の基本字母と併せて用いられる表音機能を持つ符号における出現頻度は以下の通りとなる。

### タミル語
タミル語で使用されるタミル文字における文字の出現頻度は以下の表の通りである。

### シンハラ語
シンハラ語で使用されるシンハラ文字における文字の出現頻度は以下の表の通りである。

### マラヤーラム語
マラヤーラム語で使用されるマラヤーラム文字における文字の出現頻度は以下の表の通りである。

### カンナダ語
カンナダ語の母音におけるカンナダ文字の出現頻度は以下の表の通りである。

また、カンナダ語の子音におけるカンナダ文字の出現頻度は以下の通りとなる。

### テルグ語
テルグ語の母音におけるテルグ文字の出現頻度は以下の表の通りである。

また、テルグ語の子音におけるテルグ文字の出現頻度は以下の通りとなる。

## その他の言語における文字の相対出現頻度
### ギリシア語
以下の表は Stefan Trost の分析結果をまとめたものである。分析には "WordCreator" の機能 Unicode Counter を使用した。分析にあたって利用したコーパスは 1,442,382文字（235,614単語）のもので、そのうち 1,161,745文字を集計している。ただし、分析するコーパスによっては相対出現頻度は多少異なることがある。

ギリシア語における出現頻度の高い文字（ギリシア文字）は 、、 となる。

### ヘブライ語
以下の表は Stefan Trost の分析結果をまとめたものである。分析には "WordCreator" の機能 Unicode Counter を使用した。分析にあたって利用したコーパスは 1,230,923文字（279,679単語）のもので、そのうち 937,426文字を集計している。ただし、分析するコーパスによっては相対出現頻度は多少異なることがある。

ヘブライ語における出現頻度の高い文字（ヘブライ文字）は 、、 となる。

### 中国語
中国語における文字（漢字）の出現頻度の上位20文字は以下の表の通りである。分析では2009年にインターネット上で人気のあった8つの小説から計12,379,116文字について調査したものである。

中国の古文書における文字の出現頻度上位10文字は以下の表の通りである。「不」、「一」、「人」の三文字は各年代において出現頻度が上位10位以内の高い頻度で表れる文字であった。

また、中国語の拼音（ピンイン）入力におけるアルファベットの出現頻度は以下の表の通りである。分析には小説から約50万字、新聞記事から約130万字、ネットの投稿から約120万字を抽出したデータを使用している。、、 の三つの文字の出現頻度が高く、 が最も出現頻度の低い文字であった。

### 韓国語
韓国語のハングルにおける字母（ハングル字母）の出現頻度は以下の通りとなる。

韓国語のハングルにおける文字（音節）の出現頻度上位100文字は以下の通りである。

また、1950年代に調査された韓国の文書中におけるハングルの出現頻度の高い30文字は ***' の順である。また、1950年代に調査された韓国語の文書中における漢字の出現頻度の高い30文字は ***' である。

### 台湾語
以下の表では台湾語における出現頻度の高い音節上位20文字を記載する。なお、台湾語は文字の表記法として主に漢字（全漢）、漢字ローマ字混用（漢羅）、ローマ字（全羅）の三つ存在しているため、以下の表では漢字およびローマ字が混合した出現頻度となっている。

### アムハラ語
アムハラ語で使用されるゲエズ文字（アムハラ文字）における文字の出現頻度は以下の表の通りである。分析に使用したデータの文字の総数は 12,222,876文字である。

### ゴート語
現在は死語となっているゴート語のゴート文字における文字の出現頻度は以下の表の通りである。

## 関連の出現頻度
### 単語の出現頻度
#### ジップの法則

続いて文字の出現頻度ではなく、単語の出現頻度について言及する。ある自然言語のコーパスにおける単語の出現頻度はジップの法則に従った分布となる。これは出現頻度の最も高い単語は二番目の単語の約二倍の出現頻度となることをいう。

エスペラント語で書かれたあるフィクション小説のコーパスにおける単語の出現頻度は以下の通りとなった:

la 9864、kaj 4195、mi 3934、de 2819、li 2543、esti 2395、al 1969... と続いている。

ジップの法則は集合の要素（文書内における単語など）を出現頻度の高い順に並べ、それぞれに順位を対応させると、各順位の出現確率  はその順位  の逆数におおよそ比例することを示している。ある順位における相対出現頻度は以下の式で与えられる:

: p(n) \sim \frac{1}{n}

順位が高い 1、2、3、4、5 の順番に出現確率は 1、1/2、1/3、1/4、1/5 の比率を成している。したがってジップの法則から各順位ごとの出現確率はお互いに関連した関係であるといえる。実際、上記の分析結果についても出現頻度はジップの法則に従っているといえる。

#### 日本語
日本語における語（見出し語）の出現頻度は以下の表の通りである。

下記の表は割合を表示せず、順位のみを記載する。

#### 英語

英単語の出現頻度は以下の表の通りである。ただし、単語の出現回数の加算方法としては英語の辞書の見出し語（基本語）ごとに行っており、*be* には *is*、*was*、*are*、*were* などが合算された数となるが、*I* と *me* は各々別の単語として加算されている。

下記の表は割合を表示せず、順位のみを記載する。

英語版の AWK には単語の頻度分析に関するプログラムがまとめられており、より高度な分析を行うプログラムについては下記のプログラム節に記載されている。

### 数字の出現頻度

#### 低価格帯

アルファベットや平仮名に限らず、数字においても特徴的な出現頻度の事例が知られている。例として、日本のスーパーマーケットにおける商品の金額の末尾（一の位）の数字は 8 であることが多いことが知られている。一方、アメリカやヨーロッパ、英語圏などのスーパーマーケットで見かける金額の末尾（一の位）の数字は 9 であることが多いことが知られている。具体例として、商品の価格が200円でなく199円として売られていることが挙げられる。1997年の『Marketing Bulletin』によると、ニュージーランドの新聞の広告に記載された商品価格における末尾の桁の 60% が 9 であったことが知られている。

これらの事象を確認することは、大規模な統計的調査や統計学者による分析を行う必要なく容易に確かめることができる。

#### ベンフォードの法則

一方で潜在的な例として、企業の財務会計における数字の最初の桁に関する頻度について挙げることができる。すなわち、最初の桁に現れる数字の出現頻度は互いに等しくなく、偏りがあることが知られており、これはベンフォードの法則と名づけられている。このベンフォードの法則によれば、数字の最初の桁において 1 である確率は 30% 程度であるが、9 である確率は 5% 未満である。このことから数字の最初の桁における分布をより正確に求めることで、不自然な偏りを検出し、不正や詐欺を発見するのに役立たせることができる。

数字の最初の桁における各数字の出現頻度を定量的に表すと、以下の表の通りとなる。ただし、最初の桁の数値を  とし、 の出現確率を  とする。

ベンフォードの法則では、対象となるデータセットが大規模なものでかつ一つ一つのデータが複数の桁を持ち、可能な限り実在するデータに対して現れる法則となる。

十進数の数字における最初の桁の出現確率は 10 を底とする対数を用いて表される。すなわち、最初の桁の数値  の出現確率は以下の式で与えられる:

: P(d)=\log_{10}(d+1)-\log_{10}(d)=\log_{10}(1+\frac{1}{d})

これはすなわち、数字を横軸にとり、出現確率を縦軸とすると、各数字の出現確率は対数によって描かれる分布となる。したがって、数字の最初の桁における出現確率は特有の分布に従う。

大規模なデータセットに対する数字の二桁目の出現頻度についても同様に偏りのある分布となる。しかしながら、数字の右側の桁の出現頻度を求めようとすると、次第にベンフォードの法則には従わなくなり、各数字の出現確率が均等（各数字約10%の出現確率）に近づいていくことが知られている。

なお、スーパーマーケットなどの低価格帯における末尾の数字は 8（9）であることが多いため、この性質は当てはまらない。

### 単語の長さ
単語の長さを算出する方法は主に三種類存在する。一つ目は語の形態に応じて語の長さを算出する方法である。これはある単語に対してその本体の自立部分と、助詞、助動詞などの付属部分を別々のものとみなして計算する方法である。二つ目は語の表記に応じた語の長さを算出する方法である。これはある単語に対して文字として表記されているそのままの文字数を一つの単語として計算する方法である。三つ目は語の音に応じた語の長さを算出する方法である。これはある単語に対してそれぞれの文字を拍（モーラ）に応じて語の長さを計算する方法である。

1986年に出版された『中央公論』1年分のデータを標本とした日本語における単語の長さの平均は、形態別の算出方法では 1.8723 となり、表記別の算出方法では 3.6704 であり、音別の算出方法では 4.7798 であった。

## 実装
### AWKによる頻度分析プログラム
#### 説明
以下に記載されているコードはエスペラント語における頻度分析を行うプログラムで AWK によって書かれている。出力形式として ASCII、HTML、 およびヒストグラムを対応している。頻度分析が可能な項目として以下のものが挙げられる:
* （単なる）文字の出現頻度
* 単語の頭文字の出現頻度
* 単語の末尾の文字の出現頻度
* 単語の長さの平均値とその分布
* 単語の出現頻度

BEGINパターンでは分析する頻度の機能を自由に有効・無効化することができ、出力形式のフォーマットを指定することもできる。通常下記のプログラムの頻度分析は大規模なテキストコーパスの分析についても数十秒の実行時間で終了することが多い。しかし、計算機の処理速度やテキストコーパスの規模によっては単語の出現頻度を求めるのに数十分かかる場合がある。したがって、始めて分析するコーパスの実行においては単語の出現頻度分析を無効にして実行すること推奨する。

単語の出現頻度算出機能の一つとして単語を品詞ごとに分けて名詞（-O）、形容詞（-A）、副詞（-E）、（分詞を含まない）動詞、およびその他の品詞ごとに分類することができる。

言い換えれば、複数形と対格形については基本的に -O、-A、-E の形として導かれる。すなわち、"vin" や "tiujn" のような単語はそれぞれ "vi" や "tiu" となる。また動詞の語尾 "-as"、"-is"、"-os"、"-us"、"-u" は "-i" として導かれる。動詞の分詞についても -O、-A、-E の単語になり、例えば "amantojn" は "amanto" となり "ami" にはならない。

プログラムの使用方法として、下記の折り畳みボックス内のコードをコピーし、テキストファイルに貼り付け保存（frequency.awk）。これをターミナルにて以下のコマンドを実行する:


```
awk -f frequency.awk text.cx >result.cx
```


もしくは各環境に対応したコマンドを実行する。なお、このプログラムを実行するためには実行環境内に AWK をインストールしておく必要がある。Linux、Unix 環境ではデフォルトでは AWK が搭載されており、Mac も同様に動作すると考えられる。Windows については Gnu-a website からプログラムファイルをダウンロードすることでプログラムを実行することができる。

このプログラムを実行することによって任意のコーパスに対して単語の頭文字および末尾の文字の出現頻度、単文字の出現頻度、単語の長さの平均値と分布、あるいは単語の出現頻度の頻度分析が可能となる。

#### プログラム


```awk
BEGIN {
# 以下のコードは適宜修正してください

# 分析に関する設定項目 - 1: 有効化、0: 無効化

LETTER_FREQUENCY  = 1
FIRST_LETTERS_OF_WORD = 1
LAST_LETTERS_OF_WORD = 1
WORD_LENGTH  = 1
WORD_FREQUENCY  = 1 # 実行に時間がかかる

# 出力形式に関する設定項目 - 1: 有効化、0: 無効化

FORMAT_ASCII = 1
FORMAT_HTML = 1
FORMAT_WIKI = 1

# 例外の単語

NO_VERB = "^(tiu|kiu|neniu|unu|c[x]u|c[x]iu)$"
NO_ALL_WORD = "^(kaj|tuj|nun|kun|sen|ajn|plej|malplej|tamen|amen|kvin)$"
NO_ROMAN = "^(mil|((c|ci|cim|ĉ|div|divid|il|l|lic|lim|m|v|vic|vid|viv)i))$"

# lili、livi、vili もローマ数字の例外のとして挙げられるが、ほとんど場合で考慮する必要はない

start_time=systime(); # systime() 関数が使用できない環境下では除去する必要がある。

# ==================================================================================
version="Version: 2012-01-18 17:00 Pejno Simono";

FS="[ \n\t\",.;:!?()]"; # 考慮する
}

{
gsub(/[-]/,"");
for(i=1; i<=NF; i++)
if($i~/^[a-zA-Z][a-zA-Z]+$/) # 少なくとも2文字以上
{
s=tolower($i);
if(s!~/^[ivxlcdm]+$/ || s~NO_ROMAN) # ローマ数字以外
{
n=0;
for(j=1; j<=length(s); ) # 任意の文字
{
c=substr(s,j,1);
if (c~/^[cghjsu]/)
if (substr(s,j+1,1)=="x" && substr(s,j+2,1)!="x")
c=substr(s,j,2);
if(j==1)
first[c]++; # 単語の頭文字
letter[c]++;
letters++;
j+=length(c); # 単語中の "x" まで飛ばす（X-方式）
n++;
}
last[c]++; # 単語の末尾の文字

if(n>1) # 単語の長さが 1 より大きい場合のみ
{
length[n]++; # 単語の長さ
sum+=n;
words++;

if(WORD_FREQUENCY==1)
{
s=tolower($i); # すべての単語に対して
j=length(s);
if(j>2)
{
if(s!~NO_VERB)
n=sub(/(as|is|os|us|u)$/,"i",s);
if(n==0 && s!~NO_ALL_WORD)
sub(/(jn|j|n)$/,"",s);
}
word[s]++;
}

}
}
}
}

END {
FIRST=1;
LAST=2;
ALL=3;
LENGTH=4;
WORDS=5;

ASCII=1;
HTML=2;
WIKI=3

asciiwidth=50;
htmlwidth=400; # pixel
wikiwidth=400; # pixel

if(LETTER_FREQUENCY>0)
{
if (FORMAT_ASCII>0) printout(ALL,ASCII);
if (FORMAT_HTML>0) printout(ALL,HTML);
if (FORMAT_WIKI>0) printout(ALL,WIKI);
}
if(FIRST_LETTERS_OF_WORD>0)
{
if (FORMAT_ASCII>0) printout(FIRST,ASCII);
if (FORMAT_HTML>0) printout(FIRST,HTML);
if (FORMAT_WIKI>0) printout(FIRST,WIKI);
}
if(LAST_LETTERS_OF_WORD>0)
{
if (FORMAT_ASCII>0) printout(LAST,ASCII);
if (FORMAT_HTML>0) printout(LAST,HTML);
if (FORMAT_WIKI>0) printout(LAST,WIKI);
}
if(WORD_LENGTH>0)
{
if (FORMAT_ASCII>0) printout(LENGTH,ASCII);
if (FORMAT_HTML>0) printout(LENGTH,HTML);
if (FORMAT_WIKI>0) printout(LENGTH,WIKI);
}
if(WORD_FREQUENCY>0)
{
if(FORMAT_ASCII>0) printout(WORDS,ASCII);
if(FORMAT_HTML>0) printout(WORDS,HTML);
if(FORMAT_WIKI>0) printout(WORDS,WIKI);
}

if(start_time>0) print time_needed();
print version;
}

function printout(mode,format)
{
if(mode==FIRST)
return printout2(mode,format,first);
if(mode==LAST)
return printout2(mode,format,last);
if(mode==ALL)
return printout2(mode,format,letter);
if(mode==LENGTH)
return printout2(mode,format,length);
if(mode==WORDS)
return printout2(mode,format,word);
}

function printout2(mode,format,A)
{
setup(mode);
if(format==ASCII)
return printoutASCII(mode,A);
if(format==HTML)
return printoutHTML(mode,A);
if(format=WIKI)
return printoutWIKI(mode,A);
}

function setup(mode)
{
_col=2;
_asc=0;
_colhdr="letter";
_colalign="center";
_counted="words";
_count=words;
_mez=", average word length";
_mez2="letters";

if(words>0)
_av=sum/words; # 単語の長さの平均値
if(mode==FIRST)
{
_title="First letters of a word";
return;
}
if(mode==LAST)
{
_title="Last letters of a word";
return;
}
if(mode==ALL)
{
_title="All letter";
_counted="letters";
_count=letters;
return;
}
if(mode==LENGTH)
{
_title="Word length";
_col=1;
_asc=1;
_colhdr="length";
return;
}
if(mode==WORDS)
{
_title="Word frequencies";
_colhdr="word";
_colalign="left";
}
}

function printoutASCII(mode,A, i,j,B,w,s,fmt)
{
if(_count<1)
{
print "file empty";
return;
}
i=sillysort(A,B,_col,_asc);
if(mode!=LENGTH) # 最高値
j=B[1,2]
else
j=getmax(B);
w=asciiwidth/j;
print "<" "pre>";
printf("=== %s ===\n\n",_title);
if(mode==WORDS)
fmt="%-20s\t%8s %s\n";
else
fmt="%-6s\t%8s %s\n";
printf(fmt,_colhdr,"number","probability\n")
if(mode==WORDS)
fmt="%-20s\t%s %6.2f%% %s\n";
else
fmt="%-6s\t%s %6.2f%% %s\n";
for(j=1; j<=i; j++)
{
s=B[j,1];
if(mode!=WORDS)
s=toupper(s);
printf(fmt, s, thou(B[j,2],8), 100.0*B[j,2]/_count, hist(B[j,2]*w));
}
printf("\nEl %s %s", thou(_count,0), _counted);
if(mode==LENGTH)
printf("%s %0.2f %s", _mez, _av, _mez2);
printf "\n</" "pre>\n\n";
}

function hist(w, s)
{
w-=0.5;
while(w-- > 0)
s=s "*";
return s;
}

function printoutHTML(mode,A, i,j,B,w,s)
{
if(_count<1)
{
print "file empty";
return;
}
i=sillysort(A,B,_col,_asc);
if(mode!=LENGTH) # 最高値
j=B[1,2]
else
j=getmax(B);
w=htmlwidth/j;
printf("<table border=1>\n");
printf("<tr><th colspan=4>%s</th></tr>\n",_title);
printf("<tr><td align=%s>%s</td><td align=right>number</td>", _colalign, _colhdr);
printf("<td align=center colspan=2>probability</td>\n");
for(j=1; j<=i; j++)
{
s=B[j,1];
if(mode!=WORDS)
s=toupper(s);
printf("<tr><td align=%s><b>%s</b></td>", _colalign, s);
printf("<td align=right>%s</td>", thou(B[j,2]),0);
printf("<td align=right>%0.2f%%</td>", 100.0*B[j,2]/_count);
printf("<td align=left><div style=\"width:%dpx;",B[j,2]*w);
printf("height:2ex;background:blue;\">&#160;</div></td>\n");
}
printf("<tr><th colspan=4>El %s %s", thou(_count,0), _counted);
if(mode==LENGTH)
printf("%s %0.2f %s", _mez, _av, _mez2);
printf("</th></tr>\n");
printf("</table>\n\n");
}

function printoutWIKI(mode,A, i,j,B,w,s)
{
if(_count<1)
{
print "file empty";
return;
}
i=sillysort(A,B,_col,_asc);
if(mode!=LENGTH) # 最高値
j=B[1,2]
else
j=getmax(B);
w=100.0*j/_count;
w=wikiwidth/w;
printf("\n\n");
}

function getmax(A, i,j,M)
{
for(i in A)
{
split(i, M, SUBSEP);
if(M[2]==2)
if(A[i]>j)
j=A[i];
}
return j;
}

function sillysort(A,B,col,asc, i,j,n,t)
{
for(j in A)
{
i++;
B[i,1]=j;
B[i,2]=A[j];
n=i;
if (asc==0) # desc
{
while(n>1 && B[n,col]+0>B[n-1,col]+0)
{
t=B[n-1,1]; B[n-1,1]=B[n,1]; B[n,1]=t;
t=B[n-1,2]; B[n-1,2]=B[n,2]; B[n,2]=t;
n--;
}
}
else # asc
{
while(n>1 && B[n,col]+0<B[n-1,col]+0)
{
t=B[n-1,1]; B[n-1,1]=B[n,1]; B[n,1]=t;
t=B[n-1,2]; B[n-1,2]=B[n,2]; B[n,2]=t;
n--;
}
}
}
return i;
}

function time_needed( h,m,s,eps)
{
eps=0.000001;
s=systime()-start_time;
m=int(s/60);
s-=m*60-eps;
h=int(m/60);
m-=h*60-eps;
return sprintf("Run time (hms): %i:%02i:%02i\n",h,m,s);
}

function thou(v,n, s)
{
s=sprintf("%d_",v);
while(s~/[0-9][0-9][0-9][0-9]/) # エレガント
sub(/[0-9][0-9][0-9][,_]/, ",&",s); # 興味深い
sub(/_/,"",s); # エレガントでない
while(length(s)<n)
s=" " s;
return s;
}

function _thou(v,n, i,j,s,t)
{
s=sprintf("%d",v);
for(i=length(s); i>0; i--)
{
t=substr(s,i,1) t;
if(++j%3==0)
t="," t;
}
while(length(t)<n)
t=" " t;
return t;
}
```


## 脚注

### 注釈

### 出典

## 参考文献
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
*

## 関連項目
* 
* 
* 文字の出現頻度による効果
* リポグラム
* RSTLNE - （ホイール・オブ・フォーチュン）
* 暗号関係の書籍の一覧

## 外部リンク
* 
* 
* 
* 
* 

### 便利な表
以下の文献は英単語の3から7文字目までの文字の位置や単語の長さを考慮した20,000単語中の単文字、連接文字、3文字、4文字、5文字の出現頻度をまとめた表が記載されている:
* 
* 
* 
*