ラベル programing の投稿を表示しています。 すべての投稿を表示
ラベル programing の投稿を表示しています。 すべての投稿を表示

2014年8月14日木曜日

シェルスクリプトのif文

あるコマンドの戻り値で条件分岐したい時に以下の様に書いているシェルスクリプトを結構な頻度で見掛けます。例えばgrepして特定の行が見付かった時なんかです。

grep -i "error" $LOGFILE >/dev/null 2>&1
ret=$?
if [ $ret -eq 0 ]
then
  ;; grepで目的の行が見付かった時の処理
fi

Bシェル系で直前に実行したコマンドの戻り値が$?に入る事を利用している訳ですが、この書き方は無駄ですしバグが混入し易いですよね。ifの条件も分かり難い。例えば後日別の人がこのシェルスクリプトを修正する時に、以下の様に変更したら期待した動作をしなくなります。

grep -i "error" $LOGFILE >/dev/null 2>&1
echo $LOGFILE ;; for print debug
RET=$?
if [ $RET -eq 0 ]
then
  ;; grepで目的の行が見付かった時の処理
fi

意外と知らない人が多いみたいなのですが、if文の後の開き大括弧"["testコマンドの糖衣構文です。which -a "["とすると/usr/binあたりに"["コマンドがある筈です。

if自体は直後のコマンドの戻り値が0かそれ以外かを判定して、then節かelse節を実行する文というだけなので、ifの直後に必ず大括弧[]がくる必要はありません。ただifの判定文にtestコマンドを使う事が頻繁にあるので糖衣構文として[]が用意されていて、それを判定文に使うシェルスクリプトの記法が一般化し過ぎているだけです。なので前記のコードは以下の様に書く事が出来ます。

if grep -i "error" $LOGFILE >/dev/null 2>&1
then
  ;; grepで目的の行が見付かった時の処理
fi

これだとifの条件が一目で分かるしバグの混入も減るでしょう。

2014年4月25日金曜日

【今日の読書】プログラミングGauche [700]

書名
プログラミングGauche
著者
Kahuaプロジェクト
監修
川合 史郎
出版
オライリー
価格
3200円
ISBN
978-4-87311-348-7

 本日読了。これは素晴しい本ですね。Schemeを勉強したいなら、最初に読む べき本と言って良いでしょう。全体を通してかなり実用的・実践的に書かれて いると思います。2008年に出た本なので、最新版のGauche/Kahuaに合わせた内 容で第2版とか出ないですかねえ。出たらすぐ買うのだけど。

2014年4月5日土曜日

プロジェクト・オイラー 001-008

 勉強がてらProject Eulerをやっています。まず1から8まで。使用している言語/処理系はScheme/Gaucheです。


