10/18 課題

インド出身の天才数学者ラマヌジャンについて以下のようなエピソードが知 られている. 数学者ハーディがたまたま拾ったタクシーのナンバーが XXXX (4桁の数)とい うものだった.彼がその数のことをラマヌジャンに面白くない数だと行ったと ころ,ラマヌジャンは即座に,「その数は大変面白い数で,2つの3乗数の和で 2通りに表される最小の数だ」と答えた. 問題 10000以下で2つの3乗数の和で2通りに表される数をすべて求めるプログラム を書きなさい.ファイルは,自分のホームディレクトリの下に java というディレクトリを作成して,その下にKadai1018.java という名前で作成する(クラス名もKadai1018という名前で作成する).
実行例
ktanaka@ux111> cd ~/java
ktanaka@ux111> javac Kadai1018.java
ktanaka@ux111> java Kadai1018
XXXX
..
ktanaka@ux111> 

プログラムがちゃんと動くことを確かめたら,

/home/ktanaka/bin/report1018 1
を実行すること.このプログラムは,~/java/Kadai1018.javaの有無,コンパイル ,実行できるかどうかなどをチェックする.なお,自分の名前,学生証番号,プログラムに関するコメントを Kadai1018.java の先頭にコメントとして入れること.
注意
あまり考えずにプログラミングすると,9のように1通りでしか表されない数も
9 = 13+23 = 23+13
と2通りに表されるという解がでてしまうことがある.
ヒント
3乗数 x3を計算するには, Math.powという算術演算を使って,
   Math.pow(x,3)
のように書くこともできるが,
   x*x*x
のように書く方が速いし,整数だけの計算で済むため誤差が問題になることがない.

平方根の計算には,Math.sqrtという算術関数が用意されているが,三乗根は 対応する関数が用意されていない.そこで, Math.powという算術演算を使って,

   Math.pow(x,1.0/3.0)
のようにして計算できる.
ヒント
for文の初期化部分(式1)では,変数の初期値として定数以外のものも書ける. これをうまく使うと,10以下の数のペア(順序は問わない)をすべて(かつ同じ ものは1度だけ)表示するプログラムはたとえば,以下のように書ける.
class Test{
  public static void main(String[] args){
    int i,j,n=10;
    for(i=1;i<=n;i++) // iを1からnまでの間繰り返す
      for(j=i;j<=n;j++) // jをiからnまでの間繰り返す.常にi<=jとなるので
                        // iとjを取り替えると一致してしまうようなペアは
                        // 出てこない
        System.out.println("("+i+","+j+")"); // i,j は数値なので文字列にした
                                             // うえで連結する.
  }
}

ヒント
変数を条件が成立した回数を数えるためのカウンタとして,使うプログラム例 がなかったので,付け加える.
class CountMult {
  public static void main(String[] args){
    int count,i,v;
    for(v=1;v<20;v++){ // vを1から20まで繰り返す
      count=0;         // 倍数の数を数えるカウンタの初期値を0にする
      for(i=1;i<=100;i++){ // iを1から100まで繰り返す
	if((i % v) == 0) // (1) iがvの倍数の時は
	  count++;       // カウンタの値を1足す
      }
      System.out.println("100以下の"+v+"の倍数は"+count+"個あります");
    }
  }
}
上のプログラムは,100までの間に v(1<=v<=20)の倍数がいくつあるかを表示 するプログラムである.条件(1)が成立するiがあるたびに,countを1つ増やし ていて,すべてのiをチェックし終わったあとで表示している.
ヒント
実行速度などを考慮にいれない素直な解答は,大体以下のような構造になるだ ろう(変数宣言などは取り除いている.また伏せ字にしている部分もある)
  for( xxx ; xxx ; xxx ){ // 1から10000までの数をチェックする
    count=0; // 三乗の和で何通り表されるかを数えるカウンタ
    for( xxx ; xxx ; xxx )  // この
      for( xxx ; xxx ; xxx) // 2つのforループで元の数の三乗根以下(あるいは
                            // 10000の三乗根以下でも良い)の数のペアを総て
                            // 生成する.余計に生成しても後のチェックで除ける
        if( xxxx )          // ペアの3乗の和になっているならば,
          count++;          // カウンタを1増やす
    if(count==2)            // カウンタの値が2ならば
      xxxxx;                // 数を表示する
  }
もっと効率の良いプログラムは書けるので,この方針に従わずに自分なりに 考えた解答は歓迎する.
注意
10月19日 18:00-19:30 の間,課題提出プログラムが正常に動かず,正しいプ ログラムでも「文法エラーがあります」というメッセージが出て提出できない という症状が出ていました.現在は直っているので,もう一度試してみてくだ さい.

課題の提出期限は10月20日(金)の21:00.それ以前であれば,何度でも再提出できる.