1

各行の最後にハード リターンを含め、それぞれ 60 文字の長さの 3 行のテキスト (本質的にはジブリっぽい) を生成する必要があります。行は、さまざまな長さ (通常は 1 ~ 8 文字) の単語の辞書から生成されます。単語を複数回使用することはできず、単語はスペースで区切る必要があります。これは本質的にビンパッキングの問題だと思います。

私がこれまでに取ったアプローチは、長さによってグループ化された単語の hashMap を作成することです。次に、ランダムな長さを選択し、その長さの単語をマップから取り出して、現在生成している行の末尾に追加します。スペースまたはハード リターンを考慮します。約半分の時間は機能しますが、残りの半分の時間は無限ループに陥り、プログラムがクラッシュします。

私が直面している 1 つの問題は次のとおりです。行にランダムな単語を追加すると、特定の長さの単語のグループが枯渇する可能性があります。これは、辞書内の各長さの単語数が必ずしも同じであるとは限らないためです。たとえば、長さ 1 の単語は 1 つしかない場合があります。その長さの任意の単語が利用可能です。

以下は、私がこれまでに持っているものをまとめたものです。私は ActionScript で作業していますが、どの言語でもこの問題についての洞察をいただければ幸いです。よろしくお願いします。

dictionary // map of words with word lengths as keys and arrays of corresponding words as values
lengths // array of word lengths, sorted numerically
min = lengths[0] // minimum word length
max = lengths[lengths.length - 1] // maximum word length
line = ""
while ( line.length < 60 ) {
    len = lengths[round( rand() * ( lengths.length - 1 ) )]
    if ( dictionary[len] != null && dictionary[len].length > 0 ) {
        diff = 60 - line.length // number of characters needed to complete the line

        if ( line.length + len + 1 == 60 ) {
            // this word will complete the line exactly
            line += dictionary[len].splice(0, 1) + "\n"
        }
        else if ( min + max + 2 >= diff ) {
            // find the two word lengths that will complete the line
            // ==> this is where I'm having trouble
        }
        else if ( line.length + len + 1 < 60 - max ) {
            // this word will fit safely, so just add it
            line += dictionary[len].splice(0, 1) + " "
        }

        if ( dictionary[len].length == 0 ) {
            // delete any empty arrays and update min and max lengths accordingly
            dictionary[len] = null
            delete dictionary[len]

            i = lengths.indexOf( len )
            if ( i >= 0 ) {
                // words of this length have been depleted, so
                // update lengths array to ensure that next random
                // length is valid
                lengths.splice( i, 1 )
            }
            if ( lengths.indexOf( min ) == -1 ) {
                // update the min
                min = lengths[0]
            }
            if ( lengths.indexOf( max ) == -1 ) {
                // update the max
                max = lengths[lengths.length - 1]
            }
        }
    }
}
4

2 に答える 2

1

  1. n 文字の単語は n+1 文字と考える必要があります。これは、各単語の後にスペースまたは改行があるためです。
  2. すべての単語は少なくとも 2 文字の長さであるため、59 文字まで入力する必要はありません。57 文字になった場合は、2 文字と改行を加えたものを選択する必要があります。58 になると、1 文字の単語とリターンが必要になります。
  3. 時間を最適化しようとしていますか?同じ単語を複数回使用できますか? 1行で複数回?たとえば、多くの行に「a」または「I」が含まれているのは、これらが英語で唯一の 1 文字の単語であるためです。

これが基本的な考え方です。各行について、語長の選択を開始し、それまでの語長と合計文字数を追跡します。行の終わりに近づいたら、残りの文字数より短い語長を選択します。(例えば、残り 5 文字の場合は、スペースを数えて 2 ~ 5 文字の範囲で単語を選択します。) 57 文字になった場合は、3 文字の単語を選びます (折り返しを数えます)。58文字に達したら、2文字の単語を選んでください(カウントリターン)。

必要に応じて、この時点で単語の長さをシャッフルして、すべての行が短い単語で終わらないようにすることができます。次に、単語の長さごとに、その長さの単語を選択してプラグインします。

于 2010-03-01T15:55:09.577 に答える
0
dictionnary = Group your words by lengths (like you already do)
total_length = 0
phrase = ""

while (total_length < 60){

random_length = generate_random_number(1,8)

if (total_length + random_length > 60)
{
  random_length = 60 - total_length // possibly - 1 if you cound \n and -2 if you 
                                    // append a blank anyway at the end
}

phrase += dictionnary.get_random_word_of_length(random_length) + " "
total_length += random_length + 1 

}
于 2010-03-01T16:05:29.150 に答える