Решение на Първа задача от Георги Гърдев

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

Към профила на Георги Гърдев

Резултати

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

Код

class Integer
def prime?
return false if self < 2
limit = Math.sqrt(self).floor
2.upto(limit).none? { |number| remainder(number).zero? }
end
def prime_factors
integer_to_factor = abs
2.upto(integer_to_factor).each_with_object([]) do |number, prime_factors|
while number.prime? and integer_to_factor.remainder(number).zero?
prime_factors << number
integer_to_factor /= number
end
end
end
def harmonic
downto(1).map { |number| 1 / number.to_r }.reduce(:+)
end
def digits
abs.to_s.chars.map(&:to_i)
end
end
class Array
def frequencies
each_with_object({}) { |element, hash| hash[element] = count(element) }
end
def average
reduce(:+) / size.to_f
end
def drop_every(n)
each_slice(n).map { |slice| slice.take(n - 1) }.flatten
end
def combine_with(other)
if size < other.size
intertwined = other.zip(self).map(&:reverse)
else
intertwined = zip(other)
end
intertwined.flatten.compact
end
end

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

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

Failures:

  1) Array#combine_with combines two arrays by alternatingly taking elements
     Failure/Error: [:a, :b, :c].combine_with([1, nil, 3]).should       eq [:a, 1, :b, nil, :c, 3]
       
       expected: [:a, 1, :b, nil, :c, 3]
            got: [:a, 1, :b, :c, 3]
       
       (compared using ==)
     # /tmp/d20131023-4395-1r2jwms/spec.rb:110:in `block (2 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.04339 seconds
14 examples, 1 failure

Failed examples:

rspec /tmp/d20131023-4395-1r2jwms/spec.rb:103 # Array#combine_with combines two arrays by alternatingly taking elements

История (7 версии и 3 коментара)

Георги обнови решението на 10.10.2013 19:10 (преди над 10 години)

+class Integer
+ def prime?
+ return false if self < 2
+
+ limit = Math.sqrt(self).ceil
+ (2..limit).none? { |x| self != x and self % x == 0 }
+ end
+
+ def prime_factors
+ current = abs
+ (2..current).each_with_object([]) do |x, result|
+ while x.prime? and current % x == 0
+ result << x
+ current /= x
+ end
+ end
+ end
+
+ def harmonic
+ return nil if self <= 0
+ (1..self).map { |x| 1/x.to_r }.reduce(&:+)
+ end
+
+ def digits
+ abs.to_s.chars.each_with_object([]) { |x, result| result << x.to_i }
+ end
+end
+
+class Array
+ def frequencies
+ each_with_object({}) { |x, hash| hash[x] = count(x) }
+ end
+
+ def average
+ return nil if size == 0
+ reduce(&:+) / size.to_f
+ end
+
+ def drop_every(n)
+ result = []
+ each_slice(n) do |x|
+ x.pop
+ result += x
+ end
+
+ result
+ end
+
+ def combine_with(other)
+ return other if empty?
+ return self if other.empty?
+
+ zip(other).flatten.compact
+ end
+end

Георги обнови решението на 10.10.2013 19:19 (преди над 10 години)

class Integer
def prime?
return false if self < 2
limit = Math.sqrt(self).ceil
(2..limit).none? { |x| self != x and self % x == 0 }
end
def prime_factors
current = abs
(2..current).each_with_object([]) do |x, result|
while x.prime? and current % x == 0
result << x
current /= x
end
end
end
def harmonic
return nil if self <= 0
(1..self).map { |x| 1/x.to_r }.reduce(&:+)
end
def digits
abs.to_s.chars.each_with_object([]) { |x, result| result << x.to_i }
end
end
class Array
def frequencies
each_with_object({}) { |x, hash| hash[x] = count(x) }
end
def average
return nil if size == 0
reduce(&:+) / size.to_f
end
def drop_every(n)
result = []
each_slice(n) do |x|
x.pop
result += x
end
result
end
def combine_with(other)
return other if empty?
- return self if other.empty?
-
zip(other).flatten.compact
end
end
  • result не е добро име на променлива; твърде, твърде общо е; именувай го според контекста; например, prime_factors е по-добро име; същото важи и за x; предпочитам number/element или друго, пред просто x
  • if size == 0 е по-добре изразено като if empty? (имаш го по-надолу)
  • reduce(&:+) ще работи и без & (вж. документацията)
  • Цялото нещо в Array#average може да стане на един ред, помисли как
  • Array#drop_everyпак има употреба на x, за която си заслужаваш бой през пръстите :) Това е slice/subslice/subarray или нещо сродно, но не и x
  • Пак там, забранявам ти да ползваш pop или друго, което мутира подадения slice, въпреки, че е копие; направи го на един ред някак, без pop, да видим :)
  • Пак за този метод, може да стане и без "result"; ти си от минала година, познаваш добре Enumerable (или поне би трябвало), виж дали ще можеш да го измислиш :)
  • Този each_with_object в #digits е излишен; можеш да минеш и без него, помисли как
  • Нещата в #harmonic пак могат да са на един ред и да са културно, помисли как
  • Итеративният алгоритъм в #prime_factors не ме кефи особено, но нека остане така; само ще вметна, че предпочитаме вариантите с думи за проверка за делимост, като remainder(number), Integer#zero? и т.н.

