創造工学演習の最近のブログ記事

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法: テーマに関するアイデアをカードに書き出し、ある程度出揃ったら似たアイデアを集めてタイトルをつける。 さらに似たものを集めてタイトルをつけ、アイデアをまとめていく。

マインドマップ

マインドマップとは、 最初に掲げたテーマを中心に、発想したキーワードを周囲に書き並べる。さらに、その発想キーワードの周りにさらなる発想、問題点、利点などを キーワード的に書き並べ、ある程度発散してきたら、関連するものを結びつけていく。

マインドマップは、専用のエディタなどもあるので、そういうツールを使うのもあり。

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

組み合わせ問題の基礎

簡単な問題として、「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)は、演習の実験の時間内でできる範囲とする。

何気なく、Webを見ていたら、大人の科学で面白い商品が紹介されていた。 んで、その紹介ビデオを見ていたら、昔、NHKのものづくり系の番組で 紹介されていて、実際自分でも試したことがある手軽な織物(カード織り)が、 これまた大人の科学で紹介されている。

女の子のチームでこういう織物のシミュレータ、織物レクチャ環境つくらないかな...

今年度のプログラミングコンテストは、サイコロを使ったデータ伝送なので、 通信に関係する基礎実験を行うこととする。

通信では、データ伝送時にノイズの発生などで、相手側にデータが正しく 届くとは限らない。今回のプロコンでも、サイコロのコードに変換する作業は 人間が行うことから、違う情報となって送られる可能性が高い。

このことから、今回の実験は、与えられた1行データを 自分なりの間違いチェック情報を付けて送信し、受信時で元に戻して復号するための プログラムを作る。ただし、通常のWindowsのパソコンで実験ができるように、 実際の通信を行う訳ではなく、以下の様に仮想的に関数で変換しながら行う。

  • プログラムは与えられたファイルから1行づつデータを読む。
  • この1行データは、encode(out[],in[]) によって呼び出される。 あなたは、入力したデータが後のdecode()で戻せるように、 チェックのための情報を付加し、out[] に格納する。
  • この作られたデータは、本来なら通信路に送り出されるが、 簡単な実験なので、実験用の関数でノイズを加えられる。
    ノイズの処理では、一定の確率で文字が欠落したり重複する。 さらに、一定の確率で文字の各ビットが反転する。
  • このノイズが加えられたデータを受信したとして、 あなたは、付加されたチェック情報をみて、正しく送られたか確認しながら、 もとに戻す、decode(in[]) の処理を記載する。 ノイズが加えられ、元に戻せずもう一度データが欲しい場合は、 decode()の返り値として1を返すこと。 同じデータに対し、改めて異なるノイズが加えられたうえで、 もう一度decode()が呼び出される。

上に示した、send-recv.cxx には、必要な処理が記載されているので、 この中の encode( out[],in[] ) と、decode( in[] ) の中身を作成せよ。

レポートに記載する内容

  • send-recv.cxx の 関数 encode() , decode() のプログラムリスト
  • と、その説明(チェック方法および間違いが発生したらどうなるかの説明)。
  • その実験結果。ノイズは乱数を元にしているため、複数回実験を行い、 正しく伝送されているか検証すること。
  • 実際にサイコロで情報を伝達するとして、文字をどのようにサイコロで 表現可能か『手法の一案』を示し、さらに人間が並べる作業でミスがあったら、 どういった現象が発生する可能性があるか、発生しうる様々な状況を考察せよ。
    レポートでは、実際に簡単な英単語を変換した例と、サイコロを間違えた例を示し、 ミスをチェックできることを確認せよ。

4年の創造工学演習では、電子情報工学実験の2週を創造工学の予備実験としても 利用する。このため、実験のガイダンスの後半で、創造工学演習の説明を行う。 特に、今年のプログラミングコンテストでの競技部門について説明を行う。

通信ネタの競技部門の事例

