レポート課題

Java 7 を使用してすること(なお、発展課題は解答しなくても不合格の原因にはならない)。

レポートには表紙をつけてください。

変更履歴

2013/12/24
課題2-3の図を書く負担を軽減
2013/12/18
課題2の図を書く指定を補足
2013/9/16
課題2の TDUIteratorTest の改良が反映されて無かったので、改めてリリース
2013/9/3
課題1のパッケージから Deck2 を削除。課題2の TDUIteratorTest を改良
2013/8/20
課題1の SuperRareTest を直感的に読めるように改良
2013/7/30
課題2-4の問題文の訂正は勘違いだったので、元に戻しました。 課題1-2,1-4のテストの追加
2013/7/12
課題2-4の問題文の訂正
2013/7/5
課題2のテストの修正
この修正によって、抜けていたテストができるようになり、プログラムの作成がしやすくなる。
RecursiveTest プログラムの追加
再帰とループの速度の比較用に作成したプログラム。使用は自由。
2013/5/31
課題1(新)初出
2013/5/19
課題2初出
2013/5/16
AbstractSuperRareの変数名、メソッド名の改善、SuperRareTest のテスト項目追加。なお、変数名、メソッド名の改善は対応せずに、旧版のままでプログラムを作成しても良い。
2013/5/15
課題1-4のクラス指定の誤りを訂正
2013/5/5
問題文の Rare を「抽象クラス」から「クラス」へ
2013/4/29
課題1初出

課題2

4年生
2014年6月11日17:00(この問題でも 2014年度の評価対象として受けとります。但し、4月または5月に出る新しい問題を解答することを推奨します。)

提出先: 2号館レポートボックス

順序木を利用し、キーの値で値を整列するデータ構造を作成することを考えま す。 そのためには、java.util.Map を実装し、 java.util.AbstractMap を継承し、 最小限のプログラムで動作させます。 まず、文字列をキーとして、整数値を整列するような TDUMap3 を目標としま す。 完成した後、Generics を利用した任意の型のキーと値を使用できる TDUMap を作成します。

こちらで用意したプログラムはすべて kadai フォルダに入っており、 kadai パッケージに含まれます。 また、テストプログラムを用意したので、活 用すること。 解答のプログラムは kaitou パッケージに作成しなさい。

課題2-1

はじめに、型 E の配列を受け取って java.util.Set<E> として動作する kadai.TDUSet<E> を作成します。 これは java.util.AbstractSet<E> を継承し、配列を受け取るコンスト ラクタと、 size() メソッドと iterator メソッドを実装するだけで実現できます。 なお、この TDUSet に関しては add や remove などの要素を変更するような実装は 一切しないことにします。 そのため、下記のように実装しました。

kadai.TDUSet


package kadai;
import java.util.AbstractSet;
import java.util.Iterator;

import kaitou.TDUIterator;

public class TDUSet<E> extends AbstractSet<E>{
	private E[] set;
	public TDUSet(E[] array){
		set = array;
	}
	@Override
	public int size(){
		return set.length;
	}
	@Override
	public Iterator<E> iterator(){
		return new TDUIterator<E>(set);
	}
}

これが動作するように kaitou.TDUIterator<E> を作成しなさい。 なお、 public void remove() に関しては、 java.lang.UnsupportedOperationException 例外を投げなさい。 これをテストするために、 TDUSetTest, TDUIteratorTest を利用しなさい。

課題2-2

次に、キーとして文字列、データとして整数値を持つようなクラスを java.util.Map<String,Integer> の実装として作成することを考えます。 そのため、まず、二分木の節となるクラスを java.util.Map.Entry<String,Integer> を実装したクラスが必要です。 そのため、 TDUMapEntry1 を java.util.AbstractMap.SimpleEntry<String,Integer>を継承し、 下記のように作成しました。

kadai.TDUMapEntry1


