Card tricks with Ruby

G

grrr

So suppose you have a deck of cards, that might have some number of cards.

First the cards are shuffled, in effect placed in random order.

Then the deck is split, ie. some number of cards are lifted from the top
of the deck and placed under the remaining cards.

How would one implement this? I was thinking of using an array, but how to
shuffle the deck, and how to split the deck?

grrr
 
J

James Edward Gray II

how to shuffle the deck
=> ["A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K",
"A"]=> ["6", "T", "Q", "5", "A", "J", "2", "7", "4", "8", "A", "9", "K",
"3"]
and how to split the deck?
=> ["5", "A", "J", "2", "7", "4", "8", "A", "9", "K", "3", "6", "T",
"Q"]

Hope that gives you some new ideas.

James Edward Gray II
 
J

joey__

grrr said:
So suppose you have a deck of cards, that might have some number of
cards.

First the cards are shuffled, in effect placed in random order.

Then the deck is split, ie. some number of cards are lifted from the top
of the deck and placed under the remaining cards.

How would one implement this? I was thinking of using an array, but how
to
shuffle the deck, and how to split the deck?

grrr

class Array
def shuffle
self.sort_by{rand}
end

def cut(index)
(self-self[0..index]).push(*self[0..index])
end
end
 
D

dblack

Hi --

So suppose you have a deck of cards, that might have some number of cards.

First the cards are shuffled, in effect placed in random order.

Then the deck is split, ie. some number of cards are lifted from the top
of the deck and placed under the remaining cards.

How would one implement this? I was thinking of using an array, but how to
shuffle the deck, and how to split the deck?

You could do:

def shuffle
sort_by { rand }
end

(Disclaimer: I haven't really followed the discussions of how random
this and other techniques for shuffling are.)

Here's a demo of how you might cut the deck (using a small deck here):

irb(main):015:0> deck = *1..10
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):016:0> deck.concat(deck.slice!(0,5))
=> [6, 7, 8, 9, 10, 1, 2, 3, 4, 5]


David

--
David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
 
M

Matthew Moss

deck =3D (1..52).to_a

# shuffle
deck =3D deck.sort_by { rand }

# cut
x =3D rand(52)
deck =3D deck[x..-1] + deck[0...x] # notice differing amounts of dots
 
B

Benjohn Barnes

--Apple-Mail-4-1037510236
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed
=> ["5", "A", "J", "2", "7", "4", "8", "A", "9", "K", "3", "6",
"T", "Q"]

:) Heh, cool - I didn't know values_at did that. Nice :)
Hope that gives you some new ideas.

:) I'm sure it'll be useful!
--Apple-Mail-4-1037510236--
 
S

Stephen Waits

Matthew said:
deck = deck[x..-1] + deck[0...x] # notice differing amounts of dots

I find myself constantly pointing this out too.. is anyone else bothered
by it? Has Matz weighed in on this in the past?

It seems error-prone to me. Extraordinarily more error-prone than other
"stuff" in Ruby.

--Steve
 
F

francisrammeloo

cards = cards.sort_by { rand }

How does this work??
I thought the code block should yield either -1, 0 or +1, but rand
yields a number between 0 and 1. Or am I mistaken?

Best regards,
Francis
 
D

dblack

Hi --

Matthew said:
deck = deck[x..-1] + deck[0...x] # notice differing amounts of dots

I find myself constantly pointing this out too.. is anyone else bothered by
it? Has Matz weighed in on this in the past?

It seems error-prone to me. Extraordinarily more error-prone than other
"stuff" in Ruby.

Maybe I need more caffeine, but what exactly is the problem you're
referring to?


David

--
David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
 
J

Jim Weirich

How does this work??
I thought the code block should yield either -1, 0 or +1, but rand
yields a number between 0 and 1. Or am I mistaken?

You are thing of the normal sort method which looks like this:

cards.sort { |a, b|
(a.suit <=> b.suit).nonzero? || (a.value <=> b.value)
}

With sort_by, you need to return a key value that will be used as the
comparison key for that particular value.

cards.sort_by { |card| [card.suit, card.value] }

Sort_by actually does a "Schwartzian Transform"[1] on the array to
perform the sorting.
 
F

Farrel Lifson

I think you're confusing the <=3D> operator needed to mixin Enumerable.

The block in sort_by just returns a value that the sort_by method
should assign to each element in the array so that they may be
ordered. The returned value itself could be anything as long as it
implements Comparable (or it might just need <=3D>). So for instance
when you say

deck.sort_by do |card|
card.suite
end

the sort_by method get's all the values of the suites of the cards in
the deck and then sorts them according to that. The suite could be a
string ("Hearts") or a numeric value (0=3DHearts, 1=3DDiamonds etc). For
instance

[1,2,3,4].sort_by do |number|
number % 2
end

will return [4,2,3,1]. Because the value of the block can either be 0
or 1 the array is sorted into two 'chunks': 4 & 2 (number % 2 =3D=3D0) 1
& 3 (number % 2 =3D=3D 1).

