Решение на Първа задача от Емануела Моллова

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

Към профила на Емануела Моллова

Резултати

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

Код

class Integer
def prime?
return false if self <= 1
2.upto(pred).select { |number| remainder(number).zero? }.empty?
end
def prime_factors
return [] if abs == 1
divisor = 2.upto(abs).find { |x| x.prime? and abs.remainder(x).zero? }
[divisor] + (abs / divisor).prime_factors
end
def harmonic
denumerator = 1.upto(self).reduce(:*)
numerator = 1.upto(self).map { |x| denumerator / x }.reduce(:+)
Rational(numerator, denumerator)
end
def digits
abs.to_s.chars.map { |char| char.to_i }
end
end
class Array
def frequencies
frequencies = {}
uniq.each { |element| frequencies[element] = count(element) }
frequencies
end
def average
reduce(:+) / size.to_f
end
def drop_every(n)
1.upto(size).select { |x| x.remainder(n).nonzero? }.map { |x| self[x-1] }
end
def combine_with(other)
return other if empty?
combined = zip(other).reduce(:concat).compact
difference = other.size - size
difference > 0 ? combined + other.slice(size, difference) : combined
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-hgxfk1/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.02309 seconds
14 examples, 1 failure

Failed examples:

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

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

Емануела обнови решението на 13.10.2013 16:04 (преди около 11 години)

