[QUIZ] Counting Cards (#152)

R

Ruby Quiz

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
on Ruby Talk follow the discussion. Please reply to the original quiz message,
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
your head.

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
your favor.

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.
 
R

Robert Dober

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
on Ruby Talk follow the discussion. Please reply to the original quiz message,
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
your head.

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
your favor.

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
 
J

James Gray

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
table from your email address. Thus, I think we're safe and should
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
 
R

Robert Dober

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
table from your email address. Thus, I think we're safe and should
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
 
K

Ken Bloom

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
table from your email address. Thus, I think we're safe and should have
some fun.

Only if you're careful online and they can't piece together your picture
with your email address from other sources (e.g. Facebook). If you've
ever read "Bringing down the House", there's a whole network between the
casinos to share pictures and information about card counters.

--Ken
 
J

James Gray

Only if you're careful online and they can't piece together your
picture
with your email address from other sources (e.g. Facebook). If you've
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
 
D

Denis Hennessy

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
the training page. If anyone wants to try it, download http://www.hennessynet.com/counter.tar.gz
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,
3=Ah,4=Ad,5=Kc and so on
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">
<head>
<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>
</head>
<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
 
D

Denis Hennessy

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
 
T

tho_mica_l

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",
"Ready? (Press ENTER)"
@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
@ui.message 'Your guess:'
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
 

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
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top