情報処理 Ⅱ

24
情情情情2004 情 12 情 7 情 情情 ()

Upload: maite-jimenez

Post on 30-Dec-2015

24 views

Category:

Documents


0 download

DESCRIPTION

情報処理 Ⅱ. 第9回 2004 年 12 月 7 日(火). 暗号化問題. 仕様 入力文にあるすべての 'A' を α ,すべての 'B' を β , … に置き換えて出力する.(単一換字暗号という.) 文字は, char 型の任意の値とする.ただし '\0' を除く( '\0' は必ず '\0' に置き換える,と考えてもよい). どの文字をどの文字に置き換えるかは,プログラムの中で指定する. 簡単な操作で,復号できるようにする. Wagahai Ha Nekodearu Zdjdkdl Kd Qhnrghdux. 暗号化. 復号. 暗号化問題. 方針 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 情報処理 Ⅱ

情報処理Ⅱ

第9回2004年 12月 7日(火)

Page 2: 情報処理 Ⅱ

2

暗号化問題

仕様 入力文にあるすべての 'A'を α,すべての 'B'を β,…に置き換えて出力する.(単一換字暗号という.)

文字は, char型の任意の値とする.ただし '\0'を除く( '\0'は必ず '\0'に置き換える,と考えてもよい).

どの文字をどの文字に置き換えるかは,プログラムの中で指定する.

簡単な操作で,復号できるようにする.•

 Wagahai Ha Nekodearu

 Zdjdkdl Kd Qhnrghdux

暗号化 復号

Page 3: 情報処理 Ⅱ

3

暗号化問題

方針 暗号化のための変換テーブルを,配列で保持する.

• char encrypt_table[256];char encrypt_table[256];

'D'encrypt_

table'E'…

+0

'F' 'G' …

+1+'A'

+'B'+'C'

+'D' +255

encrypt_table['A']の値

Page 4: 情報処理 Ⅱ

4

暗号化問題

方針(続き) 暗号化は,写像を用いる.

• a = 'A';a = 'A'; のとき, b = encrypt_table[a];b = encrypt_table[a]; でbの値が 'D'となるようにするには,あらかじめencrypt_table['A']の値を 'D'としておけばよい.

復号のためのテーブルは,逆写像を用いて求める.• char decrypt_table[256];char decrypt_table[256];• decrypt_table[encrypt_table['A']] = 'A';decrypt_table[encrypt_table['A']] = 'A';

gが fの逆写像であるとは,g(f(x))=x

Page 5: 情報処理 Ⅱ

5

暗号化問題

方針(続き) 定義する関数

•文字列形式の変換テーブルを,配列に変換する.•復号のためのテーブルの値を設定する.•変換テーブルを恒等写像にする(変換のリセット).•変換テーブルを用いて,文字列を暗号化もしくは復号する.

暗号化と復号はどう区別する?• ./encrypt Wakagai Ha Nekodearu./encrypt Wakagai Ha Nekodearu• ./encrypt -d Zdjdkdl Kd Qhnrghdux./encrypt -d Zdjdkdl Kd Qhnrghdux

fが恒等写像であるとは,f(x)=x

「コマンドラインオプション」と呼ばれる

Page 6: 情報処理 Ⅱ

6

定義する関数(1)

void reset_table(char *table)void reset_table(char *table) 変換テーブルを恒等写像にする(変換のリセット).

? ?encrypt_

table?…? ? … ?

table

1 'A' 'B'…0 'C' … 255

+0+1

+'A'+'B'

+'C'+255関数内の

ローカル変数(関数が終了すると,破棄される)

Page 7: 情報処理 Ⅱ

7

定義する関数(2)

void set_encrypt_table(char *table, const void set_encrypt_table(char *table, const char *from, const char *to)char *from, const char *to) 文字列形式の変換テーブルを,配列に変換する.encrypt_

table… …'D'

+'A'

'E'

+'B'

'F'

+'C'table

'A' 'B' 'C' 'D' 'E' 'F'

from to

