小説中の人物相関に関するトリビアルな発見
Awk もだいたい思い出せた、DOT 言語も初歩のレッスンはやった。ということで、Awk と DOT で『大菩薩峠』の人物相関図を作った。発見があった。馬鹿らしいような発見だが、発見ではあるだろう。
『大菩薩峠』人物相関図(クリックで拡大、2.5MB)
相関関係の考え方は、前に考えたのと同じ。
- 出会わない二人――『大菩薩峠』はすれ違いドラマ
人物 A と人物 B の名前が『大菩薩峠』本文の近い箇所で現れたら、A と B のあいだに何らかの関係(出会った、話をした、戦った、思った、など)があると見なす。Wikipedia の大菩薩峠の項で「おもな登場人物」としてあげられている44人について、たがいの関係の有無を調べると関係ありが570件あった。これを図にしたのが上の相関図。
「本文の近い箇所」をどう考えるかによって関係の数は変わるが、プログラムのパラメータを変えても最少で500件前後だった。
44人の人物全員がたがいに関係を持っているとした場合、関係の数は
44✕(44−1)÷2 = 924
である。これに対して、本文で描かれた関係が500件。これはいかにも多すぎる。『大菩薩峠』の登場人物は、ほとんどがたがいに知り合いなのではないか。
とても人物の関係を図化できるものではない。とんでもない小説だ、『大菩薩峠』は。――と思いかけたのだが、考えてみるとこれは『大菩薩峠』に限ったことではない。小説の世界は現実世界に比べればはるかに狭い。人物は少ない。そしてたがいに関係を持っている。人物間に関係がないと小説にならない。これが今回の発見。脱力ものの馬鹿らしい発見だが。
あとで使えそうなルーチンやアイデアもあるので、解析に使った Awk スクリプトをメモしておく。
Awk を思い出したのは去年の収穫。しばらく使ってみる。
『大菩薩峠』人物相関図(クリックで拡大、2.5MB)
相関関係の考え方は、前に考えたのと同じ。
- 出会わない二人――『大菩薩峠』はすれ違いドラマ
人物 A と人物 B の名前が『大菩薩峠』本文の近い箇所で現れたら、A と B のあいだに何らかの関係(出会った、話をした、戦った、思った、など)があると見なす。Wikipedia の大菩薩峠の項で「おもな登場人物」としてあげられている44人について、たがいの関係の有無を調べると関係ありが570件あった。これを図にしたのが上の相関図。
「本文の近い箇所」をどう考えるかによって関係の数は変わるが、プログラムのパラメータを変えても最少で500件前後だった。
44人の人物全員がたがいに関係を持っているとした場合、関係の数は
44✕(44−1)÷2 = 924
である。これに対して、本文で描かれた関係が500件。これはいかにも多すぎる。『大菩薩峠』の登場人物は、ほとんどがたがいに知り合いなのではないか。
とても人物の関係を図化できるものではない。とんでもない小説だ、『大菩薩峠』は。――と思いかけたのだが、考えてみるとこれは『大菩薩峠』に限ったことではない。小説の世界は現実世界に比べればはるかに狭い。人物は少ない。そしてたがいに関係を持っている。人物間に関係がないと小説にならない。これが今回の発見。脱力ものの馬鹿らしい発見だが。
あとで使えそうなルーチンやアイデアもあるので、解析に使った Awk スクリプトをメモしておく。
Awk を思い出したのは去年の収穫。しばらく使ってみる。
BEGIN {
split("竜之助 お松 七兵衛 兵馬 お浜 ... ", t)
for (i in t) {
for (j in t) {
rels[t[i],t[j]]; delete rels[t[j],t[i]]
}
}
}
FNR == 1 { printrel() }
{ page = page $0 }
FNR % 10 == 0 { printrel() }
END { printrel() }
function printrel() {
if (page == "") return
for (rel in rels) {
split(rel, X, SUBSEP)
if ((page ~ X[1]) && (page ~ X[2])) {
print X[1], X[2]
delete rels[rel]
}
}
page = ""
}
split("竜之助 お松 七兵衛 兵馬 お浜 ... ", t)
for (i in t) {
for (j in t) {
rels[t[i],t[j]]; delete rels[t[j],t[i]]
}
}
}
FNR == 1 { printrel() }
{ page = page $0 }
FNR % 10 == 0 { printrel() }
END { printrel() }
function printrel() {
if (page == "") return
for (rel in rels) {
split(rel, X, SUBSEP)
if ((page ~ X[1]) && (page ~ X[2])) {
print X[1], X[2]
delete rels[rel]
}
}
page = ""
}