Farrel
 
D

dblack

Hi --

So suppose you have a deck of cards, that might have some number of cards.

First the cards are shuffled, in effect placed in random order.

Then the deck is split, ie. some number of cards are lifted from the top
of the deck and placed under the remaining cards.

How would one implement this? I was thinking of using an array, but how to
shuffle the deck, and how to split the deck?

I have to say, it only dawned on me just now that it's kind of funny
to cut the deck when the dealer is a computer. The idea of cutting
the deck is to thwart attempts by the dealer to stack the deck. I
actually kind of love the idea that one has to do this in the case of
a computer :)


David

--
David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
 
G

gparsons

deck = deck[x..-1] + deck[0...x] # notice differing amounts of
dots

I'd never seen this before so i decided to give it a try. Without the
three dots on the righthand side it would be inclusive right? As in
you'd get the xth element twice.

- Geoff
 
D

dblack

Hi --

deck = deck[x..-1] + deck[0...x] # notice differing amounts of
dots

I'd never seen this before so i decided to give it a try. Without the
three dots on the righthand side it would be inclusive right? As in
you'd get the xth element twice.

Yes, that's right.


David

--
David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
 
J

James Edward Gray II

I think you're confusing the <=> operator needed to mixin Enumerable.

Technically, the only method required by Enumerable is each(). You
do need to provide <=>() if you want to use method like sort(), min
(), or max() without a block though.

The Comparable mix-in requires <=>().

James Edward Gray II
 
M

Matthew Moss

I point it out to people who I think may not have seen it before, just
so they don't think it a typo.

It doesn't really bother me, because I've gotten used to it. And I
regularly make use of it, as deep as I am into C++ standard template
library practice.

Unit testing could catch some errors, but I do agree if something
reasonably simple could replace it syntax-wise, it might be a tad
better. What that something simple is, I don't know... The simplest
solution would be to use mathematical notation, but that would be a
pita for the compiler to parse: [0..x)


Matthew said:
deck =3D deck[x..-1] + deck[0...x] # notice differing amounts of dots

I find myself constantly pointing this out too.. is anyone else bothered
by it? Has Matz weighed in on this in the past?

It seems error-prone to me. Extraordinarily more error-prone than other
"stuff" in Ruby.

--Steve
 
S

Stephen Waits

[snip]

Well, it's definitely one of the (very) few things that has bothered me
about Ruby. For example:

A Rubyist might argue that this is more error prone:

for(int i=0;i<10;i++)

than this:

10.times

Which is a valid argument, and the result is elegant. And, we see stuff
like this throughout Ruby. As Why's guide says often, read the code aloud.

So yes, .. vs ... really bugs me. While they are convenient operators,
I also see them as too error prone to fit in Ruby.

As an earlier mentioned example, when I've taught Ruby, I always feel
like I have to wave the red flags when I talk about ranges.
Unit testing could catch some errors, but I do agree if something
reasonably simple could replace it syntax-wise, it might be a tad
better. What that something simple is, I don't know... The simplest
solution would be to use mathematical notation, but that would be a
pita for the compiler to parse: [0..x)

Yah, [x..y], [x..y), (x..y], (x..y) would be sweetness. It's slightly
less error-prone IMO since it's following a common (math) notation.
Still, maybe not perfect.

Do any of the Ruby dinosaurs know if Matz has a stance on this issue?

--Steve
 
G

grrr

First of all I wish to humbly send my thanks everyone taking their time to
share their pearls of wisdom! You have taught me alot! Hehe my honorable
mention goes to James for the cards.sort_by{ rand } which is nice and
snappy. Also, I thought the 'deck = deck[x..-1] + deck[0...x]' was clear
to me, even if I am a ruby newb. Now lets move on..

I have to say, it only dawned on me just now that it's kind of funny to
cut the deck when the dealer is a computer. The idea of cutting the deck
is to thwart attempts by the dealer to stack the deck. I actually kind of
love the idea that one has to do this in the case of a computer :)

Yes, I want the whole deal to be as realistic as possible! Down to
last detail! In real life cards are not really shuffled into random
order!

And thus theres need for realistic Riffle! 8)

Around here, before any card games, after the deck has been
cut into two by the dealer it is of course 'recombined' by taking the two
decks, and mixing them back into one deck, in a manouver called 'the
riffle'.

"A riffle, in which half of the deck is held in each hand with the thumbs
inward, then cards are released by the thumbs so that they fall to the
table intertwined." Thus *almost* every card other card is from the other
half of the deck, and vice versa - with the odd double, triple or
quadruple cards sometimes falling on the table from either pack!

You can find a photo and detailed description of the riffle here:
http://en.wikipedia.org/wiki/Shuffle

This is done three times, and finally one of the players
gets to cut the deck and the dealer then recombines it and deals out
cards. Ie. dealer does 'cut + riffle' three times, then player 'cuts',
then dealer riffles, and game can then begin.

How would you code riffle?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,667
Latest member
DaniloB294

Latest Threads

Top