月別アーカイブ: 2013年2月

Project Euler

Project Eulerというサイトを見つけた。
このサイトにはコンピュータを使って解くタイプの数学の問題がたくさん載っている。
アカウントを取得すると各問題に回答したかどうかをサイト上で見ることができる。

10問くらい解いてみたけど、問題のタイプとしては素数とか数列とかそういった類のものが多い印象。
新しい言語を覚えるときに、このサイトに載ってる問題をその言語で解いたりすると勉強になりそう。

Schemeと再帰

Schemeチュートリアルの内容をゴリゴリ写経してます。

基本的な制御構造が繰り返しでなく再帰のため、初っぱなから再帰の洗礼に見舞われてます。
ということで再帰関数について調べたことについて書いてみます。


再帰関数とは
再帰関数とは関数それ自体が自らを呼び出す処理を持つ関数のこと。
例えば階乗の計算なんかがよく例として挙げられる。

(define (fact n)
   (if (= n 1)
      1
      (* fact (- n 1)))))

上記の関数factは関数本体からfact自身を呼び出している。
factに渡す引数は1ずつ減算されていて、n=1となったところで再帰処理の終端に到達する。
再帰処理を関数として記述するときは終端の設定を必ず行う(そうしないと無限ループに陥る)。


Flat recursion
リストのトップレベルのアイテム(アトム)を処理対象とする再帰処理をFlat recursionという(この語に関して日本語訳が見つからなかった)。
例えば下記のようなリストのトップレベル要素のみの総和を計算する関数が挙げられる。

;Flat recursion
(define (sum_list l)
  (if (null? l)
      0
      (+ (car l) (sum_list (cdr l)))))



Deep recursion
Flat recursionとは対照的に、リストの要素全てを処理対象とする再帰処理をDeep recursionという。
Deep recursionバージョンのsum_listを示すと下記のようになる。

;Deep recursion                                                                                                                  
(define (sum_list l)
  (cond ((null? l) 0)
        ((number? l) l)
        (else (+(sum_list (car l)) (sum_list (cdr l))))))



Tail recursion(末尾再帰)
関数の末尾が再帰呼び出しのみで終わっている再帰処理を末尾再帰という。
末尾再帰で階乗を計算する関数を書くと以下のような形になる。

;Tail recursion version                                                                                                          
(define (fact n)
  (define (iter product counter)
    (if (> counter n)
        product
        (iter (* counter product)
              (+ counter 1))))
    (iter 1 1))

この方法だと、引数に計算結果を渡しているので、計算の途中経過を再帰呼び出しの都度保存しておく必要が無い。そのため、末尾再帰を利用することでメモリの消費量を抑えることができる(らしい)。



…とりあえずこんな感じか。
現状、用語の確認がメインみたいな感じですな。
まだ実用的なプログラムに触れてないので、イマイチ再帰の効用について理解できてないのがちょっと。。
Schemeはリスト構造を基本に構成されているので、木構造のデータ(xmlとか)処理なんかが強いんだろうな、とかそのくらいの認識

Github漁って色んなコードを読んでみるべきかなー。

Schemeで遊ぶ

関数型プログラミング言語”Scheme”で遊んでます。

SchemeはLispの流れを汲んだプログラミング言語。
方々を調べ回ったところによると下記のような特徴を持った言語とのこと。

  • 複数のプログラミングパラダイムをサポート
    手続き型、オブジェクト指向、関数型の3つのパラダイムをサポートしている。

  • レキシカルスコープ(静的スコープ)
    レキシカルスコープを持つ言語。
    最近の言語は大抵レキシカルスコープを持っているので、取り立てて意識する必要はないと思うけれど。
    Emacs Lispや初期のLispがダイナミックスコープで実装されていたようなので、そちらと混同しないように、ということに注意。
  • プログラム内の全てのプロシージャが第一級プロシージャ
    式を関数の引数や戻り値、変数に格納する値として取り扱える。

  • シンプルな構文規則
    閉じ括弧で式を表す、前置記法で演算子を作用させる。ほぼこれだけ。
    しかし、とにかく括弧が多い。。
  • 再帰、再帰、再帰!
    繰り返し処理において再帰を多用する(らしい)。
  • 自動プログラミングやインタプリタ実装、言語処理の実装なんかに向いてる
  • Schemeを通じて特に身につけたいのは再帰処理の実装センスと関数型プログラミングのエッセンスを吸収すること。
    Processingで再帰使って絵を描いたりしたこともあったけど、どうにも再帰使った独自の実装にこぎ着けるところまでは行かなかった。
    というか自分で考えた再帰処理を実装してみると、大抵ヒープを食いつぶしてエラーを吐くという残念な結果にしかならないというトラウマが。。
    再帰は読むのも苦手なので、勘所をつかんでおきたい。

    勉強したいこと

    遅ればせながら今年初投稿。

    昨年は結構更新をサボってしまったので今年はもうちょっと更新頻度を上げたい(とかいいつつもう既に2月も半ば)。
    今年の抱負、とまでは行かないけど方針くらいは決めておきたいので、今勉強したい/やってみたいことをとりあえず挙げてみる。

    • FPGA学習ボードで遊ぶ
      2012_09_09_Terasic_DE1
      昨年の10月くらいに論理回路の勉強用にTerasicのFPGA学習ボード”DE1″(上の写真参照)を買ってみた。チュートリアル本を読んでいろいろいじってたんだけど、これを使ってHDLの勉強してみようかなと思ってる。願わくば自力でCPU実装できるところまで出来たら良いな、とか夢見ていたり。ただ、いきなりそこまで到達するのは難しそうなので、初めはマイコンのペリフェラル(SPIとかI2C)あたりを実装してみようかと考えてます。
      ちなみにこの学習ボード、現在は後述するマイコン関連の開発でロジアナとして使われていたりする(非常にもったいない)。。
    • ARMマイコン使って何か作ってみる
      2012-12-09_12_24_LPC1114
      今までマイコン関連は大昔に大学の研究でAtmel AVRをちょっと触ったのと、Arduinoで簡単な赤外線リモコン制御モジュールみたいなものを作っただけだった。もうちょっとこの分野について深めていきたいなと。メジャーなアーキテクチャであるARMのマイコン使って何か作ってみたい。
      年末年始にNXPのARMマイコンLPC1114とOLEDモジュールで遊んでたのでそれに関してまとめていこう。
    • 関数型プログラミングを勉強してみる
      前二つがハード系だったけどこれはソフト系。
      関数型プログラミングは前々から気になってたので何かしら言語を1つ選んでエッセンスだけでもつかんでおきたい。
      ということで、今はSchemeのチュートリアルを見ながら遊んでます。

    こんなところかな。
    どれもあんまり具体的な目標でないので、尻すぼみになりそうなのが非常にコワいところ。
    今年は上記に関することに関して、取り組んだ内容を出来るだけ書くようにしていきたいなぁと思ってます。