GaucheでFizzBuzzその2


前に作ったFizzBuzzをもうちょっとSchemeぽくしてみる.

以前は「関数型言語⇒再帰呼び出し」と思ってたので,再帰呼び出しで実装したけど,mapとか使えばさらにすっきり書ける.

というわけで.

#!/usr/bin/env gosh
(use srfi-1)
(define (fizzbuzz max)
(map (lambda (x)
(cond
[(= (modulo x 15) 0 ) "FizzBuzz"]
[(= (modulo x 3) 0 ) "Fizz"]
[(= (modulo x 5) 0 ) "Buzz"]
[else x]
)
)
(iota max 1)
)
)
(define (main args)
(print (fizzbuzz 30))
)

1から始まるmax個のリストをiotaで作り,それの各要素に対してmapでlambda式を適用していっている.

Gaucheで文字列操作できるの?


というわけでいろいろ試してみた.

まずはじめに文字の扱い.

文字は#\のあとにその文字を書く.h,e,l,l,oからなるリストは,

'(#\h #\e #\l #\l #\o)

でできる.

で,文字列.

文字列はほかのプログラミング言語と一緒で""で囲めばよい.helloという文字列は

"hello"

で表せる.

複雑な処理をしようと思うと,基本的にはsrfi-13という文字列ライブラリがあるので,それを使えばよい.

というわけで,最初に

(use srfi-13)

これでライブラリの読み込みができた.

で,

(string->list "hello")

とすると,文字列⇒リストの変換.