package kadai;
import java.util.AbstractMap;
public class TDUMapEntry1 extends AbstractMap.SimpleEntry<String,Integer>
{
	private static final long serialVersionUID = 1L;
	public TDUMapEntry1(String s ,Integer i){
		super(s,i);
		left=null;
		right=null;
	}
	public TDUMapEntry1 left;
	public TDUMapEntry1 right;
}

次に、TDUMap1 を java.util.AbstractMap<String,Integer> を継承し て作成することを考えます。 但し、このクラスは TDUMapEntry1 で作られた二分木に対して、根のオブジェ クトの参照からサイズ(節点の数)を返すメソッド int size() を実装すること だけを目標として考えます。 まずkadai.AbstractTDUMap1 を下記のように作成しました。

AbstractTDUMap1


package kadai;
import java.util.AbstractMap;
import java.util.Set;
import java.util.Map;
public abstract class AbstractTDUMap1 extends AbstractMap<String,Integer> {
	protected TDUMapEntry1 root;
	protected AbstractTDUMap1(){
		root=null;
	}
	protected AbstractTDUMap1(TDUMapEntry1 root){
		this.root = root;
	}
	@Override
	final public int size(){
		return size2(root);
	}
	@Override 
	public Set<Map.Entry<String,Integer>> entrySet(){
		return null;
	}
	protected abstract int size2(TDUMapEntry1 p);
}

これを継承し、二分木のサイズがきちんと返るように protected int size2(TDUMapEntry1 p) という関数を実装したクラス kaitou.TDUMap1 を作成しなさい。 これのテストには、 TDUMap1Test を使用しなさい。 なお、レポートに報告するには、この TDUMap1Test の size() メソッド呼び 出し箇所( assertEquals(0,m.size()), assertEquals(1,m.size()), assertEquals(2,m.size()), assertEquals(3,m.size()), assertEquals(6,m.size()) の 5箇所)におけるデータの木構造を図示したもの作成し、それぞれ size がどのように動作するか説明すること。

課題2-3

次に、 TDUMap1 を継承し、 entrySet() を正常に出力するようなクラス TDUMap2 を作ります。 もともと、java.util.AbstractMap は、この entrySet() だけを実装すれば動 作するようになっていますので、これを実装することで正常な java.util.Map として動作するようになります。 entrySet() を作成するために次のアルゴリズムを考えます。 大まかな方針は、まずTDUMapEntry1 の木構造から java.util.Map.Entry<String,Integer> の配列を作り、次に TDUSet に渡 したものを 戻り値として返すことです。

  1. 木構造に対してサイズを求め、そのサイズ分の配列 Map.Entry<String,Integer> [] を作成する
  2. 配列用の index を 0 に初期化する
  3. 木を一番左の要素から順番にたどるようなプログラム travarse を呼び出 し、木の要素を順に配列に貯める
  4. TDUSet<Map.Entry<String,Integer>> に作成した配列を与え て entrySet の値として返す

上記に基づいて途中まで作成したのが下記の AbstractTDUMap2 クラスです。 これを継承し、正常に動作するようにTDUMap2を作成しなさい。

kadai.AbstractTDUMap2


package kadai;
import java.util.Map;
import java.util.Set;
import kaitou.TDUMap1;
public abstract class AbstractTDUMap2 extends TDUMap1 {
	protected AbstractTDUMap2(){
		super();
	}
	protected AbstractTDUMap2(TDUMapEntry1 root){
		super(root);
	}
	protected Map.Entry<String,Integer>[] array;
	protected int index;
	@SuppressWarnings("unchecked")
	@Override
	public Set<Map.Entry<String,Integer>> entrySet(){
		array = (Map.Entry<String,Integer>[]) new Map.Entry[size()];
		index=0;
		traverse(root);
		return new TDUSet<Map.Entry<String,Integer>>(array);
	}
	protected abstract void traverse(TDUMapEntry1 p);
}