… '\0' '\0'…

Page 8: 情報処理 Ⅱ

8

定義する関数(3)

void set_decrypt_table(char *table, const void set_decrypt_table(char *table, const char *encrypt_table)char *encrypt_table) 復号のためのテーブルを設定する(逆写像を作る).

decrypt_table

+0

'A' …

+1+'A'

+'B'+'C'

+'D' +255

'D'encrypt_

table…

+0

+1+'A'

+'B'+'C'

+'D' +255

table

encrypt_table

Page 9: 情報処理 Ⅱ

9

定義する関数(4)

char *encrypt(const char *text, const char char *encrypt(const char *text, const char *table)*table) 変換テーブルを用いて,文字列を変換する. 「暗号化」と「復号」の処理を共通化している! 戻り値は,変換された文字列で, static変数 result(のポインタ値)となる.

'a' 'g' 'a''W' 'h' 'a' 'i' '\0'

'D' 'E'… 'F' 'G' …

text

'd' 'j' 'd''Z' 'k' 'd' 'l' '\0'result

戻り値static領域(関数が終了しても,破棄されない)

table

Page 10: 情報処理 Ⅱ

10

暗号化プログラムの補足

関数 set_encrypt_tableの仮引数 from, toはconst char *const char *型型である.このとき ○○ from++; to++; ×× (*from)++;

• fromの参照先 (const char型の値 )を変更しようとしている.

暗号化のように,関数開始時点で長さがわからない文字列を入力にとり,それと同じ長さの暗号文を返すときは,生成する暗号文が配列領域をはみ出さないように配慮する. encrypt.cでは, 100文字 (ナル文字を加えて 101バイト )を越える入力は,そこから無視している.

Page 11: 情報処理 Ⅱ

11

まとめ

関数を自分で定義することができる.関数を呼び出すとき,引数は値渡しで授受される.

変数には,型とは別の属性として,記憶域クラスと型修飾子を指定できる. static変数と auto変数とでは,大きく挙動が異なる.

「変数の定義」と「オブジェクトの生成」は別.オブジェクトの生成・破棄のタイミングに注意する.

Page 12: 情報処理 Ⅱ

12

次に学ぶこと

再帰 (recursion) 用途

再帰的(帰納的,循環的)な定義 バックトラック (backtrack) 分割統治法 (divide-and-conquer)

注意点 無限ループにならないようにする. 再帰を使わないほうがよいこともある.

Page 13: 情報処理 Ⅱ

13

再帰呼び出しとは

関数の内部で自分自身を呼び出すことを,再帰呼び出し(recursive call)という.

例:カウントダウンするプログラム 自作関数 countdownの定義の中で, countdownを呼び出している.

Page 14: 情報処理 Ⅱ

14

なぜ再帰呼び出しが可能なのか?

num = 2

main

x = 2

countdown

x = 0

main関数処理時に生成されるオブジェクト

countdownの呼び出し(関数処理)を終えたときの戻り先

countdown関数処理時に生成されるオブジェクト

countdown

x = 1

countdownの再帰呼び出しを終えたときの戻り先

同一の変数名 xに対して複数のオブジェクトが生成される.

このようなデータ構造を,「スタック」

という.

Page 15: 情報処理 Ⅱ

15

再帰呼び出しの注意点

出力の位置を変えると,カウントアップになる. カウントアップ,カウントダウンともに,再帰呼び出しなしのプログラムのほうが,効率はよい. なぜ再帰呼び出しは効率が悪いか?…関数呼び出しのコスト(オーバーヘッド)があるから.

Page 16: 情報処理 Ⅱ

16

再帰的な定義の例

階乗 0! = 1, 1! = 1 n! = n×(n-1)!  (n≧2)

フィボナッチ数列 a1 = 1, a2 = 1 an= an-1 + an-2   (n≧3)

再帰呼び出しを用いれば,シンプルに書ける. しかしこれらも, whileループのほうが効率がよい.

Page 17: 情報処理 Ⅱ

17

