Решение на Първа задача от Слав Керемидчиев

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

Към профила на Слав Керемидчиев

Резултати

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

Код

class Integer
def prime?
return false if self < 0
2.upto(Math.sqrt(self)).all? { |a| self.remainder(a).nonzero? }
end
def number_divisors(prime)
number, counter_number_divisors = self, 0
while number % prime == 0
counter_number_divisors += 1
number /= prime
end
counter_number_divisors
end
def prime_factors
output_array, num = [], self.abs
factors_array = 2.upto(num).to_a.select { |a| num % a == 0 and a.prime? }
factors_array.each { |x| output_array.push [x] * num.number_divisors(x) }
output_array.flatten
end
def harmonic
1.upto(self).reduce { |sum, a| sum + Rational(1, a) }
end
def digits
self.to_s.chars.map { |digit| digit.to_i }
end
end
class Array
def remove_element_from_array(element)
self.map { |array_element|
array_element if array_element != element } .compact!
end
def frequencies
no_duplicate_array, frequencies_hash = self.uniq, {}
no_duplicate_array.each { |element|
frequencies_hash[element] = self.count(element) }
frequencies_hash
end
def average
self.reduce { |sum, x| sum + x } / self.size.to_f
end
def drop_every(n)
output_array = []
self.map.with_index.each { |element, index|
output_array.push(element) if index % n == 0 }
output_array
end
def combine_with(other)
if self.size >= other.size
self.zip(other).flatten.compact
else
output_array = self.zip(other).flatten.compact
output_array.concat(other.last(other.size - self.size))
end
end
end

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

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

Failures:

  1) Integer#prime? checks if a number is prime
     Failure/Error: 0.prime?.should   eq false
       
       expected: false
            got: true
       
       (compared using ==)
     # /tmp/d20131023-4395-dk92b1/spec.rb:4: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)>'

  2) Integer#digits works with negative numbers
     Failure/Error: (-33).digits.should     eq [3, 3]
       
       expected: [3, 3]
            got: [0, 3, 3]
       
       (compared using ==)
     # /tmp/d20131023-4395-dk92b1/spec.rb:51: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)>'

  3) Array#drop_every drops every n-th element from an array.
     Failure/Error: (1..10).to_a.drop_every(3).should eq [1, 2, 4, 5, 7, 8, 10]
       
       expected: [1, 2, 4, 5, 7, 8, 10]
            got: [1, 4, 7, 10]
       
       (compared using ==)
     # /tmp/d20131023-4395-dk92b1/spec.rb:91: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)>'

  4) 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-dk92b1/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.02124 seconds
14 examples, 4 failures

Failed examples:

rspec /tmp/d20131023-4395-dk92b1/spec.rb:2 # Integer#prime? checks if a number is prime
rspec /tmp/d20131023-4395-dk92b1/spec.rb:50 # Integer#digits works with negative numbers
rspec /tmp/d20131023-4395-dk92b1/spec.rb:87 # Array#drop_every drops every n-th element from an array.
rspec /tmp/d20131023-4395-dk92b1/spec.rb:103 # Array#combine_with combines two arrays by alternatingly taking elements

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

Слав обнови решението на 13.10.2013 02:50 (преди около 11 години)