これが正常に動作することを確かめるために、TDUMap2Testを使用しなさい。 なお、プログラムの説明には、TDUMap2Testの各 entrySet() のうち、要素数0,1,3,6のそれぞれの呼び出し を呼び出すとき の木構造 と、 traverse で作成する配列をそれぞれ図示したもの作成し、 traverse がどのように動作するか説明すること。 但し、同じ結果になる場合は重複させなくてよい。

課題2-4

最後に TDUMap3 として put メソッドにより要素を追加できるように実装し ます。 put は次のように実装します。

  1. TDUMapEntry1(s,i) を作り、変数 e により参照する。
  2. root が null なら、 root=e とし、 null を返す。
  3. put2(root,e) を呼び出し、戻り値を 返す。 ここで戻り値とは、値を更新する時は保存してあった古い値とし、新規の値を 保存する場合は null とする。 また、 put2(root,e) は実際に順序木を作りデータをしまうメソッドである。

ここまでを実装したクラス kadai.AbstractTDUMap3 を以下に示します。 これを継承し、 protected Integer put2(TDUMapEntry p, TDUMapEntry e) を実装したクラス TDUMap3 を作りなさい。 なお、この実装する put2(TDUMapeEntry p, TDUMapEntry e) の仕様は次の通りです。

  1. p の指している getKey の値と e の指している getKey の値が等価なら、 p の Value を e の getValue の値に更新して、もともとあった値を返す。
  2. p の指している getKey の値より e の指している getKey の値が 小さい なら、 p.left に関して処理を行う。
    1. p.left が null なら p.left に e をつないで null を返す。
    2. さもなければ put2(p.left,e) の値を返す
  3. 大きいときは p.right に対して同様の処理を行う

kadai.AbstractTDUMap3


package kadai;
import kaitou.TDUMap2;
public abstract class AbstractTDUMap3 extends TDUMap2 {
	protected AbstractTDUMap3(){
		super();
	}
	@Override
	public Integer put(String s, Integer i){
		final TDUMapEntry1 e = new TDUMapEntry1(s,i);
		if(root==null){
			root=e;
			return null;
		}
		return put2(root,e);
	}
	protected abstract Integer put2(TDUMapEntry1 p, TDUMapEntry1 e);
}

作成したプログラムが正常に動作するかどうか、TDUMap3Testを使用して確かめなさい。 なお、TDUMap3Test において TDUMap3 の初期状態、 put("jkl",12) の呼び出し、 put("def",456) の呼び出し、 put("pqr",678) の呼び出し、 put("mno",567) の呼び出しに関して、TDUMap3 の内 部の木の構造を示し、 put2 がどのように動作するかを木の構造を用いて説明 しなさい。

課題2-5

Generics を使用し、任意の型 K, V を登録できる TDUMap<K extends Comparable<? super K>,V> を作ることを考える。 これを実現するため、Generics に対応した kadai.TDUMapEntry<K,V> を次のように定義する。


package kadai;
import java.util.AbstractMap;
public class TDUMapEntry<K,V> extends AbstractMap.SimpleEntry<K,V>
{
	private static final long serialVersionUID = 1L;
	public TDUMapEntry(K s ,V i){
		super(s,i);
		left=null;
		right=null;
	}
	public TDUMapEntry<K,V> left;
	public TDUMapEntry<K,V> right;
}

これを用いて、TDUMap を作成しなさい。 なお、作成すべきメソッド、フィールドなどは概ね次のようになるはずです。


package kaitou;
import java.util.AbstractMap;
import java.util.Map;
import java.util.Set;
import kadai.TDUMapEntry;
import kadai.TDUSet;
public class TDUMap<K extends Comparable<? super K>, V> extends AbstractMap<K, V> {
	private TDUMapEntry<K,V> root;
	public TDUMap(){...}
	public TDUMap(TDUMapEntry<K,V> root){...}
	@Override
	public int size(){...}
	private int size2(TDUMapEntry<K,V> p) {...}
	private Entry<K, V>[] array;
	private int index;
	@SuppressWarnings("unchecked")
	@Override
	public Set<Entry<K, V>> entrySet(){...}
	private void traverse(TDUMapEntry<K,V> p) {...}
	@Override
	public V put(K s, V i){...}
	private V put2(TDUMapEntry<K,V> p, TDUMapEntry<K,V> e) {...}
}

