[QUIZ SOLUTION] Euchre Hands (#55)

R

Robin Stocker

Hi

This one seemed pretty easy, so I gave it a try.

My first idea was to solve the whole sorting in the <=> method of the
Card class. But it was too confusing this way, because I had to include
all possible comparisons. Also the Card itself had to know what the
trump suit was.

Then I tried a different approach. I wrote a Card#weighting method which
returned a number, for trump jack a 41, for trump color jack a 40, and
so on. Then i sorted the card array with sort_by and the weighting. But
I wasn't satisfied yet, because again, the card had to know what suit
was trump. And the numbering was ugly, too. :)

So my final idea was to just implement the <=> method for sorting
without regard to trump. Then in my Hand class, which knows about the
trump, I wrote a sort! method for the sorting with regard to trump suit.

Now I'm interested to see other solutions :)

Robin Stocker


module Euchre

class Hand
attr_accessor :cards

def initialize( trump )
@cards = []
@trump = Card.new( trump )
end

def <<( card )
@cards << card
end

def sort!
@cards =
# First the trump jack..
@cards.select{ |c| trump_suit?(c) and c.jack? } |
# then the jack of the trump color..
@cards.select{ |c| trump_color?(c) and c.jack? } |
# then all the trump cards..
@cards.select{ |c| trump_suit?(c) }.sort.reverse |
# then a different color, so the colors alternate..
@cards.select{ |c| !trump_color?(c) and
c.suit =~ /d|c/ }.sort.reverse |
# then the cards with the same color as the trump..
@cards.select{ |c| trump_color?(c) }.sort.reverse |
# and finally the rest.
@cards.sort.reverse
end

def trump_suit?( card ) card.suit == @trump.suit end
def trump_color?( card ) card.color == @trump.color end

def to_s
@cards.join("\n")
end
end

class Card
attr_accessor :suit, :face

Suits = ['d', 'h', 'c', 's']
Faces = ['9', 'T', 'J', 'K', 'A']
Colors = {'d' => :red, 'h' => :red, 'c' => :black, 's' => :black}

def initialize( suit, face=nil )
@suit = suit.downcase
@face = face.upcase if face
end

def jack?() @face == 'J' end
def color() Colors[@suit] end

# Sort first by suit and then by face.
def <=>( other )
rel = Suits.index(@suit) - Suits.index(other.suit)
rel = Faces.index(@face) - Faces.index(other.face) if rel == 0
rel
end

def to_s
@face + @suit
end
end

end


if __FILE__ == $0
lines = readlines

trump = lines.shift.slice(/\w+/)
hand = Euchre::Hand.new(trump[0,1])

lines.join.scan(/(\w)(\w)/) do |face, suit|
hand << Euchre::Card.new(suit, face)
end

hand.sort!
puts trump
puts hand
end
 
E

Edward Faulkner

--TB36FDmn/VVEgNH/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Here's my minimalist solution: 20 lines. I believe it always gets
both rank and color-alternation correct. If you only want to get
alternation correct *most* of the time, you can cut out another five
lines. :)

SUITS =3D %w{d c h s}.map {|s| s[0]}
CARDS =3D %w{A K Q J T 9}.map {|c| c[0]}

trump,hand =3D STDIN.readline, STDIN.readlines

puts trump
trump =3D SUITS.index(trump.downcase[0])

# If the suit after the trump suit is missing, we swap it with the
# other suit of the same color. This ensures that we always have a
# correct color alternation when possible.
unless hand.find {|card| card[1] =3D=3D SUITS[(trump+1)%4]}
tmp =3D SUITS[(trump+1)%4]
SUITS[(trump+1)%4] =3D SUITS[(trump+3)%4]
SUITS[(trump+3)%4] =3D tmp
end

hand.map { |card|=20
suit =3D (SUITS.index(card[1]) - trump)%4
num =3D CARDS.index(card[0])
if num=3D=3D3 && suit=3D=3D2
suit,num =3D 0,-1 # Left bower
elsif num=3D=3D3 && suit=3D=3D0
num =3D -2 # Right bower
end
[suit,num,card.chomp]
}.sort.each{|c| puts "#{c[2]}\n" }