+class Integer
+ def prime?
+ if self < 0
+ false
+ else
+ 2.upto(Math.sqrt(self)).all? { |a| self.remainder(a).nonzero? }
+ end
+ end
+
+ def contains_prime(prime)
+ num, counter = self, 0
+ while num % prime == 0
+ counter += 1
+ num /= prime
+ end
+ counter
+ end
+
+ def prime_factors
+ arr, num = [], self.abs
+ prime_arr = 2.upto(num).to_a.select { |a| num % a == 0 and a.prime? }
+ prime_arr.each { |x| arr.push [x] * num.contains_prime(x) }
+ arr.flatten
+ end
+
+ def harmonic
+ 1.upto(self).inject { |product, a| product + Rational(1,a) }
+ end
+
+ def digits
+ self.to_s.chars.map { |a| a.to_i }
+ end
+end
+
+class Array
+ def frequencies
+ arr, freqHash = self, {}
+ while not arr.empty?
+ cnt = arr.count(arr.first)
+ freqHash[arr.first] = cnt
+ arr.delete(arr.first)
+ end
+ freqHash
+ end
+
+ def average
+ self.inject{ |sum,x| sum + x } / self.count.to_f
+ end
+
+ def drop_every(n)
+ arr = []
+ hash = Hash[self.map.with_index.to_a]
+ hash.each { |key, value| arr.push(key) if value % n == 0 }
+ arr
+ end
+
+ def combine_with(other)
+ arr = []
+ while self.any? and other.any?
+ arr.push(self.shift)
+ arr.push(other.shift)
+ end
+ if self.empty? then arr + other else arr + self end
+ end
+end

Слав обнови решението на 13.10.2013 12:46 (преди около 11 години)

