Aパターンマッチ指向プログラミング問題集

パターンマッチ指向プログラミングを体験していただくために,クイズ形式で問題を用意した.

member関数

下記の空白をうめてmember関数を完成させよ.

def member x xs :=
  match xs as list eq with
  | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}` -> True
  | _ -> False

member 1 [1,2,3,4]
-- True

member 5 [1,2,3,4]
-- False

concat関数

下記の空白をうめてconcat関数を完成させよ.

def concat xss :=
  matchAllDFS xss as `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}` with
  | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}2\vphantom{0}\hspace{5em}}` -> `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}3\vphantom{0}\hspace{5em}}`

concat [[1,2],[3],[4,5]]
-- [1,2,3,4,5]

四つ子素数

四つ子素数を列挙するプログラムを記述せよ. 四つ子素数とは,\((p,p + 2,p + 6,p + 8)\)という形の素数の四つ組のことをいう.

take 4 (matchAll primes as list integer with
        | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}` -> (p, p + 2, p + 6, p + 8))
-- [(5, 7, 11, 13), (11, 13, 17, 19), (101, 103, 107, 109), (191, 193, 197, 199)]

差が\(6\)の素数のペア

下記の空白をうめて素数のペア\((p, p+6)\)を抽出せよ.

take 6 (matchAll primes as list integer with
        | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}` -> (p, p + 6))
-- [(5, 11), (7, 13), (11, 17), (13, 19), (17, 23), (23, 29)]

intersect関数

下記の空白をうめて,2つのコレクションの共通部分を抽出するintersect関数を完成させよ.

def intersect xs ys :=
  matchAllDFS (xs, ys) as `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}` with
  | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}2\vphantom{0}\hspace{5em}}` -> `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}3\vphantom{0}\hspace{5em}}`

intersect [1,2,3,4] [2,4,5]
-- [2,4]

difference関数

下記の空白をうめて,第二引数のコレクションに含まれていない第一引数のコレクションの要素のみを抽出するdifference関数を完成させよ.

def difference xs ys :=
  matchAllDFS (xs, ys) as `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}` with
  | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}2\vphantom{0}\hspace{5em}}` -> `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}3\vphantom{0}\hspace{5em}}`

difference [1,2,3,4] [2,4,5]
-- [1,3]

doubles関数

コレクション中にちょうど\(2\)回現れる要素のみを抽出するdoubles関数を完成させよ.

def doubles xs :=
  matchAllDFS xs as `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}` with
  | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}2\vphantom{0}\hspace{5em}}` -> `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}3\vphantom{0}\hspace{5em}}`

doubles [1,2,3,2,1,1,4,5,3]
-- [2,3]

tails関数

tails関数をパターンマッチを使って定義せよ. ループ・パターンを使う回答とそうでない回答の2つを考えてみよ.

def tails xs :=
  matchAll xs as list something with
  | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}`
  -> ts

tails [1,2,3,4]
-- [[1, 2, 3, 4], [2, 3, 4], [3, 4], [4], []]

多重集合の同値性チェック

多重集合の同値性をチェックする2引数述語equalMultisetをパターンマッチを使って定義してみよ.

def equalMultiset xs ys :=
  match (xs, ys) as (list eq, multiset eq) with
  | ([], [])
  -> True
  | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}`
  -> equalMultiset xs' ys'
  | _
  -> False

equalMultiset [1,1,2] [2,1,1]
-- True

equalMultiset [1,1,2] [1,2,2]
-- False

ループ・パターンを使って再帰関数を使わずに書いてみよ.

def equalMultiset xs ys :=
  match (xs, ys) as (list eq, multiset eq) with
  | `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}2\vphantom{0}\hspace{5em}}`
  -> True
  | _
  -> False

ジョーカーの存在を考慮するポーカーの役判定

33.2.2節のポーカーの役判定のためのパターンマッチ(poker関数)の実装を一切変更せずに,cardマッチャーの定義だけを変更して,ジョーカーの存在を考慮するポーカーの役判定をできるようにせよ.

def card := matcher
  | card $ $ as (suit, mod 13) with
    | Card $s $n -> [(s, n)]
    | Joker -> `\fcolorbox{black}[gray]{1.0}{\vphantom{0}\hspace{5em}1\vphantom{0}\hspace{5em}}`
  | $ as something with
    | $tgt -> [tgt]

poker [Card Spade 5, Card Spade 6, Joker, Card Spade 8, Card Spade 9]
-- "Straight flush"
poker [Card Spade 5, Card Diamond 5, Joker, Card Club 5, Card Heart 7]
-- "Four of a kind"
この本を別の言語で読む: English, 日本語