Решение на Шеста задача от Йордан Петров

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

Към профила на Йордан Петров

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 42 успешни тест(а)
  • 5 неуспешни тест(а)

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Exchange
attr_reader :from_currency, :to_currency
attr_accessor :rate
def initialize(from_currency, to_currency, rate)
@from_currency = from_currency
@to_currency = to_currency
@rate = rate
end
end
class ExchangeRate
class Unknown < RuntimeError
end
def initialize
@exchanges = []
end
def set(from_currency, to_currency, rate)
if find_index from_currency, to_currency
@exchanges[find_index from_currency, to_currency].rate = rate
@exchanges[find_index to_currency, from_currency].rate = (1 / rate).to_d
else
@exchanges << Exchange.new(from_currency, to_currency, rate)
@exchanges << Exchange.new(to_currency, from_currency, (1 / rate).to_d)
end
end
def get(from_currency, to_currency)
if from_currency == to_currency then 1.to_d
elsif not find_index from_currency, to_currency then nil
else @exchanges[find_index from_currency, to_currency].rate
end
end
def convert(from_currency, to_currency, amount)
if from_currency == to_currency then amount
elsif not find_index from_currency, to_currency then raise Unknown
else (@exchanges[find_index from_currency, to_currency].rate * amount).to_d
end
end
private
def find_index(from_currency, to_currency)
@exchanges.index do |exchange|
exchange.from_currency == from_currency and
exchange.to_currency == to_currency
end
end
end
class Money
include Comparable
class IncompatibleCurrencies < RuntimeError
end
attr_reader :amount, :currency
def initialize(amount, currency)
@amount = amount.round(2)
@currency = currency
end
def to_s
"#{@amount.to_f} #{@currency}".sub /(?<=\.\d)\s/, "0 "
end
def in(currency, exchange_rate)
Money.new exchange_rate.convert(@currency, currency, @amount), currency
end
def *(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount * number).to_d, @currency
end
def /(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount / number).to_d, @currency
end
def +(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount + other.amount).to_d, @currency
end
def -(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount - other.amount).to_d, @currency
end
def <=>(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
self.amount <=> other.amount
end
def inspect
to_s
end
end

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

.....................F...........FF..FF........

Failures:

  1) Money arithmetic allows / with a numeric
     Failure/Error: result.amount.should eq bucks.amount.public_send(operation, numeric)
       
       expected: #<BigDecimal:8b5176c,'0.1190476190 47619048E0',18(36)>
            got: #<BigDecimal:8b51c6c,'0.12E0',9(36)>
       
       (compared using ==)
     # /tmp/d20130203-23049-13ynj6x/spec.rb:125:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Money comparison works when currencies are the same
     Failure/Error: (a < b).should be_true
       expected: true value
            got: false
     # /tmp/d20130203-23049-13ynj6x/spec.rb:181:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Money comparison works for equality when currencies are the same
     Failure/Error: (Money.new('12.45'.to_d, :BGN) == Money.new('12.451'.to_d, :BGN)).should be_false
       expected: false value
            got: true
     # /tmp/d20130203-23049-13ynj6x/spec.rb:190:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Money comparison with == raises ArgumentError when comparing with other objects
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-13ynj6x/spec.rb:195:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Money comparison with == raises IncompatibleCurrencies when currencies differ
     Failure/Error: expect do
       expected Money::IncompatibleCurrencies but nothing was raised
     # /tmp/d20130203-23049-13ynj6x/spec.rb:201:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.05878 seconds
47 examples, 5 failures

Failed examples:

rspec /tmp/d20130203-23049-13ynj6x/spec.rb:119 # Money arithmetic allows / with a numeric
rspec /tmp/d20130203-23049-13ynj6x/spec.rb:168 # Money comparison works when currencies are the same
rspec /tmp/d20130203-23049-13ynj6x/spec.rb:188 # Money comparison works for equality when currencies are the same
rspec /tmp/d20130203-23049-13ynj6x/spec.rb:194 # Money comparison with == raises ArgumentError when comparing with other objects
rspec /tmp/d20130203-23049-13ynj6x/spec.rb:200 # Money comparison with == raises IncompatibleCurrencies when currencies differ

История (5 версии и 0 коментара)

