Ruby体験記14 〜ハッシュ、シンボル、暗号
どうも。三十路です。
本日も2巻です。

Ruby 2 さまざまなデータとアルゴリズム (CD-ROM付) (プログラミング学習シリーズ)
- 作者: arton,宇野るいも
- 出版社/メーカー: 翔泳社
- 発売日: 2009/02/13
- メディア: 大型本
- 購入: 1人 クリック: 48回
- この商品を含むブログ (21件) を見る
ハッシュ
キーと値のペアで格納するオブジェクトをハッシュと呼ぶ。ハッシュの種類にはMD5やSHA256などがある。
require 'digest/sha2' p Digest::SHA256.hexdigest(File.open($0,'rb').read)
シンボル
ハッシュリテラルを示す{}を省略することができ以下の用に記述できる。
obj.foo(:name=>"次郎さん", :city=>"東京")
name等の : 頭に付けたこの表記をSymbolクラスのオブジェクトリテラル表記です。
ちなみにnameがキーで次郎がそのキーの内容。
暗号
暗号とは安全に情報を伝達させるためにもちいるものであり、その目的としてデータの秘匿、なりすまし防御、改竄の防御の3つがある。現在の暗号の安全性は総当たりで解読できるまでの時間料によって安全性が保証されている。現実的な時間内に解読されなければ安全とみなしている。
Rubyで暗号化するにはopensslライブラリを利用する。
暗号化
enc = OpenSSL::Cipher::AES256.new("CBC") enc.encrypt() #複合するにはdecryptメソッドを使えばよい enc.pkcs5_keyivgen(pass) File.open(file, "rb") do |fin| File.open("#{file}.sec", "wb") do |fout| while buff = fin.read(8000) fout.write(enc.update(buff)) end fout.write(enc.final()) end end enc.reset()
そんな日。
Ruby体験記13 〜オブジェクトの永続化、圧縮
どうも。三十路です。
今日も2巻でお勉強。

Ruby 2 さまざまなデータとアルゴリズム (CD-ROM付) (プログラミング学習シリーズ)
- 作者: arton,宇野るいも
- 出版社/メーカー: 翔泳社
- 発売日: 2009/02/13
- メディア: 大型本
- 購入: 1人 クリック: 48回
- この商品を含むブログ (21件) を見る
オブジェクトの永続化
プログラム内部で作成したデータ(オブジェクト)をそのまま保存したり復元したりするのを永続化という。
Marshalモジュールを使うことで永続化することができる。
オブジェクトをバイナリ化(ようするに保存できる形式にすること?)することをマーシャルという。逆に復元することをデマーシャルという。
#マーシャル t = Time.now puts t File.open "time_save.data", "wb" do |file| Marshal.dump t, file end #デマーシャル t = nil puts t File.open "time_save.data", "rb" do |file| t = Marshal.load file end puts t
※全てのオブジェクトをマーシャル出来るわけではない。Fileオブジェクトなどはできない(OSに依存するので仮に保存しても他の環境では読み出せない。)
小問題1
#小問題1 array = [1, 2, 3, 4, 5] File.open "array_save.data", "wb" do |file| Marshal.dump array, file end array = nil puts array File.open "array_save.data", "rb" do |file| array = Marshal.load file end puts "#{array}"
圧縮
データの内容を変えずに元のサイズよりもサイズを小さくすることを圧縮という。圧縮したデータを元に戻すことを復元または伸長、展開という。
元のデータと完全に同じように復元できる圧縮を可逆圧縮。また元には完全に戻せない圧縮を非可逆圧縮という。
def make_zero(count) r = "" if count > 1 r = "Z#{count}" elsif count == 1 r = "0" end r end def compress(nums) r = "" count = 0 nums.each_char() do |c| if c == "0" count += 1 if count == 10 r << "Z0" count = 0 end else r << make_zero(count) count = 0 r << c end end r << make_zero(count) end aa = "3200000000008000000329000000000" aa.each do |arg| puts "#{arg} => #{compress(arg)}" end require "zlib" require "pp" Zlib::GzipWriter.open "namelist.data.gz" do |gz| File.open "namelist.data", "rb" do |data| gz.write data.read end end Zlib::GzipReader.open "namelist.data.gz" do |gz| pp(Marshal.load(gz)) end
そんな日。
Ruby体験記12 〜通信、例外
どうも。三十路です。
本日も2巻。

