Document

情報科学(3)
データと計算(1)
情報の表現 事始め - 名前をつける • 区別する,識別する
– 人名: 姓と名による二名法
• 姓の種類数 ⇒ 単調減少
– 日本:29万,中国:3,000,韓国:200
日本の名前の決め方
• 自由,いい加減
– 2005年生れ,人気上位(明治生命)
• 翔,大翔,拓海,翔太,颯太,翼,海斗,輝,太陽,大和
• 陽菜,さくら,美咲,葵,美羽,美優,凛,七海,美月,
結衣
– 人名漢字
• 常用漢字のほかに287字
• 法制審議会の578字追加案(2004年6月)
– 意見募集の反応により一部削除
– 最終的に488字追加(2004年9月)
– アルファベット,アラビア数字はダメ
人名用漢字案で一部削除へ 法制審部会が検
討
法相の諮問機関、法制審議会人名用漢字部会は8日、インターネット
で公表した578文字の人名用漢字追加案について「人名にはふさわしく
ない」などとして一部の漢字を削除する方向で検討を始めた。
先月11日に追加案を公表した直後から8日までに法務省に寄せられ
た1000通以上の意見のうち、「糞」「屍」「癌」などの文字について「不適
切ではないか」との意見が半数を超えたため。人名用漢字部会は23日
の会合で、意見の集計結果とともに削除方針について審議する予定。2
けた程度の漢字の削除が決まる可能性が高いとみられる。
これを受け同部会は追加案を正式決定し、法相に諮問。法務省は戸籍
法施行規則(省令)を改正する。今秋にも新たな漢字が名前に使えるよう
になる。
同部会は今回の追加検討の際、「常用性があり、平易であること」を原
則にJIS漢字表から選定。漢字自体が持つ意味が人名にふさわしいか
どうかについては「意味を検討し始めると各委員の意見が異なり、収拾
がつかなくなる」(関係者)として検討しなかった結果、「糞」などの漢字が
含まれることになった。(共同通信)
[2004年7月9日]
自由すぎるために制約を付加
• 字画姓名判断
• その他無意味な迷信
キリスト教,ユダヤ教,イスラム教
文化圏
• 名前は聖人の名前の集合から選ぶのが基本
– フランスでは最近まで約500の名前の中から選
ぶことが法律的に義務づけられていた
命名規則
• 競走馬の命名規則
–
–
–
–
カタカナで9文字以内
既登録馬や抹消後5年以内の馬名と不一致
過去の有名な馬名と同一のものは不許可
馬名としてふさわしくないものは不許可
生物の学名
• リンネ式階層分類
– 界,門,綱,目,科,属,種
• 動物界脊椎動物門哺乳綱サル目ヒト上科ヒト属ホモ・
サピエンス種
• 学名: ラテン語二名法
– 属名: 名詞(頭文字は大文字)
– 種小名: 形容詞(小文字)
内包と外延
• 名前付けの2つの流儀
– 日本式: 制約条件を与える
– フランス式: 集合を明示する
• 集合の定義
– 内包的(intensional): 集合の要素が満たすべき条件を
与える.例:ジャイアンツの選手
– 外延的(extensional): 集合の要素を具体的に並べ挙げ
る.例:上原,阿部,高橋,…
名前付け
対象物の空間
名前の空間
人
空間の性質: 「対象」も「人名」もそれぞれの要素に
ついて「等しい」と「等しくない」という判別述語関数
が定義されている.
人名
関数としての性質
• 単射
– 同じ名前を持つ人はいない
• 全射
– どの名前にもその名前を持つ人がいる
• ありえねぇ
Ruby
文字列の印刷と入力
• 挨拶プログラム
puts "Hello, I am a Ruby program."
• 会話プログラム
puts "Hello, I am a Ruby program."
puts "What is your name?"
name = gets.chop # 1行読んで改行を取り去る
puts "How are you, " + name + "?"
# + は文字列の場合,文字列を連接する
Ruby
文字列の「等しい」と「等しくない」
"David" == "David"
"駒場太郎" == "駒場太郎"
name = "David"
name == "David"
name == "DAVID"
name != "DAVID"
電話番号は名前か?
• 名前は文字という記号で表現
– 文字には文化的な意味が付与されている
• 符号(code): 特定の意味と結びつかない記
号
– モールス信号
– 電話番号では数字を符号として使用,数値に意
味はない
• 実は記号そのものに意味の中立性,代替可
能性がある
符号化
シニフィエ
シニフィアン
たとえば,n個の符号 m桁でnm個の対象を表現
近さの構造
対象空間の中の近さは記号列の近さに反映される
f -1(a)
加入電話の電話番号
記号
列
f -1(b)
f
加入電話
10桁の数字列
a
g -1(a)
b
g-1(a)
10進数表現
g
10進10桁で表せる自然数
階層構造
類似の階層構造
• 年月日
– 日本流
YYMMDD (実はISOの標準)
– ヨーロッパ流 DDMMYY
– アメリカ流
MMDDYY
なおいずれも,年は本来4桁で2桁は省略形
• 住所
– 日本流: 都道府県,市町村,丁目,番地,号
– 欧米流: 番地,通り,市,州/郡など
Ruby
写像の表現
• 配列: 自然数 → データ
eto = ["子","丑","寅","卯","辰","巳",
"午","未","申","酉","戌","亥"]
eto[0]
eto[5]
eto[11]
• ハッシュ: 任意のデータ → データ
directory = {"総長" => "21000", "学部長" => "46001",
"守衛" => "46666"}
directory["総長"]
directory["守衛"]
これは復習
Ruby
使ってみよう
eto = ["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
print “生まれた年は(西暦)? ” # printは最後に改行がない
year = gets.to_i # 数として読み込む
puts "あなたの干支は" + eto[(year-1900)%12] + "です."
# putsは最後に改行がつく
構造的な表現
• 名前の替わりに性質を列挙して対象を表現
– イチロー
「マリナーズの選手で守備はライトで打順は1番」
– 性質: 属性名と値の対の集合
– 申込書: 名前,住所,電話番号,…
Ruby
クラス
class BaseballPlayer
attr_accessor :team, :position, :bat_order
# こうしておくと,いちいちteamとかpositionとかのメソッドを定義しなくていい
def initialize(t,p,bo)
@team = t
@position = p
@bat_order = bo
end
end
ichiro = BaseballPlayer.new("Mariners", "right field", 1)
puts "Ichiro's team is " + ichiro.team
puts "Ichiro's position is " + ichiro.position
puts "Ichiro's batting order is %d"%ichiro.bat_order
データベース
• 属性名と値の組で表されたデータを大量に集
めたもの
• オペラ作品のデータベース
– [作品名:椿姫;作曲者:ヴェルディ;初演1853;
言語:イタリア語;構成:3幕]
• 属性にデータの型が対応
– 文字列,整数,…
表形式
• 属性が共通で順序を固定
作品名
作曲者
初演
言語
構成
椿姫
ヴェルディ
1853
イタリア語
3幕
カルメン
ビゼー
1875
フランス語
4幕
オテロ
ヴェルディ
1887
イタリア語
4幕
タンホイザー
ワグナー
1845
ドイツ語
3幕
フィガロの結婚
モーツァルト
1786
イタリア語
4幕
フィデリオ
ベートーヴェン
1805
ドイツ語
2幕
Ruby
class Opera
attr_accessor :title, :composer, :year, :language, :acts
def initialize(*x) # *のついた(最後の)変数は残った引数の列を配列として受け取る
@title, @composer, @year, @language, @acts = x # 便利な書き方ができる
end
end
operas = Array.new(6)
operas[0] = Opera.new("椿姫", "ヴェルディ", 1853, "イタリア語", "3幕")
operas[1] = Opera.new("カルメン", "ビゼー", 1875, "フランス語", "4幕")
operas[2] = Opera.new("オテロ", "ヴェルディ", 1887, "イタリア語", "4幕")
operas[3] = Opera.new("タンホイザー", "ワグナー", 1845, "ドイツ語", "3幕")
operas[4] = Opera.new("フィガロの結婚", "モーツァルト", 1786, "イタリア語", "4幕")
operas[5] = Opera.new("フィデリオ", "ベートーヴェン", 1805, "ドイツ語", "2幕")
operas.each do |x| # operasのそれぞれをxとして,以下を実行する イテレータ
px
end
operas.each do |x| # “\t”, “\n“ はそれぞれタブ,改行
print x.title, "\t", x.composer, "\t", x.year, "\t",
x.language, "\t", x.acts, "\n"
end
まず,計算とは関数と考える
• そして関数は写像である.
入力空間
出力空間
計算を構成する演算
• 整数の四則演算
• 実数の四則演算
• 論理演算
Ruby
整数計算
# n角形の対角線の数を求める
# 入力:n,出力:対角線の数 を与える関数
n = ARGV[0].to_i
# ARGVはコマンドラインの引数の文字列の配列
# to_iは文字列を数に変換する
d = (n-3)*n/2;
print "The number of diagonals of ", n,
"-polygon is ", d, ".\n"
Ruby
Rubyのメソッドによる関数定義
ObjectというRuby世界の中の大親分に対するメソッド
として定義するとどこでも使える関数となる
def diagonals(n)
(n-3)*n/2
end
print "The number of diagonals of ", 8,
"-polygon is ", diagnals(8), ".\n"
Ruby
実数計算
# 摂氏温度を華氏に変換
tC = ARGV[0].to_f # 浮動小数点数へ変換
tF = 1.8*tC + 32.0
print "摂氏 ", tC, " 度は,華氏 ", tF, " 度です.\n“
# BMIの計算
def bmi(height, weight)
# 関数定義
weight/height**2
end
puts “あなたの身長(m)は?“; h = gets.to_f
puts "あなたの体重(kg)は?“; w = gets.to_f
print “あなたのBMIは”, bmi(h,w), “です\n“ # 関数の呼出し
Ruby
論理計算
• n%2==0
– nが2で割り切れるときtrue,割り切れないとき
false
• (y%4 == 0) && (y%100 != 0) || (y%400 == 0)
– yが4で割り切れかつ100で割り切れないか,yが
400で割り切れるときtrue,そうでなければfalse
Ruby
# チョーハン
n = ARGV[0].to_i
if n%2==0
puts "チョー"
else
puts "ハン"
end
条件分岐
# 閏年
y = ARGV[0].to_i
if (y%4 == 0) && (y%100 != 0) ||
(y%400 == 0)
puts "Leap year."
else
puts "Common year."
end
Ruby
# 閏年 森型分岐
year = ARGV[0].to_i
if year%100==0
if year%400==0
puts "Leap year."
else
puts "Common year."
end
else
if year%4==0
puts "Leap year."
else
puts "Common year."
end
end
分岐の複合
# 閏年 梯子型分岐
year = ARGV[0].to_i
if year%400==0
puts "Leap year."
elsif year%100==0
puts "Common year."
elsif year%4==0
puts "Leap year."
else
puts "Common year."
end
Ruby
if
梯子型
then
else
if
then
else
if
then
else
森型
if
if
then
then
else
if
then
if
else
then
else
else
Ruby
梯子型の別の例 論語
puts "何歳ですか?"
age = gets.to_i
if age < 15
puts "無"
elsif age < 30
puts "志于學"
elsif age < 40
puts "立"
elsif age < 50
puts "不惑"
elsif age < 60
puts "知天命"
elsif age < 70
puts "耳順"
else
puts "從心所欲、不踰矩"
end
Ruby
# BMI判定
puts "あなたの身長(m)は?"
height = gets.to_f
puts "あなたの体重(kg)は?"
weight = gets.to_f
bmi = weight/height**2
print "あなたのBMIは", bmi,
"です.\n"
if bmi >= 26.4
puts "太りすぎです."
elsif bmi >= 24.0
puts "太り気味です."
else
puts "問題ありません."
end
応用
# 星座
Zodiac = ["山羊座", "水瓶座", "魚座",
"牡羊座", "牡牛座", "双子座",
"蟹座", "獅子座", "乙女座",
"天秤座", "蠍座", "射手座"]
StartDay =
[21,19,21,21,22,22,23,23,24,24,23,22]
print "生まれた月は? “; month = gets.to_i
print "生まれた日は? “; day = gets.to_i
print "あなたの星座は"
if day < StartDay[month-1]
print Zodiac[month-1], "です.\n"
else
print Zodiac[month%12], "です.\n"
end
Ruby
関数の関数
cube = lambda {|x| x**3} # 関数定義
def double(x,p) # 関数pを引数としてもらう関数
p.call(p.call(x))
end
puts double(2,cube) #=> 512
関数の合成
f
g
Ruby
関数の合成の例
def compose(x,f,g)
g.call(f.call(x))
end
cube = lambda {|x| x**3}
down = lambda {|x| x-1}
puts compose(4,cube,down) #=>63
Ruby
関数を値として返してもよい
def compose(f,g)
lambda {|x| g.call(f.call(x))}
end
cube = lambda {|x| x**3}
down = lambda {|x| x-1}
puts compose(cube,down).call(4) #=>63
構造のあるデータにおける計算
• 有理数
– 約分,負数,逆数,四則演算,表示を定義
• 複素数
– 負数,逆数,四則演算,表示を定義
• その他書いてみた例
– 預金口座
– じゃんけん
– トランプのカードの強さ
変数と代入
• 変数: 記憶域の場所を指す名前
x
3
y
5
name
hanako
• 代入: 変数の指す場所に値をしまう操作
– 形式 変数名=式
x=3
y = x+2
name = "hanako"
代入の意味
• 等号 = を使うが数学的等式ではない
– 左辺(変数名)と右辺(式)は対称ではない
– 左辺の変数は記憶場所を指し,右辺の式の中の
変数は記憶場所にしまわれた値を指す
x = x+1
– 順序によって結果が変わる
[A]
x=2
x = x+1
y=x
[B]
x=2
y=x
x = x+1
x
2
4
3
2
y
3
2
オブジェクト
• オブジェクト: 意味的なまとまりのあるデータの単位
– 単純なもの: 整数,文字列など
– 複雑なもの: 有理数,スタック,リストなど
• メソッド: オブジェクトに対して可能な操作
– 整数に対する加算,文字列に対する置換
– スタックに対するpush, pop
• クラス: 同じ種類のオブジェクトを総称したもの
– クラスからここのオブジェクトが生成される
– オブジェクトに適用可能なメソッドはクラスで定まる
Ruby
変数とオブジェクト
• あらゆるオブジェクトは変数に代入できる
BaseballPlayer
はクラス
class BaseballPlayer
attr_accessor :team, :position, :bat_order
def initialize(t,p,bo)
@team = t
これ
これも
@position = p
変数
も変
数
@bat_order = bo
オブジェクト
end
の生成
end
ichiro = BaseballPlayer.new("Mariners", "right field", 1)
ichiro
は変数
変数の有効範囲
• 局所変数: 宣言された場所の含まれる範囲内での
み有効
– 範囲:
• 通常はメソッド定義の初めから終わり
• より小さい単位はブロック
• より大きい単位はクラス/モジュール定義の初めから終わり
• インスタンス変数: 1つのオブジェクト内で有効
– Rubyでは変数名の語頭に@をおく規約
• クラス変数:1つのクラス内で有効
– Rubyでは変数名の語頭に@@をおく規約
• 大域変数: プログラム全体で有効
– Rubyでは変数名の語頭に$をおく規約
状態
• 変数にどんな値(オブジェクト)がしまわれているかは
プログラム実行中に変化
• 変数と値の結びつき全体を状態という
– 状態は時間で変化
• 状態のレベル
– メソッドの状態: 局所変数が現在持つ値
– オブジェクトの状態: インスタンス変数が現在持つ値
– プログラムの状態: 大域変数が現在持つ値
より短い時間間隔ではオブジェクトの状態の総体
関数の世界と状態の世界
• 関数は入力と出力の数学的な関係を表す
→ 状態(時間変化)はない
• 関数の計算をプログラムのメソッドとして実現する場
合,計算の途中に状態変化が起こりうる
• また,計算の前後でオブジェクトの状態が一般に異
なることがある(副作用)
• 逆にオブジェクトの状態変化は,一般に,変数に関
数の出力やそれを含む式を代入してもたらされる