Related
I'm new with OCaml and I am trying to define a type to make a deck of cards, what I have now is:
type palo = Espada | Basto | Oro | Copa
type valor = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
type carta = Carta of palo*valor
what I want to know if there is a way in which I can define a deck as a list of carta with every combination palo - valor available and then "shuffle" it.
Thank you very much in advance.
Edit:
I should probably clarify that this is a Spanish deck and that is why there is no Jack, Queen, King or Ace
Well, you could, certainly, a good way to do it is a Fisher-Yates/Knuth shuffle
So, you would create an array of length 12 * 4 = 48 cards and then shuffle it (you can find this shuffle code in this page) and then use Array.to_list if you want to keep a list of cards and not an array.
[EDIT]
I took the liberty of rewriting your types :
type palo = Espada | Basto | Oro | Copa
type valor = Uno | Dos | Tres | Quatro | Cinco | Seis | Siete |
Ocho | Nueve | Diez | Once | Doce
type carta = palo * valor
You don't need to say that carta is a Carta of palo * valor since you have only one constructor ;-) carta will be an alias for the couple palo * valor.
But, actually, an easiest way to do would be to have the types :
type palo = Espada | Basto | Oro | Copa
type valor = int
type carta = palo * valor
and to ensure that your valor can't be greater than 12, for example. It would make the card creation much easier. (For example, doing so :
let cards = Array.init 48 (fun i ->
let palo =
if i < 12 then Espada
else if i < 24 then Basto
else if i < 36 then Oro
else Copa
in palo, i mod 12 + 1
)
)
[SECOND EDIT]
If you really want to have your valor types, this is one way to do :
type palo = Espada | Basto | Oro | Copa
type valor = Uno | Dos | Tres | Quatro | Cinco | Seis | Siete |
Ocho | Nueve | Diez | Once | Doce
type carta = palo * valor
let lv = [Uno; Dos; Tres; Quatro; Cinco; Seis; Siete;
Ocho; Nueve; Diez; Once; Doce]
let cards =
let new_list p = List.map (fun v -> p, v) lv in
let l1 = new_list Espada in
let l2 = new_list Basto in
let l3 = new_list Oro in
let l4 = new_list Copa in
List.rev_append l1 (List.rev_append l2 (List.rev_append l3 l4))
As you can see, I created a list of valors and for each palo I add the palo to each element of this list (since lists are persistent data structures, it gives me a new list, it does not modify the previous one) and then I concatenate the four lists.
And an even better way to do :
let lp = [Espada; Basto; Oro; Copa]
let cardsb =
let new_list p = List.map (fun v -> p, v) lv in
List.fold_left (fun acc p ->
List.rev_append (new_list p) acc) [] lp
Which uses iterators which is beautiful, so wow, so charming !
The problem os these last methods is that you can't be sure that you put all your constructors in the list and the typing system won't warn you about it. :-(
In my ongoing attempt to get better at Haskell, I'm attempting to solve a problem where I'd like to create a series of list comprehensions of this form:
m2 = [[x1,x2] | x1 <- [2..110], x2 <- [x1..111]]
m3 = [[x1,x2,x3] | x1 <- [2..22], x2 <- [x1..22], x3 <- [x2..24]]
m4 = [[x1,x2,x3,x4] | x1 <- [2..10], x2 <- [x1..10], x3 <- [x2..10], x4 <- [x3..12]]
...
Where x1 <= x2 ... <= xn, the number following m is the length of the sublists, and the first n - 1 terms are bounded by the same upper bound, while the nth term is bounded by some larger number.
I could certainly write all of it out by hand, but that's not particularly good practice. I'm wondering if there's a way to generate these lists up to a particular maximum m value. My immediate thought was Template Haskell, but I don't know enough about it to determine whether it's usable. Is there some other solution that's escaping me?
In pseudo-Haskell, what I'm looking for is some method that does something like:
mOfN n bound term = [ [x1..xn] | x1 <- [2..bound], x2 <- [x1..bound], ..., xn <- [x(n-1)..term] ]
The main issue is that I can't figure out how I would dynamically create x1,x2, etc.
Is this what you are looking for?
import Data.List (tails)
mofn 0 xs = [ [] ]
mofn m xs = [ y:zs | (y:ys) <- tails xs, zs <- mofn (m-1) ys ]
i.e. mofn 3 [1..5] is:
[[1,2,3],[1,2,4],[1,2,5],[1,3,4],[1,3,5],[1,4,5],[2,3,4],[2,3,5],[2,4,5],[3,4,5]]
The key is the tails function which returns successive tails of a list.
Update
Is this what you are looking for?
mofn' 1 lo hi bnd = [ [x] | x <- [lo..bnd] ]
mofn' k lo hi bnd = [ x:ys | x <- [lo..hi], ys <- mofn' (k-1) x hi bnd ]
mofn' 3 1 3 5 is:
[[1,1,1], [1,1,2], [1,1,3], [1,1,4], [1,1,5],
[1,2,2], [1,2,3], [1,2,4], [1,2,5],
[1,3,3], [1,3,4], [1,3,5],
[2,2,2], [2,2,3], [2,2,4], [2,2,5],
[2,3,3], [2,3,4], [2,3,5],
[3,3,3], [3,3,4], [3,3,5]
]
I just encountered this example on learnyouahaskell.com. However, I don't understand it at all.
ghci> let xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]
ghci> [ [ x | x <- xs, even x ] | xs <- xxs]
[[2,2,4],[2,4,6,8],[2,4,2,6,2,6]] -- This is the output
My problem is that while I do understand the idea of list comprehensions, I don't get what the xxs means.
If it was just the name of the list of lists, how can we split up a name and do something like xs <- xxs. To me that doesn't make sense at all.
Can someone help?
xxs is the list of lists bound in the let expression. I think you're being confused by the similarity of xxs and xs, they are just two independent names with no relation. You can replace xs with sublist or any other valid name.
ghci> let xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]
ghci> [ [ x | x <- sublist, even x ] | sublist <- xxs]
So we're not splitting on the name we're just using the <- list comprehension operator to iterate over the elements of a [[a]] and then have another comprehension for iterating over the elements of each [a] sublist.
For example I have a list [1,3,5] and another list [2,4,6], how do I append these two lists in such way it will form into a List of Lists like this: [[1,3,5],[2,4,6]]?
How do I manipulate the list if I add another list at the end [7,8,9] to look like [[1,3,5],[2,4,6],[7,8,9]]?
L1 = [1,3,5],
L2 = [2,4,6],
[L1,L2].
You just need create a list containing both lists.
A = [1,3,5],
B = [2,4,6],
[A, B].
-module(lol).
-export([new/0, append/2, head/1, tail/1]).
new() -> [].
append(H, []) when is_list(H) -> [H];
append(H, T) when is_list(H) -> [H | T].
head([H | _]) when is_list(H) -> H.
tail([_ | T]) -> T.
In the shell you could then:
> Herp = lol:append([1,3,4], lol:new()).
[[1,2,3]]
> Derp = lol:append([4,5,6], Herp).
[[4,5,6],[1,2,3]]
> lol:head(Derp).
[4,5,6]
I leave the rest as exercise for the user.
1> [1,2,3 | [1,2,3]].
[1,2,3,1,2,3]
2> lists:append([1,2,3], [1,2,3]).
[1,2,3,1,2,3]
How do you create a list-based matrix of 1's with given row and column counts? For example, like:
row=3,column=4 -> [[1,1,1,1],[1,1,1,1],[1,1,1,1]]
Here's an alternative method using list comprehension. Let's have a look at the basics:
Prelude> [ 2*x | x <- [1..4] ]
[2,4,6,8]
So that gives you one number for each element in the list [1..4]. Why not, instead of doubling x, just have a 1:
Prelude> [ 1 | x <- [1..4] ]
[1,1,1,1]
And if we want three of them, we can pull the same trick:
Prelude> [ [1|x<-[1..4]] | x<-[1..3] ]
[[1,1,1,1],[1,1,1,1],[1,1,1,1]]
Thus we can define
twoDlist r c = [ [1|x<-[1..c]] | x<-[1..r] ]
which gives
Prelude> twoDlist 3 4
[[1,1,1,1],[1,1,1,1],[1,1,1,1]]
You can do this with replicate:
onesMatrix rows cols = replicate rows (replicate cols 1)
import Control.Applicative
import Data.Functor
matrix r c = [1] <* [1..c] <$ [1..r]