Ruby 2 さまざまなデータとアルゴリズム (CD-ROM付) (プログラミング学習シリーズ)
- 作者: arton,宇野るいも
- 出版社/メーカー: 翔泳社
- 発売日: 2009/02/13
- メディア: 大型本
- 購入: 1人 クリック: 48回
- この商品を含むブログ (21件) を見る
通信
openメソッドにURIを指定する。
require "open-uri" xml = nil open "http://codezine.jp/rss/new/20/index.xml" do |http| xml = http.read() end
例外
エラーを示す特別なオブジェクトを例外と呼ぶ。Rubyではプログラム実行時にエラーを発見すると、例外を関数やメソッドの呼び出し元へと送る。
begin〜endで囲い、rescueで発生した例外を受け取る。Errnoはエラー番号の略。ensureは最後に必ず実行したい処理をここへ記述、例外があった場合は例外が先に実行されてからensureが実行される。
begin File.open("aaaaaa") do |file| puts file.read end rescue Errno::ENOENT => e puts e rescue NameError => e puts e rescue => e ensure puts "" end
そんな日。
Ruby体験記11 〜特殊変数、Array#each、String#each_char、条件式2、ライブラリの作成
どうも。三十路です。
本日も2巻。

Ruby 2 さまざまなデータとアルゴリズム (CD-ROM付) (プログラミング学習シリーズ)
- 作者: arton,宇野るいも
- 出版社/メーカー: 翔泳社
- 発売日: 2009/02/13
- メディア: 大型本
- 購入: 1人 クリック: 48回
- この商品を含むブログ (21件) を見る
特殊変数
Rubyでは共通で利用するオブジェクトを既定の特殊変数として参照可能にしている。
| 変数名 | 内容 |
|---|---|
| $0 | 現在実行中のRubyプログラムのファイル名 |
| $: | require関数やload関数がライブラリをロードするために参照するフォルダ名の配列 |
| $DEBUG | デバッグモードならtrueが設定される変数。Rubyをデバッグモードで実行するには-dを指定する |
| $stdin | 標準入力。既定ではコンソール入力が割り当てられる |
| $stdout | 標準出力。既定ではコンソール出力が割り当てられる |
| $stderr | 標準エラー出力。既定ではコンソール出力が割り当てられる |
| $* | Rubyプログラムに与えられた引数を格納した配列 |
Array#each
Array#eachメソッドとはブロック引数をとり、ブロック変数として配列内の要素を順番に与えて処理できる。
例)
array = "日,月,火,水,木,金,土".split(",") array.each do |str| puts "#{str}" end
上記をfor文で
array = "日,月,火,水,木,金,土".split(",") for i in 0..array.size-1 puts "#{array[i]}" end
またインデックス値を1つずつ増やしたり、1つずつ減らしたりするのには、Integer#uptoやInteger#downtoのが処理が見やすくなるかもしれない。
String#each_char
先頭から末尾まで順に1文字ずつブロック変数に設定して、ブロック引数を呼び出す。
str= "日月火水木金土" str.each_char do |s| puts "#{s}" end
条件式2
条件が成り立たなければ処理するという条件分岐式がある。
以下2つは同じ意味である。
if !条件式
unless 条件式
ライブラリの作成
いままでどおりにプログラムを組むだけでそれをライブラリとして利用できる。その際にいくつか注意点。
ファイル名は全て小文字。またクラス名や関数名に「_」を利用している場合はファイル名には「-」を付ける。
そんな日。
Ruby体験記10 〜日付と時刻の扱い
どうも。三十路です。
今日も2巻。

