Jenaro Calviño
Jenaro Calviño

Reputation: 193

defining OCaml type structure

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

Upvotes: 0

Views: 203

Answers (1)

Lhooq
Lhooq

Reputation: 4441

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. :-(

Upvotes: 3

Related Questions