Kamuycikap - SentenceDataBase

日々の勉強の記録を気分で書き綴るブログ

Emacs Lisp: 等しいリスト

Emacs Lisp: 等しいリスト

リストとリストを比べて同じかどうか調べる関数を定義してみる。
リストの要素は全てシンボルか整数であることと、2つのリストのそれぞれの要素がeqで比較するとtになることと考えます。

(defun equiv (x y)
  (cond
   ((and (null x) (null y)) t)
   ((or (null x) (null y)) nil)
   (t (and (eq (car x) (car y))
           (equiv (cdr x) (cdr y))))))

(equiv '(1 t dog) '(1 t rabbit))  ;; => nil

equivが終了するのはxとyのどちらかがnilになるとき。
条件式(and (null x) (null y))は、xとyの両方がnilであるかどうか調べているのですが、これは引数の2つが同じ長さかどうかを調べています。

条件式(or (null x) (null y)) nil)はどちらか一方がnilであるかどうかを調べています。
そもそもリストの長さが異なる場合は等しくないのでnilを返します。

最終的な条件式(tに行くのは、少なくともxとyにひとつ以上の要素が入っている場合です。
このばあい、xとyが等しくなるのは

  1. xのcar要素とyのcar要素が等しい
  2. xのcdr要素とyのcdr要素が等しい

の両方の条件を満たした時になります。

リストのネストには対応していないので、、、、後日にでも対応したものを作ってみよう。

Emacs Lisp: 連想リスト

Emacs Lisp: 連想リスト

ドット対リストです。
ドット対のcarが指すデータが、cdrで取得する値を連想させるデータになっているリスト。

'((rose . red)(violet . blue)(lily . white))

連想リストを活用する関数「assq」を定義。
CommonLispにassocって名前の関数があったような気が・・・まぁ、気にしない。

(defun assq (key alist)
  (cond
   ((null alist) nil)
   ((eq key (car (car alist))) (car alist))
   (t (assq key (cdr alist)))))

(assq 'rose '((rose . red)(violet . blue)(lily . white))) ;; => (rose . red)

Emacs Lisp: 集合

Emacs Lisp: 集合

ある対象データがある集合の要素かどうか、つまり、特定のシンボルが、リストの中に含まれているかどうか検出。
集合に含まれていれば「t」、そうでなければ「nil」を返す。
集合はリストで表現する。
関数の第一引数は検査対象となるデータ。
第二引数は集合を表すリスト。
要素であるかどうかは「eq」で比較。

(defun memq (x set)
  (cond
   ((null set) nil)
   ((eq x (car set)) t)
   (t (memq x (cdr set)))))

(memq 'dog '(rat2 pig rat))  ;; => nil

特定のリストがリストの中に含まれているかどうか検出する関数も作ってみる。

(defun subset (set1 set2)
  (cond
   ((null set1) t)
   ((null (memq (car set1) set2)) nil)
   (t (subset (cdr set1) set2))))

(subset '(3 2 1) '(1 2 3)) ;; => t

RaspberryPiに小型LCDを接続してみた

RaspberryPi Mini Color LCD Serial Module

大阪でんでんタウンの「Arduinoファンクラブ」に参加してきました。
そこで安く譲っていただいたカラーLCDのセットアップ手順。

LCDボード概要

ST7756R搭載の160×128ドットカラーTFTLCDモジュールとFTDI FT230X搭載のRaspberryPiボード。

セットアップの順番

  1. RaspberryPiがネットワークに接続できるようにしておく
  2. RaspberryPi起動(Raspbian)
  3. SPIセットアップ
  4. LCDモジュールセットアップ
  5. LCD起動
  6. 解像度の設定
  7. 画面全体に出したい場合の設定

RaspberryPiをネットワークに接続

これは・・・・実際に動かす環境に依存しますね。
部屋のLANケーブルを差し込むだけでオッケーだったりします。
初めての建物や部屋を訪れる場合は、優先ケーブルを差し込むのがめんどくさくなくて良いです。
無線の設定を公開している場所では・・・・そもそも、RaspberryPiにはディスプレイが存在していないので、VNCか何かでリモート接続して動かす方法で対応とか・・・かな。

RaspberryPiの起動

LCDの接続をお忘れなく。
電源スイッチはついていないので、電源ケーブルを差し込むだけ。

SPIセットアップ

$ sudo nano /etc/modules

最下行に「spidev」を追加する

$ sudo nano /etc/modprobe.d/raspi-blacklist.conf

このファイルで、「blacklist spi-bcm2708」の行頭に#を追加してコメントアウトする。

$ sudo reboot

再起動!!

LCDモジュールセットアップ

$ git clone https://github.com/yishii/RaspberryPi_lcdfbcp.git
$ cd ./RaspberryPi_lcdfbcp
$ cd ./lcdfbcp
$ make
$ sudo make install

これで、インストール完了
gitでダウンロードした状態でのディレクトリ名は臨機応変に変わる可能性あり。

LCD起動

sudo lcdfbcp -m st7735r &

これでLCDが表示されるはず。

解像度の設定

sudo nano /boot/config.txt

このファイルに

framebuffer_width=320
framebuffer_height=256

この二行を追加すると、解像度が変わるので、視力検査のような状態から見れる状態にかわる。
追加場所は・・・・framebufferで文字列検索すると、それらしい場所がヒットする。

画面全体に出したい場合の設定 <- なぜかこれうまくいかなかった

sudo raspi-config

メニューが出てくるので

  1. Advanced Options -> Overscan ->

の順番で操作

起動時に有効にする方法

$ nano /etc/inittab

ファイル先頭あたりに追加

if::respawn:/user/bin/lcdfbcp -m st7735r

これでおっけー


優良アダルトサイト紹介の最終形態!!MaxInfo

Emacs Lisp: 再帰とリスト

Emacs Lisp: 再帰とリスト

関数引数として、リストが指定された場合、全て再帰的に処理するには?

再帰の定石(リストバージョン)
●終了条件を調べ、終了なら初期値を返す
●リストの最初の要素に対して処理をする
●処理結果を引数として自分自身を呼び出す

渡されたリストの要素を全て加算する。

(defun sum (l)
  (cond
   ((null l) 0)
   (t (+ (car l) (sum (cdr l))))))

(sum '(1 3 7)) ;; => 11


リストの要素を置き換える関数replを作る

(defun repl (lst old new)
  (cond
   ((null lst) nil)
   ((eq (car lst) old)
    (cons new (repl (cdr lst) old new)))
   (t (cons (car lst) (repl (cdr lst) old new)))))

(repl '(dog pig dog) 'dog 'rat) ;; => rat pig rat

関数del
第二引数のリストの中から、第三引数のxと同じ要素を全て削除する。

(defun del (x lst)
  (cond
   ((null lst) nil)
   ((eq (car lst) x) (del x (cdr lst)))
   (t (cons (car lst) (del x (cdr lst))))))

(del 'pig '(rat pig dog pig))

Emacs Lisp: 再帰について

階乗を作る

再帰処理で階乗を作る

再帰の定石
●終了条件を調べ、終了なら初期値を返す
●引数に対して処理をする
●処理結果を引数として自分自身を呼び出す
(defun factorial-test (n)
  (cond
   ((zerop n) 1)
   (t (* n (factorial (1- n))))))

(factorial 4)


差が1の等差数列の和

(defun arith-prog-test (n)
  (cond
   ((zerop n) 0)
   (t (+ n (arith-prog-test (1- n))))))

(arith-prog 10)

比が2の等比数列の和
=> f(n) = 2^n + f(n - 1), f(0) = 1
終了条件がf(0) = 1で、処理が2^n + f(n - 1)なので

(defun geom-prog1-test (n)
  (cond
   ((zerop n) 1)
   (t (+ (expt 2 n) (geom-prog1-test (1- n))))))

(geom-prog1-test 3)

別の式で表現
=> f(n) = 1 + 2 x f(n - 1), f(0) = 1

(defun geom-prog2-test (n)
  (cond
   ((zerop n) 1)
   (t (+ 1 (* 2 (geom-prog2-test (1- n)))))))

(geom-prog2-test 3)


フィボナッチ数列を表現
n番目のフィボナッチ数列の値を表示する関数
終了条件が2つあります。f(1) = 1, f(2) = 1
処理部分はこれ。f(n - 1) + f(n - 2)

=> f(n) = f(n - 1) + f(n - 2), f(1) = 1, f(2) = 1

  • > 1,1,2,3,5,8,13,21,34.....
(defun fibonacci (x)
  (cond
   ((= x 1) 1)
   ((= x 2) 1)
   (t (+ (fibonacci (- x 1))
         (fibonacci (- x 2))))))

(fibonacci 5)

Emacs Lisp: 関数について  andとorを使ってみる

and と or

Emacs Lisp メモ

;; 引数がリストかどうかを評価
(defun listp (x)
  (or (null x)
      (consp x)))

(setq kin '(a b c d))

(listp kin)         ; => t


閏年計算をandとorで書いてみる。
4で割り切れたら閏年
ただし100で割り切れたら普通の年
もし100で割り切れたとしても、400で割り切れたら閏年

(defun leap (n)
  (cond
   ((and (= (% n 4) 0)
         (or (= (% n 400) 0)
             (/= (% n 100) 0)))
    t)
   (t nil)))

(leap 2012)  ;; => t

さらに簡略すると・・・・
こうなります。

(defun leap (n)
  (and (= (% n 4) 0)
        (or (= (% n 400) 0)
            (/= (% n 100) 0))))

(leap 2012)
関数定義の秘訣
- condを使って処理を書く
- その後に、簡略できそうなら簡略する
- 簡略するときはandとorを活用する。