Ruby 2 さまざまなデータとアルゴリズム (CD-ROM付) (プログラミング学習シリーズ)
- 作者: arton,宇野るいも
- 出版社/メーカー: 翔泳社
- 発売日: 2009/02/13
- メディア: 大型本
- 購入: 1人 クリック: 48回
- この商品を含むブログ (21件) を見る
日付と時刻の扱い
1970年1月1日9時からの経過した秒数を数値にして扱う。タイムゾーン指定もできる。(これって指定した国の1970年1月1日9時からの経過時間になるの? -> 1970年1月1月0時+タイムゾーンからの経過時間?)
TimeクラスとdateライブラリのDate,DateTimeで日付と時刻を扱える。
例)
now = Time.now puts now jt = Time.local(2009, 1, 1, 15, 32, 45) puts jt aprilfool = Time.local(2009, 1) puts aprilfool
日付の表示形式はstrftimeで変更できる
例)
puts Time.now.strftime("%Y/%m/%d %X")
strftimeメソッドでの書式指定子
| 指定子 | 意味 |
|---|---|
| %Y | 年(1970から2038) |
| %y | 年(下2桁) |
| %m | 月(01から12) |
| %d | 日(01から31) |
| %H | 時(00から23) |
| %M | 分(00から59) |
| %S | 秒(00から59) |
| %x | %m/%d/%y |
| %X | %H:%M:%S |
| %c | %x %X |
| %% | テンプレート文字列内に%を含めたい場合 |
そんな日。
Ruby体験記9 〜ヘルプ、クラス、添付ライブラリ、メソッドチェイン、2次元配列、ブロックの簡易記法、エスケープシーケンス、降番順ループ、
どうも。三十路です。
本日でこの本での勉強も最後となりました。

プログラミング学習シリーズ Ruby 1 はじめてのプログラミング
- 作者: arton,宇野るいも
- 出版社/メーカー: 翔泳社
- 発売日: 2009/01/29
- メディア: 大型本
- 購入: 5人 クリック: 95回
- この商品を含むブログ (30件) を見る
つーても。シリーズものなのであと2冊あるんですけどね・・・。
いままでの内容、変数、関数、条件分岐、ループの手法を組み合わせたものは手続き型プログラミングというらしい。
名前なんぞどうでもいい気もするが一応覚えておく。
Rubyはオブジェクト指向プログラミング言語なのでこれからはそれを勉強。
ってことで次の本にうつる。
最後の8章はファイルの扱いばかりなのでGoogle App Engineでは扱えないから読んでもいみなしぞうってことで飛ばす。
そんなわけで2巻。

