algorithm - F# syntax with sets and updating -
in f# im trying remove occurence in set if condition met, it's not working way i'd to.
the trick removing elements set function set.filter
, takes function argument - filter
feed in every value of set function, , add new set if function returns true
. example implementation might be:
let filter f (original : set<'t>) = set [ value in original if f value yield value ]
which has type filter : ('t -> bool) -> set<'t> -> set<'t>
. example of using be
filter (fun x -> x % 2 = 0) (set [ 1; 2; 3; 4; 5 ])
this filters set numbers, return value set [ 2; 4 ]
.
i'm not entirely sure problem you're having exactly, here solution game mastermind using knuth's algorithm, albeit random starting guess, rather choice of "1122".
i thought quite nice exercise, though writing checkguess
function hardest part of me!
you can run test opening in f# interactive running function playmastermind ()
, show guesses.
/// colours pegs allowed be. type peg = blue | red | green | yellow | purple | brown /// shared instance of system.random () class random number /// generators. let private rnd = new system.random () /// make random set of 4 peg colours. let randomguess () = let randompeg () = match rnd.next(1, 6) | 1 -> blue | 2 -> red | 3 -> green | 4 -> yellow | 5 -> purple | 6 -> brown | _ -> failwith "random number generation failed." [ randompeg (); randompeg (); randompeg (); randompeg () ] /// iterate on colours make of possible combinations. let allpossibles = let colours = [ blue; red; green; yellow; purple; brown] set [ in colours b in colours c in colours d in colours -> [ a; b; c; d ] ] /// number of white , black pegs when comparing solution guess. let checkguess solution guess = /// create map of (colour -> count). let tomap = list.countby id >> map.oflist /// compute how many pegs' colours shared in guesses. let mapintersect map1 map2 = let overlap peg count = match map.tryfind peg map2 | none -> 0 | num -> min num count map.fold (fun acc peg count -> acc + overlap peg count) 0 map1 /// compare see if each peg in correct place. let blacks = list.map2 (fun x y -> if x = y 1 else 0) solution guess |> list.sum // number of pegs of right colour wrong location // same total number of pegs of right colour subtract ones // in right place. let whites = mapintersect (tomap solution) (tomap guess) - blacks whites, blacks /// random element of set. let randomsetelement set = let arr = set.toarray set arr.[rnd.next (array.length arr)] let playmastermind () = // creates closure can check our guess against solution, // without storing actual value of solution. let checkanswer = checkguess (randomguess ()) let rec loop turncount remaining = if set.count remaining = 1 let answer = set.maxelement remaining printfn "the answer %a, calculated in %d turns." answer (turncount - 1) else let guess = randomsetelement remaining let (whites, blacks) = checkanswer guess printfn "on turn %d guessed %a, gave %d white pins , %d black pins." turncount guess whites blacks /// remove possibilities solution wouldn't give /// same numbers of white , black pins , continue. loop (turncount + 1) (set.filter (fun possible -> (whites, blacks) = checkguess possible guess) remaining) // play game! loop 1 allpossibles
Comments
Post a Comment