info

自作CPUのメモ

自作CPUのメモ

頓挫中: NTSCでテレビに出力できる程度の性能をもった8bitCPU

Apple2を参考にシフトレジスタで16種類の信号を出せるようにする

ATARI2600のTIAを参考にラインバッファに書き込み終わったらHLTで割り込みを待つ

課題: タイミング発生のためにカウンタの嵐になってしまう

 

ちょっとしたLEDゲームが作れる4bitCPU

ハーバードアーキテクチャ

8bitアドレス空間のプログラムメモリ(とりあえず64step分を作る)

4bitアドレス空間のRAM

ジャンプテーブルを別のROMに格納

スタック

関数

「プログラミング作法」のマルコフ連鎖アルゴリズムをRubyに翻訳してMeCabを使って日本語対応してみた

日本語版

分かち書きのみ、コードゴルフ

lambda_driverでうまくmapにシンボルを渡せなかったのでgive4eachを使った
メソッドチェーンのワンライナーはうまく改行してDSLっぽくすると読みやすいかも

隙あらばinject、inject小技集

ruby 2.0.0p598

1から10の数を足し合わせた時、途中の状態の数列が欲しい。

(1..10).inject(nil) do |(acc, arr), i| #引数マッチング                          
  next [i, [i]] if arr.nil? #injectの初期化                                     
  [acc + i, arr << acc + i] #次の(acc,arr)に入る                                
end
[55, [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]]

それぞれの要素の間の距離を知りたい

include Math
srand 1145141341893890016
a = (1..10).to_a.shuffle # [5, 3, 4, 7, 6, 10, 2, 8, 9, 1]                      
b = (1..10).to_a.shuffle # [7, 5, 8, 2, 6, 1, 10, 9, 3, 4]                      

a.zip(b).inject(nil) do |((old_x, old_y), arr) ,(x, y)|
  next [[x, y], [0.0]] if arr.nil?
  kyori = sqrt((old_x - x)**2 + (old_y - y)**2)
  [[x, y], arr << kyori]
end
[[1, 4],
 [0.0,
  2.8284271247461903,
  3.1622776601683795,
  6.708203932499369,
  4.123105625617661,
  6.4031242374328485,
  12.041594578792296,
  6.082762530298219,
  6.082762530298219,
  8.06225774829855]]

schemeの引数マッチングを見て思いついた。with_indexの出番が減る、何かスマートなinject初期化方法が欲しい

書籍「7つの言語7つの世界」Io言語2日目セルフスタディ

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));
           );
)

書籍「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)))

未だに引数がいつ評価されるかわからない