ホーム » スタッフ (ページ 126)

スタッフ」カテゴリーアーカイブ

2025年6月
1234567
891011121314
15161718192021
22232425262728
2930  

検索・リンク

2015年4月5日(第417回)

入学式のため、収録でお送りしました。

  • まるよし Train Pops ~ 国語と遊ぼう! 第97便 「送り仮名」
  • 放送・メディア研究会の部活紹介動画
  • 新入生に向けてのアドバイス
  • 桜の話

担当:松島(4C・MC)、田嶋(3C)、川﨑(2EI・MIX)、植村(2E)、中村(教員)、西(教員)

創造工学演習・プログラム予備実験(1)

プログラミングコンテストの競技部門では、パズルのような組み合わせ問題が 出題されることが多い。そこで、この予備実験では、きわめて単純なパズル問題(組み合わせ問題) のプログラムについて扱う。

組み合わせ問題の基礎

簡単な問題として、「100未満の整数の値を3つ選び、その値を辺の長さとした場合、 直角三角形となるものをすべて表示する。」について考える。

一番簡単な方法は、以下となるであろう。

#include <stdio.h>
#include <math.h>
#include <time.h>
// 整数比の直角三角形の一覧を求める。
void integer_triangle( int n ) {
for( int a = 1 ; a < n ; a++ ) {
for( int b = 1 ; b < n ; b++ ) {
// 一番ダサい方法
for( int c = 1 ; c < n ; c++ ) {
if ( a*a + b*b == c*c ) {
printf( "%d %d %d\n" , a , b , c ) ;
}
}
}
}
}
int main() {
integer_triangle( 100 ) ;
return 0 ;
}

しかしこのプログラムの欠点としては、100×100×100回のループで無駄な処理が多い。

ループ回数を減らすだけなら、最も内側の処理を、計算で整数値か確認すればいい。

void integer_triangle( int n ) {
for( int a = 1 ; a < n ; a++ ) {
for( int b = 1 ; b < n ; b++ ) { // ココも改良できるよね?
int d = a*a + b*b ;
int c = (int)sqrt( d ) ; // 斜辺Cの整数値を求め、改めて確認する。
if ( c*c == d ) {
printf( "%d %d %d\n" , a , b , c ) ;
}
}
}
}

(1) 計算誤差の問題を考えてみよう。(問題点を十分に考えたらここをクリック)

たとえば、3:4:5の直角三角形で、3*3+4*4 = 25 だが、sqrt(25)は実数で計算するから、 計算誤差で4.99999で求まったらどうなるだろうか?

1~100までの数値で、"int a = sqrt( (double)(i*i) ) ;" を計算してみて、 異なる値が求まることはあるか? 多少の計算誤差があっても正しく処理が行われるにはどうすればいいか、考えてみよう。

(2) 無駄な答えについて考えてみよう。(問題点を十分に考えたらここをクリック)

このプログラムの答えでは、簡単な整数比の答えの「整数倍の答え」も表示されてしまう。 たとえば、(3:4:5)の答えのほかに、(6:8:10)も表示される。 こういった答えを表示しないようにするにはどうすればよいか?

また、この2つのプログラムの処理時間を実際に比べてみる。

int main() {
time_t start , end ;
// time() 関数は、秒数しか求まらないので、
// あえて処理を1000回繰り返し、数秒かかる処理にする。
start = time( NULL ) ;
for( int i = 0 ; i < 1000 ; i++ ) {
// ただし、関数内のprintfをコメントアウトしておくこと
integer_triangle( 100 ) ;
}
end = time( NULL ) ;
printf( "%lf\n" , difftime( end , start ) ) ;
return 0 ;
}

再帰プログラミング

組み合わせ問題では、forループの多重の入れ子で問題を解けない場合が多い。 (書けないことはないけど無駄なループで処理が遅くなるか、入れ子段数が可変にできない。)

こういった場合には、再帰プログラミングがよく利用される。 もっとも簡単な再帰の例として、階乗のプログラムを考える。 通常であれば、以下のような for ループで記述することになるだろう。

// 階乗の計算
int fact( int x )
{ // ループ
int f = 1 ;
for( int i = 2 ; i <= x ; i++ )
f = f * i ;
return f ;
}

再帰呼び出しでは、関数の処理の中に、自分自身の関数呼び出しが含まれる。 また、無限に自分自身を呼び出したら処理が止まらないので、 問題を一つ小さくして、これ以上小さくできないときは処理を止めるように記述する。

int fact( int x )
{ // 再帰呼び出し
if ( x <= 1 )
return 1 ;
else
return x * fact( x - 1 ) ;
}

指定長を指定辺の組み合わせで作る

再帰を使った簡単なパズル問題として、以下のプログラムを作成したい。

配列の中に、複数の辺の長さが入っている。これを組み合わせて指定した長さを作れ。 使用する辺はできるだけ少ない方がよい。
int a[] = { 4 , 5 , 2 , 1 , 3 , 7 } ;
(例) 辺の長さ10を作るには、(5,4,1)とか(7,3)などが考えられる。
これは、ナップサック問題の基本問題で、容量の決まったナップサックに最大量入れる組合せを求めるのと同じである。

このプログラムを解くには…

10 を [4,5,2,1,3,7] で作るには...
 (0) 6=10-4 を [5,2,1,3,7]で作る。
 (1) 5=10-5 を [4,2,1,3,7]で作る。
 (2) 8=10-2 を [5,4,1,3,7]で作る。
 (3) 9=10-1 を [5,2,4,3,7]で作る。
 (4) 7=10-3 を [5,2,1,4,7]で作る。
 (5) 3=10-7 を [5,2,1,3,4]で作る。

