Решение на Четвърта задача от Мартин Симеонов

Обратно към всички решения

Към профила на Мартин Симеонов

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 53 успешни тест(а)
  • 4 неуспешни тест(а)

Код

class Card
attr_reader :rank, :suit
def initialize(rank, suit)
@rank = rank
@suit = suit
end
def to_s
"#{@rank.to_s.capitalize} of #{@suit.to_s.capitalize}"
end
def ==(other)
to_s == other.to_s
end
def <(other)
ranks = {jack: 11, queen: 12, king: 13, ace: 14}
suits = {clubs: 1, diamonds: 2, hearts: 3, spades: 4}
if suits[suit] < suits[other.suit]
true
elsif suits[suit] > suits[other.suit]
false
else
ranks.fetch(rank, rank) < ranks.fetch(other.rank, other.rank)
end
end
def >(other)
not (self < other or self == other)
end
def <=>(other)
return 0 if self == other
return -1 if self < other
return 1 if self > other
end
end
class Deal
def initialize(deal)
@deal = deal
end
def size
@deal.size
end
end
class Deck
include Enumerable
def initialize(deck = Array.new)
@deck = deck
if @deck.empty?
ranks = [:ace, :king, :queen, :jack] + (2..10).to_a.reverse
generate_deck(ranks)
end
end
def each
@deck.each { |card| yield card }
end
def size
@deck.size
end
def draw_top_card
@deck.shift
end
def draw_bottom_card
@deck.pop
end
def top_card
@deck.first
end
def bottom_card
@deck.last
end
def shuffle
@deck.shuffle!
self
end
def to_s
string_deck = Array.new
@deck.each { |card| string_deck << card.to_s }
string_deck
end
def sort
@deck.sort! { |current, following| following <=> current }
self
end
def deal
Deal.new(@deck)
end
private
def generate_deck(ranks)
suits = [:spades, :hearts, :diamonds, :clubs]
suits.each do |suit|
ranks.each { |rank| @deck << Card.new(rank, suit) }
end
end
end
class WarDeal < Deal
def play_card
play_card = @deal.sample
@deal.delete_if { |card| card == play_card }
end
def allow_face_up?
size <= 3
end
end
class WarDeck < Deck
def deal
WarDeal.new(@deck.shift(26))
end
end
class BeloteDeal < Deal
def initialize(deal)
super(deal)
@ranks = {:jack => 10, :queen => 11, :king => 12, 10 => 13, :ace => 14}
end
def highest_of_suit(suit)
cards_of_suit = @deal.select { |card| card.suit == suit }
cards_of_suit.sort_by { |card| @ranks.fetch(card.rank, card.rank) }.last
end
def belote?
cards = @deal.select { |card| card.rank == :queen or card.rank == :king}
return true if cards.select { |card| card.suit == :clubs }.size == 2
return true if cards.select { |card| card.suit == :diamonds }.size == 2
return true if cards.select { |card| card.suit == :hearts }.size == 2
return true if cards.select { |card| card.suit == :spades }.size == 2
false
end
def tierce?
@deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
suits = @deal.group_by(&:suit)
suits.each_value { |suit| return true if find_consecutive(suit, 3)}
false
end
def quarte?
@deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
suits = @deal.group_by(&:suit)
suits.each_value { |suit| return true if find_consecutive(suit, 4)}
false
end
def quint?
@deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
suits = @deal.group_by(&:suit)
suits.each_value { |suit| return true if find_consecutive(suit, 5)}
false
end
def carre_of_jacks?
carre?(:jack)
end
def carre_of_nines?
carre?(9)
end
def carre_of_aces?
carre?(:ace)
end
private
def carre?(rank)
@deal.select { |card| card.rank == rank }.size == 4
end
def find_consecutive(cards, number)
correct = 0
ranks = cards.map { |card| @ranks.fetch(card.rank, card.rank) }
expected = ranks.first
ranks.each do |rank|
expected == rank ? correct += 1 : break
expected = expected.next
end
correct == number
end
end
class BeloteDeck < Deck
def initialize(deck = Array.new)
@deck = deck
if(@deck.empty?)
ranks = [:ace, 10, :king, :queen, :jack, 9, 8, 7]
generate_deck(ranks)
end
end
def sort
ranks = {:jack => 10, :queen => 11, :king => 12, 10 => 13, :ace => 14}
@deck.sort_by! { |card| [card.suit, ranks.fetch(card.rank, card.rank)] }
@deck.reverse!
end
def deal
BeloteDeal.new(@deck.shift(8))
end
end
class SixtySixDeal < Deal
def twenty?(trump_suit)
suits = @deal.group_by(&:suit)
suits.delete(trump_suit)
suits.each_value do |cards|
queen = cards.any? { |card| card.rank == :queen }
king = cards.any? { |card| card.rank == :king }
return true if queen and king
end
false
end
def forty?(trump_suit)
suits = @deal.group_by(&:suit)
suits.each do |suit, cards|
queen = cards.any? { |card| card.rank == :queen }
king = cards.any? { |card| card.rank == :king }
return true if (queen and king) and trump_suit == suit
end
false
end
end
class SixtySixDeck < BeloteDeck
def initialize(deck = Array.new)
@deck = deck
if(@deck.empty?)
ranks = [:ace, 10, :king, :queen, :jack, 9]
generate_deck(ranks)
end
end
def deal
SixtySixDeal.new(@deck.shift(6))
end
end