これが正常に動作することを TDUMapTestによりテスト結果を 報告しなさい。

課題2-6

下記のプログラム test.TDUMapDemo がどのようなプログラムか説明しなさい。 そして、HashMap, TreeMap, TDUMap についてそれぞれ 5 回測定し、結果を比較しなさい。 また、どうしてそのような結果になったかを考察しなさい。

test/TDUMapDemo.java


package test;
import java.util.Map;
import java.util.HashMap;
import java.util.TreeMap;
import kaitou.TDUMap;
public class TDUMapDemo {
	final private static int n = 10000;
	final private static int wordLength = 5;
	public static void main(String[] args) {
		@SuppressWarnings("unchecked")
		Map<String,Double>[] maps = (Map<String, Double>[])(new Map[]{
				new HashMap<String,Double>(),
				new TreeMap<String,Double>(),
				new TDUMap<String,Double>()
		});
		int k = (int)(Math.random() * maps.length);
		String[] testWords = generateStrings(n);
		double[] testDoubles = generateDouble(n);
		StopWatch sw = new StopWatch();
		test(maps[k],testWords,testDoubles);
		System.out.println(maps[k].getClass().getName()+":"+sw);
	}
	private static void test(Map<String, Double> m, String[] testWords,
			double[] testDoubles) {
		for(int i=0; i<testWords.length; i++){
			m.put(testWords[i], testDoubles[i]);
			m.entrySet();
		}
	}
	private static double[] generateDouble(int n2) {
		double[] result = new double[n2];
		for(int i=0 ; i<n2; i++){
			result[i]=Math.random();
		}
		return result;
	}
	private static String[] generateStrings(int n2) {
		String[] result = new String[n2];
		for(int i=0; i<n2; i++){
			result[i]=generateString(wordLength);
		}
		return result;
	}
	final private static String alphabets = "abcdefghijklmnopqrstuvwxyz";
	private static String generateString(int i) {
		StringBuilder result = new StringBuilder();
		for(int j=0; j<i; j++){
			result.append(alphabets.charAt((int)(Math.random()*alphabets.length())));
		}
		return result.toString();
	}
}

test.StopWatch.java


package test;
import java.util.Date;
public class StopWatch {
	private Date now ;
	public StopWatch() {
		now=new Date() ;
	}
	@Override
	public String toString(){
		Date next=new Date();
		double time=(double)(next.getTime()-now.getTime())/1000.0 ;
		now=next;
		return String.valueOf(time);
	}
}

プログラム

上記のプログラムをまとめたものを ダウンロード できます。

課題2のレポート作成上の注意

プログラムの動作の説明において、特定のデータ構造を例示し、図示して説明 すること。 但し、図とプログラムに矛盾がある場合、不合格になります。

今回の合否の分水嶺は、課題 2-2, 2-3, 2-4 の再帰のプログラムの説明にお ける終了条件の説明がプログラムと一致しているか否かという点であろうと考 えています。 ご注意下さい。

なお、再帰が遅いという指摘がありますが、極端に遅いわけではありません。 次のプログラムを試すと、どの程度の遅さか分かると思います。

test/RecursiveTest.java


