Return a sequence of elements in Haskell - list

I want to return a sequence of Cards in a game in Haskell. For example:
[(SIX,D),(SEVEN,D),(EIGHT,S)] ~> [(SIX,D),(SEVEN,D)]
[(SIX,D),(SEVEN,S)] ~> []
[(SIX,D),(SEVEN,D)] ~> [(SIX,D),(SEVEN,D)]
Until now, I have this function:
findSeq :: [Card] -> [Card]
findSeq [] = []
findSeq (h:t)
| null t = [h]
| Just h == (pCard (head t) pack) = h:findSeq t
| otherwise = [h]
Which returns even the first card: i.e, unsuitable for example 2 above. How can I return a sequence, or nothing else if there is no sequence of consecutive elements in there?
I also tried filtering them, but I received 'too many arguments exception'. Any help?

This is how I would do it:
import Data.List (groupBy)
import Data.Function (on)
data Suit = Clubs | Diamonds | Hearts | Spades deriving Eq
data Face = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
| Jack | Queen | King deriving Enum
type Card = (Face, Suit)
findSequences :: [Card] -> [[Card]]
findSequences = [sequence | sequence <- groupBy ((==) `on` snd),
contiguous (map fst sequence),
length sequence > 1]
contiguous :: Enum a => [a] -> Bool
contiguous (x:xs) = map fromEnum xs == take (length xs) [fromEnum x + 1 ..]
The findSequences function finds all the sequences in the deck (except single card sequences).