Иначе, решението е прилично като цяло. :)

Георги обнови решението на 10.10.2013 21:56 (преди над 10 години)

class Integer
def prime?
return false if self < 2
limit = Math.sqrt(self).ceil
- (2..limit).none? { |x| self != x and self % x == 0 }
+ (2..limit).none? { |number| self != number and remainder(number).zero? }
end
def prime_factors
current = abs
- (2..current).each_with_object([]) do |x, result|
- while x.prime? and current % x == 0
- result << x
- current /= x
+ (2..current).each_with_object([]) do |number, prime_factors|
+ while number.prime? and current.remainder(number).zero?
+ prime_factors << number
+ current /= number
end
end
end
def harmonic
- return nil if self <= 0
- (1..self).map { |x| 1/x.to_r }.reduce(&:+)
+ (1..self).map { |number| 1/number.to_r }.reduce(:+) or nil
end
def digits
- abs.to_s.chars.each_with_object([]) { |x, result| result << x.to_i }
+ abs.to_s.chars.map(&:to_i)
end
end
class Array
def frequencies
- each_with_object({}) { |x, hash| hash[x] = count(x) }
+ each_with_object({}) { |element, hash| hash[element] = count(element) }
end
def average
- return nil if size == 0
- reduce(&:+) / size.to_f
+ empty? ? nil : reduce(:+) / size.to_f
end
def drop_every(n)
- result = []
- each_slice(n) do |x|
- x.pop
- result += x
- end
-
- result
+ each_slice(n).map { |slice| slice.take(n-1) }.flatten
end
def combine_with(other)
- return other if empty?
- zip(other).flatten.compact
+ empty? ? other : zip(other).flatten.compact
end
-end
+end

Мерси за коментарите :) Някои от нещата ми станаха очевидни веднага като прочетох забележките...

Колкото до x и result дълбоко съжалявам! :D Не спазих много Clarity over Brevity. За вбъдеще ще гледам да се поправя. :)

prime_factors и на мен не ми харесва от самото начало, че е итеративен, ще помисля още върху него.

Относно remainder - в момента не ми харесва много какво се случи в Integer#prime? - за да събера решението в 80 знака, трябваше да махна self, а само remainder(number).zero? лично на мен ми е по-нечетимо от self % number == 0.

За Array#average не знам дали това се очакваше като едноредово решение, но ми звучи добре...

Георги обнови решението на 10.10.2013 22:43 (преди над 10 години)

class Integer
def prime?
return false if self < 2
limit = Math.sqrt(self).ceil
(2..limit).none? { |number| self != number and remainder(number).zero? }
end
def prime_factors
current = abs
(2..current).each_with_object([]) do |number, prime_factors|
while number.prime? and current.remainder(number).zero?
prime_factors << number
current /= number
end
end
end
def harmonic
- (1..self).map { |number| 1/number.to_r }.reduce(:+) or nil
+ (1..self).map { |number| 1/number.to_r }.reduce(:+)
end
def digits
abs.to_s.chars.map(&:to_i)
end
end
class Array
def frequencies
each_with_object({}) { |element, hash| hash[element] = count(element) }
end
def average
empty? ? nil : reduce(:+) / size.to_f
end
def drop_every(n)
each_slice(n).map { |slice| slice.take(n-1) }.flatten
end
def combine_with(other)
empty? ? other : zip(other).flatten.compact
end
end
  • Има нужда от интервал около / тук: 1/number.to_r
  • current в prime_factors продължава да не бъде добро име, трябва да търсим по-добро
  • За average, имах предвид да ползваш постфиксен if/unless, но предвид последните промени и уточнения в условието на задачата, окей е дори да няма проверка там.
  • Ред 38, трябва да има интервали около -