+class Integer
+ def prime?
+ return false if self <= 1
+ 2.upto(pred).select { |x| self % x == 0 }.empty?
+ end
+
+ def prime_factors
+ return [] if abs == 1
+ result = 2.upto(abs).find { |x| x.prime? and abs % x == 0 }
+ [].push(result) + (abs / result).prime_factors
+ end
+
+ def harmonic
+ denumerator = 1.upto(self).reduce(:*)
+ numerator = 1.upto(self).map { |x| denumerator / x }.reduce(:+)
+ Rational(numerator, denumerator)
+ end
+
+ def digits
+ (abs).to_s.split(//).map{ |x| x.to_i }
+ end
+end
+
+class Array
+ def frequencies
+ result = {}
+ uniq.each { |x| result[x] = count(x) }
+ return result
+ end
+
+ def average
+ reduce(:+) / (size).to_f
+ end
+
+ def drop_every(n)
+ select { |x| (index(x) + 1) % n != 0 }
+ end
+
+ def combine_with(other)
+ return other if empty?
+ zip(other).reduce(:concat).compact
+ end
+end

Емануела обнови решението на 13.10.2013 16:08 (преди около 11 години)

class Integer
def prime?
return false if self <= 1
2.upto(pred).select { |x| self % x == 0 }.empty?
end
def prime_factors
return [] if abs == 1
- result = 2.upto(abs).find { |x| x.prime? and abs % x == 0 }
+ result = 2.upto(abs).find { |x| x.prime? and abs % x == 0 }
[].push(result) + (abs / result).prime_factors
end
def harmonic
denumerator = 1.upto(self).reduce(:*)
numerator = 1.upto(self).map { |x| denumerator / x }.reduce(:+)
Rational(numerator, denumerator)
end
def digits
(abs).to_s.split(//).map{ |x| x.to_i }
end
end
class Array
def frequencies
result = {}
uniq.each { |x| result[x] = count(x) }
return result
end
def average
reduce(:+) / (size).to_f
end
def drop_every(n)
select { |x| (index(x) + 1) % n != 0 }
end
def combine_with(other)
return other if empty?
zip(other).reduce(:concat).compact
end
end

Много добро решение!

Ето малко бележки:

  • number е по-добро име от x на ред 4
  • Съшото важи и за result на ред 9; какво е това там? Може би factor, number, divisor? Само result не е достатъчно
  • [].push(result) е доста странен начин да се напише [result]
  • Добра практика за по-четим код е когато имаме няколко реда с равенства един под друг, да ги подравняваш по символа =; например, при теб това може да стане на ред 14-15
  • Ред 20: виж какво прави String#chars и помисли дали няма по-добро име за x-а там
  • Пак там, трябва да има интервал преди {
  • Няма никаква нужда от скобите около abs на ред 20, както и същите около size на ред 32
  • В Ruby няма нужда да пишеш return, ако искаш да върнеш стойността на последно изпълнения израз в метод; това важи за ред 28, например
  • Пак за този ред, result - знаеш :) По-добре щеше да е frequencies (няма проблем да има такава локална променлива) или нещо друго; аз бих използвал element вместо x на следващия ред
  • Имаш логически проблем (бъг) в метода drop_every; потърси го
  • Предпочитаме вариантите с думи на проверката за делимост, т.е. remainder(number), zero? и nonzero?
  • Не съм убеден, че твоят combine_with ще работи правилно; премисли го внимателно

Би ли споделила дали си се занимавала преди с Ruby и ако не, как разбра за нещата, които си използвала в решението, тъй като за повечето от тях не сме говорили все още, а си ги използвала съвсем на място?

Благодаря много за забележките и коментарите, ще се поправя възможно най-скоро! :) С Ruby не съм се занимавала преди, но имахме курс по функционално програмиране, в който учихме Scheme и Haskell и някои неща ми се виждат сходни (особено map, reduce, select). А иначе отворих документацията за класовете Array, Hash, Integer и Enumerable и започнах да разглеждам какви методи има и да търся такива, които биха послужили за 8-те функции. На места се допитвах и до Google (например как да разделя Integer-и и да получа дробно число). Накрая прочетох набързо и style guide-а и там пишеше, че е по-добре да се ползва map отколкото collect, find отколкото detect и т.н. и така научих за още някои методи (аз например бях ползвала detect).

Емануела обнови решението на 14.10.2013 18:20 (преди около 11 години)

class Integer
def prime?
return false if self <= 1
- 2.upto(pred).select { |x| self % x == 0 }.empty?
+ 2.upto(pred).select { |number| remainder(number).zero? }.empty?
end
def prime_factors
return [] if abs == 1
- result = 2.upto(abs).find { |x| x.prime? and abs % x == 0 }
- [].push(result) + (abs / result).prime_factors
+ divisor = 2.upto(abs).find { |x| x.prime? and abs.remainder(x).zero? }
+ [divisor] + (abs / divisor).prime_factors
end
def harmonic
denumerator = 1.upto(self).reduce(:*)
- numerator = 1.upto(self).map { |x| denumerator / x }.reduce(:+)
+ numerator = 1.upto(self).map { |x| denumerator / x }.reduce(:+)
Rational(numerator, denumerator)
end
def digits
- (abs).to_s.split(//).map{ |x| x.to_i }
+ abs.to_s.chars.map { |char| char.to_i }
end
end
class Array
def frequencies
- result = {}
- uniq.each { |x| result[x] = count(x) }
- return result
+ frequencies = {}
+ uniq.each { |element| frequencies[element] = count(element) }
+ frequencies
end
def average
- reduce(:+) / (size).to_f
+ reduce(:+) / size.to_f
end
def drop_every(n)
- select { |x| (index(x) + 1) % n != 0 }
+ 1.upto(size).select { |x| x.remainder(n).nonzero? }.map { |x| self[x-1] }
end
def combine_with(other)
return other if empty?
- zip(other).reduce(:concat).compact
+ array = zip(other).reduce(:concat).compact
+ diff = other.size - size
+ if (diff > 0) then array + other.slice(size, diff) else array end
end
-end
+end

Емануела обнови решението на 16.10.2013 12:40 (преди около 11 години)

class Integer
def prime?
return false if self <= 1
2.upto(pred).select { |number| remainder(number).zero? }.empty?
end
def prime_factors
return [] if abs == 1
divisor = 2.upto(abs).find { |x| x.prime? and abs.remainder(x).zero? }
[divisor] + (abs / divisor).prime_factors
end
def harmonic
denumerator = 1.upto(self).reduce(:*)
numerator = 1.upto(self).map { |x| denumerator / x }.reduce(:+)
Rational(numerator, denumerator)
end
def digits
abs.to_s.chars.map { |char| char.to_i }
end
end
class Array
def frequencies
frequencies = {}
uniq.each { |element| frequencies[element] = count(element) }
frequencies
end
def average
reduce(:+) / size.to_f
end
def drop_every(n)
1.upto(size).select { |x| x.remainder(n).nonzero? }.map { |x| self[x-1] }
end
def combine_with(other)
return other if empty?
- array = zip(other).reduce(:concat).compact
- diff = other.size - size
- if (diff > 0) then array + other.slice(size, diff) else array end
+ combined = zip(other).reduce(:concat).compact
+ difference = other.size - size
+ difference > 0 ? combined + other.slice(size, difference) : combined
end
-end
+end