--TB36FDmn/VVEgNH/
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFDgJmYnhUz11p9MSARAt1cAKC8/V15WvvXCnxPxtmkvOPHLS9KRwCbBu4G
9+kkX5s6DVtZP4uGzXHKX5g=
=EaVm
-----END PGP SIGNATURE-----

--TB36FDmn/VVEgNH/--
 
R

Ryan Leavengood

I made two solutions, both of which use the same basic algorithm of
applying weights (where smaller is better) to the cards and then
sorting by weight. The comments in the first "normal" version should
explain things.

The second version is my highly golfed version which I think is about
as small as my algorithm can get. It is 242 bytes. I would be very
interested to see if anyone can go smaller, either by tweaking mine
more, or more likely, by golfing another algorithm. Obviously the
golfed code has zero error handling, so it will probably choke on any
bad input.

Normal code:

class String
def to_suit
self[0..0].downcase
end
end

class EuchreSort
# These represent preferred sorting order
SUITS =3D %w{Diamonds Clubs Hearts Spades} # Alphabetical, then by color
CARDS =3D %w{A K Q J T 9} # Highest to lowest

def initialize(trump)
@trump =3D trump
trump_index =3D SUITS.index(trump)
raise "Invalid trump suit: #{trump}" unless trump_index
@right_bower =3D "J#{trump.to_suit}"
# The ordering used in SUITS ensures this works
@left_bower =3D "J#{SUITS[(trump_index+2)%4].to_suit}"
# Apply weights to suits starting from the trump, wrapping
# around as needed
@suit_weights =3D {}
weight =3D 10
trump_index.upto(trump_index+3) do |i|
@suit_weights[SUITS[i%4].to_suit] =3D weight
weight +=3D 10
end
end

def sort(hand)
weights =3D {}
hand.each do |card|
raise "Invalid card: #{card}" if card !~ /\A[#{CARDS.join}]{1}[dchs]{=
1}\z/
weights[card] =3D
case card
when @right_bower: 0
when @left_bower: 1
else
@suit_weights[card[1..1]] + CARDS.index(card[0..0])
end
end
hand.sort_by {|c| weights[c]}
end
end

if $0 =3D=3D __FILE__
hand =3D STDIN.collect {|i|i.chomp}
trump =3D hand.shift
es =3D EuchreSort.new(trump)
puts trump
puts es.sort(hand)
end

Golfed code (I'm not sure how Gmail will wrap this, but it should be
all on one line):