package test;
public class RecursiveTest {
	public static final int N = 1000;
	private static Job job;
	interface Job {
		void perform();
	}
	private static class Pi implements Job{		
		@Override
		public void perform() {
			double x = Math.PI*2.0;
		}
	}
	private static class Sqrt implements Job{		
		@Override
		public void perform() {
			double x = Math.sqrt(2.0);
		}
	}
	private static class Sin implements Job{		
		@Override
		public void perform() {
			double x = Math.sin(2.0);
		}
	}
	private static class Log implements Job{		
		@Override
		public void perform() {
			double x = Math.log(2.0);
		}
	}
	private static class Rand implements Job {
		@Override
		public void perform() {
			double x = Math.random();
		}
	}
	public static void main(String[] args) throws InterruptedException {
		StopWatch sw = new StopWatch();
		Job[] jobs = {new Pi(), new Rand(), new Sqrt(), new Sin(), new Log()};
		int r = (int)(Math.random()*2);
		job = jobs[(int)(Math.random()*jobs.length)];
		switch(r){
		case 0: 
			loop1(0);
			break;
		case 1:
			rec1(0);
			break;
		}
		System.out.println(r+","+job.getClass().getSimpleName()+":"+sw);
	}
	private static void loop1(int n) {
		for(int i=n; i<N; i++)
			loop2(0);
	}
	private static void loop2(int i) {
		for(int j=i; j<N; j++)
			loop3(0);
	}
	private static void loop3(int i) {
		for(int k=i; k<N; k++){
			job.perform();
		}
	}
	private static void rec1(int n) throws InterruptedException{
		if(n<N){
			rec2(0);
			rec1(n+1);
		}
	}
	private static void rec2(int n) {
		if(n<N){
			rec3(0);
			rec2(n+1);
		}
	}
	private static void rec3(int n) {
		if(n<N){
			job.perform();
			rec3(n+1);
		}
	}
}

課題1(新)

古い問題は別ページへ

4年生
2014年5月21日17:00(この問題でも 2014年度の評価対象として受けとります。但し、4月に出る新しい問題を解答することを推奨します。)
提出先:
2号館レポートボックス
注意
2,3年生は12月4日以降の遅れレポートは一切受けとりません。

ランダムにカードを引いて集めることを考える。 そのために、部分的に開発したソフトウェア gacha の仕様の一部 の説明を別に示した。 さて、以下の設問において kotae パッケージを作り、 その中に指定されたクラスを作成せよ。

なお、テストクラスを用意したので、各設問 において、指示のあるテストクラスを用いてテストを行い、正常であった旨を 報告せよ。

課題1-1

player/Statistics1 を10回実行して、3種類のカードが揃うまでの回数を計測 し、平均値を求めなさい。

課題1-2

Deck1 のカードに加え、Rare カードとして (id=10, name="RareAka"), (id=11, name="RareAo"), (id=12, name="RareKuro"), となる 3 つの合計 6 種類のカードを持つ Deck2 クラス kotae パッケージに作成しなさい。 但し、これらのカード種自体は Deck2 の static メソッド getList により List<Card> 型のインスタンスが得られるようにすること。

なお、テスト用にDeck2Testプログラムを 用意したので、活用すること。

課題1-3

Deck2 を使う Main2, Statistics2 を示す。

player/Main2.java


package player;
import kotae.Deck2;
import java.io.IOException;
public class Main2 {
	public static void main(String[] args) throws IOException {
		new Player().play(new Deck2());
	}
}

player/Statistics2.java


package player;
import kotae.Deck2;
public class Statistics2 {
	public static void main(String[] arg){
		int[] watchlist = {0,1,2,10,11,12};
		Statistics s = new Statistics(watchlist, new Player(), new Deck2());
		s.calc();
	}	
}

Statistics2 を10回実行して、6種類のカードが揃うまでの回数を計測 し、平均値を求めなさい。

課題1-4

次に、プレイヤーの手の揃い具合により、確率が変動するようなカード種 SuperRare を考える。 これは、カード種に対してプレイヤーの所持カードを見せることで、レア度を 変えるようにする。 つまり、まず、以下のようなメソッドを作成する。

  1. CardCollection クラスのインスタンスをコンストラクタに与える。
  2. そして、SuperRare クラスではこの CardCollection を使い、alreadyOwned メソッドにより、特定のカード種を持っているかどうかを調べられるようにす る。
  3. 揃えるべきカードが残り何枚かを数えるために、全カードの見本リストを 与える setMokuhyou メソッドを作る