(list->string '(#\h #\e #\l #\l #\o)) ; "hello"

とすると,リスト⇒文字列の変換.直観的.

大文字,小文字の置き替えは,

(character-upcase #\a)     ; A
(string-upcase "hello")    ; HELLO
(character-downcase #\A)   ; a
(string-downcase "HELLO")  ; hello

でOK.

頭文字だけ大文字にする時は

(string-titlecase "hello world")   ;Hello World

でOK.

部分文字列の取り出しは

(substring "Hello World!" 6 11)    ;World

で,6文字目から11文字目の前まで取り出せる.

連結,分割も簡単

(string-append "hello" "world")       ; "hello world"
(string-join ("hello" "world") ", ")  ; "hello, world"
(string-join ("hello" "world") "||")  ; "hello||world"
(string-split "hello world" " ")      ; ("hello" "world")

正規表現は,#/正規表現/で表せる.

その正規表現にマッチするかどうかのテストは

(rxmatch #/test/ "hellotestworld")

マッチした結果を使って何かをしたいときは上のrxmatchを使って

(rxmatch-if (rxmatch #/test/ "hellotestworld") (str) str "not match")

これは,マッチすればマッチした部分を(str)に入れて,strを,そうでなければ"not match"を返す.要は if-then-elseな文.

マッチした文字列を置き換えたいときは

(string-replace #/test/ "hellotestworld" " TEST ") ; hello TEST world"

でOK.

文字列まわりの関数で使いそうなやつを一通りおぼえた.

バブルソートは諦めて選択ソート


さっきのやつを修正した.今回はちゃんと動いているぽい.

#!/usr/bin/env gosh
(define (selectsort listdata)
(define (exceptmax lst)
(if (pair? lst)
(if (= (fold max -1 lst) (car lst))
(cdr lst)
(append (list (car lst)) (exceptmax (cdr lst)))
)
()
)
)
(if (pair? listdata)
(append (selectsort (exceptmax listdata)) (list (fold max -1 listdata)))
listdata
)
)
(define (main args)
(let ((inputlist `(9 0 1 8 2 7 3 6 4 5)))
(print inputlist)
(print (selectsort inputlist))
)
)

Gauche3日目


注:このプログラムは間違えています.

昨日のBubbleSortをもうちょっと修正.

letを使って複数出てくる(bsort-swap (car lstdata) (cdr lstdata))をまとめた.

#!/usr/bin/env gosh
(define (bsort lstdata)
(define (bsort-swap x lst)
(if (pair? lst)
(if (< x (car lst))
(append (list x) lst)
(append (list (car lst)) (bsort-swap x (cdr lst)))
)
(list x)
)
)
(if (pair? lstdata)
(let (( sortlist (bsort-swap (car lstdata) (cdr lstdata))))
(append (list (car sortlist)) (bsort (cdr sortlist)))
)
lstdata
)
)
(define (main args)
(let ((inputlist `(9 0 1 8 2 7 3 6 4 5)))
(print inputlist)
(print (bsort inputlist))
)
)

またちょっとすっきりした.

さらにGauche2日目


defineの中でさらにdefineできるらしい.ある関数Aからしか呼ばれないようなローカルな関数(?)Bを作る場合は,関数Aの定義内でBを定義する方が良い.

そこで,バブルソートを修正.

注:このプログラムは間違えています.

#!/usr/bin/env gosh
(define (bsort lstdata)
(define (bsort-swap x lst)
(if (pair? lst)
(if (< x (car lst))
(append (list x) lst)
(append (list (car lst)) (bsort-swap x (cdr lst)))
)
(list x)
)
)
(if (pair? lstdata)
(
append (list (car (bsort-swap (car lstdata) (cdr lstdata))))
(bsort (cdr (bsort-swap (car lstdata) (cdr lstdata))))
)
lstdata
)
)
(define (main args)
(let ((inputlist `(9 0 1 8 2 7 3 6 4 5)))
(print inputlist)
(print (bsort inputlist))
)
)

すっきりしたかな….(ソーティングがこれでいいのかは未だ疑問)

Gauche2日目


昨日の件で,HelloWorldを書いたんですが,どうもlambdaとかいらないらしい.

そこで,書き直してみた.

#!/usr/bin/env gosh
(define (HelloOnce)
(print "Hello World!")
)
(define (HelloNTimes x)
(if (> x 0)
(cons
(HelloNTimes (- x 1))
(print x ":Hello World!")
)
)
)
(define (main args)
(print "***Print once***")
(HelloOnce)
(print "***Print 10 times***")
(HelloNTimes 10)
)

ちょっとすっきり.でも何かさみしい.

Gaucheでバブルソート


FizzBuzzしたし,とりあえずソーティングでもやってみるか~と思ってバブルソートしてみた.

ら,鬼のようにむずかった(涙

Gauche1日目にして無茶した.

注:このプログラムは間違えています.

#!/usr/bin/env gosh
(define bsort-swap
(lambda (x lst)
(if (pair? lst)
(if (< x (car lst))
(append (list x) lst)
(append (list (car lst)) (bsort-swap x (cdr lst)))
)
(list x)
)
)
)
(define bsort
(lambda (lstdata)
(if (pair? lstdata)
(append
(list (car (bsort-swap (car lstdata) (cdr lstdata))))
(bsort (cdr (bsort-swap (car lstdata) (cdr lstdata))))
)
lstdata
)
)
)
(define (main args)
(let ((inputlist `(9 0 1 8 2 7 3 6 4 5)))
(print inputlist)
(print (bsort inputlist))
)
)

こんなんでいいのかな?もっとうまく書けそうな気もするが.まあいいか.初日だし.

GaucheでFizzBuzz


だいたい分かってきた.

で,FizzBuzz.3の倍数のときにFizz,5の倍数のときにBuzz,3と5の倍数のときにはFizzBuzzを表示するプログラム.

#!/usr/bin/env gosh
(define fizzbuzz
( lambda (x)
(if (> x 1) (fizzbuzz (- x 1)))
(cond
((= ( modulo x (* 3 5)) 0) (print x ":FizzBuzz"))
((= ( modulo x 3 ) 0 ) (print x ":Fizz"))
((= ( modulo x 5 ) 0) (print x ":Buzz"))
(else (print x))
)
)
)
(define (main args)
(fizzbuzz 30)
)

適当ですが.