2011-08-18
書籍「7つの言語7つの世界」Io言語2日目セルフスタディ
プログラミング, Io, 7つの言語7つの世界 | |
![]()
http://github.com/yppp/sevenlang
dim2sum := method(n, n flatten sum) dim2sum := method(n, n prepend(0) reduce(x, y, x = x + y sum))
Listに自分で定義した平均を求めるメソッドを追加、数字以外が混ざっていたら例外を投げるように
List myAvg := method(reduce(x, y, if(y proto != Number, Exception raise("二度と数字以外を入れるんじゃねーぞ、バーカ!"), x + y)) / size)
二次元配列を現わすプロトタイプを書くdimはxとyの大きさのリストを確保、ゲッターとセッター、transposeは行列で言う所の転置をするメソッド
Dim2list := Object clone do(
dim := method(x, y, result := list(); y repeat(nl := list(); x repeat(nl append(nil)); result append(nl)); self lis := result);
set := method(x, y, val, self lis at(y) atPut(x, val); self lis);
get := method(x, y, self lis at(y) at(x));
transpose := method(
result := Dim2list clone;
write(self lis at(0) size, self lis size, "\n");
result dim(self lis size, self lis at(0) size);
self lis at(0) size repeat(i,
self lis size repeat(j,
write(i,j,"\n");
result set(j, i, self get(i, j)))));
)
maread := method(path, lis := list(); File open(path) readLines foreach(line, lis append(line split(" ") select(v, v != "") map(v, v asNumber))); File open(path) close; lis);
mawrite := method(path, lis, f := File open(path); lis foreach(v, f write(v join(" ") append("\n" at(0)))); File open(path) close; lis);
数当てゲーム、前の答えより近づいたか遠くなったか答えるたび表示する
hitandblow := method(
f := File standardInput
num := (Random value(99) + 1) floor;
prev := 0;
10 repeat(i,
in := f readLine asNumber;
if(num == in, "hit!" println; break);
if(prev != 0, if(prev > ((num - in) abs), "near" println, "far" println));
prev = (num - in) abs;
if(i == 9, write("fail ", "atarinumber ", num));
);
)
2011-08-09
書籍「7つの言語7つの世界」Io言語やってみる
7つの言語7つの世界, Io, プログラミング | |
![]()
フィボナッチ数
fib := method(n,
if(n < 2, n, fib(n - 1) + fib(n - 2))
)
Io> fib(10)
==> 55
ループ版
fib := method(n,
fir ::= 0
sec ::= 1
tmp ::= 0
n repeat(
tmp = sec
sec = sec + fir
fir = tmp
)
fir
)
fib(31) println
分母がゼロの時答えがゼロになるように
Io> 42 type ==> Number
数字はNumberクラスなんだなぁ
んで
Number / := method(n, if(n == 0, 0, self / n))
これでは無限ループになってしまう
割り算のメソッドをコピーすればいいと思いついたまではよかったけど、どうやって取得できるかで詰まった
# div := / これじゃダメ
div := Number getSlot("/")
Number / := method(n, if(n == 0, 0, self div(n)))
未だに引数がいつ評価されるかわからない
2011-08-06
書籍「7つの言語7つの世界」Rubyの章の最後の問題
プログラミング, Ruby, 7つの言語7つの世界 | |
![]()
method_missingテクニックを使って、CSVの一行目にある物をメソッド名にしてあとの二行をその列にある物を表示させる、attr_accessorもこんなふうに実現してるのかなあ
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
2011-08-05
書籍「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]}
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}
2011-08-01
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