a=3D$<.read.split("\n");s=3D%w{d c h
s};c=3D'AKQJT9';t=3Da.shift;u=3D(t[0]+32).chr;i=3Ds.index(u);v=3Ds[(i+2)%4]=
;w=3D[1];i.upto(i+3){|j|w<<s[j%4]};m=3D{};a.each{|k|m[k]=3Dk=3D~/(J#{u})|(J=
#{v})/?$1?0:1:w.index(k[1..1])*10+c.index(k[0..0])};puts
t,a.sort_by{|k|m[k]}

Ryan
 
J

James Edward Gray II

Hi

This one seemed pretty easy, so I gave it a try.

Just FYI, this solution seems to have trouble with certain inputs:

Neo:~/Documents/Ruby/Ruby Quiz$ ruby solutions/euchre_hand.rb >
test_hand.txt
Neo:~/Documents/Ruby/Ruby Quiz$ ruby solutions/Robin\ Stocker/
euchre_hands.rb test_hand.txt
solutions/Robin Stocker/euchre_hands.rb:58:in `-': nil can't be
coerced into Fixnum (TypeError)
from solutions/Robin Stocker/euchre_hands.rb:58:in `<=>'
from solutions/Robin Stocker/euchre_hands.rb:27:in `sort'
from solutions/Robin Stocker/euchre_hands.rb:27:in `sort!'
from solutions/Robin Stocker/euchre_hands.rb:80
Neo:~/Documents/Ruby/Ruby Quiz$ cat test_hand.txt
hearts
9s
9d
Kd
Ah
Qd

That's really not meant as a complaint. I appreciate you sharing
your solution. It works more often than not and always seems to
produce correct answers when it does. I just thought you might like
to know.

James Edward Gray II
 
J

James Edward Gray II

=begin


This is mine, I didn't bother putting it into a class.

Hmm, is this correct:

Neo:~/Documents/Ruby/Ruby Quiz$ ruby solutions/euchre_hand.rb >
test_hand.txtNeo:~/Documents/Ruby/Ruby Quiz$ ruby solutions/Christian
\ Neukirchen/euchre_hands.rb test_hand.txt
Qh
9h
Qd
9d
Qc
Neo:~/Documents/Ruby/Ruby Quiz$ cat test_hand.txt
hearts
Qd
9h
9d
Qc
Qh

I would have answered:

hearts
Qh
9h
Qc
Qd
9d

Which doesn't put two red suits together. Getting back to the
question of the quiz, how do we know when we're right?

James Edward Gray II
 
R

Robin Stocker

James said:
Just FYI, this solution seems to have trouble with certain inputs:

Ah, thank you... I just noticed that I forgot the queen in my Faces array :)

I also updated the script to get the alternating colors right.

Thanks for finding this (stupid) error.

Robin Stocker


module Euchre

class Hand
attr_accessor :cards

def initialize( trump )
@cards = []
@trump = Card.new( trump )
end

def <<( card )
@cards << card
end

def sort!
second_suit = @cards.find{ |c| !trump_color?(c) }.suit
@cards =
# First the trump jack..
@cards.select{ |c| trump_suit?(c) and c.jack? } |
# then the jack of the trump color..
@cards.select{ |c| trump_color?(c) and c.jack? } |
# then all the trump cards..
@cards.select{ |c| trump_suit?(c) }.sort.reverse |
# then a different color, so the colors alternate..
@cards.select{ |c| c.suit == second_suit }.sort.reverse |
# then the cards with the same color as the trump..
@cards.select{ |c| trump_color?(c) }.sort.reverse |
# and finally the rest.
@cards.sort.reverse
end

def trump_suit?( card ) card.suit == @trump.suit end
def trump_color?( card ) card.color == @trump.color end

def to_s
@cards.join("\n")
end
end

class Card
attr_accessor :suit, :face

Suits = ['d', 'h', 'c', 's']
Faces = ['9', 'T', 'Q', 'J', 'K', 'A']
Colors = {'d' => :red, 'h' => :red, 'c' => :black, 's' => :black}

def initialize( suit, face=nil )
@suit = suit.downcase
@face = face.upcase if face
end

def jack?() @face == 'J' end
def color() Colors[@suit] end

# Sort first by suit and then by face.
def <=>( other )
rel = Suits.index(@suit) - Suits.index(other.suit)
rel = Faces.index(@face) - Faces.index(other.face) if rel == 0
rel
end

def to_s
@face + @suit
end
end

end


if __FILE__ == $0
lines = readlines

trump = lines.shift.slice(/\w+/)
hand = Euchre::Hand.new(trump[0,1])

lines.join.scan(/(\w)(\w)/) do |face, suit|
hand << Euchre::Card.new(suit, face)
end

hand.sort!
puts trump
puts hand
end
 
D

Dale Martenson

I used to play euchre a lot in college so this was fun. It might be fun
writing an entire euchre game.

What I did was first think about the best test to prove my solution. If
you have a completely shuffled euchre deck for a specfic trump, the
entire deck would take on a known order. So I wrote four tests:

require 'test/unit'
require 'euchre'

HEARTS_AS_TRUMP_DECK = [
'Jh','Jd','Ah','Kh','Qh','Th','9h',
'As','Ks','Qs','Js','Ts','9s',
'Ad','Kd','Qd','Td','9d',
'Ac','Kc','Qc','Jc','Tc','9c'
]

SPADES_AS_TRUMP_DECK = [
'Js','Jc','As','Ks','Qs','Ts','9s',
'Ad','Kd','Qd','Jd','Td','9d',
'Ac','Kc','Qc','Tc','9c',
'Ah','Kh','Qh','Jh','Th','9h'
]

DIAMONDS_AS_TRUMP_DECK = [
'Jd','Jh','Ad','Kd','Qd','Td','9d',
'Ac','Kc','Qc','Jc','Tc','9c',
'Ah','Kh','Qh','Th','9h',
'As','Ks','Qs','Js','Ts','9s',
]

CLUBS_AS_TRUMP_DECK = [
'Jc','Js','Ac','Kc','Qc','Tc','9c',
'Ah','Kh','Qh','Jh','Th','9h',
'As','Ks','Qs','Ts','9s',
'Ad','Kd','Qd','Jd','Td','9d'
]

class TestEuchre < Test::Unit::TestCase
def setup
@ed = EuchreDeck.new
@eh = EuchreHand.new
@ed.shuffle
while( card = @ed.deal )
@eh.add_card( card )
end
end

def test_hearts_as_trump
@eh.trump = "Hearts"
assert_equal( HEARTS_AS_TRUMP_DECK, @eh.hand )
end

def test_spades_as_trump
@eh.trump = "Spades"
assert_equal( SPADES_AS_TRUMP_DECK, @eh.hand )
end

def test_diamonds_as_trump
@eh.trump = "Diamonds"
assert_equal( DIAMONDS_AS_TRUMP_DECK, @eh.hand )
end

def test_clubs_as_trump
@eh.trump = "Clubs"
assert_equal( CLUBS_AS_TRUMP_DECK, @eh.hand )
end
end

I took the original input program and created a EuchreDeck class:

class EuchreDeck
def initialize
# build a Euchre deck
@cards = Array.new
%w{9 T J Q K A}.each do |face|
%w{d c s h}.each do |suit|
@cards << face + suit
end
end
end

def shuffle
@cards = @cards.sort_by { rand }
end

def deal
@cards.shift
end
end

I wrote a EuchreHand class that would take cards dealt to it and
originize them by a computed card value using sort.

class EuchreHand
Suit = Struct.new( :suit, :alternate_suit_1, :eek:ff_suit,
:alternate_suit_2 )

@@suits = {
"Diamonds"=>Suit.new("d","c","h","s"),
"Clubs"=>Suit.new("c","h","s","d"),
"Spades"=>Suit.new("s","d","c","h"),
"Hearts"=>Suit.new("h","s","d","c")
}

@@face_values_trump = {
"J" => 6,
"A" => 4,
"K" => 3,
"Q" => 2,
"T" => 1,
"9" => 0
}

@@face_values_regular = {
"A" => 5,
"K" => 4,
"Q" => 3,
"J" => 2,
"T" => 1,
"9" => 0
}

MAX_CARDS_PER_SUIT = 7

def initialize
@trump = nil
@hand = []
end

def left_brower?( card )
card == "J#{@trump.off_suit}"
end

def trump?( card )
card[1].chr == @trump.suit
end

def trump=( suit_string )
@trump = @@suits[ suit_string ]
end

def trump
@@suits.index(@trump)
end

def add_card( card )
@hand.push( card )
end

def card_value( card )
face = card[0].chr
suit = card[1].chr

if left_brower?(card) then
suit_value = @trump.to_a.reverse.index( @trump.suit ) *
MAX_CARDS_PER_SUIT
face_value = @@face_values_trump[ face ] - 1
elsif trump?(card) then
suit_value = @trump.to_a.reverse.index( @trump.suit ) *
MAX_CARDS_PER_SUIT
face_value = @@face_values_trump[ face ]
else
suit_value = @trump.to_a.reverse.index( suit ) *
MAX_CARDS_PER_SUIT
face_value = @@face_values_regular[ face ]
end

suit_value + face_value
end

def hand
@hand.sort {|x,y| card_value(y)<=>card_value(x) }
end
end

Once my tests passed, I rewrote the original input program as:

require 'euchre'

# choose trump
puts %w{Diamonds Clubs Spades Hearts}[rand(4)]

ed = EuchreDeck.new
ed.shuffle
5.times{ puts ed.deal }

And the sort program as:

require 'euchre'

eh = EuchreHand.new

eh.trump = gets.strip

while card = gets
eh.add_card( card.strip )
end

puts eh.trump
puts eh.hand

It would be a fun to attempt to create a EuchreBot to actually play.

--Dale
 
J

James Edward Gray II

I used to play euchre a lot in college so this was fun. It might be
fun
writing an entire euchre game.
[snip]

It would be a fun to attempt to create a EuchreBot to actually play.

I agree. Maybe if you and I got a server together, building AI
players would make a good quiz for it? Drop me and email if this
interests you...

James Edward Gray II

P.S. Nice proof of your solution!
 
D

Dominik Bathon

Here is my solution.

It also sorts the the cards by a score computed depending on the trump =20
suit, lower is better.

Dominik


The code:

class EuchreCard

SUIT_COLOR =3D {
:diamonds =3D> :red,
:hearts =3D> :red,
:clubs =3D> :black,
:spades =3D> :black
}
SUIT_ORDER =3D [:diamonds, :clubs, :hearts, :spades]
RANK_ORDER =3D [:nine, :ten, :jack, :queen, :king, :ace]

attr_reader :rank, :suit

def initialize(str)
str =3D str.to_s.downcase
@rank =3D
if str[0] =3D=3D ?9
:nine
else
RANK_ORDER.find { |rank| rank.to_s[0] =3D=3D str[0] }
end
@suit =3D SUIT_ORDER.find { |suit| suit.to_s[0] =3D=3D str[1] }
raise "unknown card rank" unless rank
raise "unknown card suit" unless suit
end

def to_s
unless rank =3D=3D :nine
rank.to_s[0, 1].upcase
else
"9"
end + suit.to_s[0, 1]
end

def sort_score(trump)
if rank =3D=3D :jack && suit =3D=3D trump
0
elsif rank =3D=3D :jack && SUIT_COLOR[suit] =3D=3D SUIT_COLOR[tr=
ump]
1
else
ti =3D SUIT_ORDER.index(trump)
raise "unknown trump suit: #{trump}" unless ti
suit_score =3D (SUIT_ORDER.index(suit) - ti) % 4
10 + suit_score * 10 - RANK_ORDER.index(rank)
end
end
end

if $0 =3D=3D __FILE__
trump =3D gets.strip.downcase.to_sym
unless EuchreCard::SUIT_COLOR.has_key? trump
warn "unknown trump suit: #{trump}"
exit 1
end
cards =3D readlines.map { |line| EuchreCard.new(line.strip) }
cards =3D cards.sort_by { |card| card.sort_score(trump) }
puts trump.to_s.capitalize, cards
end
 
D

Dominik Bathon

Here is another solution to the problem. I got the idea for this while =20
reading Dale Martenson's solution.

It doesn't really "solve" the problem, instead it cheats ;-) , but on the=
=20
other side it is short and should be correct if the order hash is correct=
 
Z

Zed Lopez

Terse, but almost reasonable version:

class Euchre
OTHER_COLOR =3D {'c' =3D> 's', 's' =3D> 'c', 'h' =3D> 'd', 'd' =3D> 'h'}
attr_reader :trump_suit
def initialize(suit_name)
@trump_suit =3D suit_name
@trump =3D @trump_suit[0,1].downcase
end
def <<(card)
(@hand ||=3D []) << card
end
def hand
suits =3D @hand.map {|card| card[1,1]}.uniq
i =3D suits.index(@trump) and suits.push(suits.slice!(i))
suits[-3],suits[-2] =3D suits[-2],suits[-3] if suits.length > 2 and
OTHER_COLOR[suits[-1]] =3D=3D suits[-2]
@hand.sort_by do |x|
rank, suit =3D x.split('')
if rank =3D=3D 'J' and @trump =3D=3D suit : 50
elsif rank =3D=3D 'J' and OTHER_COLOR[suit] =3D=3D @trump : 40
else '9TJQKA'.index(rank) + suits.index(suit)*10
end
end.reverse
end
end

euchre =3D Euchre.new(gets.strip)
5.times { euchre << gets.strip }
puts euchre.trump_suit, euchre.hand

Golfed, but weighing in a good 80 characters more than Ryan's (but,
hey, it's my first golf outing in Ruby.) Like his, it should be one
line.

a=3D[];6.times{a<<gets.strip};puts t=3Da.shift;o=3DHash[*%w{C S S C H D D
H}];t=3Dt[0,1];s=3Da.map{|c|c[1,1].upcase}.uniq;i=3Ds.index(t)and
s.push(s.slice!(i));s.length>2&&o[s[-1]]=3D=3Ds[-2]&&(s[-3],s[-2]=3Ds[-2],s=
[-3]);puts
a.sort_by{|c|r,z=3Dc.upcase.split('');r=3D=3D'J'&&t=3D=3Dz&&50||r=3D=3D'J'&=
&o[z]=3D=3Dt&&40||'9TJQKA'.index(r)+s.index(z)*9}.reverse
 
D

Dominik Bathon

A couple of my early attempts depended on the idea that the trump suit
absolutely determined the ranking of the cards, independent of knowing
anything else. It doesn't work, though.

Indeed, I didn't realize that till now (even though James wrote a similar=
=20
reply to Christian's solution)...

So my first solution is "wrong", too. I will post new versions.

Thanks,
Dominik
 
R

Ryan Leavengood

Thanks to inspiration from reading Zed Lopez's code, I've been able to
cut my golfed solution from 242 bytes to 214. Unfortunately for you
Zed, this now means your is now 108 bytes longer :)

