書籍「7つの言語7つの世界」Rubyの章の最後の問題
method_missingテクニックを使って、CSVの一行目にある物をメソッド名にしてあとの二行をその列にある物を表示させる、attr_accessorもこんなふうに実現してるのかなあ
githubにリポジトリつくったよ
http://github.com/yppp/sevenlang
# -*- coding:utf-8 -*- class CsvRow def initialize(header, row) @header = header.map{|x| x.strip} @row = row.map{|x| x. strip} end def method_missing name, *args namest = name.to_s ret = nil @header.zip(@row) do |x, y| if namest == x then ret = y break end end super if ret.nil? ret end end module ActsAsCsv def self.included(base) base.extend ClassMethods end module ClassMethods def acts_as_csv include InstanceMethods end module InstanceMethods def read @csv_contents = [] filename = self.class.to_s.downcase + '.txt' File::open(filename) do |f| @headers = f.gets.chomp.split(",") f.each do |row| @csv_contents << CsvRow::new(@headers, row.chomp.split(",")) end end end def each(&block) @csv_contents.each &block end attr_accessor :headers, :csv_contents def initialize read end end end end class RubyCsv include ActsAsCsv acts_as_csv end m = RubyCsv::new m.each{|row| puts row.one} m.each{|row| puts row.two} m.each{|row| puts row.teeeee}
読み込ませたcsv
one,two, teeeee lions, tigers,cat camel, alpaca,lama
書籍「7つの言語7つの世界」でRubyの章を読み飛ばそうと思ったけど、一部の問題だけ解く
配列をハッシュにしろ
[1,2,3].zip([[4, 5, 6],5,6]).inject(Hash::new){|x, y| x[y[0]] = y[1]; x}
配列が入れ子じゃなかったら
Hash[*[1,2,3].zip([4,5,6]).flatten]
16個と4個の配列を4個と1個づつで表示させろ
eachを使って
te = Array::new(16){|x| x} fo = Array::new(4){|x| x} fo.each.with_index {|x, y| p [fo[y], te[x*4..x*4+3]]}
each_sliceを使って
te = Array::new(16){|x| x} fo = Array::new(4){|x| x} te.each_slice(4).with_index{|x, y| p [fo[y], x]}
Treeクラスを改造して、ハッシュを木構造に変換
class Tree attr_accessor :name, :children def initialize(arg) if arg[:rootname].nil? then @name = arg[:hash].keys[0] if arg[:hash].values[0].empty? then @children = [] else @children = arg[:hash].values[0].map do |x, y| Tree::new rootname: x, hash: y end end else @name = arg[:rootname] if arg[:hash].empty? then @children = [] else @children = arg[:hash].map do |x, y| Tree::new rootname: x, hash: y end end end end def visit(&block) block.call self end def visit_all(&block) visit &block children.each{|x| x.visit_all &block} end end tree = Tree::new(hash: {grandpa: {dad: {child1: [], child2: []}, uncle: {child3: [], child4: []}}}) tree.visit_all{|x| p x.name}
RubyでBrainfuck処理系作ってみた
意味無いと思うけどジャンプテーブル構築時についでに命令文字をシンボルにコンパイルするようにしてる
https://github.com/yppp/brainf_ck
# -*- encoding:utf-8 -*- class Brainfuck class ProgramError < StandardError end def initialize(src) @souce = src @program = [] @tape = [] @jmptab = {} @pc = 0 @cur = 0 end def compile stack = [] @program = @souce.chars.map.with_index do |x, y| case x when '+' :inc when '-' :dec when '>' :next when '<' :prev when '[' stack.push y :lb when ']' r = stack.pop raise ProgramError, "]が多すぎます" if r.nil? @jmptab[y] = r @jmptab[r] = y :rb when '.' :dot when ',' :cor end end raise ProgramError, "[が多すぎます" unless stack.empty? end def exec until @program[@pc].nil? @tape[@cur] ||= 0 case @program[@pc] when :inc @tape[@cur] += 1 when :dec @tape[@cur] -= 1 when :next @cur += 1 when :prev @cur -= 1 when :lb if @tape[@cur] == 0 then @pc = @jmptab[@pc] end when :rb if @tape[@cur] != 0 then @pc = @jmptab[@pc] end when :dot print @tape[@cur].chr when :cor $stdin.getc end @pc += 1 end end end bf = Brainfuck::new "+++++++++[>+++++++++[<[>>+>+<<<-]>>>[<<<+>>>-]<.><<-]>[-]<<-]" bf.compile bf.exec
Brainfuck言語やってみた
九九を9の段から1の段までASCII文字じゃなく数字として出力
+++++++++ [>+++++++++ [<[>>+>+<<<-]>>>[<<<+>>>-]<.><<-] >[-]<<-]
使うメモリの番地
0 出力する段の数
1 足す回数のカウンタ
2 結果になる値
3 コピーのための0番地に戻すテンポラリ領域
http://cfs.maxn.jp/neta/onlineBrainFuck.html
での出力
[HT][DC2][ESC]$-6?HQ[BS][DLE][CAN] (08@H[BEL][SO][NAK][FC]#*18?[ACK][NP][DC2][CAN][RS]$*06[ENQ] [SI][DC4][EM][RS]#(-[EOT][BS][NP][DLE][DC4][CAN][FC] $[ETX][ACK][HT][NP][SI][DC2][NAK][CAN][ESC][STX][EOT][ACK][BS] [NP][SO][DLE][DC2][SOH][STX][ETX][EOT][ENQ][ACK][BEL][BS][HT]
http://brainfuck.bake-neko.net/bfi.html
http://www.iamcal.com/misc/bf_debug/
いろいろな処理系を使ってみると吉
scheme(gauche)で世界のナベアツ問題
3がつく数と3の倍数の時だけアホになる(片仮名になる)それ以外は普通に数字を表示
peercastの大会で課題だったので、っていうか就活の課題やれ俺www
(use srfi-1) (use srfi-13) (define (unpack x y) (if (= x 0) y (unpack (quotient x 10) (append (list (modulo x 10)) y)))) (define (3baisu? x) (= (modulo x 3) 0)) (define (3gatuku? x) (any (lambda (i) (= i 3)) (unpack x '()))) (define (senkurai x) "セン") (define (hyakukurai x) (ref '( "" "ヒャク" "ニヒャク" "サンビャク" "ヨンヒャク" "ゴヒャク" "ロッピャク" "ナナヒャク" "ハッピャク" "キュウヒャク") x)) (define (jukurai x) (ref '( "" "ジュウ" "ニジュウ" "サンジュウ" "ヨンジュウ" "ゴジュウ" "ロクジュウ" "ナナジュウ" "ハチジュウ" "キュウジュウ") x)) (define (ichikurai x) (ref '( "" "イチ" "ニ" "サン" "ヨン" "ゴ" "ロク" "ナナ" "ハチ" "キュウ") x)) (define func `(() ,ichikurai ,jukurai ,hyakukurai ,senkurai)) (define (tokatakana x) (let loop ((lis (unpack x '())) (kana "")) (if (= (length lis) 0) kana (loop (cdr lis) (string-append kana ((ref func (length lis)) (car lis))))))) (for-each print (map (lambda (x) (if (or (3baisu? x) (3gatuku? x)) (string-append (tokatakana x) "!") x)) (iota 1000 1 1)))
出力の最後のほう
950 キュウヒャクゴジュウイチ! 952 キュウヒャクゴジュウサン! キュウヒャクゴジュウヨン! 955 956 キュウヒャクゴジュウナナ! 958 959 キュウヒャクロクジュウ! 961 962 キュウヒャクロクジュウサン! 964 965 キュウヒャクロクジュウロク! 967 968 キュウヒャクロクジュウキュウ! 970 971 キュウヒャクナナジュウニ! キュウヒャクナナジュウサン! 974 キュウヒャクナナジュウゴ! 976 977 キュウヒャクナナジュウハチ! 979 980 キュウヒャクハチジュウイチ! 982 キュウヒャクハチジュウサン! キュウヒャクハチジュウヨン! 985 986 キュウヒャクハチジュウナナ! 988 989 キュウヒャクキュウジュウ! 991 992 キュウヒャクキュウジュウサン! 994 995 キュウヒャクキュウジュウロク! 997 998 キュウヒャクキュウジュウキュウ! 1000
luaでメタプログラミング(DSL)
宣言、luaは引数が文字列リテラル、テーブルリテラルだと、括弧が省略できる、ここではgenerateという関数を作っている、ようするに何かを操作する関数を作ればいい
generate "iroiro"
文脈依存、luaにはRubyやCommonLispのような、instance_evalのみたいなダイナミックスコープを扱う仕組みがない、だから文脈依存を使いたい時はオブジェクトを受けとる、もしくはテーブルを引数にしてもいい
pokemon_add (function(dep) dep.name = "pikacyu" dep.actor_type_is "enemy" dep.pokemon_type_is "denki") --もしくは pokemon_add { name = "pikacyu", actor_type = "enemy", pokemon_type_is = "denki"}
単位、ちょっと苦しいか?
mega(5) + kiro(100) + 500 >5100500
語彙、luaのmethod_missingはメタテーブルの__indexメソッドを再定義すればいい、もちろんグローバルでも有効、上のpokemon_addを定義してみる
setmetatable(_G, { __index = function(t, k) return function(...) local objname,member = string.match(objname, "^(.+)_(.+)") if(objname == "pokemon") then _G[objname][member](...) else error(...) end end}) function pokemon:new() local t = {actortype = nil, nigatetype= nil, tokuitype = nil} setmetatable(t, {}) return t end function pokemon:add (f) f(self) end --宣言に加えたい物をメソッドとして加えていく
階層データ、luaはもともとデータファイルとして開発された、テーブルにテーブルを入れ子にすればいい
感想、"function"っていちいち打つのがめんどくさい、Rubyで言うブロックが欲しいって思う
Lispだってlambdaって打つのがめんどくさいけどまだ打つのが楽w キーボードで上の段使ってない
function うつとき縦の動きがあるお、あとダイナミックスコープの必要性を知った