Георги обнови решението на 11.10.2013 15:53 (преди над 10 години)

class Integer
def prime?
return false if self < 2
limit = Math.sqrt(self).ceil
- (2..limit).none? { |number| self != number and remainder(number).zero? }
+ 2.upto(limit).none? { |number| self != number and remainder(number).zero? }
end
def prime_factors
- current = abs
- (2..current).each_with_object([]) do |number, prime_factors|
- while number.prime? and current.remainder(number).zero?
+ integer_to_factor = abs
+ 2.upto(integer_to_factor).each_with_object([]) do |number, prime_factors|
+ while number.prime? and integer_to_factor.remainder(number).zero?
prime_factors << number
- current /= number
+ integer_to_factor /= number
end
end
end
def harmonic
- (1..self).map { |number| 1/number.to_r }.reduce(:+)
+ downto(1).map { |number| 1 / number.to_r }.reduce(:+)
end
def digits
abs.to_s.chars.map(&:to_i)
end
end
class Array
def frequencies
each_with_object({}) { |element, hash| hash[element] = count(element) }
end
def average
- empty? ? nil : reduce(:+) / size.to_f
+ reduce(:+) / size.to_f
end
def drop_every(n)
- each_slice(n).map { |slice| slice.take(n-1) }.flatten
+ each_slice(n).map { |slice| slice.take(n - 1) }.flatten
end
def combine_with(other)
empty? ? other : zip(other).flatten.compact
end
-end
+end

Георги обнови решението на 13.10.2013 00:10 (преди над 10 години)

class Integer
def prime?
return false if self < 2
- limit = Math.sqrt(self).ceil
- 2.upto(limit).none? { |number| self != number and remainder(number).zero? }
+ limit = Math.sqrt(self).floor
+ 2.upto(limit).none? { |number| self.remainder(number).zero? }
end
def prime_factors
integer_to_factor = abs
2.upto(integer_to_factor).each_with_object([]) do |number, prime_factors|
while number.prime? and integer_to_factor.remainder(number).zero?
prime_factors << number
integer_to_factor /= number
end
end
end
def harmonic
downto(1).map { |number| 1 / number.to_r }.reduce(:+)
end
def digits
abs.to_s.chars.map(&:to_i)
end
end
class Array
def frequencies
each_with_object({}) { |element, hash| hash[element] = count(element) }
end
def average
reduce(:+) / size.to_f
end
def drop_every(n)
each_slice(n).map { |slice| slice.take(n - 1) }.flatten
end
def combine_with(other)
- empty? ? other : zip(other).flatten.compact
+ if size < other.size
+ interwined = other.zip(self).map(&:reverse)
+ else
+ interwined = zip(other)
+ end
+
+ interwined.flatten.compact
end
-end
+end

Георги обнови решението на 16.10.2013 10:47 (преди над 10 години)

class Integer
def prime?
return false if self < 2
limit = Math.sqrt(self).floor
- 2.upto(limit).none? { |number| self.remainder(number).zero? }
+ 2.upto(limit).none? { |number| remainder(number).zero? }
end
def prime_factors
integer_to_factor = abs
2.upto(integer_to_factor).each_with_object([]) do |number, prime_factors|
while number.prime? and integer_to_factor.remainder(number).zero?
prime_factors << number
integer_to_factor /= number
end
end
end
def harmonic
downto(1).map { |number| 1 / number.to_r }.reduce(:+)
end
def digits
abs.to_s.chars.map(&:to_i)
end
end
class Array
def frequencies
each_with_object({}) { |element, hash| hash[element] = count(element) }
end
def average
reduce(:+) / size.to_f
end
def drop_every(n)
each_slice(n).map { |slice| slice.take(n - 1) }.flatten
end
def combine_with(other)
if size < other.size
- interwined = other.zip(self).map(&:reverse)
+ intertwined = other.zip(self).map(&:reverse)
else
- interwined = zip(other)
+ intertwined = zip(other)
end
- interwined.flatten.compact
+ intertwined.flatten.compact
end
end