The fixes were:

1. Using s[x,1] instead of s[x..x] to get a single character from a
string. This saved 2 bytes.
2. Calculating the weights INSIDE the sort_by, instead of using a
separate hash. This seems so obvious now I slapped my head when I saw
Zed's code doing this. This saved a whopping 26 bytes.

So, if anyone is interested:

a=3D$<.read.split("\n");s=3D%w{d c h
s};c=3D'AKQJT9';t=3Da.shift;u=3D(t[0]+32).chr;i=3Ds.index(u);v=3Ds[(i+2)%4]=
;w=3D[1];i.upto(i+3){|j|w<<s[j%4]};puts
t,a.sort_by{|k|k=3D~/(J#{u})|(J#{v})/?$1?0:1:w.index(k[1,1])*10+c.index(k[0=
,1])}

I will be highly impressed if someone can go shorter than this. Also
if anyone wants it I can post a message "decoding" the above.

Ryan
 
D

David Balmain

Ryan, how about changing /(J#{u})|(J#{v})/ to /J[#{u}#{v}]/? That'll
save you a couple more characters. :p

Thanks to inspiration from reading Zed Lopez's code, I've been able to
cut my golfed solution from 242 bytes to 214. Unfortunately for you
Zed, this now means your is now 108 bytes longer :)

