Poker hand - Determining a full house in F# - f#

Having this issue of my fullHouse function = true when there's a three-of-a-kind.
The function checks for a 3 of a kind and a pair but it satisfies the logic with just a three of a kind (D, Ace)(C, Ace)(S, Ace)(D, Ten)(D, 9). This isn't a full house but it's allowing the same 3 aces to satisfy both the pair AND the 3 of a kind.
How do I restrict this so it cannot reduce the 3 of a kind into a pair?
Thanks!
EDIT: F# Newbie
EDIT_2: A full house is when out of your hand of 5 cards you have a 3 of a kind (3 of the same value (suit doesn't matter but they have to be 3x aces or 3x tens etc)) AND a pair (2x ten's, 2x 8's etc - suit doesn't matter)
Input:
fullHouse [(D, K);(C, K);(S, K);(D, T);(D, V 9)];;
Expected output: False,
Actual output: True
Input:
fullHouse [(D, K);(C, K);(S, K);(D, T);(C, T)];;
Expected output: True,
Actual Output: True

My take on this would be to handle all the cases of Four of a Kind, Full House, Triple, Pair or none of the above all together.
To do this, I would use List.groupBy in order to group by card values. This will give you a list of lists of each group of the same card value. For example:
[(D, K);(C, K);(S, K);(D, T);(D, V 9)] |> List.groupBy (snd);;
Gives the result:
[(K, [(D, K); (C, K); (S, K)]); (T, [(D, T)]); (V 9, [(D, V 9)])]
i.e. A list of three Kings, a list of one Ten and a list of one Nine.
Now you just need to make sure the longest sublists appear at the start for convenient pattern matching, so simply order this list by the number of cards contained in each sublist and then you can pattern match against the hand to obtain the result.
let (|FourOfKind|FullHouse|Triple|Pair|Other|) hand =
let groups = hand |> List.groupBy (snd) |> List.sortByDescending (List.length << snd)
match groups with
|(v, [c1; c2; c3; c4]) :: rest -> FourOfKind (c1, c2, c3, c4)
|(v, [c1; c2; c3]) :: (v2, [c4; c5]) :: rest -> FullHouse(c1, c2, c3, c4, c5)
|(v, [c1; c2; c3]) :: rest -> Triple(c1, c2, c3)
|(v, [c1; c2]) :: rest -> Pair(c1, c2)
|_ -> Other
You could then do, e.g.
let printHand = function
|FourOfKind _ -> printfn "Four of a Kind"
|FullHouse _ -> printfn "Full House"
|Triple _ -> printfn "Triple"
|Pair _ -> printfn "Pair"
|Other -> printfn "Other"
Then in fsi:
printHand [(D, K);(C, K);(S, K);(D, T);(D, V 9)];;
Triple
printHand [(D, K);(C, K);(S, K);(D, T);(C, T)];;
Full House

Related

Taking two streams and combining them in OCaml

I want to take two streams of integers in increasing order and combine them into one stream that contains no duplicates and should be in increasing order. I have defined the functionality for streams in the following manner:
type 'a susp = Susp of (unit -> 'a)
let force (Susp f) = f()
type 'a str = {hd : 'a ; tl : ('a str) susp }
let merge s1 s2 = (* must implement *)
The first function suspends computation by wrapping a computation within a function, and the second function evaluates the function and provides me with the result of the computation.
I want to emulate the logic of how you go about combining lists, i.e. match on both lists and check which elements are greater, lesser, or equal and then append (cons) the integers such that the resulting list is sorted.
However, I know I cannot just do this with streams of course as I cannot traverse it like a list, so I think I would need to go integer by integer, compare, and then suspend the computation and keep doing this to build the resulting stream.
I am at a bit of a loss how to implement such logic however, assuming it is how I should be going about this, so if somebody could point me in the right direction that would be great.
Thank you!
If the the input sequences are sorted, there is not much difference between merging lists and sequences. Consider the following merge function on lists:
let rec merge s t =
match s, t with
| x :: s , [] | [], x :: s -> x :: s
| [], [] -> s
| x :: s', y :: t' ->
if x < y then
x :: (merge s' t)
else if x = y then
x :: (merge s' t')
else
y :: (merge s t')
This function is only using two properties of lists:
the ability to split the potential first element from the rest of the list
the ability to add an element to the front of the list
This suggests that we could rewrite this function as a functor over the signature
module type seq = sig
type 'a t
(* if the seq is non-empty we split the seq into head and tail *)
val next: 'a t -> ('a * 'a t) option
(* add back to the front *)
val cons: 'a -> 'a t -> 'a t
end
Then if we replace the pattern matching on the list with a call to next, and the cons operation with a call to cons, the previous function is transformed into:
module Merge(Any_seq: seq ) = struct
open Any_seq
let rec merge s t =
match next s, next t with
| Some(x,s), None | None, Some (x,s) ->
cons x s
| None, None -> s
| Some (x,s'), Some (y,t') ->
if x < y then
cons x (merge s' t)
else if x = y then
cons x (merge s' t')
else
cons y (merge s t')
end
Then, with list, our implementation was:
module List_core = struct
type 'a t = 'a list
let cons = List.cons
let next = function
| [] -> None
| a :: q -> Some(a,q)
end
module List_implem = Merge(List_core)
which can be tested with
let test = List_implem.merge [1;5;6] [2;4;9]
Implementing the same function for your stream type is then just a matter of writing a similar Stream_core module for stream.

Confused with F# List.Fold (powerset function)

I understand and wrote a typical power set function in F# (similar to the Algorithms section in Wikipedia)
Later I found this implementation of powerset which seems nice and compact, expect that I do not understand it.
let rec powerset = function
| [] -> [[]]
| h::t -> List.fold (fun xs t -> (h::t)::t::xs) [] (powerset t);
I broke this down to a 1 step non-recursive function to find the powerset of [1;2] and hardcoded the value of power set of 2 at the end [[2]; []]
let right = function
| [] -> [[]]
| h::t -> List.fold (fun acc t -> (h::t)::t::acc) [] [[2]; []];
The output is [[1]; []; [1; 2]; [2]] which is correct.
However I was expecting List.Fold to output [[1; 2]; []; [1; 2]; [2]].
Since I was not certain about the 't', I modified the variable names, and I did get what I had expected. Of course this is not the correct powerset of [1;2].
let wrong = function
| [] -> [[]]
| h::t -> List.fold (fun acc data -> (h::t)::data::acc) [] [[2]; []];
For me 't' (the one withing fun and not the h::t) is simply a name for the second argument to 'fun' but that is obviously not the case. So what is the difference in the "right" and "wrong" F# functions I have written ? And what exactly does 't' here refer to ?
Thank you ! (I am new to F#)
In your "right" example, t is originally the name of the value bound in the pattern match, but it is hidden by the parameter t in the lambda expression passed to List.fold. Whereas in your "wrong" example, t is captured as a closure in the lambda expression. I think maybe you don't intend this capture, instead you want:
//now it works as you expect, replaced "t" with "data" in your lambda expression.
let wrong = function
| [] -> [[]]
| h::t -> List.fold (fun acc data -> (h::data)::data::acc) [] [[2]; []];
let rec powerset = function
| [] -> [[]]
| h::t -> List.fold (fun xs t -> (h::t)::t::xs) [] (powerset t);
here is the understanding/english translation of the code:
if the list (you want to power) is empty, then return a list, which contains an empty list in it
if the list is h::t (with head h and the rest as t, so h is an element and t is a list). then:
A. (powerset t): calculate the power set of t
B. (fun xs t -> (h::t)::t::xs) means that you apply/fold this function to the (powerset t). more details: xs is an accumulator, it is initialized to []. xxx::xs means you add something to an existing powerest xs. Here xxx is (h::t)::t, which are two elements to be added to the head of xs. (h::t) means add head to t and t means each element in (powerset t). <- the confusing part lies in t, the t in (powerset t) is the rest of the list, while the other t means an element in (powerset t).
here is an imperative translation of the fold function :
let h::t = list
let setfort = powerset t
xs <- []
foreach s in setfort do
xs <- xs.add(t) // t is a valid subset of list
xs <- xs.add(h::t) // t with h is also a valid subset of list
t is a variable bound by pattern matching. List.fold is a fancy way of avoiding explicit looping. Now, go and read some introductory tutorials about F#.

what is wrong with my unpair implementation?

I'm trying to figure out WHY i'm getting the error below more than I am interested in a correct implementation of my method.
I have the following f# code that is supposed to unpair a list of tuples into a list containing all the items in the tuples like so:
let unpair l =
let rec loop acc l =
match l with
| [] -> acc
| (x,y)::tl ->
loop (acc # x # y) tl
loop [] l
//should print:
// [1 2 3 4 5 6]
printf "["
List.iter (printf "%A") (unpair [(1, 2); (3, 4); (5, 6)])
printfn "]"
I get the following error for each of my ints when calling unpair:
This expression was expected to have type 'a list but here has type int
Why is it expecting 'a list?
The problem is in the following expression
acc # x # y
The # is used to combine list values together yet here x and y are typed to int. What you're looking for is the :: operator which will add items to a list. Additionally you are building up the list backwards in that expression. Use the following and it should fix your issue
x :: y :: acc
As JaredPar explains, you need to use x::acc to add elements to the accumulator. If you want to append elements to the end, you could write acc # [x], but that's very inefficient, as it needs to copy the whole list for every single element.
The usual solution is to add elements to the front and then reverse the list at the end of the processing:
let unpair l =
let rec loop acc l =
match l with
| [] -> List.rev acc // NOTE: Reverse the list here
| (x,y)::tl ->
loop (y::x::acc) tl // Add elements to the front
loop [] l
This is a lot more efficient than using acc # [x], because it keeps adding elements to the front (which takes just a small constant time) and then creates a single copy of the whole list at the end.
The same function can be also nicely & efficiently implemented using sequence expressions:
let unpair l =
[ for x, y in l do
yield x
yield y ]

F# return element pairs in list

I have been looking for an elegant way to write a function that takes a list of elements and returns a list of tuples with all the possible pairs of distinct elements, not taking into account order, i.e. (a,b) and (b,a) should be considered the same and only one of them be returned.
I am sure this is a pretty standard algorithm, and it's probably an example from the cover page of the F# documentation, but I can't find it, not even searching the Internet for SML or Caml. What I have come up with is the following:
let test = [1;2;3;4;5;6]
let rec pairs l =
seq {
match l with
| h::t ->
yield! t |> Seq.map (fun elem -> (h, elem))
yield! t |> pairs
| _ -> ()
}
test |> pairs |> Seq.toList |> printfn "%A"
This works and returns the expected result [(1, 2); (1, 3); (1, 4); (1, 5); (1, 6); (2, 3); (2, 4); (2, 5); (2, 6); (3, 4); (3, 5); (3, 6); (4, 5); (4, 6); (5, 6)] but it looks horribly unidiomatic.
I should not need to go through the sequence expression and then convert back into a list, there must be an equivalent solution only involving basic list operations or library calls...
Edited:
I also have this one here
let test = [1;2;3;4;5;6]
let rec pairs2 l =
let rec p h t =
match t with
| hx::tx -> (h, hx)::p h tx
| _ -> []
match l with
| h::t -> p h t # pairs2 t
| _ -> []
test |> pairs2 |> Seq.toList |> printfn "%A"
Also working, but like the first one it seems unnecessarily involved and complicated, given the rather easy problem. I guess my question is mor about style, really, and if someone can come up with a two-liner for this.
I think that your code is actually pretty close to an idiomatic version. The only change I would do is that I would use for in a sequence expression instead of using yield! in conjunction with Seq.map. I also usually format code differently (but that's just a personal preference), so I would write this:
let rec pairs l = seq {
match l with
| h::t -> for e in t do yield h, elem
yield! pairs t
| _ -> () }
This is practically the same thing as what Brian posted. If you wanted to get a list as the result then you could just wrap the whole thing in [ ... ] instead of seq { ... }.
However, this isn't actually all that different - under the cover, the compiler uses a sequence anyway and it just adds conversion to a list. I think that it may be actually a good idea to use sequences until you actually need a list (because sequences are evaluated lazilly, so you may avoid evaluating unnecessary things).
If you wanted to make this a bit simpler by abstracting a part of the behavior into a separate (generally useful) function, then you could write a function e.g. splits that returns all elements of a list together with the rest of the list:
let splits list =
let rec splitsAux acc list =
match list with
| x::xs -> splitsAux ((x, xs)::acc) xs
| _ -> acc |> List.rev
splitsAux [] list
For example splits [ 1 .. 3 ] would give [(1, [2; 3]); (2, [3]); (3, [])]. When you have this function, implementing your original problem becomes much easier - you can just write:
[ for x, xs in splits [ 1 .. 5] do
for y in xs do yield x, y ]
As a guide for googling - the problem is called finding all 2-element combinations from the given set.
Here's one way:
let rec pairs l =
match l with
| [] | [_] -> []
| h :: t ->
[for x in t do
yield h,x
yield! pairs t]
let test = [1;2;3;4;5;6]
printfn "%A" (pairs test)
You seem to be overcomplicating things a lot. Why even use a seq if you want a list? How about
let rec pairs lst =
match lst with
| [] -> []
| h::t -> List.map (fun elem -> (h, elem)) t # pairs t
let _ =
let test = [1;2;3;4;5;6]
printfn "%A" (pairs test)

F# Split list into sublists based on comparison of adjacent elements

I've found this question on hubFS, but that handles a splitting criteria based on individual elements. I'd like to split based on a comparison of adjacent elements, so the type would look like this:
val split = ('T -> 'T -> bool) -> 'T list -> 'T list list
Currently, I am trying to start from Don's imperative solution, but I can't work out how to initialize and use a 'prev' value for comparison. Is fold a better way to go?
//Don's solution for single criteria, copied from hubFS
let SequencesStartingWith n (s:seq<_>) =
seq { use ie = s.GetEnumerator()
let acc = new ResizeArray<_>()
while ie.MoveNext() do
let x = ie.Current
if x = n && acc.Count > 0 then
yield ResizeArray.to_list acc
acc.Clear()
acc.Add x
if acc.Count > 0 then
yield ResizeArray.to_list acc }
This is an interesting problem! I needed to implement exactly this in C# just recently for my article about grouping (because the type signature of the function is pretty similar to groupBy, so it can be used in LINQ query as the group by clause). The C# implementation was quite ugly though.
Anyway, there must be a way to express this function using some simple primitives. It just seems that the F# library doesn't provide any functions that fit for this purpose. I was able to come up with two functions that seem to be generally useful and can be combined together to solve this problem, so here they are:
// Splits a list into two lists using the specified function
// The list is split between two elements for which 'f' returns 'true'
let splitAt f list =
let rec splitAtAux acc list =
match list with
| x::y::ys when f x y -> List.rev (x::acc), y::ys
| x::xs -> splitAtAux (x::acc) xs
| [] -> (List.rev acc), []
splitAtAux [] list
val splitAt : ('a -> 'a -> bool) -> 'a list -> 'a list * 'a list
This is similar to what we want to achieve, but it splits the list only in two pieces (which is a simpler case than splitting the list multiple times). Then we'll need to repeat this operation, which can be done using this function:
// Repeatedly uses 'f' to take several elements of the input list and
// aggregate them into value of type 'b until the remaining list
// (second value returned by 'f') is empty
let foldUntilEmpty f list =
let rec foldUntilEmptyAux acc list =
match f list with
| l, [] -> l::acc |> List.rev
| l, rest -> foldUntilEmptyAux (l::acc) rest
foldUntilEmptyAux [] list
val foldUntilEmpty : ('a list -> 'b * 'a list) -> 'a list -> 'b list
Now we can repeatedly apply splitAt (with some predicate specified as the first argument) on the input list using foldUntilEmpty, which gives us the function we wanted:
let splitAtEvery f list = foldUntilEmpty (splitAt f) list
splitAtEvery (<>) [ 1; 1; 1; 2; 2; 3; 3; 3; 3 ];;
val it : int list list = [[1; 1; 1]; [2; 2]; [3; 3; 3; 3]]
I think that the last step is really nice :-). The first two functions are quite straightforward and may be useful for other things, although they are not as general as functions from the F# core library.
How about:
let splitOn test lst =
List.foldBack (fun el lst ->
match lst with
| [] -> [[el]]
| (x::xs)::ys when not (test el x) -> (el::(x::xs))::ys
| _ -> [el]::lst
) lst []
the foldBack removes the need to reverse the list.
Having thought about this a bit further, I've come up with this solution. I'm not sure that it's very readable (except for me who wrote it).
UPDATE Building on the better matching example in Tomas's answer, here's an improved version which removes the 'code smell' (see edits for previous version), and is slightly more readable (says me).
It still breaks on this (splitOn (<>) []), because of the dreaded value restriction error, but I think that might be inevitable.
(EDIT: Corrected bug spotted by Johan Kullbom, now works correctly for [1;1;2;3]. The problem was eating two elements directly in the first match, this meant I missed a comparison/check.)
//Function for splitting list into list of lists based on comparison of adjacent elements
let splitOn test lst =
let rec loop lst inner outer = //inner=current sublist, outer=list of sublists
match lst with
| x::y::ys when test x y -> loop (y::ys) [] (List.rev (x::inner) :: outer)
| x::xs -> loop xs (x::inner) outer
| _ -> List.rev ((List.rev inner) :: outer)
loop lst [] []
splitOn (fun a b -> b - a > 1) [1]
> val it : [[1]]
splitOn (fun a b -> b - a > 1) [1;3]
> val it : [[1]; [3]]
splitOn (fun a b -> b - a > 1) [1;2;3;4;6;7;8;9;11;12;13;14;15;16;18;19;21]
> val it : [[1; 2; 3; 4]; [6; 7; 8; 9]; [11; 12; 13; 14; 15; 16]; [18; 19]; [21]]
Any thoughts on this, or the partial solution in my question?
"adjacent" immediately makes me think of Seq.pairwise.
let splitAt pred xs =
if Seq.isEmpty xs then
[]
else
xs
|> Seq.pairwise
|> Seq.fold (fun (curr :: rest as lists) (i, j) -> if pred i j then [j] :: lists else (j :: curr) :: rest) [[Seq.head xs]]
|> List.rev
|> List.map List.rev
Example:
[1;1;2;3;3;3;2;1;2;2]
|> splitAt (>)
Gives:
[[1; 1; 2; 3; 3; 3]; [2]; [1; 2; 2]]
I would prefer using List.fold over explicit recursion.
let splitOn pred = function
| [] -> []
| hd :: tl ->
let (outer, inner, _) =
List.fold (fun (outer, inner, prev) curr ->
if pred prev curr
then (List.rev inner) :: outer, [curr], curr
else outer, curr :: inner, curr)
([], [hd], hd)
tl
List.rev ((List.rev inner) :: outer)
I like answers provided by #Joh and #Johan as these solutions seem to be most idiomatic and straightforward. I also like an idea suggested by #Shooton. However, each solution had their own drawbacks.
I was trying to avoid:
Reversing lists
Unsplitting and joining back the temporary results
Complex match instructions
Even Seq.pairwise appeared to be redundant
Checking list for emptiness can be removed in cost of using Unchecked.defaultof<_> below
Here's my version:
let splitWhen f src =
if List.isEmpty src then [] else
src
|> List.foldBack
(fun el (prev, current, rest) ->
if f el prev
then el , [el] , current :: rest
else el , el :: current , rest
)
<| (List.head src, [], []) // Initial value does not matter, dislike using Unchecked.defaultof<_>
|> fun (_, current, rest) -> current :: rest // Merge temporary lists
|> List.filter (not << List.isEmpty) // Drop tail element

Resources