# [QUIZ] Counting Cards (#152)

Discussion in 'Ruby' started by Ruby Quiz, Jan 11, 2008.

1. ### Ruby QuizGuest

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Learning to count cards is much easier than Hollywood or the casinos would have
us believe. Some systems only require you to track a single running total in

One such system, called the Knock-out system of card counting, is extra easy.
You start your count at 4 - (4 x number_of_decks). That gives us an initial
running count of 0, -4, -20, or -28 for the common casino shoe sizes of 1, 2, 6,
or 8 decks. From there, you add one each time you see a 2, 3, 4, 5, 6 or 7 and
subtract one when you see a 10, jack, queen, king, or ace. The 8 and 9 cards do
not affect the count. Once you learn to track the running count, you can make
strategy decisions and vary your bets based on the times when the count is in

That's not a lot to remember, but it does take practice to get fast. You really
need to get to where you can count a deck in 20 to 30 seconds if you are going
to keep up with those fast moving casinos dealers.

This week's Ruby Quiz is to build a training program for helping you learn to
count cards.

The program needs to show you one or more cards at a time, running through a
Blackjack shoe. As it goes, the program should track the running count. Have
it pause at random intervals, ask you the count, and notify you if you are right
or wrong.

Both the time to go through the deck and the number of cards displayed at a time
should be configurable. It's important to practice with seeing multiple cards
at once because you learn to cancel out pairs of high and low cards. It might
even be nice to provide a mixed mode, which varies the number of cards shown at
a time.

You can show cards as simple Strings, ASCII art, or full graphics as you prefer.
You may wish to make cards fully disappear after their display time though, to
make the conditions more like they would be in a casino.

Ruby Quiz, Jan 11, 2008

2. ### Robert DoberGuest

On Jan 11, 2008 2:56 PM, Ruby Quiz <> wrote:
> The three rules of Ruby Quiz:
>
> 1. Please do not post any solutions or spoiler discussion for this quiz until
> 48 hours have passed from the time on this message.
>
> 2. Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3. Enjoy!
>
> Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
> if you can.
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
> Learning to count cards is much easier than Hollywood or the casinos would have
> us believe. Some systems only require you to track a single running total in
>
> One such system, called the Knock-out system of card counting, is extra easy.
> You start your count at 4 - (4 x number_of_decks). That gives us an initial
> running count of 0, -4, -20, or -28 for the common casino shoe sizes of 1, 2, 6,
> or 8 decks. From there, you add one each time you see a 2, 3, 4, 5, 6 or 7 and
> subtract one when you see a 10, jack, queen, king, or ace. The 8 and 9 cards do
> not affect the count. Once you learn to track the running count, you can make
> strategy decisions and vary your bets based on the times when the count is in
>
> That's not a lot to remember, but it does take practice to get fast. You really
> need to get to where you can count a deck in 20 to 30 seconds if you are going
> to keep up with those fast moving casinos dealers.
>
> This week's Ruby Quiz is to build a training program for helping you learn to
> count cards.
>
> The program needs to show you one or more cards at a time, running through a
> Blackjack shoe. As it goes, the program should track the running count. Have
> it pause at random intervals, ask you the count, and notify you if you are right
> or wrong.
>
> Both the time to go through the deck and the number of cards displayed at a time
> should be configurable. It's important to practice with seeing multiple cards
> at once because you learn to cancel out pairs of high and low cards. It might
> even be nice to provide a mixed mode, which varies the number of cards shown at
> a time.
>
> You can show cards as simple Strings, ASCII art, or full graphics as you prefer.
> You may wish to make cards fully disappear after their display time though, to
> make the conditions more like they would be in a casino.
>

Nice quiz James but shall those who want to continue to play BJ in
casinos maybe refrain from posting answers .
I am saying this just to be the only to answer of course.
Robert
--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Robert Dober, Jan 11, 2008

3. ### James GrayGuest

On Jan 11, 2008, at 10:15 AM, Robert Dober wrote:

> Nice quiz James but shall those who want to continue to play BJ in
> casinos maybe refrain from posting answers .
> I am saying this just to be the only to answer of course.

If you're asking me if counting cards is illegal, the answer is no, at
least in the United States. The casinos like to push that myth but
they will need to overturn a Supreme Court ruling to turn it into
reality.

