Comment detail

与えた条件を満たす候補 (Nested Flatten)
イマイチ。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#light
type ListBuilder () =
    member l.Bind (v,f) = List.concat (List.map f v)
    member l.Return x = [x]
    member l.Let(v,f) = f v

let guard c = if c then [()] else []

let doList = new ListBuilder()

let rec all_comb = function
    | 0 -> [[]]
    | n -> doList { let! rest = all_comb (n-1)
                    let! result = [(true::rest);(false::rest)]
                    return result }

let num_args cmds =
    List.filter ((<>) "not") cmds
    |> List.length
    |> (+) 1

let rec satisfy (cmds:string list) (bools:bool list) =
    match cmds,bools with
    | [],b::[]            -> b
    | "not"::[],b::[]     -> not b
    | "not"::cs,b::bs     -> satisfy cs ((not b)::bs)
    | "and"::"not"::cs,b::b'::bs -> satisfy cs ((b && (not b'))::bs)
    | "or"::"not"::cs,b::b'::bs  -> satisfy cs ((b || (not b'))::bs)
    | "and"::cs,b::b'::bs -> satisfy cs ((b && b')::bs)
    | "or"::cs,b::b'::bs  -> satisfy cs ((b || b')::bs)

let get_combs cmds =
    doList { let! cont = all_comb (num_args cmds)
             do! guard (satisfy cmds cont)
             return cont }

do get_combs ["and";"or";"not";"and"]
   |> (print_any >> print_newline)
nskj77さんのコードを参考に修正してみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#light
type ListBuilder () =
    member l.Bind (v,f) = List.concat (List.map f v)
    member l.Return x = [x]
    member l.Let(v,f) = f v

let guard c = if c then [()] else []

let doList = new ListBuilder()

let rec satisfy prev bs cmds =
    match bs, cmds with
    | b::[], _     -> prev b
    | b::bs, cmd::cmds ->
            match cmd with
            | "not" -> satisfy prev ((not b)::bs) cmds
            | "and" -> satisfy ((&&) (prev b)) bs cmds
            | "or"  -> satisfy ((||) (prev b)) bs cmds

let rec all_comb = function
    | 0 -> [[]]
    | n -> doList { let! rest = all_comb (n-1)
                    let! result = [(true::rest);(false::rest)]
                    return result }

let get_combs cmds =
    let len = 1 + (List.length (List.filter ((<>) "not") cmds))
    doList { let! bs = all_comb len
             do! guard (satisfy (fun x -> x) bs cmds)
             return bs }

do get_combs ["and";"or";"not";"and"]
   |> (print_any >> print_newline)
さらにモナドを使わずに書き直してみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#light
let rec satisfy prev bs cmds =
    match bs, cmds with
    | b::[], _     -> prev b
    | b::bs, cmd::cmds ->
            match cmd with
            | "not" -> satisfy prev ((not b)::bs) cmds
            | "and" -> satisfy ((&&) (prev b)) bs cmds
            | "or"  -> satisfy ((||) (prev b)) bs cmds

let rec all_comb = function
    | 0 -> [[]]
    | n -> [ for res in all_comb (n-1) ->> [true::res;false::res] ]

let get_combs cmds =
    let len = 1 + (List.length (List.filter ((<>) "not") cmds))
    [for bs in all_comb len when satisfy (fun x -> x) bs cmds -> bs]

do get_combs ["and";"or";"not";"and"]
   |> (print_any >> print_newline)

Index

Feed

Other

Link

Pathtraq

loading...