そこで、ここまでの考えを、以下のようなプログラムで記述してみる。

// 指定されたデータを入れ替える。
void swap( int*a , int*b )
{ int x = *a ;
*a = *b ;
*b = x ;
}
void check( int array[] , int size , int len , int n )
{
// array[] 配列
// size    配列サイズ
// len     作りたい長さ
// n       使った個数
for( int i = n ; i < size ; i++ ) {
// i番目を先頭に...
swap( &array[ n ] , &array[ i ] ) ;
printf( "check( array , %d , %d , %d )\n" ,
size , len - array[ n ] , n+1 ) ;
// 最初のswapでの変更を元に戻す。
swap( &array[ i ] , &array[ n ] ) ;
}
}
int main() [
int a[] = { 4 , 5 , 2 , 1 , 3 , 7 } ;
check( a , 6 , 10 , 0 ) ;
}

(1) これを再帰呼び出しにしてみよう。どう書けばいい?(考えたらここをクリック)

void check( int array[] , int size , int len , int n )
{
// array[] 配列
// size    配列サイズ
// len     作りたい長さ
// n       使った個数
if ( len < 0 ) {
// 指定した丁度の長さを作れなかった。
;
} else if ( len == 0 ) {
// 指定した長さを作れたので答えを表示。
for( int i = 0 ; i < n ; i++ ) {
printf( "%d " , array[ i ] ) ;
}
printf( "\n" ) ;
} else {
// 問題を一つ小さくして再帰。
for( int i = n ; i < size ; i++ ) {
swap( &array[ n ] , &array[ i ] ) ;
printf( "check( array , %d , %d , %d )\n" ,
size , len - array[ n ] , n+1 ) ;
check( array , size , len - array[ n ] , n + 1 ) ;
swap( &array[ i ] , &array[ n ] ) ;
}
}
}

(2) 少ない組み合わせの方がポイントが高い場合には、プログラムをどう変更する?
(3) 答えが1つだけで良い場合は、プログラムをどう変更する?
(4) このプログラムでは、冗長な答えがあるか?ないか?検討せよ。
(5) 前設問の整数比直角三角形のプログラムで、冗長な答えを削除するプログラムを作成せよ。
# ただし、(2)〜(5)は、演習の実験の時間内でできる範囲とする。

バドミントン部、武生高校練習試合

今日は午後から、武生高校バド部との練習試合でした。

1503301340_320x320.jpg

2015年3月29日(第416回)

  • まるよし Train Pops ~ 国語と遊ぼう! 第96便 「話し方研究会」

山野さんが高専学生として最後の出演でした

  • 思い出に残ったこと

情報公開制度と個人情報保護の講習会

情報公開制度

法人に、個人や法人が(理由を問わず)情報公開を求めることができる制度。 請求書は、300円の手数料。不開示情報でなければ、ありのまま原則公開。

不開示情報とは、個人情報・個人他機関の利益を害する恐れがあるものなど。(情報公開法第5条)

存否応答拒否(法8条): 個人情報が含まれる場合や、特定の法人名を指定した請求では、「文書の有無をお答えできません。」

不開示理由の提示では、どの情報が不開示情報に該当するのか、開示するとどういった支障があるのか、法5条何号に該当するのか….を最低でも示す必要がある。

個人情報の保護について

個人情報とは、特定の個人を識別できるもの。保有個人情報は、法人職員が業務上作成取得したもの。 非個人情報になるものとして、法人などの団体そのものに関する情報。 記号や数字の文字列だけから個人を特定できないもの。(学籍番号などは、他の情報とヒモ付すれば個人特定ができるので個人情報) 特定の個人を識別できない統計情報。

利用目的以外のために、保有個人情報を利用したり提供はダメ。

保有個人情報の開示請求

2015年3月22日(第415回)

  • まるよし Train Pops ~ 国語と遊ぼう! 第95便 「比喩」
  • 卒業式のエピソード
  • 来年度の抱負
  • 入学式の話題
  • 花粉症の話

担当:山野(3C・MIX)、川﨑(1EI・MC)、小藤(1B)、田中(1B)、西(教員)

磁気テープもらいました。

退官される先生から、磁気テープもらいました。(^_^)
容量わかると良いんだけど、不明っす。
授業の雑談のネタに使わせてもらいます。

1503191838_640x480.JPG

2015年3月15日(第414回)

  • まるよし Train Pops ~ 国語と遊ぼう! 第94便「言い間違い」 
  • 卒業研究の話
  • テスト勉強の話
  • 仮進級の話
  • メールテーマについての話

ゲスト:井上さん(5EI)、今田さん(5EI)、中村さん(5EI)

担当:前田勝(5EI・MIX)、中村(教員・MC)

2015年3月8日(第413回)

  • まるよし Train Pops ~ 国語と遊ぼう! 第93便「アクセント」 後編
  • マグネットコンテスト表彰式の様子
  • 入試について
  • 春休みについて

担当:田嶋(2C)、森山(1M・MC)、山田(1B)、植村(1E)、西(教員)

2015年3月1日(第412回)

  • まるよし Train Pops ~ 国語と遊ぼう! 第92便「アクセント」 前編
  • 左義長まつりでの活動について
  • 明石高専での発表会について
  • 五味が答える!

ゲスト:富山高専 五味先生

担当:山野(3C・MIX)、島脇(1B・MC)、川﨑(1EI)、小藤(1B)、西(教員)

システム

最新の投稿(電子情報)

アーカイブ

カテゴリー