;; Project Euler
;; http://odz.sakura.ne.jp/projecteuler/


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Problem 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; 指定した自然数 n で割り切れるかを判定する関数を創る関数
;; 戻り値 1引数の関数
;; 引数 1つの自然数 (n)
(define (mod-n n)
  (if (zero? n)
      (error "Natural number required, but got zero.")
      (lambda (x)
 (if (zero? (modulo x n))
     #t
     #f))))

;; 指定した2つの自然数からなる集合の環集合を返す
;; 戻り値 自然数のリスト
;; 引数 自然数からなる2つのリスト
(define (union l1 l2)
  (cond
   ((null? l1) l2)
   ((null? l2) l1)
   (else
    (lset-union eq? l1 l2))))

;; 引数nが3で割り切れるか判定する
;; 戻り値 真偽値
;; 引数 自然数 n
(define (mod3? n)
  ((mod-n 3) n))

;; 引数nが5で割り切れるか判定する
;; 戻り値 真偽値
;; 引数 自然数 n
(define (mod5? n)
  ((mod-n 5) n))

(mod5? 10)
(mod5? 11)

;; プロジェクトオイラーの問題1のメイン
;; 与えられた自然数からなるリストの内、3の倍数と5の倍数の総和を求める
;; 戻り値 1つの自然数(3の倍数と5の倍数の総和)
;; 引数 自然数からなる1つのリスト l
(define (pj-euler1 l)
  (cond
   ((null? l) 0)
   (else
    (fold + 0
   (union 
    (filter mod3? l) 
    (filter mod5? l))))))

(pj-euler1 (iota 1000))
(pj-euler1 (iota 10))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Problem 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; n項までのフィボナッチ数を求める
;; 戻り値 自然数(フィボナッチ数)
;; 引数 自然数 n
(define (fibo n)
  (cond
   ((zero? n) 1)
   ((zero? (- n 1)) 2)
   (else
    (+ (fibo (- n 1)) (fibo (- n 2))))))

(time (fibo 100))

;; CPS版フィボナッチ数
(define (fibo/cps n cont)
  (cond
   ((zero? n) (cont 1))
   ((zero? (- n 1)) (cont 2))
   (else
    (fibo/cps (- n 1) 
       (lambda (y) (fibo/cps (- n 2) 
        (lambda (z) (cont (+ y z)))))))))

(time (fibo/cps 100 (lambda (x) x)))

;; tati
(define (fib-i n)
  (if (or (zero? n) (= n 1))
      (values 1 1)
      (receive (cur prev)
   (fib-i (- n 1))
 (values (+ cur prev) cur))))

;;動的計画法版フィボナッチ数
(define (fibo/dyna n)
  (let loop ((a 1) (b 2) (i n))
    (let1 c (+ a b)
      (if (<= i 2)
   c
   (loop b c (- i 1))))))


;; n以下のフィボナッチ数の内偶数の物を返す
(time (let loop ((n 0) (ret 0))
  (let1 f (fibo/dyna n)
    (if (< f 4000000)
 (if (even? f)
     (loop (+ n 1) (+ ret f))
     (loop (+ n 1) ret)))
 ret)))
   

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Problem 3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(use srfi-1)

;; 与えられた自然数 n 以下の素数のリストを返す
;; 戻り値 n 以下の素数のリスト
;; 引数 n 閾値となる自然数
(define (primes n)
  (let loop ((l (unfold (cut > <> n) values (cut + <> 2) 3))
             (prime-list '(2)))
    (let1 m (car l)
      (if (> (expt m 2) n)
   (append (reverse prime-list) l)
   (loop (remove (lambda (x) (zero? (modulo x m))) l) (cons m prime-list))))))

(define val 600851475143)
(define plist (reverse (primes (truncate (sqrt val)))))
(
(define (pj-euler3 n ls)
  (cond
   ((zero? n) 0)
   ((null? ls) (error "list required, but got ()"))
   (else
    (if (zero? (modulo n (car ls)))
 (car ls)
 (pj-euler3 n (cdr ls))))))

(time (pj-euler3 val (reverse (primes (truncate (sqrt val))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Problem 4
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use srfi-13)

(* 999 999)
(string-reverse (number->string 123))

;; 与えられた数が回文数か判定する関数
(define (palindromic? n)
  (cond
   ((zero? n) #t)
   ((< n 10) #t)
   (else
    (let* ((stringed-n (number->string n))
   (reversed-n (string-reverse stringed-n)))
      (string=? stringed-n reversed-n)))))

(define pal 

;; 入力した自然数の平方根が整数になるか調べる関数
(define (sq-int? n)
  (integer? (sqrt n)))

(time (take-right (filter sq-int? (filter palindromic? (iota (- (* 999 999) (* 100 100)) (* 100 100)))) 1))


(sqrt 10201)

  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Problem 5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define max-v (lcm 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20))

(define (lcm? n)
  (if (zero? n) #f
   (and
    (zero? (modulo n 20))
    (zero? (modulo n 19))
    (zero? (modulo n 18))
    (zero? (modulo n 17))
    (zero? (modulo n 16))
    (zero? (modulo n 15))
    (zero? (modulo n 14))
    (zero? (modulo n 13))
    (zero? (modulo n 12))
    (zero? (modulo n 11)))))

(time (length (iota max-v -20)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Problem 6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use srfi-1)

(define n 100)

(define (pj-euler6 n)
  (- (expt (apply + (iota n 1)) 2)
     (apply + (map (lambda (x) (* x x)) (iota n 1)))))

(time (pj-euler6 n))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Problem 7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define idx 10001)

(time (list-ref (primes (* 50 idx)) idx))

(use util.stream)
(use srfi-42)
(define (primes-shiro)
  (stream-filter (lambda (k)
     (not (any?-ec (: j 3 (sqrt k) 2) (zero? (modulo k j)))))
   (stream-cons 2 (stream-iota -1 3 2))))

(time (stream->list (stream-take (primes-shiro) idx)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Problem 8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define quant 7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450)

(define (integer->list i)
  (letrec ((i->rl (lambda (j)
      (cons (modulo j 10)
     (if (< j 10)
         '()
         (i->rl (quotient j 10)))))))
    (reverse (i->rl i))))

(define (1st l)
  (car l))
(define (2nd l)
  (car (cdr l)))
(define (3rd l)
  (car (cdr (cdr l))))
(define (4th l)
  (car (cdr (cdr (cdr l)))))
(define (5th l)
  (car (cdr (cdr (cdr (cdr l))))))

(define l (integer->list 7316717653133062491922511967442657474))

(define (pj-euler8 l)
  (cond
   ((> 5 (length l)) '())
   (else
    (cons (* (1st l) (2nd l) (3rd l) (4th l) (5th l)) (pj-euler8 (cdr l))))))
  
(time (apply max (pj-euler8 (integer->list quant))))

2014年4月1日火曜日

【今日の読書】Scheme修行 [698]

書名
Scheme修行
著者
Daniel P. Friedman and Matthias Felleisen
訳者
元吉 文男、横山 晶一
出版
オーム社
価格
2800円
ISBN
978-4-274-06826-3

 Scheme手習いの続編です。章立ても、手習いが1章から10章となっていて本書は11章から始まります。手習いの「はじめに」には「この本の内容を2回以下で理解出来ると思わない事」という注意がありました。本書では「5回以下で理解出来ると思わない事」というより難しい事を示唆する注意になっています。

 僕は手習いは2回読んで、Yコンビネータ以外は何とか理解できたかなという程度でした。修行も2回読んだのですが、やはり手習いに比べると難解な部分が多く理解出来ていない割合が多いですね。継続は概念そのものは理解は出来るものの、活用方法がよく解りませんでした。継続については苦戦したので

この当たりを合わせて読んで理解の助けにしました。(Shiroさんのなんでも継続は続きがあるみたいなので是非読みたいですね)

 Schemeの入門書として前書と合わせてお勧めされる事の多い本だと思うのですが、決して親切な本では無いなというのが正直な印象です。理解に苦しむ所が出てきても、その理解出来ない状況を突破する為の助けが全然無いので、淡泊な本文を必死に読むのですが本当に難しい部分はやっぱり読んでも分からないわけです。なんかedのエラーメッセージの様な文章だなと。

2014年2月27日木曜日

【今日の読書】プログラミングの基礎 [695]

書名
プログラミングの基礎
著者
浅井 健一
出版
サイエンス社
価格
2300円
ISBN
978-4-7819-1160-1

 本日読了。これは良書ですね。プログラミングの初学者には大変おすすめ です。書籍中で利用している言語はOCamlというややマイナな(関数型)言語です が、言語仕様とは分離したプログラミングの本質的な部分で役立つ内容ばかり です。