10を自然数の和に分割する
十進BASIC_算数 へ戻る
大学生のための数学 へ戻る
2014.08.16


( 問題A )
  21歳から30歳までの年齢の異なる十人が年齢順に並んでいます。 皿の上に団子が10個乗っており、 年齢順に団子を1個以上好きな数だけ取って行きます。 ただし、 前の人がとった数よりも多く取ることはできません。 皿から団子がなくなったらストップです。 団子をもらえない人もあります。 このとき何通りの取り方があるでしょうか?


( 問題B )
  各位の数の総和が 10 であり、 かつ、 位が低くなるにつけて決してその位の数が小さくならない自然数、 例えば 136 や 11233 など、 は全部でいくつあるでしょうか?


  問題A の答えは 問題B の答えよりも 1 つだけ多くなっています。 問題A と 問題B の答えを見つけるために、 次のようなよく似たプログラムを2つ作りました。

  このような FOR i = a TO b が幾重にもなっているプログラムは低級なものと考えられているようです。 十進BASIC をダウンロードすると、 SAMPLE の中に PARTITIO.BAS というプログラムがあります。 これは高級なプログラムで再帰関数が用いられています。 このプログラムを使ってもこの問題を解くことができます。

  では、 10を分割するアルゴリズムについて考えてみましょう。 まずは、 分割の概念の発想の転換から始めます。 10を2分割する場合の数は一般的には5通りですが、 ここでは10を2分割する方法を次の10通りとします。
    10+0   9+1   8+2   7+3   6+4   5+5
    4+6    3+7   2+8   1+9
  なぜこうするのかと申しますと、 それは、 もうこれ以上分割しない数と、 今後も分割する可能性のある数との2つに分割しているからです。 2分割した最初の数をもうこれ以上分割しない数とし、 「 既得数 」 と呼ぶことにします。 そして、 2分割した最後の数をこれからも分割する可能性のある数とし、 「 未得数 」 と呼ぶことにします。 そして、 「 未得数 」 が 0 になるように分割されたものを 「 完成された分割 」 ということにします。
  次に3分割する方法ですが、 それは2分割した数をさらに2つに分割することによって3分割を作ることにします。 すると、 たとえば 4+6 であれば、 次のような6通りに3分割されることになります。
    4+(6+0)    4+(5+1)    4+(4+2)
    4+(3+3)    4+(2+4)    4+(1+5)
  カッコの中の数は 「 既得数 」 と 「 未得数 」 とに分解されています。 これからは同じ分割方法がいくつも現れないようにするため、 既得数が左から大きい順になってない分割方法は没にします。 上記の例では 4+(6+0) と 4+(5+1) が没になります。
  次は4分割に挑みましょう。 例えば 4+(2+4) から4分割を作ってみましょう。 すると次のような通りになります。
    4+2+(4+0)   4+2+(3+1)   4+2+(2+2)   4+2+(1+3)
  このうち既得数が左から大きい順になってない分割方法 4+2+(4+0) と 4+2+(3+1) は没にします。
  次は5分割です。 たとえば 4+2+(2+2) から5分割を作ってみましょう。 次の2つになります。
    4+2+2+(2+0)    4+2+2+(1+1)
  両方とも既得数が左から大きい順になっているので没になりません。 しかも 4+2+2+(2+0) は 「 未得数 」 が 0 になっていますので、 「 完成された分割 」 です。

  以上のような方法で 「 完成された分割 」 を見つけていけば、 すべての分割方法が解ります。 これを利用して新たにプログラムを作ってみました。

  このプログラムに現れる a 〜 i の記号は 「 未得数 」 を表しています。 「 既得数 」 と 「 未得数 」 の和は分岐する前の親の 「 未得数 」 に等しいという性質、 既得数が左から大きい順になっていないものは除外すること、 「 未得数 」 が 0 になれば 「 完成された分割 」 になるということが用いられています。 最初に掲載したプログラムたちに比べるとアルゴリズムを利用していて少しはましかと思いますが、やはり PARTITIO.BAS に比べると随分見劣りします。