Ruby 2 さまざまなデータとアルゴリズム (CD-ROM付) (プログラミング学習シリーズ)
- 作者: arton,宇野るいも
- 出版社/メーカー: 翔泳社
- 発売日: 2009/02/13
- メディア: 大型本
- 購入: 1人 クリック: 48回
- この商品を含むブログ (21件) を見る
へるぷ?とクラスと添付ライブラリ
Rubyには組み込みクラスと呼ばれる実行プログラム内に組み込まれたクラス群と、多数の独立したクラスをまとめた添付ライブラリというものがある。
これらを見るためにリファレンスマニュアルがある。以下のURLからダウンロードできる模様。
http://redmine.ruby-lang.org/wiki/rurema
メソッドチェイン
メソッド呼び出しを行いその戻り値がオブジェクトの場合、その戻り値のオブジェクトのメソッドを呼び出すことをメソッドチェインという。
2次元配列
配列の要素に配列が入れられたものを2次元配列という。さらに3次元以上つくることができこれらを総称して多次元配列という。
str = "あ,い,う,え,お"
sentences << str.split(",") #カンマ区で区切られたところで区切って配列を作り、その配列を配列の最後に追加する
配列の長さはsizeで得られる
sentences.size
ブロックの簡易記法
a = Array.new(10) do |i| Array.new(10, 0) end ||> を以下のように1行で記述可能 >|ruby| a = Array.new(10) {|i| Array.new(10, 0)}
エスケープシーケンス
「\」はエスケープシーケンスの開始を示す文字。エスケープシーケンスとは現在の状態を一時的に離れて別の一連の処理を実行する制御を指す。
http://wisdom.sakura.ne.jp/programming/c/Cdata1.html
降番順のループ
Integer#downtoメソッドを使う。
以下の例はオブジェクトの値から引数(downtoメソッドの)で指定した値までの書く整数をブロック変数に入れながらブロックを実行する。1ずつ減らす。
3,2,1,0
3.downto(0) do |i| end
その反対に以下の例は、オブジェクトの値から引数でしたいした値までの各整数をブロック変数に入れながらブロックを実行する。1ずつ増やす。
3,4,5,6
3.upto(6) do |i| end
小問題5(P45)
1)
BITMAPFILEHEADER = "a2VIV" BITMAPINFOHEADER = "VVVvvVVVVVV" WIDTH = 640 HEIGHT = 480 FILEHEADER_LEN = 14 INFOHEADER_LEN = 40 COLOR_USED = 2 COLORTBL_LEN = 4 * COLOR_USED HEADERS_LEN = INFOHEADER_LEN + FILEHEADER_LEN + COLORTBL_LEN pas = Array.new(HEIGHT) {|i| Array.new(WIDTH, 0)} pas[0][WIDTH / 2] = 1 for i in (1..HEIGHT - 1) for j in (1..WIDTH - 2) pas[i][j] = pas[i - 1][j - 1] + pas[i - 1][j + 1] end end File.open("pascal_rev.bmp", "wb") do |file| file.write(["BM", HEADERS_LEN + WIDTH * HEIGHT, 0, HEADERS_LEN].pack(BITMAPFILEHEADER)) file.write([INFOHEADER_LEN, WIDTH, HEIGHT, 1, 8, 0, 0, 0, 0, COLOR_USED, COLOR_USED].pack(BITMAPINFOHEADER)) file.write("\xff\xff\xff\0") file.write("\0\0\0\0") (HEIGHT - 1).downto(0) do |y| 0.upto(WIDTH - 1) do |x| if pas[y][x] % 2 == 0 file.write("\x01") else file.write("\0") end end end end
2)
BITMAPFILEHEADER = "a2VIV" BITMAPINFOHEADER = "VVVvvVVVVVV" WIDTH = 640 HEIGHT = 480 FILEHEADER_LEN = 14 INFOHEADER_LEN = 40 COLOR_USED = 2 COLORTBL_LEN = 4 * COLOR_USED HEADERS_LEN = INFOHEADER_LEN + FILEHEADER_LEN + COLORTBL_LEN pas = Array.new(HEIGHT) {|i| Array.new(WIDTH, 0)} pas[0][WIDTH / 2] = 1 for i in (1..HEIGHT - 1) for j in (1..WIDTH - 2) pas[i][j] = pas[i - 1][j - 1] + pas[i - 1][j + 1] end end def bmpfile_write(pas, filename, color1, color2) File.open(filename, "wb") do |file| file.write(["BM", HEADERS_LEN + WIDTH * HEIGHT, 0, HEADERS_LEN].pack(BITMAPFILEHEADER)) file.write([INFOHEADER_LEN, WIDTH, HEIGHT, 1, 8, 0, 0, 0, 0, COLOR_USED, COLOR_USED].pack(BITMAPINFOHEADER)) file.write(color1) file.write(color2) (HEIGHT - 1).downto(0) do |y| 0.upto(WIDTH - 1) do |x| if pas[y][x] % 2 == 0 file.write("\0") else file.write("\x01") end end end end end bmpfile_write pas, "pascal_br.bmp", "\0\0\0\0", "\xff\0\0\0" bmpfile_write pas, "pascal_wr.bmp", "\xff\xff\xff\0", "\0\0\xff\0"
3)
BITMAPFILEHEADER = "a2VIV" BITMAPINFOHEADER = "VVVvvVVVVVV" WIDTH = 640 HEIGHT = 480 FILEHEADER_LEN = 14 INFOHEADER_LEN = 40 COLOR_USED = 2 COLORTBL_LEN = 4 * COLOR_USED HEADERS_LEN = INFOHEADER_LEN + FILEHEADER_LEN + COLORTBL_LEN pas = Array.new(HEIGHT) {|i| Array.new(WIDTH, 0)} pas[0][WIDTH / 2] = 1 for i in (1..HEIGHT - 1) for j in (1..WIDTH - 2) pas[i][j] = pas[i - 1][j - 1] + pas[i - 1][j + 1] end end File.open("pascal_mod5.bmp", "wb") do |file| file.write(["BM", HEADERS_LEN + WIDTH * HEIGHT, 0, HEADERS_LEN].pack(BITMAPFILEHEADER)) file.write([INFOHEADER_LEN, WIDTH, HEIGHT, 1, 8, 0, 0, 0, 0, COLOR_USED, COLOR_USED].pack(BITMAPINFOHEADER)) file.write("\xff\xff\xff\0") file.write("\0\0\0\0") (HEIGHT - 1).downto(0) do |y| 0.upto(WIDTH - 1) do |x| if pas[y][x] % 5 == 0 file.write("\0") else file.write("\x01") end end end end
そんな日。
Ruby体験記8 〜ハッシュ
どうも。三十路です。
今日も元気よくこの本でお勉強です。