ここまでを作成したクラスをAbstractSuperRareとして以下に示す。

card/AbstractSuperRare.java


package card;
import java.util.List;
import kotae.SuperRare;
import player.CardCollection;
public abstract class AbstractSuperRare extends AbstractCard {
	private CardCollection cardcollection;
	protected int zenmaisuu;
	protected List<SuperRare> mokuhyou;
	protected AbstractSuperRare(){
		super();
	}
	protected final boolean alreadyOwned() {
		return cardcollection.contains(this);
	}
	protected final void setMokuhyou(List<SuperRare> list) {
		this.mokuhyou = list;
		this.zenmaisuu = list.size();
	}
	public final void setCardCollection(CardCollection cc) {
		this.cardcollection=cc;
	}
}

このクラスを継承し、次の仕様を持つ rate メソッドを実装する SuperRare クラスを kotae パッケージに作りなさい。

  1. rate は次の値を返す
    1. 基本的には 100 を返す
    2. 揃う残り2種類の時は、持っていないカードのレア度は 10倍
    3. 揃う残り1種類の時は、持っていないカードのレア度は 100倍

なお、テスト用 にSuperRareTestプログラム を用意したので、活用すること。

また、 SuperRareFactory クラスを示す。

card/SuperRareFactory.java


package card;
import java.util.List;
import player.CardCollection;
import kotae.SuperRare;
public class SuperRareFactory extends AbstractCardFactory<SuperRare> {
	public SuperRareFactory(int num, String[] names) {
		super(num, names, new SuperRare());
	}
	public List<SuperRare> getList(CardCollection cc){
		List<SuperRare> list = super.getList();
		for(SuperRare card : list){
			card.setCardCollection(cc);
			card.setMokuhyou(list);
		}
		return list;
	}
}

課題1-5

SuperRareAka, SuperRareAo, SuperRareKuro と既存の Aka, Ao, Kuro を混ぜたDeck3 と、それを使う Main3, Statistics3 を示す。

gacha/Deck3.java


package gacha;
import java.util.List;
import player.CardCollection;
import card.Card;
import card.SuperRareFactory;
public class Deck3 extends AbstractDeck {
	public static List<Card> getList(CardCollection cardcollection){
		List<Card> list= Deck1.getList();
		String[] names = new String[]{"SuperRareAka", "SuperRareAo", "SuperRareKuro"};
		SuperRareFactory superRareFactory = new SuperRareFactory(20,names);
		list.addAll(superRareFactory.getList(cardcollection));
		return list;
	}
	public Deck3(CardCollection cardcollection){
		super(getList(cardcollection));
		bunpu = new Bunpu3(this);
	}	
}

player/Main3.java


package player;
import gacha.Deck3;
import java.io.IOException;
public class Main3 {
	public static void main(String[] args) throws IOException {
		Player player = new Player();
		player.play(new Deck3(player.collection));
	}
}

player/Statistics3.java


package player;
import gacha.Deck3;
public class Statistics3 {
	public static void main(String[] arg){
		int[] watchlist = {0,1,2,20,21,22};
		Player player = new Player();
		Statistics s = new Statistics(watchlist, player, new Deck3(player.collection));
		s.calc();
	}	
}

Statistics3 を10回実行して、6種類のカードが揃うまでの回数を計測 し、平均値を求めなさい。

課題1-6

「不当景品類及び不当表示防止法」4条の2や、告示された 「懸賞による景品類の提供に関する事項の制限」の第5項などを参照し、 本課題における実験結果と比較して、なぜこのような法律があるのか考察しな さい。

発展課題1-7

3種類のカードがそれぞれ確率1/3で出るとき、繰り返し引いて全種類揃うまで の平均試行回数を求めなさい。

なお、以上の提供したファイルをすべてまとめた 課題ファイル集 を用意した。

おまけ

