Clojureのvectorは、順序を持ち、インデックスでアクセスでき、0個以上の値からなる不変のコレクションです。つまり、いったん作成されたベクターは変更できません。ベクターを操作する関数は新しいベクターを返し、元のベクターは変わりません。ベクターに入れる値は、型が異なっていてもかまいません。ベクターは次のように定義できます。
(def empty [])
(def single-value [5])
(def single-value-alternative (vector 5))
(def three-values [1 "a" "b"])
要素は、インデックスを使ってベクターから取り出せます。Clojureのベクターは0から始まるので、最初の要素のインデックスは常に0です。
(def numbers [2 3 5])
;; Read value from vector
(get numbers 2)
;;=> 5
;; Update value in vector
(assoc numbers 2 9)
;;=> [2 3 9]
元のベクターは変わりません。
numbers
;;=> [2 3 5]
更新後の値を覚えておくには、その値をそのまま渡していくか、varに束縛しておく必要があります。
(def updated-numbers
(assoc numbers 2 9))
(get updated-numbers 2)
;;=> 9
熱心なバードウォッチャーであるあなたは、この7日間に庭へやって来た鳥の数を記録しています。
タスクは6つあり、どれも庭に来た鳥の数を扱うものです。
比較のために、先週の記録をいつも手元に残しています。先週の記録は0、2、5、3、7、8、4でした。先週の記録を入れたベクターを作成してください:
last-week
;;=> [0 2 5 3 7 8 4]
today関数を実装して、今日庭に来た鳥の数を返してください。鳥の数は日ごとに並んでいて、最初の要素が最も古い日の数、最後の要素が今日の数です。
(def birds-per-day [2 5 0 7 4 1])
(today birds-per-day)
;;=> 1
inc-bird関数を実装して、今日の数を増やしてください:
(inc-bird birds-per-day)
;;=> [2 5 0 7 4 2]
day-without-birds?述語関数を実装して、庭に鳥が一羽も来なかった日があればtrueを、そうでなければfalseを返してください:
(day-without-birds? birds-per-day)
;;=> true
n-days-count関数を実装して、週の最初から庭に来た鳥の数を返してください。ただし、数えるのは週の最初から指定された日数分だけにします。
(n-days-count birds-per-day 4)
;;=> 14
日によっては、ほかの日より忙しいこともあります。忙しい日とは、庭に5羽以上の鳥が来た日のことです。
busy-days関数を実装して、忙しい日の数を返してください:
(busy-days birds-per-day)
;;=> 2
この1年で、同じ変わったパターンになる週があることに気づきました。それは、鳥の数が1羽と0羽を交互に繰り返すパターンです。odd-week?関数を実装して、今週の鳥の数のパターンがこの変わったパターンに一致すればtrueを返してください:
(odd-week? [1 0 1 0 1 0 1])
;;=> true