However, when gambling at the casinos, you are on private property and
essentially subject to their whims. They can and definitely do:
alter the rules of the game to remove your advantage, force you to
stop varying your bets (the card counter's main weapon), or eject you
from the game or the casino. The point is, it's not illegal but you
still don't want to be caught doing it.

The key is not to get noticed. Pit bosses are trained in many card
counter recognition tricks. They will watch for someone who doesn't
make basic strategy errors, someone who varies their bets at seemingly
random times, someone who doesn't drink or tip the dealer, etc. Some
of them are also trained to count cards themselves. Once identified,
they will take countermeasures, so it's that identification process
you never want to get past.

Pit bosses tend to try relying on memorizing your most prominent
physical feature for possible future encounters.

The point of all of this is simple: while it's conceivable that
participating in this quiz could get you identified as a card counter,
it's unlikely a pit boss will recognize you when you sit down at the
have some fun.

If Ruby Quiz becomes responsible for more people winning at the
Blackjack tables, that's just an added bonus to me.

James Edward Gray II

James Gray, Jan 11, 2008
4. ### Robert DoberGuest

On Jan 11, 2008 5:48 PM, James Gray <> wrote:
> On Jan 11, 2008, at 10:15 AM, Robert Dober wrote:
>
> > Nice quiz James but shall those who want to continue to play BJ in
> > casinos maybe refrain from posting answers .
> > I am saying this just to be the only to answer of course.

>
> If you're asking me if counting cards is illegal, the answer is no, at
> least in the United States. The casinos like to push that myth but
> they will need to overturn a Supreme Court ruling to turn it into
> reality.
>
> However, when gambling at the casinos, you are on private property and
> essentially subject to their whims. They can and definitely do:
> alter the rules of the game to remove your advantage, force you to
> stop varying your bets (the card counter's main weapon), or eject you
> from the game or the casino. The point is, it's not illegal but you
> still don't want to be caught doing it.
>
> The key is not to get noticed. Pit bosses are trained in many card
> counter recognition tricks. They will watch for someone who doesn't
> make basic strategy errors, someone who varies their bets at seemingly
> random times, someone who doesn't drink or tip the dealer, etc. Some
> of them are also trained to count cards themselves. Once identified,
> they will take countermeasures, so it's that identification process
> you never want to get past.
>
> Pit bosses tend to try relying on memorizing your most prominent
> physical feature for possible future encounters.
>
> The point of all of this is simple: while it's conceivable that
> participating in this quiz could get you identified as a card counter,
> it's unlikely a pit boss will recognize you when you sit down at the
> have some fun.
>
> If Ruby Quiz becomes responsible for more people winning at the
> Blackjack tables, that's just an added bonus to me.

Thx for that detailed description of what is going on - I kind of
understood it like this.

Robert
>
> James Edward Gray II
>
>
>

--
http://ruby-smalltalk.blogspot.com/

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Robert Dober, Jan 11, 2008
5. ### Ken BloomGuest

On Fri, 11 Jan 2008 11:48:53 -0500, James Gray wrote:

> The point of all of this is simple: while it's conceivable that
> participating in this quiz could get you identified as a card counter,
> it's unlikely a pit boss will recognize you when you sit down at the
> some fun.

Only if you're careful online and they can't piece together your picture
ever read "Bringing down the House", there's a whole network between the
casinos to share pictures and information about card counters.

--Ken

--
Ken (Chanoch) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

Ken Bloom, Jan 11, 2008
6. ### James GrayGuest

On Jan 11, 2008, at 1:40 PM, Ken Bloom wrote:

> On Fri, 11 Jan 2008 11:48:53 -0500, James Gray wrote:
>
>> The point of all of this is simple: while it's conceivable that
>> participating in this quiz could get you identified as a card
>> counter,
>> it's unlikely a pit boss will recognize you when you sit down at the
>> have
>> some fun.

>
> Only if you're careful online and they can't piece together your
> picture
> ever read "Bringing down the House", there's a whole network between
> the
> casinos to share pictures and information about card counters.

I knew that they use to do a lot of this in the past. I wasn't sure
how much it still goes on after Griffin went bankrupt. The courts did
rule they were invading privacy after all.

I guess I still feel it's unlikely spies are watching the Ruby Quiz in
the hopes of nabbing card counters using training software. Imagining
them scouring the Web for more details on these just seems to add to
the paranoia.

Of course, only participate in this quiz if you feel safe.

James Edward Gray II

James Gray, Jan 11, 2008
7. ### Denis HennessyGuest

This week's puzzle had two challenges:

1. Implement a simple card counting scheme.
2. Present a simulated card deal to the user to help him develop the
counting technique.

The real challenge is the second part. I ruled out the card names
(3d,As,Tc...) and the ascii art options which left me needing a way of
display proper graphic card images. I had a brief look at some gui
toolkits (shoes, tk, ...) but in the end decided on a browser-based
approach. I made a simple rails app and used an ajax request to update
and unpack it into a temporary directory. Then run ./script/server
and browse to http://localhost:3000/card_counter

The card counting algorithm is implemented first. The Counter class
contains both the shuffled shoe as well as the running count.

card_counter.rb:
CARDS = %w{A K Q J T 9 8 7 6 5 4 3 2}
SUITS = %w{c s h d}

class Counter
def initialize(decks)
@count = 4 - 4*decks
@shoe = []
decks.times do
CARDS.each do |c|
SUITS.each do |s|
@shoe << c.to_s + s.to_s
end
end
end
size = 52*decks
size.times do |i|
j = rand(size)
@shoe,@shoe[j] = @shoe[j],@shoe
end
end

def deal
card = @shoe.pop
@count += 1 if "234567".include? card[0,1].to_s
@count -= 1 if "TJQKA".include? card[0,1].to_s
card
end

def count
@count
end

def size
@shoe.size
end
end

Then I made a rails app with a controller called
card_counter_controller.rb and a web page (practice.html.erb) to 'run'
the training. The interesting bit is the periodically_call_remote()
call which gets a new set of cards every n seconds and displays them
to the user. A pause button suspends the dealing and displays the
current count. I found a free set of card images at http://www.jfitz.com/cards/

card_counter_controller.rb:
require 'card_counter'

class CardCounterController < ApplicationController

def practice
session[:counter] = Counter.new params[:decks].to_i
session[:min] = params[:min].to_i
session[:max] = params[:max].to_i
session[:delay] = params[:delay].to_i
end

def deal
min = session[:min]
max = session[:max]
counter = session[:counter]
max = counter.size if counter.size<max
min = max if max < min
count = min + rand(max-min+1)
text = ""
text = "Shoe complete" if count == 0
count.times do
card = session[:counter].deal
text += "<img src='/images/#{card_index(card)}.png' width='72'
height='96'/>\n"
end
text += "<p id='count' style='visibility: hidden'>Count is
#{counter.count}</p>"
render :text => text
end

# Convert card name ("6d", "Qs"...) to image index where 1=Ac,2=As,
def card_index(card)
c = CARDS.index card[0,1].to_s
s = SUITS.index card[1,1].to_s
c * 4 + s + 1
end
end

practice.html.erb:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-
strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<%= javascript_include_tag :defaults %>
<title>Practice Card Counting</title>
<script type="text/javascript">
//<![CDATA[
paused = false;
function pause() {
paused = !paused;
if (paused) {
\$('count').setStyle('visibility: visible');
\$('pause').update('Continue')
} else {
\$('pause').update('Pause')
}
}
//]]>
</script>
<body>
<a id='pause' href="#" onClick="pause()">Pause</a>
<div id="cards"></div>

<%= periodically_call_remote(
:condition => "paused == false",
:update => "cards",
:frequency => session[:delay],
:url => { :action => "deal" }) %>
</body>
</html>

Enjoy,
Denis
>

Denis Hennessy, Jan 13, 2008
8. ### Denis HennessyGuest

On 13 Jan 2008, at 18:21, Robert Dober wrote:

> The attached solution does not seem to work on Windows
> (Timeout::timeout does not timeout) and as I have no Mac I cannot
> tell.

It does indeed work fine on a Mac.

/dh

Denis Hennessy, Jan 13, 2008
9. ### tho_mica_lGuest

Re: Counting Cards (#152)

Two basic ASCII front-ends are provided. If figlet is available and
the
script is run with the -f command line option, you get a slightly
more
appealing visualization of the cards. Otherwise only the card names
are
displayed.

Command-line options:
quiz152 [TIME=2] [CARDS=2] [DECKS=4] [MAXSTEP=10]
- pause between deals
- max cards displayed simultaneously
- number of decks
- after max steps, users are asked to make their guess

Thomas.

#!/usr/bin/env ruby
# Author:: Thomas Link (micathom AT gmail com)
# Created:: 2008-01-11.

module Quiz152; end

class Quiz152::Game
NAMES = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
VALUES = [1] * 6 + [0, 0] + [-1] * 5
SUITS = ['c', 'd', 'h', 's']

def initialize(ui, time=2, cardn=2, decks=4, maxstep=10)
@ui = ui.new(self)
@time = time
@msgtime = 1
@cardn = cardn
@maxstep = maxstep
cards = NAMES.zip(VALUES)
@cards = SUITS.inject([]) {|a, s| a += cards.map{|c| c.dup
<< s}} * decks
@decks = decks
@count = 4 - 4 * decks
end

def run
@ui.message "Decks: #@decks",
"Pause: #{@time}s",
"Cards at a time: 1-#@cardn",
@ui.input
while deal(rand(@maxstep) + 1)
break unless query_count
end
@ui.message "Bye!"
end

def deal(n)
n.times do
@ui.deal_new
(1 + rand(@cardn)).times do |i|
cname, cvalue, csuit =
@cards.delete_at(rand(@cards.size))
if cname
@ui.deal_card(i, cname, csuit)
@count += cvalue
else
@ui.message('This is the end.')
return false
end
end
@ui.deal_show
sleep @time
end
return true
end

def query_count
@ui.clear
count = @ui.input.chomp
if ['q', 'x', 'bye', 'exit', 'quit'].include?(count)
return false
else
case count.to_i
when 0
@ui.message "The current count is #@count."
when @count
@ui.message "Well."
else
@ui.message "It's always a pleasure playing with you.
(count: #@count)"
end
sleep @msgtime
return true
end
end

end

class Quiz152::TextUI
def initialize(game)
@game = game
clear
end

def message(*text)
text.each {|t| puts t}
end

def input
STDIN.gets
end

def clear
100.times {puts "\n"}
end

def deal_card(nth, name, suit)
@output << [name]
end

def deal_new
@output = []
clear
end

def deal_show
@output.transpose.each do |lines|
puts lines.join(' ')
end
puts
end

end

class Quiz152::Figlet < Quiz152::TextUI
def initialize(*args)
super
@t_card = <<'CARD'
__________________
/ \
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
\__________________/
CARD
@t_suit = {
'c' => <<'SUIT',
_
_/ \_
/ \_/ \
\_/^\_/
/_\
SUIT
'd' => <<'SUIT',

/\
/ \
\ /
\/
SUIT
'h' => <<'SUIT',
_ _
/ \/ \
\ /
\ /
\/
SUIT
's' => <<'SUIT',
__
/ \
| |
\_/\_/
/__\
SUIT
}
end

def deal_card(nth, name, suit)
card = @t_card.dup.split("\n")
fill_card(card, @t_suit[suit], 3, 2)
fill_card(card, `figlet -k "#{name}"`, 8, 8)
@output << card
end

def fill_card(template, text, x0, y0)
text.each_with_index do |l, i|
template[i + y0][x0 .. (x0 + l.size - 2)] = l.chomp
end
template
end
end

if __FILE__ == \$0
ui = Quiz152::TextUI
loop do
case ARGV[0]
when '-h', '--help'
puts "#\$0 [TIME=2] [CARDS=2] [DECKS=4] [MAXSTEP=10]"
exit 1
when '-f', '--figlet'
ui = Quiz152::Figlet
ARGV.shift
else
break
end
end

Quiz152::Game.new(ui, *ARGV.map{|e| e.to_i}).run
end

tho_mica_l, Jan 13, 2008
10. ### Robert DoberGuest

On Jan 13, 2008 11:34 PM, Denis Hennessy <> wrote:
> On 13 Jan 2008, at 18:21, Robert Dober wrote:
>
> > The attached solution does not seem to work on Windows
> > (Timeout::timeout does not timeout) and as I have no Mac I cannot
> > tell.

>
> It does indeed work fine on a Mac.

Oh thanks, BTW great solution you have come up with.
R.

Robert Dober, Jan 14, 2008