今年のプログラミングコンテストでは、サイコロでデータ通信を行うテーマとなっている。

  • 基本は、送信側は、与えられた英数字に合わせて、サイコロでデータを表現する。
  • サイコロは、トレイに並べてWebカメラの前に置く。
    すると、一定周期で撮影したデータを受信側で、サイコロを見ることができる。
  • 受信側は、そのサイコロの並びを解析して、元の文字を取り出す。

こういったテーマであるが、その難しさを理解してもらうために、 過去のプロコンでの通信関連の競技を説明する。

ポケベルコードで勝利

送信側、受信側の2部屋があり、ネットワークでのみ情報交換が可能。 送信側は、送信側の部屋の様子についての問題の答えを、ネットワーク通信で受信側に送る。 こうなると、Skypeの様なソフトで音声通話するとか、デジカメの画像情報を、伝送するとかの作戦がとられたけど、実際のこの回の優勝チームは、 ポケベルコードだけを送るプログラムを作ったチームであった。 この頃は、携帯電話もなかったし、ポケベルで情報交換していた時代だったので、 優勝した女子チームは、ポケベルコードを素でデコードできた...

赤青緑黄のボールで通信

送信側の部屋と受信側の部屋は、2つのパイプが通っていて、 このパイプには、赤青緑黄の4色のボールを転がすことができる。 このボールを使って、簡単な文面を4色の並びに変換して送る。

ただし、パイプのボールは、何個かに1個のランダムなペースで、 ボールが抜かれる可能性がある。 簡単に考えると、4色を00/01/10/11に割りつければ、ボール1個を送るたびに、 2ビットの伝送が可能である。 しかし、途中でボールが抜かれる可能性があるので、 データ区切りの先頭を見つける必要性、通信でのデッドロックにならないルール決め、 などの必要性を説明する。 また、人間が間違えてボールを送る可能性もあるため、 間違い訂正の手段として、パリティチェックチェックサムCRC(巡回冗長検査)などの話をする。

創造工学・実験(PHP)

創造工学の実験として、 ネットワーク系課題の取り組み者への実験テーマとして、PHPの説明を行う。

追記:実験中、ディレクトリのパーミッション変更を Samba 経由で行おうとしたけど、 Windows端末でのエクスプローラのフォルダ・プロパティに、「セキュリティ」タブが 表示されなくって、ちょっと焦る。 その場は、telnet login + chmod で対応したけど、なぜだろうと調べてみた。
なるほど、フォルダオプションの「簡易ファイルの共有を使用する」をOffにすればいいのか。5年の実験でも同じ環境を使うので、メモしておこう。

短期間という割にそれなりの完成度の高いものが多く、真面目に取り組んでいた人の成果。

1108021030_960x640.JPG
2日間の発表を終え、教員・学生の評価でポイントの高かったものを以下に掲載。
評価順位テーマ
教員1Kinnect Keeper
2デスクト++
3写真で巡る旅日記
学生1写真で巡る旅日記
2TRPG
3Kinnect Keeper

今日は、創造工学演習で自分たちがこの後作ろうとするシステムの アイデアをまとめた資料の提出日。 高専プロコンへの応募を想定しているので、その書式に沿ったパワポA4 x 12枚の資料。

でも提出資料だけれど、見て何をするシステムなのか、さっぱり解らない資料もぞろぞろ。 例年だったらプロコン応募締め切りがあるので、 ボツネタ回収になっちゃうけど今年は、時間的な余裕もあるのでダメだしを行う。

資料が解らない原因は、利用者がどう使うのかが明確に書かれていなかったり...。 機材をどう使うのか分かるような、イメージ図(ポンチ絵)とか、 利用者が実際に使う状況のシナリオとか重要だよねぇ〜...と伝える。

2016年4月

          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

アーカイブ

Google

このアーカイブについて

このページには、過去に書かれたブログ記事のうち創造工学演習カテゴリに属しているものが含まれています。

前のカテゴリはプログラム応用です。

次のカテゴリは卒研です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。