プログラミング学習シリーズ Ruby 1 はじめてのプログラミング
- 作者: arton,宇野るいも
- 出版社/メーカー: 翔泳社
- 発売日: 2009/01/29
- メディア: 大型本
- 購入: 5人 クリック: 95回
- この商品を含むブログ (30件) を見る
ハッシュ
配列と同様にデータの管理する型。ハッシュはキーで管理する。
animals = {}
animals["犬"] = "わんわん"
animals["猫"] = "ニャーニャー"
animals["牛"] = "モーモー"
puts animals["犬"]
puts animals["猫"]
puts animals["牛"]
キーと値を => でつなぐこともできます。
animals = {
"犬"=>"わんわん",
"猫"=>"ニャーニャー",
"牛"=>"モーモー"
}
puts animals["犬"]
puts animals["猫"]
puts animals["牛"]
練習問題
#7.1
def delete_multiple array, current, max a = current while a <= max array[a] = nil a += current end end def last_number array i = -1 while !array[i] i -= 1 end array[i] end MAX=100 puts "上限値は#{MAX}です" nums = [] for i in 0..MAX nums << i end primes = [] for i in 2..MAX if nums[i] primes << i delete_multiple(nums, i, MAX) if i * i > last_number(nums) break end end end for i in 2..MAX if nums[i] primes << nums[i] end end puts "#{MAX}までの素数は#{primes}"
#7.2
PAPER=0 SCISORS=1 STONE=2 WIN={ [PAPER, STONE] => true, [SCISORS, PAPER]=>true, [STONE, SCISORS]=>true } HANDS={PAPER=>"パー",SCISORS=>"チョキ",STONE=>"グー"} com_win=0 plr_win=0 while com_win < 3 && plr_win < 3 puts "パーは0、チョキは1、グーは2?" #choice = gets() choice = rand(3) player = Integer(choice) computer = rand(3) puts "あなた:#{HANDS[player]}, コンピューター:#{HANDS[computer]}" if WIN[[player, computer]] plr_win += 1 elsif WIN[[computer, player]] com_win += 1 else puts "あいこ" end end if plr_win >=3 puts "あなたの勝ち" else puts "あなたの負け" end
そんな日。