分割統治法

対象領域を細分化して求め(分割),全体として正しい解になる(統治)ようにする.

例 : クイックソート

4 2 516837

1 7 865432

1 8 765432

2 8 57613 4

「4より小」と「4より大」に分ける.

Page 18: 情報処理 Ⅱ

18

ソート (sort)

データを,何らかの基準基準で順番に並べること.「整列」ともいう. 例

試験の点数順試験の点数順に学生番号を出力する 時系列で出力される情報を,キーワードごとキーワードごとに並べる

学生番号: 0003氏名:さしすせそ情処Ⅰの点数: 90情処Ⅱの点数: 0修得単位数: 24

学生番号: 0002氏名:かきくけこ情処Ⅰの点数: 60情処Ⅱの点数: 99修得単位数: 48

学生番号: 0001氏名:あいうえお情処Ⅰの点数: 80情処Ⅱの点数: 75修得単位数: 52

学生番号: 0002氏名:かきくけこ情処Ⅰの点数: 60情処Ⅱの点数: 99修得単位数: 48

学生番号: 0001氏名:あいうえお情処Ⅰの点数: 80情処Ⅱの点数: 75修得単位数: 52

学生番号: 0003氏名:さしすせそ情処Ⅰの点数: 90情処Ⅱの点数: 0修得単位数: 24

学生番号で昇順ソート 情処Ⅰの点数で降順ソート

(ソートの)「キー」という

ソートの対象となる個々の情報を「レコード」という

Page 19: 情報処理 Ⅱ

19

ソートをする際の問題点

計算の手間 処理時間(比較回数)が,レコード数の 2乗に比例する方法は,遅い.

レコード数 nに対して, n log n に比例するだけの比較回数でソートできる方法が最善である.

重複キー キーが同じでもレコードが異なっていれば,別物として扱わなければならない.

安定性

Page 20: 情報処理 Ⅱ

20

文字列並べ替え問題

仕様 コマンドライン引数の各語を,昇順にソートして出力する.

• Mukashi Mukashi Aru Tokoroni Ojiisanto Mukashi Mukashi Aru Tokoroni Ojiisanto Obaasanga Sunde ImashitaObaasanga Sunde Imashita

• Aru Imashita Mukashi Mukashi Obaasanga Aru Imashita Mukashi Mukashi Obaasanga Ojiisanto Sunde TokoroniOjiisanto Sunde Tokoroni

キーは,語の先頭文字とする.• "Mukashi" > "Aru"• "Aru" < "Tokoroni"• "Ojiisanto" == "Obaasanga"

クイックソートを用いる.一般には(辞書順),"Ojiisanto" > "Obaasanga"

Page 21: 情報処理 Ⅱ

21

クイックソートの考え方

4 2 516837 4≦7なので,何もせず青矢印を進める.

4 2 516837 4 > 3なので,赤矢印を進めてから交換し,青矢印を進める.

4 2 516873

4 2 51683 7

4 2 576813

4 > 1なので,交換が発生する.

緑矢印から橙矢印までをソートしたい.

Page 22: 情報処理 Ⅱ

22

クイックソートの考え方

4 2 576813

p =基準値 < p≦

基準値未満 < p <  基準値以上

< p≦未調査p =

走査の位置

pは,配列中の要素を指す整数値またはポインタ値

Page 23: 情報処理 Ⅱ

23

クイックソートの考え方

4 8 576213 配列の走査は終了.緑矢印と赤矢印の値を交換しておく.

4 2 576813 4 > 2なので,交換が発生する.

2 8 576413

2 8 576413 赤矢印の左と右で別々にソートする.ここで再帰呼び出しを使用する.

1 7 865432

Page 24: 情報処理 Ⅱ

24

まとめ

再帰呼び出しを用いて関数を定義すると,プログラムがすっきり書けることがある. 再帰的に定義された問題に適用すると,効果的.

一般に,再帰を用いないほうが効率的である. 関数内の auto変数は,関数呼び出しごとに生成される点に注意.