Йордан обнови решението на 16.01.2013 14:08 (преди около 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Exchange
+ attr_reader :from_currency, :to_currency
+ attr_accessor :rate
+
+ def initialize(from_currency, to_currency, rate)
+ @from_currency = from_currency
+ @to_currency = to_currency
+ @rate = rate
+ end
+end
+
+class ExchangeRate
+ class Unknown < RuntimeError
+ end
+
+ def initialize
+ @exchanges = []
+ end
+
+ def set(from_currency, to_currency, rate)
+ if find_index from_currency, to_currency
+ @exchanges[find_index from_currency, to_currency].rate = rate
+ @exchanges[find_index to_currency, from_currency].rate = BigDecimal.new(1/rate)
+ else
+ @exchanges << Exchange.new(from_currency, to_currency, rate)
+ @exchanges << Exchange.new(to_currency, from_currency, BigDecimal.new(1/rate))
+ end
+ end
+
+ def get(from_currency, to_currency)
+ @exchanges[find_index from_currency, to_currency].rate if find_index from_currency, to_currency
+ end
+
+ def convert(from_currency, to_currency, amount)
+ if from_currency == to_currency then amount
+ elsif not find_index from_currency, to_currency then raise Unknown
+ else BigDecimal.new(@exchanges[find_index from_currency, to_currency].rate * amount)
+ end
+ end
+
+ private
+
+ def find_index(from_currency, to_currency)
+ @exchanges.index do |exchange|
+ exchange.from_currency == from_currency and
+ exchange.to_currency == to_currency
+ end
+ end
+end
+
+class Money
+ include Comparable
+
+ class IncompatibleCurrencies < RuntimeError
+ end
+
+ attr_reader :amount, :currency
+
+ def initialize(amount, currency)
+ @amount = amount.round(2)
+ @currency = currency
+ end
+
+ def to_s
+ if @amount.to_s("F").match /\.\d\d\z/ then @amount.to_s("F") + " " + @currency.to_s
+ else @amount.to_s("F") + "0 " + @currency.to_s
+ end
+ end
+
+ def in(currency, exchange_rate)
+ Money.new exchange_rate.convert(@currency, currency, @amount), currency
+ end
+
+ def *(number)
+ raise ArgumentError if not number.is_a? Numeric
+ Money.new (self.amount * number).to_d, @currency
+ end
+
+ def /(number)
+ raise ArgumentError if not number.is_a? Numeric
+ Money.new (self.amount / number).to_d, @currency
+ end
+
+ def +(other)
+ raise ArgumentError if not other.is_a? Money
+ raise IncompatibleCurrencies if self.currency != other.currency
+ Money.new (self.amount + other.amount).to_d, @currency
+ end
+
+ def -(other)
+ raise ArgumentError if not other.is_a? Money
+ raise IncompatibleCurrencies if self.currency != other.currency
+ Money.new (self.amount - other.amount).to_d, @currency
+ end
+
+ def <=>(other)
+ raise ArgumentError if not other.is_a? Money
+ raise IncompatibleCurrencies if self.currency != other.currency
+ self.amount <=> other.amount
+ end
+
+ def inspect
+ to_s
+ end
+end

Йордан обнови решението на 16.01.2013 15:18 (преди около 12 години)

require 'bigdecimal'
require 'bigdecimal/util'
class Exchange
attr_reader :from_currency, :to_currency
attr_accessor :rate
def initialize(from_currency, to_currency, rate)
@from_currency = from_currency
@to_currency = to_currency
@rate = rate
end
end
class ExchangeRate
class Unknown < RuntimeError
end
def initialize
@exchanges = []
end
def set(from_currency, to_currency, rate)
if find_index from_currency, to_currency
@exchanges[find_index from_currency, to_currency].rate = rate
- @exchanges[find_index to_currency, from_currency].rate = BigDecimal.new(1/rate)
+ @exchanges[find_index to_currency, from_currency].rate = BigDecimal.new(1 / rate)
else
@exchanges << Exchange.new(from_currency, to_currency, rate)
- @exchanges << Exchange.new(to_currency, from_currency, BigDecimal.new(1/rate))
+ @exchanges << Exchange.new(to_currency, from_currency, BigDecimal.new(1 / rate))
end
end
def get(from_currency, to_currency)
@exchanges[find_index from_currency, to_currency].rate if find_index from_currency, to_currency
end
def convert(from_currency, to_currency, amount)
if from_currency == to_currency then amount
elsif not find_index from_currency, to_currency then raise Unknown
else BigDecimal.new(@exchanges[find_index from_currency, to_currency].rate * amount)
end
end
private
def find_index(from_currency, to_currency)
@exchanges.index do |exchange|
exchange.from_currency == from_currency and
exchange.to_currency == to_currency
end
end
end
class Money
include Comparable
class IncompatibleCurrencies < RuntimeError
end
attr_reader :amount, :currency
def initialize(amount, currency)
@amount = amount.round(2)
@currency = currency
end
def to_s
- if @amount.to_s("F").match /\.\d\d\z/ then @amount.to_s("F") + " " + @currency.to_s
- else @amount.to_s("F") + "0 " + @currency.to_s
- end
+ "#{@amount.to_f} #{@currency}".sub(/(?<=\.\d)\s/, "0 ")
end
def in(currency, exchange_rate)
Money.new exchange_rate.convert(@currency, currency, @amount), currency
end
def *(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount * number).to_d, @currency
end
def /(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount / number).to_d, @currency
end
def +(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount + other.amount).to_d, @currency
end
def -(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount - other.amount).to_d, @currency
end
def <=>(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
self.amount <=> other.amount
end
def inspect
to_s
end
end

Йордан обнови решението на 16.01.2013 15:20 (преди около 12 години)

require 'bigdecimal'
require 'bigdecimal/util'
class Exchange
attr_reader :from_currency, :to_currency
attr_accessor :rate
def initialize(from_currency, to_currency, rate)
@from_currency = from_currency
@to_currency = to_currency
@rate = rate
end
end
class ExchangeRate
class Unknown < RuntimeError
end
def initialize
@exchanges = []
end
def set(from_currency, to_currency, rate)
if find_index from_currency, to_currency
@exchanges[find_index from_currency, to_currency].rate = rate
@exchanges[find_index to_currency, from_currency].rate = BigDecimal.new(1 / rate)
else
@exchanges << Exchange.new(from_currency, to_currency, rate)
@exchanges << Exchange.new(to_currency, from_currency, BigDecimal.new(1 / rate))
end
end
def get(from_currency, to_currency)
@exchanges[find_index from_currency, to_currency].rate if find_index from_currency, to_currency
end
def convert(from_currency, to_currency, amount)
if from_currency == to_currency then amount
elsif not find_index from_currency, to_currency then raise Unknown
else BigDecimal.new(@exchanges[find_index from_currency, to_currency].rate * amount)
end
end
private
def find_index(from_currency, to_currency)
@exchanges.index do |exchange|
exchange.from_currency == from_currency and
exchange.to_currency == to_currency
end
end
end
class Money
include Comparable
class IncompatibleCurrencies < RuntimeError
end
attr_reader :amount, :currency
def initialize(amount, currency)
@amount = amount.round(2)
@currency = currency
end
def to_s
- "#{@amount.to_f} #{@currency}".sub(/(?<=\.\d)\s/, "0 ")
+ "#{@amount.to_f} #{@currency}".sub /(?<=\.\d)\s/, "0 "
end
def in(currency, exchange_rate)
Money.new exchange_rate.convert(@currency, currency, @amount), currency
end
def *(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount * number).to_d, @currency
end
def /(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount / number).to_d, @currency
end
def +(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount + other.amount).to_d, @currency
end
def -(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount - other.amount).to_d, @currency
end
def <=>(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
self.amount <=> other.amount
end
def inspect
to_s
end
end

Йордан обнови решението на 16.01.2013 16:41 (преди около 12 години)

require 'bigdecimal'
require 'bigdecimal/util'
class Exchange
attr_reader :from_currency, :to_currency
attr_accessor :rate
def initialize(from_currency, to_currency, rate)
@from_currency = from_currency
@to_currency = to_currency
@rate = rate
end
end
class ExchangeRate
class Unknown < RuntimeError
end
def initialize
@exchanges = []
end
def set(from_currency, to_currency, rate)
if find_index from_currency, to_currency
@exchanges[find_index from_currency, to_currency].rate = rate
@exchanges[find_index to_currency, from_currency].rate = BigDecimal.new(1 / rate)
else
@exchanges << Exchange.new(from_currency, to_currency, rate)
@exchanges << Exchange.new(to_currency, from_currency, BigDecimal.new(1 / rate))
end
end
def get(from_currency, to_currency)
- @exchanges[find_index from_currency, to_currency].rate if find_index from_currency, to_currency
+ if from_currency == to_currency then BigDecimal.new('1.00')
+ elsif not find_index from_currency, to_currency then nil
+ else @exchanges[find_index from_currency, to_currency].rate
+ end
end
def convert(from_currency, to_currency, amount)
if from_currency == to_currency then amount
elsif not find_index from_currency, to_currency then raise Unknown
else BigDecimal.new(@exchanges[find_index from_currency, to_currency].rate * amount)
end
end
private
def find_index(from_currency, to_currency)
@exchanges.index do |exchange|
exchange.from_currency == from_currency and
exchange.to_currency == to_currency
end
end
end
class Money
include Comparable
class IncompatibleCurrencies < RuntimeError
end
attr_reader :amount, :currency
def initialize(amount, currency)
@amount = amount.round(2)
@currency = currency
end
def to_s
"#{@amount.to_f} #{@currency}".sub /(?<=\.\d)\s/, "0 "
end
def in(currency, exchange_rate)
Money.new exchange_rate.convert(@currency, currency, @amount), currency
end
def *(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount * number).to_d, @currency
end
def /(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount / number).to_d, @currency
end
def +(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount + other.amount).to_d, @currency
end
def -(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount - other.amount).to_d, @currency
end
def <=>(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
self.amount <=> other.amount
end
def inspect
to_s
end
end

Йордан обнови решението на 16.01.2013 16:49 (преди около 12 години)

require 'bigdecimal'
require 'bigdecimal/util'
class Exchange
attr_reader :from_currency, :to_currency
attr_accessor :rate
def initialize(from_currency, to_currency, rate)
@from_currency = from_currency
@to_currency = to_currency
@rate = rate
end
end
class ExchangeRate
class Unknown < RuntimeError
end
def initialize
@exchanges = []
end
def set(from_currency, to_currency, rate)
if find_index from_currency, to_currency
@exchanges[find_index from_currency, to_currency].rate = rate
- @exchanges[find_index to_currency, from_currency].rate = BigDecimal.new(1 / rate)
+ @exchanges[find_index to_currency, from_currency].rate = (1 / rate).to_d
else
@exchanges << Exchange.new(from_currency, to_currency, rate)
- @exchanges << Exchange.new(to_currency, from_currency, BigDecimal.new(1 / rate))
+ @exchanges << Exchange.new(to_currency, from_currency, (1 / rate).to_d)
end
end
def get(from_currency, to_currency)
- if from_currency == to_currency then BigDecimal.new('1.00')
+ if from_currency == to_currency then 1.to_d
elsif not find_index from_currency, to_currency then nil
else @exchanges[find_index from_currency, to_currency].rate
end
end
def convert(from_currency, to_currency, amount)
if from_currency == to_currency then amount
elsif not find_index from_currency, to_currency then raise Unknown
- else BigDecimal.new(@exchanges[find_index from_currency, to_currency].rate * amount)
+ else (@exchanges[find_index from_currency, to_currency].rate * amount).to_d
end
end
private
def find_index(from_currency, to_currency)
@exchanges.index do |exchange|
exchange.from_currency == from_currency and
exchange.to_currency == to_currency
end
end
end
class Money
include Comparable
class IncompatibleCurrencies < RuntimeError
end
attr_reader :amount, :currency
def initialize(amount, currency)
@amount = amount.round(2)
@currency = currency
end
def to_s
"#{@amount.to_f} #{@currency}".sub /(?<=\.\d)\s/, "0 "
end
def in(currency, exchange_rate)
Money.new exchange_rate.convert(@currency, currency, @amount), currency
end
def *(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount * number).to_d, @currency
end
def /(number)
raise ArgumentError if not number.is_a? Numeric
Money.new (self.amount / number).to_d, @currency
end
def +(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount + other.amount).to_d, @currency
end
def -(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
Money.new (self.amount - other.amount).to_d, @currency
end
def <=>(other)
raise ArgumentError if not other.is_a? Money
raise IncompatibleCurrencies if self.currency != other.currency
self.amount <=> other.amount
end
def inspect
to_s
end
end