The fixes were:

1. Using s[x,1] instead of s[x..x] to get a single character from a
string. This saved 2 bytes.
2. Calculating the weights INSIDE the sort_by, instead of using a
separate hash. This seems so obvious now I slapped my head when I saw
Zed's code doing this. This saved a whopping 26 bytes.

So, if anyone is interested:

a=3D$<.read.split("\n");s=3D%w{d c h
s};c=3D'AKQJT9';t=3Da.shift;u=3D(t[0]+32).chr;i=3Ds.index(u);v=3Ds[(i+2)%= 4];w=3D[1];i.upto(i+3){|j|w<<s[j%4]};puts
t,a.sort_by{|k|k=3D~/(J#{u})|(J#{v})/?$1?0:1:w.index(k[1,1])*10+c.index(k=
[0,1])}

I will be highly impressed if someone can go shorter than this. Also
if anyone wants it I can post a message "decoding" the above.

Ryan
 
D

David Balmain

Here's my terribly hacky version of Ryans;

a=3D$<.read.split("\n");s=3D%w{d c h
s};c=3D'AKQJT9';t=3Da.shift;u=3D(t[0]+32).chr;i=3Ds.index(u);v=3Ds[i-2];w=
=3D[1];4.times{|j|w<<s[j-i]};puts
t,a.sort_by{|k|k=3D~/J[#{u}#{v}]/?$1?0:1:w.index(k[1,1])*10+c.index(k[0,1])=
}

Ryan, how about changing /(J#{u})|(J#{v})/ to /J[#{u}#{v}]/? That'll
save you a couple more characters. :p

Thanks to inspiration from reading Zed Lopez's code, I've been able to
cut my golfed solution from 242 bytes to 214. Unfortunately for you
Zed, this now means your is now 108 bytes longer :)

The fixes were:

1. Using s[x,1] instead of s[x..x] to get a single character from a
string. This saved 2 bytes.
2. Calculating the weights INSIDE the sort_by, instead of using a
separate hash. This seems so obvious now I slapped my head when I saw
Zed's code doing this. This saved a whopping 26 bytes.

So, if anyone is interested:

a=3D$<.read.split("\n");s=3D%w{d c h
s};c=3D'AKQJT9';t=3Da.shift;u=3D(t[0]+32).chr;i=3Ds.index(u);v=3Ds[(i+2= )%4];w=3D[1];i.upto(i+3){|j|w<<s[j%4]};puts
t,a.sort_by{|k|k=3D~/(J#{u})|(J#{v})/?$1?0:1:w.index(k[1,1])*10+c.index= (k[0,1])}

I will be highly impressed if someone can go shorter than this. Also
if anyone wants it I can post a message "decoding" the above.

Ryan
 
D

David Balmain

Ryan, how about changing /(J#{u})|(J#{v})/ to /J[#{u}#{v}]/? That'll
save you a couple more characters. :p

Damn, now I can see why you did it that way. Sorry. Please disregard.
Thanks to inspiration from reading Zed Lopez's code, I've been able to
cut my golfed solution from 242 bytes to 214. Unfortunately for you
Zed, this now means your is now 108 bytes longer :)

The fixes were:

1. Using s[x,1] instead of s[x..x] to get a single character from a
string. This saved 2 bytes.
2. Calculating the weights INSIDE the sort_by, instead of using a
separate hash. This seems so obvious now I slapped my head when I saw
Zed's code doing this. This saved a whopping 26 bytes.

So, if anyone is interested:

a=3D$<.read.split("\n");s=3D%w{d c h
s};c=3D'AKQJT9';t=3Da.shift;u=3D(t[0]+32).chr;i=3Ds.index(u);v=3Ds[(i+2= )%4];w=3D[1];i.upto(i+3){|j|w<<s[j%4]};puts
t,a.sort_by{|k|k=3D~/(J#{u})|(J#{v})/?$1?0:1:w.index(k[1,1])*10+c.index= (k[0,1])}

I will be highly impressed if someone can go shorter than this. Also
if anyone wants it I can post a message "decoding" the above.

Ryan
 
P

Pit Capitain

David said:
Ryan, how about changing /(J#{u})|(J#{v})/ to /J[#{u}#{v}]/? That'll
save you a couple more characters. :p

Damn, now I can see why you did it that way. Sorry. Please disregard.

No, your idea is right: he could still save one character using
/J(#{u})|(#{v})/

Regards,
Pit
 
A

Adam Shelly

------=_Part_32527_30812562.1132555782725
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Here's mine. I believe it always handles red-black ordering correctly even
with empty suits.

class EuchreHand
SUIT =3D [?c,?d,?s,?h]
VAL =3D [?A,?Q,?K,?J,?T,?9]
def initialize input
@trump =3D input.shift
@hand =3D {}
4.times {|s| @hand[SUIT]=3D[]}
input.each{|card| @hand[card[1]] << card[0] }
end
def display
puts @trump
t=3DSUIT.index(@trump.downcase[0])
get_jacks(SUIT[t])
get_jacks(SUIT[(t+2)%4])
if @hand[SUIT[(t+1)%4]].empty?
t.downto(0){|s| show_suit s}
(3).downto(t+1) {|s| show_suit s}
else
(t..3).each {|s| show_suit s}
(0...t).each {|s| show_suit s}
end
end
def get_jacks suit
if @hand[suit].include? ?J
puts [?J,suit].pack('c*')
@hand[suit].delete(?J)
end
end
def show_suit s
suit =3D SUIT
@hand[suit].sort{|a,b| VAL.index(a)<=3D>VAL.index(b)}.each{|v|
puts [v,suit].pack('c*')
}
end
end

if __FILE__ =3D=3D $0
input =3Dreadlines
e =3D EuchreHand.new(input)
e.display
end
 
D

David Balmain

David said:
Ryan, how about changing /(J#{u})|(J#{v})/ to /J[#{u}#{v}]/? That'll
save you a couple more characters. :p

Damn, now I can see why you did it that way. Sorry. Please disregard.

No, your idea is right: he could still save one character using
/J(#{u})|(#{v})/

Regards,
Pit

This is the last time I play golf. It's addictive and I should be working.

a=3D$<.read.split("\n");s=3D%w{d c h
s};c=3D'AKQJT9';t=3Da.shift;u=3D(t[0]+32).chr;i=3Ds.index(u);v=3Ds[i-2];w=
=3D[1];puts
t,a.sort_by{|k|(k=3D~/J[#{u+v}]/?0:99)+(s.index(k[1,1])-i)%4*10+c.index(k[0=
,1])}

184 characters. And this time I think it works.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top