創造工学演習発表会
創造工学演習
- 07/30 (不明飛行物捕手) UFOキャッチャーのシミュレータをUnityで作成。UFOキャッチャーの有名な技をいくつか実践できることを目指した。(UFOキャッチャーに3000円ツッコム想定でレベル変化。俺は500円以上ツッコンだことない) #創造工学演習
- 07/30 (不明飛行物捕手) UFOキャッチャーのシミュレータ #創造工学演習 https://twitter.com/TohruSaitoh/status/1…
- 07/30 (Typing. edu) タイピング練習とプログラミングのためのタイピング? もう少しプログラミングの言語をイメージした練習ワードをでるようにして欲しかったり。でもこれは情報系ジジイ教員の感想ね。 #創造工学演習
- 07/30 (sin Go!!) 信号はsignalとかsignだしsign(しん)go(ごー)じゃね? #創造工学演習
- 07/30 (sin Go!!) 運転支援で信号の変化を予測できないか…。信号情報はVICSから取得したいが、そのハードは開発困難で想定データを受信できたとしてシステム構築。データが公開されている地域も限定的なのでデータフォーマットなども想定で作らざるおえなかったみたい。 #創造工学演習
- 07/30 (sin Go!!) #創造工学演習 https://twitter.com/TohruSaitoh/status/1…
- 07/30 (ideal idea) アイデア発想の支援するために、曼荼羅法などの機能を実装。関連ワードの検索で支援。検索結果の内容を評価ができれば高評価だけど…。関連ワード検索などは動くけど複数人の利用を想定したセッション管理は未実装かな。 #創造工学演習
- 07/30 (ideal idea) #創造工学演習 https://twitter.com/TohruSaitoh/status/1…
- 07/30 (UnEI-C) 学祭の運営の支援システム構築。発表がソフトコンペのような丁寧なアイデア提案型で始まったけど、全般にわたるいい説明ですな。1人説明だけどな。支援のためのページを簡単生成できるような自動化について議論が欲しかった。 #創造工学演習
- 07/30 (UnEI-C) #創造工学演習 https://twitter.com/TohruSaitoh/status/1…
- 07/30 質問者から「実際にお客さんにサービス提供したとして幾ら?」との質問。シビアな質問だけど、先日訪問した情報・経営システム工学課程なら、定番の質問だろうな。ま、本科4年では意識を持てるだけで充分。 #創造工学演習
- 07/30 →ALL 自分たちで作ったもの写メってTweetしたかぁ?? #創造工学演習
- 07/30 (忘れ物防止) RFIDで忘れ物防止システムの構築。発表は実装重視型かな。個人的には好きだけどね。グループで作るネタをうまく配分してたかな。 #創造工学演習
- 07/30 (忘れ物防止) #創造工学演習 https://twitter.com/TohruSaitoh/status/1…
- 07/30 (ceries) 複数の希望に応じた候補のランキングなどのアルゴリズムの説明が欲しい。Instagram連携にチャレンジしているのは女の子らしくってGoodだけど、そこは未完か…残念。 #創造工学演習
- 07/30 (ceries) 週末デートをどうするか支援するアプリだとぉ〜。非リア充は土日は引きこもりなんだよ。 #創造工学演習
- 07/30 (TCMS) 注文までのインタフェースは基本が完成していた。作るメニューの画面を写真とテキストを与えたら自動生成するなどの対応を期待。発注の流れをメールに割り切ったのは基本機能を完成させる点でアリかな。 #創造工学演習
- 07/30 (競技部門) 敵の行動予測をしたい,先の手をもっと読ませたいとの目標だけど、同じじゃ無いか? 領域ポイントの戦略がこのゲームの面白さなので、フィールドスカスカのターン数のはず。スカスカな状態で終わるターン数でもっと戦略を試してほしい。 #創造工学演習
高専プロコン連携シンポジウム2019
〜セキュリティの観点からプロコンに期待すること〜
高専プロコンの応募に合わせ、以下のような講演会が開催されます。
今年度は、課題部門で「ICT を活用した地域活性化」,自由部門で「クラウドコンピューティング」「オープンデータ」「サイバーセキュリティ」「人工知能」がキーワードに挙げられており、高専生に現場のニーズや動向を学習する機会として、開催されます。
日 時: | 5月20日(月) 16:20〜16:50 Skype for businessを用いた動画配信 |
学内場所: | 電子情報工学科3F 情報処理演習室 |
講 師: | 株式会社日立製作所 セキュリティ事業統括本部サイバーセキュリティ技術本部 セキュリティ人材統括センタセンタ長千葉寛之様 |
講演テーマ: | セキュリティの観点からプロコンに期待すること |
補 足: | 発言・質問は、Twitter(ハッシュタグ #procon30 にて)受付 |
予備実験2 パズル問題
プログラミングコンテストの競技部門では、パズルのような組み合わせ問題が 出題されることが多い。そこで、この予備実験では、きわめて単純なパズル問題(組み合わせ問題) のプログラムについて扱う。
組み合わせ問題の基礎
簡単な問題として、「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 ) ; }
ここ以降は、指定長さを指定辺の組み合わせで作ると、Flood-fill の選択とする。
指定長を指定辺の組み合わせで作る
再帰を使った簡単なパズル問題として、以下のプログラムを作成したい。
配列の中に、複数の辺の長さが入っている。これを組み合わせて指定した長さを作れ。 使用する辺はできるだけ少ない方がよい。
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)は、演習の実験の時間内でできる範囲とする。
Flood fill アルゴリズム
前の問題は、今年度のプログラミングコンテストの課題のパズルとは、方向性が違うので、今年度のプロコンの競技部門に近いパズルネタで演習。(Wikipedia Flood-fill参照)
以下の image のような2次元配列が与えられたら、指定座標(x,y)を中心に周囲を塗りつぶす処理を作成せよ。
include <stdio.h> // *は壁 SPCは白 この領域の指定位置を#で塗りつぶす。 char image1[10][10] = { // (4,4)始点で塗りつぶし後 "*********" , // ********* "* * *" , // * *###* "* * *" , // * *###* "* * *" , // * *####* "*** ***" , // ***###*** "* * *" , // *####* * "* * *" , // *###* * "* * *" , // *###* * "*********" , // ********* } ; char image2[10][10] = { // 応用問題用の画像例 "*********" , // * のような隙間は通り抜けられる "* * *" , // * ようにするにはどうすればいい? "* ** *" , // ** "* ** *" , // ** これは通り抜けられない "*** ***" , // ** "* * *" , "* * *" , "* * *" , "*********" , } ; // 盤面を表示 void print_image( char image[10][10] ) { for( int y = 0 ; y < 9 ; y++ ) { for( int x = 0 ; x < 9 ; x++ ) { printf( "%c" , image[y][x] ) ; } printf( "\n" ) ; } } // 再帰呼び出しを使った flud_fill アルゴリズム void flood_fill( char image[10][10] , int x , int y , char fill ) { // 指定座標が空白なら if ( image[y][x] == ' ' ) { // その座標を埋める image[y][x] = fill ; ////////////////////////////////////// // ここに周囲をflud_fillする処理を書く // ////////////////////////////////////// } } int main() { print_image( image1 ) ; flood_fill( image1 , 4 , 4 , '#' ) ; print_image( image1 ) ; return 0 ; }
応用問題
Wikipediaのflood-fill のプログラムの説明のアルゴリズムでは、左図黒のような斜めに並んだブロックは、境界として通り抜けられないようにつくられている。
そこで、斜めに並んだブロックは通り抜けられるルールとした場合のプログラムを記述せよ。
予備実験1 データベースの操作
データベースの基本操作
- SQL演習環境(学内からのみアクセス可能)
- SQLの基本(DB授業資料) — (create table,insert,select まで)
- SQLと結合(DB授業資料) — (where節から串刺し検索まで)
データベースをWebから操作
練習問題
- 上記の db_query.php を改良して、ユーザ名を入力してもらい、その名前のデータを表示するプログラムに改造する。
- おなじく、年齢を入力したら、指定した年齢以上の人のデータを表示するプログラムに改良する。
創造工学演習・予備実験(SQLとPHP)
先週のPHPの予備実験に引き続き、データベースの説明とそのプログラムで演習を行う。
<?php // データの保存先 $dbfile = "/home/guests/guest0/public_data/tsaitoh.db" ; if ( !file_exists( $dbfile ) ) { // データベースの宣言と初期化 $db = new SQLite3( $dbfile ) ; $cmd = "create table nametel ( name char( 20 ) , phone char( 20 ) ) ;" ."insert into nametel ( name , phone ) values ( 't-saitoh' , '090-1111-1111' ) ;" ."insert into nametel ( name , phone ) values ( 'tomoko' , '090-2222-2222' ) ;" ."insert into nametel ( name , phone ) values ( 'mitsuki' , '090-3333-3333' ) ;" ."insert into nametel ( name , phone ) values ( 'ayuka' , '090-4444-4444' ) ;" ; if ( $db->exec( $cmd ) ) { print "Success.\n" ; } else { print "Fail\n" ; } $db = null ; } ?> <html> <head> <title></title> </head> <body> <?php // 警告表示の抑止 ini_set( 'error_reporting' , E_WARNING ) ; // データベース処理(検索処理) $db = new SQLite3( $dbfile ) ; $id = $_REQUEST[ "name" ] ; if ( $db !== FALSE && $id != "" ) { // SQL命令の生成(インジェクションの危険性指摘は別述) $cmd = "select * from nametel where name='$id' ;" ; print $cmd ; // 問い合わせの実行 $result = $db->query( $cmd ) ; print "<table border='1'>\n" ; print "<tr><td>name</td><td>phone</td></tr>" ; while( ($row = $result->fetchArray( SQLITE3_BOTH )) !== FALSE ) { print "<tr>" ."<td>".$row[0]."</td>" ."<td>".$row[1]."</td>" ."</tr>\n" ; } print "</table>\n" ; } ?> <form method="post" action="sql.php"> <input type="text" name="name" /> <input type="submit" value="exec" /> </form> <?php // データベース登録処理 $newname = $_REQUEST[ "newname" ] ; $newphone = $_REQUEST[ "newphone" ] ; if ( $newname != "" && $newphone != "" ) { // データ登録用SQL $cmd = "insert into nametel ( name , phone ) values ( '$newname' , '$newphone' ) ;" ; // データ登録 $db->exec( $cmd ) ; print "$newname さんの電話番号 $newphone を登録しました" ; } ?> <form method="post" action="sql.php"> <input type="text" name="newname" /> <input type="text" name="newphone" /> <input type="submit" value="exec" /> </form> </body> </html>
SQLとPHP
SQLとPHPのプログラムの練習。
SQLの基礎
簡単にSQLの文法を勉強したあと、自分で簡単なデータベースを作り検索してみる。 Windowsのエディタで、SQLの命令を入力し、 ブラウザの実験環境のSQLの入力フォームの所にコピー&ペーストで実験する。
PHPでデータベースを読みだす
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" id="sixapart-standard"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <h1>SQLの実験</h1> <form method="GET" action="sample.php"> <input type="text" name="A" /> <input type="submit" value="QUERY" /> </form> <?php // SQLのデータベースファイル $DBFILE = "説明で聞いたファイルの場所を記載/名前.db" ; // フォームの値をもらう $a = $_REQUEST[ "A" ] ; // データベースを開く $db = new SQLite3( "$DBFILE" ) ; // 実行したいSQL $sql = "select * from S where 業者番号='$a' ;" ; // SQL実行 if ( ($query = $db->query( $sql )) !== FALSE ) { // SQL実行に成功 print "<pre>" ; print '$a'." = $a\n" ; // 1件づつ全部読み込み while( ($res=$query->fetchArray(SQLITE3_ASSOC)) !== FALSE ) { // 1行分のデータの配列の全要素の繰り返し // $res[0],$res[1],... foreach( $res as $key => $value ) { print "$key=$value " ; } print "\n" ; } print "</pre>" ; } ?> </body> </html>
アイデアをまとめる方法
4EIの創造工学演習で、今日はアイデア出し。 といっても、発散しがちなアイデアを形にするのは難しい。 一般的な手法を以下にまとめる。
一般的には、アイデアを発散させ、その後一旦アイデアを評価して絞込む。 そしてそのアイデアをより良いものに変えていく。 参考 SlideShareより
KJ法
KJ法: テーマに関するアイデアをカードに書き出し、ある程度出揃ったら似たアイデアを集めてタイトルをつける。 さらに似たものを集めてタイトルをつけ、アイデアをまとめていく。
マインドマップ
マインドマップとは、 最初に掲げたテーマを中心に、発想したキーワードを周囲に書き並べる。さらに、その発想キーワードの周りにさらなる発想、問題点、利点などを キーワード的に書き並べ、ある程度発散してきたら、関連するものを結びつけていく。
マインドマップは、専用のエディタなどもあるので、そういうツールを使うのもあり。
自宅で監視カメラを動かしてみた
今度の週末は、家族旅行の予定。 だけど、子どもがその間、最近病院に連れて行った婆ちゃん猫を 心配している。
そこで、使っていなかったWebカメラで、急遽、監視カメラを動かしてみた。 奥さんからは、解像度低いじゃんとツッコミを受けるが、 もともとのWebカメラの性能だと思うし…
余りにも他愛もないコードだけど、 この手のお遊びプログラムは、 学生さんに「こんなこと簡単にできるよ」と見せることも多いので、 PHPコードに改良&コメント付けをしておく。
監視カメラを動かすまで
fswebcamが一番簡単に使えそうだったので…
(( fswebcamをインストール)) $ sudo aptitude install fswebcam
fswebcamの出力をそのまま画像形式で返すプログラム。
(( webcam.php )) <?php // 画像形式、キャッシュさせない header( "Content-Type: image/jpg" ) ; header( "Cache-Control: no-store, no-cache, must-revalidate" ); // 連続読み出し用にファイルロック $flock = fopen( "/var/www-support/.webcam.lock" , (file_exists( "/var/www-support/.webcam.lock" ) ? "rb+" : "wb+" )) ; if ( flock( $flock , LOCK_EX ) ) { system( "/usr/bin/fswebcam -q -d /dev/video1" ." -p YUYV" // 画像形式 ." -D 0" // delay ." -S 3" // skip frame ." -r 320x240" // 解像度 //." -r 640x480" ." --title \"tsaitoh.net's webcam\"" ." --jpeg 75 -" ) ; fclose( $flock ) ; } ?>
webcam.php の出力画像を、連続で読み出すように、 JavaScriptで設定を書き加える。 <meta http-equiv=”refresh” content=”5″> みたいな方法だと、reload の度に画像がちらつくので、JavaScriptで reload させることになった。
(( index.php )) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" id="sixapart-standard"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=320,height=320,initial-scale=1"/> <title>自宅監視カメラ</title> <script type="text/javascript"> <!-- var count = 0 ; function reload() { count = (count + 1) % 100 ; // 画像を更新(キャッシュ画像を使わないように番号付) var img = document.getElementById( "image" ) ; img.src = "webcam.php?"+String(count) ; img.id = "image" ; // 動きの少ない相手用に確認表示 var txt = document.getElementById( "text" ) ; txt.innerText = "自宅監視カメラ: "+String( count ) ; } // --> </script> </head> <body> <p align="center"> <img id="image" src="webcam.php" onload="reload()" /> <div id="text"></div> </p>