0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Coding Kata]schemeでアナグラムを書いてみた

Last updated at Posted at 2019-02-24

概要

Clean Coder を立ち読みして、コード型の考え方が自分に合ってそうだったのでやってみる。
カタは空手の型から来ているらしい。
基礎練とかそういうの好きなので、こういう地味な基礎練的なのは自分に合っている。と思う。

今回のお題

お題はCodingDojoというサイトから取ってくる。
今回はAnagramをやってみる。

課題

標準入力で単語を受け取って、アナグラムを二つ作って返す。

  • 例) scheme -> chesem, hcemse

使用言語

今回はなんとなく好きなschemeでやってみる。
(シンプルに書けて考え方がわかりやすいと思ったので)

  • 今回使用した環境
    • gauche 0.9.5

ちなみにgaucheはscheme処理系の一つ。
他の処理系(racketとか)より機能が充実してて便利なので、schemeやるならオススメ。らしい。

解いてみる

schemeで受け取った文字列を変換し、アナグラムを作って出力させる関数を作る。

schemeでこれをプログラミングする時、次の2つを考える必要がある。

  1. 受け取った文字列をリスト化する

  2. ランダムにアナグラム化するロジックを考える必要がある。

  3. でリスト化することはそれほど難しくない。
    schemeの文字列はダブルクォートで囲むことで作成できる。

gosh> (define s "scheme")
gosh> (string? s)
# t                             

文字列から一文字づつ取り出してconsしてリスト化しようと思ったけど、
string->listで文字列をリスト化できるのでこっちを使う。

gosh> (define slist (string->list s))
slist
gosh> slist
(#\s #\c #\h #\e #\m #\e)
gosh> (pair? slist)
# t

2.の方がいまいち思いつかない。
乱数を使って文字列から一文字づつ取り出し、consするとかだろうか…
と思ったらすでに関数があった。

ここのshuffleという関数を使う。

これを使うためにuseマクロでgauche.sequenceを取り込む

gosh> (use gauche.sequence)

これはrequireしてimportするのと同じ

gosh> (require "gauche/sequence")
gosh> (import gauche.sequence)

requireすることで、別ファイルの関数を読み込み、評価し、importすることで変数や関数を取り込んで使える様にしている。

gosh> (shuffle slist)
(#\c #\h #\e #\e #\s #\m)
gosh> (shuffle slist)
(#\m #\s #\e #\c #\e #\h)

最後にlistをstringに戻す。listをstringに戻すにはlist->stringを使う

gosh> slist
(#\s #\c #\h #\e #\m #\e)
gosh> (list->string slist)
"scheme"

shuffleした結果をlist->stringで元に戻すにはこう書く。

gosh> (list->string (shuffle slist))
"echmes"
gosh> (list->string (shuffle slist))
"cemehs"

これでできそう。コードを書いてみる。

;; 受け取った文字列をランダムでアナグラム化する
;; shuffle用にmoduleをインポートする
(use gauche.sequence)

(define (anagram str)
  (let ((slist (string->list str)))
    (let ((agm1 (list->string (shuffle slist)))
          (agm2 (list->string (shuffle slist))))
      (list agm1 agm2))))

実行結果は下記の通り

gosh> (anagram "scheme")
("meshec" "ceehsm")

ここでは、返却値をアナグラムした結果のリストにした。(テスト可能なコードにするため)

テストする

さらに、テストコードを書いていく。テストの合格条件は以下2つ。

  1. 返却したリストの要素数が2つであること
  2. リストの文字列が引数のアナグラムであること

1.は簡単。リストの要素数をlengthで調べれば良い。

gosh> (length (anagram "scheme"))
2

2.の方が重要。ここでは、引数とアナグラムの結果両方をソートして比較する。
sortを使えば、文字列もソートしてくれる。

gosh> s
"scheme"
gosh> (sort s)
"ceehms"

アナグラムの結果もsortする。結果は同じになる。

gosh> (define anagram-list (anagram "scheme"))
anagram-list
gosh> anagram-list
("escmeh" "cmsehe")
gosh> (sort (car anagram-list)) ;; "escmeh"をソート
"ceehms"
gosh> (sort (cadr anagram-list)) ;; "cmsehe"をソート
"ceehms"

これらを使ってテストコードを書く。テストにはgauche.testを使う。

testディレクトリを作成して、その中にテストコードを放り込む。ディレクトリ構成はこんな感じ

.
├── anagram.scm
└── test
    └── anagram-test.scm

テストコードはこう書く。

(use gauche.test)
(test-start "anagram")
(load "../anagram.scm")

;; テスト用にアナグラム結果のリストを作る。
(define str "scheme")
(define test-anagram-list (anagram str))

(test-section "anagram-test")

;; アナグラム結果が2つであることをテスト
(test* "number of anagram list" 2 (length test-anagram-list))

;; アナグラムが正しくできていることのテスト
;; 比較用に引数をsortした文字列を用意
(define sorted-str (sort str))

(test* "anagram 1" sorted-str (sort (car test-anagram-list))) ;; 一つ目のテスト
(test* "anagram 2" sorted-str (sort (cadr test-anagram-list))) ;; 二つ目のテスト

(test-end)

テスト結果

gosh> Testing anagram ...
# <undef>
gosh> #t
gosh> str
gosh> test-anagram-list
gosh> <anagram-test>-----------------------------------------------------------------
# <undef>
gosh> test number of anagram list, expects 2 ==> ok
# <undef>
gosh> sorted-str
gosh> test anagram 1, expects "ceehms" ==> ok
# <undef>
gosh> test anagram 2, expects "ceehms" ==> ok
# <undef>
gosh> passed.
0

所感

あんまり大したことやってないけどどうせなのでまとめてみた。
今回はライブラリに頼りすぎてて自分で考えてない感が強いので、次はもっとゴリゴリ書いてみたい。

参考

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?