Лог от изпълнението

...........F............F.....F....................F.....

Failures:

  1) WarDeck behaves like a deck #to_s returns the names of the cards, each on its own line
     Failure/Error: expect(small_deck.to_s.strip).to eq "Ace of Spades\n9 of Clubs"
     NoMethodError:
       undefined method `strip' for ["Ace of Spades", "9 of Clubs"]:Array
     Shared Example Group: "a deck" called from /tmp/d20151112-27349-1v95p1e/spec.rb:140
     # /tmp/d20151112-27349-1v95p1e/spec.rb:68:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) BeloteDeck behaves like a deck #to_s returns the names of the cards, each on its own line
     Failure/Error: expect(small_deck.to_s.strip).to eq "Ace of Spades\n9 of Clubs"
     NoMethodError:
       undefined method `strip' for ["Ace of Spades", "9 of Clubs"]:Array
     Shared Example Group: "a deck" called from /tmp/d20151112-27349-1v95p1e/spec.rb:191
     # /tmp/d20151112-27349-1v95p1e/spec.rb:68:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) BeloteDeck hand #tierce? with tierce returns true for cards with names
     Failure/Error: expect(hand.tierce?).to be true
       
       expected #<TrueClass:20> => true
            got #<FalseClass:0> => false
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
     # /tmp/d20151112-27349-1v95p1e/spec.rb:284:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) SixtySixDeck behaves like a deck #to_s returns the names of the cards, each on its own line
     Failure/Error: expect(small_deck.to_s.strip).to eq "Ace of Spades\n9 of Clubs"
     NoMethodError:
       undefined method `strip' for ["Ace of Spades", "9 of Clubs"]:Array
     Shared Example Group: "a deck" called from /tmp/d20151112-27349-1v95p1e/spec.rb:400
     # /tmp/d20151112-27349-1v95p1e/spec.rb:68:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.07532 seconds
57 examples, 4 failures

Failed examples:

rspec /tmp/d20151112-27349-1v95p1e/spec.rb:67 # WarDeck behaves like a deck #to_s returns the names of the cards, each on its own line
rspec /tmp/d20151112-27349-1v95p1e/spec.rb:67 # BeloteDeck behaves like a deck #to_s returns the names of the cards, each on its own line
rspec /tmp/d20151112-27349-1v95p1e/spec.rb:272 # BeloteDeck hand #tierce? with tierce returns true for cards with names
rspec /tmp/d20151112-27349-1v95p1e/spec.rb:67 # SixtySixDeck behaves like a deck #to_s returns the names of the cards, each on its own line

История (2 версии и 1 коментар)

Мартин обнови решението на 11.11.2015 17:24 (преди над 8 години)

+class Card
+ attr_reader :rank, :suit
+
+ def initialize(rank, suit)
+ @rank = rank
+ @suit = suit
+ end
+
+ def to_s
+ "#{@rank.to_s.capitalize} of #{@suit.to_s.capitalize}"
+ end
+
+ def ==(other)
+ to_s == other.to_s
+ end
+
+ def <(other)
+ ranks = {jack: 11, queen: 12, king: 13, ace: 14}
+ suits = {clubs: 1, diamonds: 2, hearts: 3, spades: 4}
+
+ if suits[suit] < suits[other.suit]
+ true
+ elsif suits[suit] > suits[other.suit]
+ false
+ else
+ ranks.fetch(rank, rank) < ranks.fetch(other.rank, other.rank)
+ end
+ end
+
+ def >(other)
+ not (self < other or self == other)
+ end
+
+ def <=>(other)
+ return 0 if self == other
+ return -1 if self < other
+ return 1 if self > other
+ end
+end
+
+class Deal
+ def initialize(deal)
+ @deal = deal
+ end
+
+ def size
+ @deal.size
+ end
+end
+
+class Deck
+ include Enumerable
+
+ def initialize(deck = Array.new)
+ @deck = deck
+ if @deck.empty?
+ ranks = [:ace, :king, :queen, :jack] + (2..10).to_a.reverse
+ generate_deck(ranks)
+ end
+ end
+
+ def each
+ @deck.each { |card| yield card }
+ end
+
+ def size
+ @deck.size
+ end
+
+ def draw_top_card
+ @deck.shift
+ end
+
+ def draw_bottom_card
+ @deck.pop
+ end
+
+ def top_card
+ @deck.first
+ end
+
+ def bottom_card
+ @deck.last
+ end
+
+ def shuffle
+ @deck.shuffle!
+ self
+ end
+
+ def to_s
+ string_deck = Array.new
+ @deck.each { |card| string_deck << card.to_s }
+ string_deck
+ end
+
+ def sort
+ @deck.sort! { |current, following| following <=> current }
+ self
+ end
+
+ def deal
+ Deal.new(@deck)
+ end
+
+ private
+
+ def generate_deck(ranks)
+ suits = [:spades, :hearts, :diamonds, :clubs]
+
+ suits.each do |suit|
+ ranks.each { |rank| @deck << Card.new(rank, suit) }
+ end
+ end
+end
+
+class WarDeal < Deal
+ def play_card
+ play_card = @deal.sample
+ @deal.delete_if { |card| card == play_card }
+ end
+
+ def allow_face_up?
+ size <= 3
+ end
+end
+
+class WarDeck < Deck
+ def deal
+ WarDeal.new(@deck.shift(26))
+ end
+end
+
+class BeloteDeal < Deal
+ def initialize(deal)
+ super(deal)
+ @ranks = {:jack => 10, :queen => 11, :king => 12, 10 => 13, :ace => 14}
+ end
+
+ def highest_of_suit(suit)
+ cards_of_suit = @deal.select { |card| card.suit == suit }
+ cards_of_suit.sort_by { |card| @ranks.fetch(card.rank, card.rank) }.last
+ end
+
+ def belote?
+ cards = @deal.select { |card| card.rank == :queen or card.rank == :king}
+ return true if cards.select { |card| card.suit == :clubs }.size == 2
+ return true if cards.select { |card| card.suit == :diamonds }.size == 2
+ return true if cards.select { |card| card.suit == :hearts }.size == 2
+ return true if cards.select { |card| card.suit == :spades }.size == 2
+ false
+ end
+
+ def tierce?
+ @deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
+ suits = @deal.group_by(&:suit)
+ suits.each_value { |suit| return true if find_consecutive(suit, 3)}
+ false
+ end
+
+ def quarte?
+ @deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
+ suits = @deal.group_by(&:suit)
+ suits.each_value { |suit| return true if find_consecutive(suit, 4)}
+ false
+ end
+
+ def quint?
+ @deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
+ puts @deal
+ suits = @deal.group_by(&:suit)
+ suits.each_value { |suit| return true if find_consecutive(suit, 5)}
+ false
+ end
+
+ def carre_of_jacks?
+ carre?(:jack)
+ end
+
+ def carre_of_nines?
+ carre?(9)
+ end
+
+ def carre_of_aces?
+ carre?(:ace)
+ end
+
+ private
+
+ def carre?(rank)
+ @deal.select { |card| card.rank == rank }.size == 4
+ end
+
+ def find_consecutive(cards, number)
+ correct = 0
+ ranks = cards.map { |card| @ranks.fetch(card.rank, card.rank) }
+ expected = ranks.first
+ ranks.each do |rank|
+ expected == rank ? correct += 1 : break
+ expected = expected.next
+ end
+ return true if correct == number
+ false
+ end
+end
+
+class BeloteDeck < Deck
+ def initialize(deck = Array.new)
+ @deck = deck
+ if(@deck.empty?)
+ ranks = [:ace, 10, :king, :queen, :jack, 9, 8, 7]
+ generate_deck(ranks)
+ end
+ end
+
+ def sort
+ ranks = {:jack => 10, :queen => 11, :king => 12, 10 => 13, :ace => 14}
+
+ @deck.sort_by! { |card| [card.suit, ranks.fetch(card.rank, card.rank)] }
+ @deck.reverse!
+ end
+
+ def deal
+ BeloteDeal.new(@deck.shift(8))
+ end
+end
+
+class SixtySixDeal < Deal
+ def twenty?(trump_suit)
+ suits = @deal.group_by(&:suit)
+ suits.delete(trump_suit)
+ suits.each_value do |cards|
+ queen = cards.any? { |card| card.rank == :queen }
+ king = cards.any? { |card| card.rank == :king }
+
+ return true if queen and king
+ end
+ false
+ end
+
+ def forty?(trump_suit)
+ suits = @deal.group_by(&:suit)
+ suits.each do |suit, cards|
+ queen = cards.any? { |card| card.rank == :queen }
+ king = cards.any? { |card| card.rank == :king }
+
+ return true if (queen and king) and trump_suit == suit
+ end
+ false
+ end
+end
+
+class SixtySixDeck < BeloteDeck
+ def initialize(deck = Array.new)
+ @deck = deck
+ if(@deck.empty?)
+ ranks = [:ace, 10, :king, :queen, :jack, 9]
+ generate_deck(ranks)
+ end
+ end
+
+ def deal
+ SixtySixDeal.new(@deck.shift(6))
+ end
+end

Мартин обнови решението на 11.11.2015 17:28 (преди над 8 години)

class Card
attr_reader :rank, :suit
def initialize(rank, suit)
@rank = rank
@suit = suit
end
def to_s
"#{@rank.to_s.capitalize} of #{@suit.to_s.capitalize}"
end
def ==(other)
to_s == other.to_s
end
def <(other)
ranks = {jack: 11, queen: 12, king: 13, ace: 14}
suits = {clubs: 1, diamonds: 2, hearts: 3, spades: 4}
if suits[suit] < suits[other.suit]
true
elsif suits[suit] > suits[other.suit]
false
else
ranks.fetch(rank, rank) < ranks.fetch(other.rank, other.rank)
end
end
def >(other)
not (self < other or self == other)
end
def <=>(other)
return 0 if self == other
return -1 if self < other
return 1 if self > other
end
end
class Deal
def initialize(deal)
@deal = deal
end
def size
@deal.size
end
end
class Deck
include Enumerable
def initialize(deck = Array.new)
@deck = deck
if @deck.empty?
ranks = [:ace, :king, :queen, :jack] + (2..10).to_a.reverse
generate_deck(ranks)
end
end
def each
@deck.each { |card| yield card }
end
def size
@deck.size
end
def draw_top_card
@deck.shift
end
def draw_bottom_card
@deck.pop
end
def top_card
@deck.first
end
def bottom_card
@deck.last
end
def shuffle
@deck.shuffle!
self
end
def to_s
string_deck = Array.new
@deck.each { |card| string_deck << card.to_s }
string_deck
end
def sort
@deck.sort! { |current, following| following <=> current }
self
end
def deal
Deal.new(@deck)
end
private
def generate_deck(ranks)
suits = [:spades, :hearts, :diamonds, :clubs]
suits.each do |suit|
ranks.each { |rank| @deck << Card.new(rank, suit) }
end
end
end
class WarDeal < Deal
def play_card
play_card = @deal.sample
@deal.delete_if { |card| card == play_card }
end
def allow_face_up?
size <= 3
end
end
class WarDeck < Deck
def deal
WarDeal.new(@deck.shift(26))
end
end
class BeloteDeal < Deal
def initialize(deal)
super(deal)
@ranks = {:jack => 10, :queen => 11, :king => 12, 10 => 13, :ace => 14}
end
def highest_of_suit(suit)
cards_of_suit = @deal.select { |card| card.suit == suit }
cards_of_suit.sort_by { |card| @ranks.fetch(card.rank, card.rank) }.last
end
def belote?
cards = @deal.select { |card| card.rank == :queen or card.rank == :king}
return true if cards.select { |card| card.suit == :clubs }.size == 2
return true if cards.select { |card| card.suit == :diamonds }.size == 2
return true if cards.select { |card| card.suit == :hearts }.size == 2
return true if cards.select { |card| card.suit == :spades }.size == 2
false
end
def tierce?
@deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
suits = @deal.group_by(&:suit)
suits.each_value { |suit| return true if find_consecutive(suit, 3)}
false
end
def quarte?
@deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
suits = @deal.group_by(&:suit)
suits.each_value { |suit| return true if find_consecutive(suit, 4)}
false
end
def quint?
@deal.sort_by! { |card| [card.suit, @ranks.fetch(card.rank, card.rank)] }
- puts @deal
suits = @deal.group_by(&:suit)
suits.each_value { |suit| return true if find_consecutive(suit, 5)}
false
end
def carre_of_jacks?
carre?(:jack)
end
def carre_of_nines?
carre?(9)
end
def carre_of_aces?
carre?(:ace)
end
private
def carre?(rank)
@deal.select { |card| card.rank == rank }.size == 4
end
def find_consecutive(cards, number)
correct = 0
ranks = cards.map { |card| @ranks.fetch(card.rank, card.rank) }
expected = ranks.first
ranks.each do |rank|
expected == rank ? correct += 1 : break
expected = expected.next
end
- return true if correct == number
- false
+ correct == number
end
end
class BeloteDeck < Deck
def initialize(deck = Array.new)
@deck = deck
if(@deck.empty?)
ranks = [:ace, 10, :king, :queen, :jack, 9, 8, 7]
generate_deck(ranks)
end
end
def sort
ranks = {:jack => 10, :queen => 11, :king => 12, 10 => 13, :ace => 14}
@deck.sort_by! { |card| [card.suit, ranks.fetch(card.rank, card.rank)] }
@deck.reverse!
end
def deal
BeloteDeal.new(@deck.shift(8))
end
end
class SixtySixDeal < Deal
def twenty?(trump_suit)
suits = @deal.group_by(&:suit)
suits.delete(trump_suit)
suits.each_value do |cards|
queen = cards.any? { |card| card.rank == :queen }
king = cards.any? { |card| card.rank == :king }
return true if queen and king
end
false
end
def forty?(trump_suit)
suits = @deal.group_by(&:suit)
suits.each do |suit, cards|
queen = cards.any? { |card| card.rank == :queen }
king = cards.any? { |card| card.rank == :king }
return true if (queen and king) and trump_suit == suit
end
false
end
end
class SixtySixDeck < BeloteDeck
def initialize(deck = Array.new)
@deck = deck
if(@deck.empty?)
ranks = [:ace, 10, :king, :queen, :jack, 9]
generate_deck(ranks)
end
end
def deal
SixtySixDeal.new(@deck.shift(6))
end
end

Имаш дребни проблеми със спазването на конвенциите.

twenty? и другите подобни могат да станат по-добре, ако ползваш правилно подходящите методи от Enumerable.

Прегледай решенията на колеги и нашето примерно решение за алтернативни идеи.