Well, mathematically it actually makes perfect sense to consider a single card a sequence of one card. So it's a good idea to not change that behaviour as such... just extend the definition so you can obtain the real desired result from that.
The real problem is not that you get single cards as single-element sequences, but that you don't get anything behind them. To fix that, you need to first obtain not merely the first, but all sequences in the list:
findSeqs :: [Card] -> [[Card]]
findSeqs [] = []
findSeqs [h] = [[h]]
findSeqs (h:t#(h':_)) -- avoid `head` and `null`... pattern matching FTW!
| Just h == (pCard h' pack) = h ^: findSeqs t
| otherwise = [h] : findSeqs t
I've used the helper
(^:) :: a -> [[a]] -> [[a]]
h ^: (hl:ls) = (h:hl) : ls
_ ^: [] = []
Once you have findSeqs, you merely need to skim the result for the first non-degenerate sequence.

Related

How to get a random value for a custom datatype in SML?

How would one return a random value for a data type like below?
datatype rank = Jack | Queen | King | Ace | Num of int
I am working on a function generate a list of random cards for input to another function, so there is also the need for a similar function for suit.
The output should either be a symbol like Jack, King, etc, or an int from 2 to 9.
The code below is incorrect:
fun pick_rank() =
case Random.randRange(2,13) of 13 => Ace
| 12 => King
| 11 => Queen
| 10 => Jacl
| Int v => v
How would one return a random value for a data type like below?
datatype rank = Jack | Queen | King | Ace | Num of int
I have two answers: Either you generate each value uniquely, or you generate all possible values, shuffle them and pick one. If you just want a random variable in isolation, the former is easiest. But if you want to simulate a card game in which drawing the same card twice is not possible, then you probably want the shuffle.
You can see how I made a command-line blackjack game. I'll repeat both approaches here:
(* There are 13 card ranks, 4 suits *)
datatype rank
= Ace | Two | Three | Four | Five | Six | Seven
| Eight | Nine | Ten | Jack | Queen | King
datatype suit = Hearts | Clubs | Diamonds | Spades
datatype card = Card of suit * rank
fun concatMap f xs = List.concat (List.map f xs)
fun product xs ys = concatMap (fn x => map (fn y => (x,y)) ys) xs
val allCards = map Card
(product
[Hearts,Clubs,Diamonds,Spades]
[Ace,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King])
(* Create a new pseudo-random number generator, prng *)
val prng = Random.newgen ()
(* rlist determines a random index in [0 ; length xs[. *)
fun rlist xs = Random.range (0, length xs) prng
(* remove removes the n'th element of a list *)
fun remove (_, []) = raise Domain
| remove (0, card::library) = library
| remove (n, card::library) = card::remove (n-1, library);
(* randomtake removes and returns the i'th (random) element of a list *)
fun randomtake library =
let val i = rlist library
val card = List.nth (library, i)
val rest = remove (i, library)
in
(card, rest)
end
(* Shuffling is done by removing random cards until there are no cards left *)
fun shuffle [] = []
| shuffle cards =
let val (c,r) = randomtake cards
in
c :: shuffle r
end
Using these functions, you could pick a single random card by doing randomtake allCards, or you could pick any amount of random cards without picking the same card by first shuffle allCards and pick the top elements.
Note that these are not efficient methods. As an exercise, you could implement the Fisher-Yates shuffle.

OCaml function to check if list is palindrome with floor(n/2) recursive calls and no list allocation

I have this task on uni, I have researched for a long time, but I cannot find out, how to write this function.
I need it to check if a list is a palindrome, call itself recursively at most floor(n/2) times and not allocate any auxiliary list (so I can use no list constructors).
Any ideas? Tbh, I would like an algorithm than a full solution.
I have come up with this and it works:
let palindrom l =
let rec aux l0 l1 =
match (l0, l1) with
| _,[] -> (true,[])
| hd :: tl, [x] -> (hd = x, tl)
| _, hd1 :: tl1 -> let (pal, ll) = aux l0 tl1 in
match ll with
| [] -> (pal, [])
| hd::tl -> (pal && hd1 = hd, tl) in
match l with
[] -> true
| _ -> fst (aux l l)
You can use a recursive helper function that
on the way in, takes two arguments: a remainder of the list, and a remainder of the list that is twice as far away from the start of the list to be checked.
reaches its base case in the middle of the list to be checked (when the second list becomes empty, or - in the case of an odd length - has a single element only)
on the way out, returns an option for a list, the remainder that still has to be checked in reverse for equality - or None when the palindrome failed to match
Example:
// in
hannah hannah
annah nnah
nnah ah
nah
// out
n <-> nah
a <-> ah
h <-> h

How do I use :: when pattern matching in OCaml

let rec (l:int list) f int list =
match l with
| [] -> []
| hd::tl -> 2+tl
I want to know is hd the first element and then tl is the second element because when i do this I keep getting an error, if tl is not the second element how would i access the second element an in depth explanation of hd::tl would be highly appreciated thank you
No tl is not the second element, it is the rest of the list and it has type 'a list. Here hd and tl are just variable names that you choose to bind to the first element of a list, and to the rest of the list (i.e., to a list that contains all elements except the first one). You can choose other names, e.g., fst::rest. Getting the second element, in that case would be as easy as fst::snd::rest (or x::y::rest - again the name doesn't matter).
What you're trying to use is called pattern matching. It is a feature of some languages, that provides a mechanism to easily deconstruct compound data structures. The idea is that if you're deconstructing data structures the same way as you're constructing them, e.g,
let xs = [1;2;3;4]
and here is the deconstructing
let [x1;x2;x3;x4] = xs
In fact, [x;y;...;z] is a syntactic sugar for a more basic syntax x :: y:: ... :: z :: [], so another way to construct the [1;2;3;4] list is to use the following construct: 1::2::3::4::[]. The same works in the opposite direction, e.g.,
let x1::x2::x3::x4::[] = xs
Now we are ready to the next step, what if the structure on the right doesn't match the structure on the left, e.g.,
let [x;y;z] = [1;2]
or
let x::y::z::[] = 1::2::[]
In that case, the matching will fail. In our case in runtime. To prevent this, and to allow programmers to handle all possible configuration of their data structures OCaml provides the match construct in which you specify multiple variants of the value structure, and the first one that matches is chosen, e.g.,
let orcish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
The function above anticipates only lists that have up to three elements (because Orcs can't count beyond three). But we can. For this we will use the following feature -- if the last element of the list pattern is not [] (that is matches only and only with the empty list, and designates the end-of-list), but anything else (i.e., a variable), then this variable will be bound to all elements, e.g.,
let rec elvish_length xs = match xs with
| [] -> 0
| x :: [] -> 1
| x :: y :: [] -> 2
| x :: y :: z :: [] -> 3
| x :: y :: z :: leftovers -> 3 + elvish_length leftovers
So now, we anticipate all possible list patterns. However, the function is now overcomplicated (because Elves are complicating). Now, let's finally derive a normal, human readable, length function,
let rec length xs = match xs with
| [] -> 0
| x :: xs -> 1 + length xs
As an exercise, try to prove to yourself that this function anticipates all possible lists.
:: is read cons and is an infix version of List.cons. In a functional language like Ocaml, list is a linked list where i.e.[e1; e2; e3; e4] can be reduced to something like this:
cons(::)
/ \
e1 cons(::)
/ \
e2 cons(::)
/ \
e3 cons(::)
/ \
e4 [ ]
Basically, any list can be reduced to a tree of recursive cons expressions, which makes recursion so useful in Ocaml or similar functional languages. At each level, you can reduce a list to its head and its tail, where tail is the list minus its head and can be reduced further until last :: []. So with the above example, you can recursively reduce the list until you find the last element by pattern-matching:
let find_last li =
match li with
| [] -> None (* no element *)
| [last] -> Some last (* found last *)
| head :: tail -> find_last tail (* keep finding *)
;;
Note that [last] can be replaced with last::[] and head::tail with List.cons head tail. What is important is at any point a list can always be reduced to head :: tail, where head is the first element and tail is the list without head.
Pattern-matching is useful in matching the "shape" or state of the reducing list.

Data.Random.Extras Usage

I'm trying to use a shuffle function from Data.Random.Extras package on the list of cards I have created. My code:
module Cards where
import Data.Random.Extras
data Suit = Clubs
| Diamonds
| Hearts
| Spades
deriving (Eq,Enum,Ord,Show,Bounded)
data Value = Two
| Three
| Four
| Five
| Six
| Seven
| Eight
| Nine
| Ten
| Jack
| Queen
| King
| Ace
deriving (Eq,Enum,Ord,Show,Bounded)
data Card = Card Value Suit
deriving (Eq,Ord,Show)
type Deck = [Card]
-- Generate deck of cards
generateDeck :: Deck
generateDeck = [Card val suit | suit <- [Clubs .. Spades], val <- [Two .. Ace]]
-- Print deck of cards
printDeck :: Deck -> IO ()
printDeck deck = putStr (formatDeck deck)
where
formatDeck [] = []
formatDeck (x:xs) = (show x) ++ "\n" ++ formatDeck xs
The problem is that when I'm trying to execute shuffle $ generateDeck on GHCi prompt I'm getting:
No instance for (Show (Data.RVar.RVar [Card]))
arising from use of 'print'
Possible fix:
Add an instance declaration for (Show (Data.RVar.RVar [Card]))
In a stmt of an interactive GHCi command: print it
I spent hours searching and trying to solve/understand this without any success. I would really appreciate your help.
Thank you.
That is because the type of shuffle is [a] -> RVar [a]. So you don't get back an [a] which you could use directly but some mysterious RVar. RVar is a bit like IO in that an RVar a is not a value of type a but more of a mean of getting a value of type a. In order to actually get a value of type a you have to use runRVar :: RandomSource m s => RVar a -> s -> m a. Looking at the documentation of RandomSource, there are multiple instances for it. One example would be MonadRandom m => RandomSource m StdRandom. So we can use runRVar like this (because IO is an instance of MonadRandom):
> import Data.Random (runRVar, StdRandom(..))
> import Data.Random.Extras (shuffle)
> runRVar (shuffle [1..10]) StdRandom :: IO [Int]
[3,10,8,5,6,7,4,2,9,1]
Or another instance of MonadRandom, that doesn't involve IO would be State StdGen a:
> -- Above imports and
> import Control.Monad.State (State,evalState)
> import System.Random (StdGen,mkStdGen)
> shuffledState = runRVar (shuffle [1..10]) StdRandom :: State StdGen [Int]
> evalState shuffledState $ mkStdGen 0 -- 0 is the seed
[6,8,7,5,10,9,2,3,1,4]

all possibilities of dividing a list in two in Haskell

What's the most direct/efficient way to create all possibilities of dividing one (even) list into two in Haskell? I toyed with splitting all permutations of the list but that would add many extras - all the instances where each half contains the same elements, just in a different order. For example,
[1,2,3,4] should produce something like:
[ [1,2], [3,4] ]
[ [1,3], [2,4] ]
[ [1,4], [2,3] ]
Edit: thank you for your comments -- the order of elements and the type of the result is less important to me than the concept - an expression of all two-groups from one group, where element order is unimportant.
Here's an implementation, closely following the definition.
The first element always goes into the left group. After that, we add the next head element into one, or the other group. If one of the groups becomes too big, there is no choice anymore and we must add all the rest into the the shorter group.
divide :: [a] -> [([a], [a])]
divide [] = [([],[])]
divide (x:xs) = go ([x],[], xs, 1,length xs) []
where
go (a,b, [], i,j) zs = (a,b) : zs -- i == lengh a - length b
go (a,b, s#(x:xs), i,j) zs -- j == length s
| i >= j = (a,b++s) : zs
| (-i) >= j = (a++s,b) : zs
| otherwise = go (x:a, b, xs, i+1, j-1) $ go (a, x:b, xs, i-1, j-1) zs
This produces
*Main> divide [1,2,3,4]
[([2,1],[3,4]),([3,1],[2,4]),([1,4],[3,2])]
The limitation of having an even length list is unnecessary:
*Main> divide [1,2,3]
[([2,1],[3]),([3,1],[2]),([1],[3,2])]
(the code was re-written in the "difference-list" style for efficiency: go2 A zs == go1 A ++ zs).
edit: How does this work? Imagine yourself sitting at a pile of stones, dividing it into two. You put the first stone to a side, which one it doesn't matter (so, left, say). Then there's a choice where to put each next stone — unless one of the two piles becomes too small by comparison, and we thus must put all the remaining stones there at once.
To find all partitions of a non-empty list (of even length n) into two equal-sized parts, we can, to avoid repetitions, posit that the first element shall be in the first part. Then it remains to find all ways to split the tail of the list into one part of length n/2 - 1 and one of length n/2.
-- not to be exported
splitLen :: Int -> Int -> [a] -> [([a],[a])]
splitLen 0 _ xs = [([],xs)]
splitLen _ _ [] = error "Oops"
splitLen k l ys#(x:xs)
| k == l = [(ys,[])]
| otherwise = [(x:us,vs) | (us,vs) <- splitLen (k-1) (l-1) xs]
++ [(us,x:vs) | (us,vs) <- splitLen k (l-1) xs]
does that splitting if called appropriately. Then
partitions :: [a] -> [([a],[a])]
partitions [] = [([],[])]
partitions (x:xs)
| even len = error "Original list with odd length"
| otherwise = [(x:us,vs) | (us,vs) <- splitLen half len xs]
where
len = length xs
half = len `quot` 2
generates all the partitions without redundantly computing duplicates.
luqui raises a good point. I haven't taken into account the possibility that you'd want to split lists with repeated elements. With those, it gets a little more complicated, but not much. First, we group the list into equal elements (done here for an Ord constraint, for only Eq, that could still be done in O(length²)). The idea is then similar, to avoid repetitions, we posit that the first half contains more elements of the first group than the second (or, if there is an even number in the first group, equally many, and similar restrictions hold for the next group etc.).
repartitions :: Ord a => [a] -> [([a],[a])]
repartitions = map flatten2 . halves . prepare
where
flatten2 (u,v) = (flatten u, flatten v)
prepare :: Ord a => [a] -> [(a,Int)]
prepare = map (\xs -> (head xs, length xs)) . group . sort
halves :: [(a,Int)] -> [([(a,Int)],[(a,Int)])]
halves [] = [([],[])]
halves ((a,k):more)
| odd total = error "Odd number of elements"
| even k = [((a,low):us,(a,low):vs) | (us,vs) <- halves more] ++ [normalise ((a,c):us,(a,k-c):vs) | c <- [low + 1 .. min half k], (us,vs) <- choose (half-c) remaining more]
| otherwise = [normalise ((a,c):us,(a,k-c):vs) | c <- [low + 1 .. min half k], (us,vs) <- choose (half-c) remaining more]
where
remaining = sum $ map snd more
total = k + remaining
half = total `quot` 2
low = k `quot` 2
normalise (u,v) = (nz u, nz v)
nz = filter ((/= 0) . snd)
choose :: Int -> Int -> [(a,Int)] -> [([(a,Int)],[(a,Int)])]
choose 0 _ xs = [([],xs)]
choose _ _ [] = error "Oops"
choose need have ((a,k):more) = [((a,c):us,(a,k-c):vs) | c <- [least .. most], (us,vs) <- choose (need-c) (have-k) more]
where
least = max 0 (need + k - have)
most = min need k
flatten :: [(a,Int)] -> [a]
flatten xs = xs >>= uncurry (flip replicate)
Daniel Fischer's answer is a good way to solve the problem. I offer a worse (more inefficient) way, but one which more obviously (to me) corresponds to the problem description. I will generate all partitions of the list into two equal length sublists, then filter out equivalent ones according to your definition of equivalence. The way I usually solve problems is by starting like this -- create a solution that is as obvious as possible, then gradually transform it into a more efficient one (if necessary).
import Data.List (sort, nubBy, permutations)
type Partition a = ([a],[a])
-- Your notion of equivalence (sort to ignore the order)
equiv :: (Ord a) => Partition a -> Partition a -> Bool
equiv p q = canon p == canon q
where
canon (xs,ys) = sort [sort xs, sort ys]
-- All ordered partitions
partitions :: [a] -> [Partition a]
partitions xs = map (splitAt l) (permutations xs)
where
l = length xs `div` 2
-- All partitions filtered out by the equivalence
equivPartitions :: (Ord a) => [a] -> [Partition a]
equivPartitions = nubBy equiv . partitions
Testing
>>> equivPartitions [1,2,3,4]
[([1,2],[3,4]),([3,2],[1,4]),([3,1],[2,4])]
Note
After using QuickCheck to test the equivalence of this implementation with Daniel's, I found an important difference. Clearly, mine requires an (Ord a) constraint and his does not, and this hints at what the difference would be. In particular, if you give his [0,0,0,0], you will get a list with three copies of ([0,0],[0,0]), whereas mine will give only one copy. Which of these is correct was not specified; Daniel's is natural when considering the two output lists to be ordered sequences (which is what that type is usually considered to be), mine is natural when considering them as sets or bags (which is how this question seemed to be treating them).
Splitting The Difference
It is possible to get from an implementation that requires Ord to one that doesn't, by operating on the positions rather than the values in a list. I came up with this transformation -- an idea which I believe originates with Benjamin Pierce in his work on bidirectional programming.
import Data.Traversable
import Control.Monad.Trans.State
data Labelled a = Labelled { label :: Integer, value :: a }
instance Eq (Labelled a) where
a == b = compare a b == EQ
instance Ord (Labelled a) where
compare a b = compare (label a) (label b)
labels :: (Traversable t) => t a -> t (Labelled a)
labels t = evalState (traverse trav t) 0
where
trav x = state (\i -> i `seq` (Labelled i x, i + 1))
onIndices :: (Traversable t, Functor u)
=> (forall a. Ord a => t a -> u a)
-> forall b. t b -> u b
onIndices f = fmap value . f . labels
Using onIndices on equivPartitions wouldn't speed it up at all, but it would allow it to have the same semantics as Daniel's (up to equiv of the results) without the constraint, and with my more naive and obvious way of expressing it -- and I just thought it was an interesting way to get rid of the constraint.
My own generalized version, added much later, inspired by Will's answer:
import Data.Map (adjust, fromList, toList)
import Data.List (groupBy, sort)
divide xs n evenly = divide' xs (zip [0..] (replicate n [])) where
evenPSize = div (length xs) n
divide' [] result = [result]
divide' (x:xs) result = do
index <- indexes
divide' xs (toList $ adjust (x :) index (fromList result)) where
notEmptyBins = filter (not . null . snd) $ result
partlyFullBins | evenly == "evenly" = map fst . filter ((<evenPSize) . length . snd) $ notEmptyBins
| otherwise = map fst notEmptyBins
indexes = partlyFullBins
++ if any (null . snd) result
then map fst . take 1 . filter (null . snd) $ result
else if null partlyFullBins
then map fst. head . groupBy (\a b -> length (snd a) == length (snd b)) . sort $ result
else []