Eclipse のセッティングの方法

  1. Java のプロジェクトを作成する
  2. 右クリックで properties を選択し、Text file encoding を UTF-8 にする。
  3. 課題ファイル集(9月3日版) をダウンロードする。
  4. プロジェクトを右クリックし、import を選ぶ
  5. General の中の Archive file を選ぶ
  6. ダウンロードしたファイルを選択すると、 src の中にファイルが取り込 まれる
  7. test パッケージ中のエラーが出ているファイルを開き、ソースコードの上部の org.junit の波線付近にカーソルを当てると、いくつか改善のための選択肢が出る。そのうち fix Project setup を選ぶと、Add JUnit4 Library ... の表示が出るので、 Ok を押す

なお、問題訂正などでプログラムが変更になった場合、上記の最新のファイル 集をダウンロードした後で、作業中のプロジェクトでもう一度importして下さ い。 上書きするファイルが検出されるとダイアログが表示されますが、 Yes ALL で問題だけ最新の状態になるはずです。

採点基準

  1. 問題をちゃんと理解すること。 特に解答が楽になるようにとか、「わかりやすく」とか「しっかり」など、非 科学的な理由で勝手に問題を作り替えてはいけません。
  2. プログラムが正常に動作すること。 指定した出力を正確に出すこと。 また、指定していない表示を行わないこと。 さらに、多少の動作条件の変化に対して、正常に対応できること。 特に、テストに対しては正常に動作しても、考えうる他の正常な入力に対して暴走するようなプログラムは不可です。
  3. 実行例を付けること。 実行可能なプログラムに関して、正しく実行された実行例を必ずつけること。 なお、問題の趣旨を理解しており、膨大な出力のうち、全ての出力が必ずしも 必要ないと判断される場合は、出力の一部を省略しても良い。
  4. 説明が適切であること。 プログラムの内容を正しく説明していなければなりません。 また、テストの内容を理解し、テスト結果からプログラムが正常であることを 理由を付けて判定すること。

レポート作成上の注意点

  1. 表紙をつけてください。 また、再提出時は前回の表紙をつけてください。
  2. プログラミングのレポートでは必ずプログラムの説明をすること。 その時に、一行一行を日本語に直訳するのではなく、データの読み込みとか、 出力とかの部分に分割し、機能毎に使用した手法を説明すること。 プログラム中にコメントを入れてもプログラムの説明とはみなさないので注意 する事。 プログラムの説明はつぎのように説明をしてください。
    1. プログラム全体の構成(どんなフィールドやメソッドを作成したか)
    2. 各部分の機能(メソッド毎に説明すること)
    3. それぞれの機能を実現するために行ったプログラミング上の工夫(特に複雑なアルゴリズムは図示すること)
  3. 「問題を解きなさい」という問に対して「解きました。合ってました」で は正解ではないことはわかるはず。 「テストしなさい」という問に対しては、テストの方法の説明、実際のテスト の実施方法、テスト結果、検証などを説明して下さい。
  4. レポートは手書きでもワープロでも構いません。但し、実行結果はコン ピュータの出力を添付すること。 また、なるべく白黒で作成すること。実行結果などでどうしても色が付いてしまうような場合はそのままで構いません。 実行結果が無いレポートは不合格です。
  5. 考察は必ず書いて下さい。
  6. 不必要なことはなるべく書かない事。 長過ぎるレポートは減点します。またなるべく両面印刷にしてください。 但し、文字は必要以上に小さくしない事。レポート本文の文字は 10 ポイント 以上のものを使う事。

なお、写したと思われるほど酷似したレポートが複数提出された場合、原著が どれかの調査を行わず、抽選で一通のレポートのみを評価 の対象とし、他は提出済みの不合格レポートとして再提出は課しません。 自分で意図せずに他人にコピーされてしまった場合も同様ですので、レポート の取り扱いについては十分に注意して下さい。


坂本直志 <[email protected]>
東京電機大学工学部情報通信工学科