class Integer
def prime?
- if self < 0
- false
- else
+ if self < 0
+ false
+ else
2.upto(Math.sqrt(self)).all? { |a| self.remainder(a).nonzero? }
end
end
def contains_prime(prime)
num, counter = self, 0
while num % prime == 0
counter += 1
num /= prime
end
counter
end
def prime_factors
arr, num = [], self.abs
prime_arr = 2.upto(num).to_a.select { |a| num % a == 0 and a.prime? }
prime_arr.each { |x| arr.push [x] * num.contains_prime(x) }
arr.flatten
end
def harmonic
- 1.upto(self).inject { |product, a| product + Rational(1,a) }
+ 1.upto(self).inject { |product, a| product + Rational(1,a) }
end
def digits
- self.to_s.chars.map { |a| a.to_i }
+ self.to_s.chars.map { |a| a.to_i }
end
end
class Array
def frequencies
- arr, freqHash = self, {}
- while not arr.empty?
- cnt = arr.count(arr.first)
- freqHash[arr.first] = cnt
- arr.delete(arr.first)
- end
- freqHash
+ arr, freqHash = self, {}
+ while not arr.empty?
+ cnt = arr.count(arr.first)
+ freqHash[arr.first] = cnt
+ arr.delete(arr.first)
+ end
+ freqHash
end
def average
- self.inject{ |sum,x| sum + x } / self.count.to_f
+ self.inject{ |sum,x| sum + x } / self.count.to_f
end
def drop_every(n)
arr = []
hash = Hash[self.map.with_index.to_a]
hash.each { |key, value| arr.push(key) if value % n == 0 }
arr
end
def combine_with(other)
arr = []
while self.any? and other.any?
arr.push(self.shift)
arr.push(other.shift)
end
if self.empty? then arr + other else arr + self end
end
end

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

  • В prime? може да ползваш постфиксен if и да го напишеш така: return false if self < 0, оставяйки на следващия ред основната логика на метода
  • self. се "подразбира", когато предшества извикване на метод (ще го кажем по-натам) и е излишен; в почти всички такива случаи се пропуска (напр. ред 6, 20, 31, 47...)
  • contains_prime е кофти име; аз го разбирам като лошо именуван предикатен метод; именувай го нещо в духа на "брой делители"
  • arr, num, counter, cnt, prime_arr, a и т.н. са все лоши имена; съкращавайки няколко символа, не печелиш нищо, а губиш много; стреми се да спазваш clarity over brevity; избягвай общи имена; например, в prime_factors, няма никакъв проблем да имаш локална променлива, която се казва prime_factors, или factors, или divisors, или...
  • Методите inject и reduce са синоними и предпочитаме reduce, по-близък е до идеята на това, което искаме да постигнем
  • На ред 27, вместо product, щеше да е по-точно, ако беше написал sum
  • Пак там, трябва да има интервал след запетаята тук: 1, a
  • Ред 31, отново име -- вместо a, по-добре digit
  • Ред 37, freqHash е не само лошо име, но и такова, което не отговаря на конвенциите; консултирай се с ръководството по стил
  • while notuntil; друга форма е while arr.any? (за arr вече знаеш...)
  • На ред 41 променяш текущия списък, което е ужасно; ако веднъж извикам frequences на даден списък и той ще се опразни; ползвай `each, поне
  • Ред 47, интервал преди { и след sum,
  • Пак там, не ползвай count така; ползвай length или size; count има повече възможности и се ползва в друг контекст (напр. както си го ползвал във frequences)
  • В drop_every, няма нужда да правиш хеш, за да обходиш списъка с индекс; пробвай просто map.with_index.each { |element, index| ... } - ще си работи като пушка
  • Изцяло трябв да пренапишеш combine_with, защото пак мутираш (променяш) обектите, а това е смъртен грях
  • На ред 63, не ползвай така if/then/else; ползвай тернарният оператор foo ? bar : baz (ако това остане в крайното ти решение)

Слав обнови решението на 14.10.2013 15:30 (преди около 11 години)

class Integer
def prime?
- if self < 0
- false
- else
- 2.upto(Math.sqrt(self)).all? { |a| self.remainder(a).nonzero? }
- end
+ return false if self < 0
+ 2.upto(Math.sqrt(self)).all? { |a| self.remainder(a).nonzero? }
end
- def contains_prime(prime)
- num, counter = self, 0
- while num % prime == 0
- counter += 1
- num /= prime
+ def number_divisors(prime)
+ number, counter_number_divisors = self, 0
+ while number % prime == 0
+ counter_number_divisors += 1
+ number /= prime
end
- counter
+ counter_number_divisors
end
def prime_factors
- arr, num = [], self.abs
- prime_arr = 2.upto(num).to_a.select { |a| num % a == 0 and a.prime? }
- prime_arr.each { |x| arr.push [x] * num.contains_prime(x) }
- arr.flatten
+ output_array, num = [], self.abs
+ factors_array = 2.upto(num).to_a.select { |a| num % a == 0 and a.prime? }
+ factors_array.each { |x| output_array.push [x] * num.number_divisors(x) }
+ output_array.flatten
end
def harmonic
- 1.upto(self).inject { |product, a| product + Rational(1,a) }
+ 1.upto(self).reduce { |sum, a| sum + Rational(1, a) }
end
def digits
- self.to_s.chars.map { |a| a.to_i }
+ self.to_s.chars.map { |digit| digit.to_i }
end
end
class Array
+ def remove_element_from_array(element)
+ self.map { |array_element|
+ array_element if array_element != element } .compact!
+ end
+
def frequencies
- arr, freqHash = self, {}
- while not arr.empty?
- cnt = arr.count(arr.first)
- freqHash[arr.first] = cnt
- arr.delete(arr.first)
- end
- freqHash
+ no_duplicate_array, frequencies_hash = self.uniq, {}
+ no_duplicate_array.each { |element|
+ frequencies_hash[element] = self.count(element) }
+ frequencies_hash
end
def average
- self.inject{ |sum,x| sum + x } / self.count.to_f
+ self.reduce { |sum, x| sum + x } / self.size.to_f
end
def drop_every(n)
- arr = []
- hash = Hash[self.map.with_index.to_a]
- hash.each { |key, value| arr.push(key) if value % n == 0 }
- arr
+ output_array = []
+ self.map.with_index.each { |element, index|
+ output_array.push(element) if index % n == 0 }
+ output_array
end
def combine_with(other)
- arr = []
- while self.any? and other.any?
- arr.push(self.shift)
- arr.push(other.shift)
+ if self.size >= other.size
+ self.zip(other).flatten.compact
+ else
+ output_array = self.zip(other).flatten.compact
+ output_array.concat(other.last(other.size - self.size))
end
- if self.empty? then arr + other else arr + self end
end
end