マルコフ連鎖で作られた文章は、文字数が調節されていません。生成に使ったデータが多いと、際限なく文章が作られ、結果的に超長文になってしまいます。

そこで、生成される文字数を適切な長さに調節するためにも、文字数の計測と調節用の関数を作ってみました。

もちろん「。」単位で区切っているので文章の途中でバッサリ切り落とされることはありません。

プログラムの概要

フローチャート図

フローチャート図

ソースコード

#! /usr/bin/python3
import sys

DEFAULT_LENGTH = 2000

def measure(sentence,length):

    
    sentence = sentence.split("。")
    count = 0
    new          = []
    new_sentence = ""

    for str in sentence:
        str = str + "。"
        if str != "。":
            new.append(str)
            count = count + len(str)

        if count > length:
            new_sentence = "".join(new)
            return new_sentence,count,True

    new_sentence = "".join(new)
    return new_sentence,count,False

if __name__ == "__main__":
    try:
        while True:

            sentence = input("適当な文字列を入力してください。\n")
            length   = input("長さは?(デフォルト:{}文字)".format(DEFAULT_LENGTH))
            if length == "":
                length = DEFAULT_LENGTH

            new_sentence,count,result = measure(sentence,int(length))

            if result:
                print("文字数:{}文字".format(count))
                print(new_sentence)
            else:
                print("指定した文字数、{}文字を満たしていません。文字数:{}文字".format(length,count))
                print(new_sentence)

    except KeyboardInterrupt:
        print("\nprogram was ended.\n")
        sys.exit()

このプログラムの解説

このプログラムは、文字列と数値を入力して使います。指定した数値に、文字数が収まるように文章を作り直します。

そのまま起動しても、関数として呼び出しても使用可能です。指定した文字数を満たしていない場合は、入力された文章の文字数と原文をそのまま出力します。

while文の無限ループなので、通常起動時でも連続して使用できます。

工夫したところ

文字数を一文単位で計測する

文字列変数の文字数を計測するのは簡単です。len関数を使えばいいだけのことですから。

しかし、len関数を使ったとしても、「。」単位で区切らずに文字数単位で区切ってしまうと、文章の最後が「。」で終わらずに途中で途切れてしまいます。

だから、まずは「。」ごとに区切ってリストに代入し、その文字数を計測していくように作りました。これで文章の最後が「。」で終わるように出力できます。

関数の返り値を2つ以上に指定する

今回のプログラムでは生成された文章の変数、文字数のカウント値、指定された値を超過したか否か、といった3つの値を同時に返却しています。

ご覧の通り、3つの返り値それぞれに変数を用意して代入させ、後の処理を決めているのです。

指定した値を超過した場合はTrue、不足している場合はFalseを返却するので、マルコフ連鎖の文章自動生成プログラムで自動生成をやり直すこともできるでしょう。

動作環境

  • Python3がインストールされたUbuntu

実際に動かしてみる

起動すると、メイン関数が文章の入力を促します。マルコフ連鎖で作られた文章でも、自分で作った文章でも構いません。原稿をコピペしてエンターキーを押しましょう。

適当な文章を入力する

次に、調節してほしい文字数を入力します。何も入力せずにエンターキーを押すとDEFAULT_LENGTHに代入されている値になります。

文字数の計測が始まり、指定した文字数よりも文章が長い場合は、文字数に合わせて切り取られます。

文字数に合わせて調節される

文章が見やすく、簡潔になりました。

一方で、指定した文字数に及ばない場合は、その旨を報告され、原文がそのまま出力されます。

足りない場合は文章がそのまま出力される

メリットとデメリット

メリット

  • 標準モジュールのみで作られている
  • 一文単位で計測するので、中途半端な文章にならない
  • マルコフ連鎖の自動文章生成プログラムと連携可能

まず、いつものことですが標準モジュールのみで作られているので環境を選びません。

一文単位で計測していくので、文章が途中で途切れてしまうこともないでしょう。

関数化されているので、マルコフ連鎖の自動文章生成プログラムと連携可能です。

デメリット

  • 文脈を無視して文字数を計測し、文章を生成している
  • 指定した文字数を超過した場合、それ以降は問答無用で切り捨てられる
  • 改行に対応していない

まず、指定された文字数を超過した場合、それ以降の文章は問答無用で切り捨てられます。文章の最後の方に良い内容が書かれてあったとしても、このプログラムには関係ありません。

もちろん、このプログラムには文脈を把握することなんてできません。だから、これから文章の本題に入る場合でも、指定した文字数を超過した場合は問答無用で切り捨てられます。

それから、改行に対応していません。文章の途中で改行があると、挙動がおかしくなります。改行を予め削除しておくなどの対策が必要です。

以上の点からあくまでも、マルコフ連鎖の自動文章生成プログラムの補助関数として利用するべきです。

結論

マルコフ連鎖の自動文章生成プログラムは、データが大量にあると、際限なく文章が生成されてしまいます。適度な長さに文章を自動でカットできるこの関数は、地味に役に立ちそうです。

それから、最初に指定する数値を非常に大きい値(99999など)にすれば、文字数の計測ツールとして使えなくはないでしょう。

関連記事

マルコフ連鎖による自動文章生成プログラム

【内部リンク】マルコフ連鎖による日本語文章自動生成プログラムの覚書【Python】

マルコフ連鎖を活用して、テキストファイルから自動的に新しい文章を生成します。

生成される文章の中には、事実に反するものもありますが、適切に関数化されており、改善の余地があるでしょう。

連続した「です」「ます」を検知する

【内部リンク】文章で連続する「です」「ます」を検知して、ハイライト表示で警告するPython関数【自然言語処理】

末尾の2文字を抜き取って、それが3連続以上であればハイライト表示します。

形態素解析ツールを使用していないので、環境を選ばないメリットがあります。ブログに投稿する原稿のチェックなどにも使えるでしょう。

連続した文頭を検知する

【内部リンク】連続する接続詞(文頭)を検知してハイライト表示で警告するPython関数【自然言語処理】

文章の最初の3文字を抜き取って検査することで、連続した文頭を検知することができます。

こちらも同じく形態素解析ツールを使用していないので接続詞だけをピンポイントで検知することは難しいですが、標準モジュールのみなので、環境を選びません。