Решение на Първа задача от Николай Петков

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

Към профила на Николай Петков

Резултати

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

Код

def calculate_number(number, first_value, second_value)
for i in 2...number
if i % 2 == 0
first_value = first_value + second_value
else second_value = first_value + second_value
end
end
[first_value, second_value].max
end
def check_number(number, first_value, second_value)
if number == 1
first_value
elsif number == 2
second_value
end
calculate_number(number, first_value, second_value)
end
def series(name, number)
if name == 'fibonacci'
return check_number(number, 1, 1)
elsif name == 'lucas'
return check_number(number, 2, 1)
end
check_number(number, 1, 1) + check_number(number, 2, 1)
end

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

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

Failures:

  1) series handles lucas series for base cases
     Failure/Error: series('lucas', 2).should eq 1
       
       expected: 1
            got: 2
       
       (compared using ==)
     # /tmp/d20141023-2426-12rb39x/spec.rb:26: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) series handles summed series for base cases
     Failure/Error: series('summed', 2).should eq 2
       
       expected: 2
            got: 3
       
       (compared using ==)
     # /tmp/d20141023-2426-12rb39x/spec.rb:46: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.01342 seconds
12 examples, 2 failures

Failed examples:

rspec /tmp/d20141023-2426-12rb39x/spec.rb:24 # series handles lucas series for base cases
rspec /tmp/d20141023-2426-12rb39x/spec.rb:44 # series handles summed series for base cases

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

Николай обнови решението на 14.10.2014 15:59 (преди над 9 години)

+def numerical_range(number, first_value, second_value)
+ for i in 2...number
+ if i%2 == 0
+ first_value = first_value + second_value
+ else second_value = first_value + second_value
+ end
+ end
+ return (first_value > second_value)?first_value:second_value
+end
+
+def check_number(number, first_value, second_value)
+ if number == 1
+ return first_value
+ elsif number == 2
+ return second_value
+ else return (number < 1)?0:numericalRange(number,first_value, second_value)
+ end
+end
+
+
+def series(name, number)
+ if name == 'fibonacci'
+ return checkNumber(number, 1, 1)
+ elsif name == 'lucas'
+ return checkNumber(number, 2, 1)
+ end
+return checkNumber(number, 1, 1) + checkNumber(number, 2, 1)
+end

Николай обнови решението на 14.10.2014 16:01 (преди над 9 години)

def numerical_range(number, first_value, second_value)
for i in 2...number
if i%2 == 0
first_value = first_value + second_value
else second_value = first_value + second_value
end
end
return (first_value > second_value)?first_value:second_value
end
def check_number(number, first_value, second_value)
if number == 1
return first_value
elsif number == 2
return second_value
- else return (number < 1)?0:numericalRange(number,first_value, second_value)
+ else return (number < 1)?0:numerical_range(number,first_value, second_value)
end
end
def series(name, number)
if name == 'fibonacci'
- return checkNumber(number, 1, 1)
+ return check_number(number, 1, 1)
elsif name == 'lucas'
- return checkNumber(number, 2, 1)
+ return check_number(number, 2, 1)
end
-return checkNumber(number, 1, 1) + checkNumber(number, 2, 1)
+return check_number(number, 1, 1) + check_number(number, 2, 1)
end
  • Не пиши return на последния израз от фунцкия, неговата стойност се връща по подразбиране (например 27 ред). По същата логика можеш да махнеш return-ите от check_number, защото if израза е последен и функцията ще върне неговата стойност, а неговата стойност е тази на мачнатия бранч.

  • Разгледай case конструкцията.

  • numerical_range не е добро име. По-скоро calculate_number, или compute_number :)

  • Когато ползваш тернарен оператор оставяй места около ? и :, иначе се чете много трудно.

  • Няма нужда да проверяваш за number < 1, защото не искаме задачата да работи с неположителни числа, а и нулевият член на Фибоначи е различен от този на Лукас.

  • Имаш странни функции check_number и numerical_range. Какво прави numerical_range ? Смята nth-тото число от някоя редица по подадени начални стойности, но се държи коректно само, ако n > 2. check_number прави същото нещо, но коректно за всяко положително число. В такава ситуация можеш да се замислиш за дизайна. Ако имаш разни функции, които трудно дефинираш какво правят и трудно им се измислят имена, значи нещо не е наред.

    numerical_range прави излишно сложни неща. Може да се подобри малко четимостта, ако не се ползва for и ползваш функции като even?, max, но въпреки това си остава объркващо. Помисли за по прост алгоритъм, пак може да ползваш само две променливи и итеративно да сметнеш всички стойности, или пък ако искаш направи рекурсивно решение, стига да е изразително и разбираемо :).

  • Слагай място около %, за повече информация style guide-a.

Николай обнови решението на 15.10.2014 13:16 (преди над 9 години)

-def numerical_range(number, first_value, second_value)
+def calculate_number(number, first_value, second_value)
for i in 2...number
if i%2 == 0
first_value = first_value + second_value
else second_value = first_value + second_value
end
end
- return (first_value > second_value)?first_value:second_value
+ (first_value > second_value) ? first_value : second_value
end
def check_number(number, first_value, second_value)
if number == 1
- return first_value
+ first_value
elsif number == 2
- return second_value
- else return (number < 1)?0:numerical_range(number,first_value, second_value)
+ second_value
+ else
+ calculate_number(number, first_value, second_value)
end
end
-
def series(name, number)
if name == 'fibonacci'
return check_number(number, 1, 1)
elsif name == 'lucas'
return check_number(number, 2, 1)
end
-return check_number(number, 1, 1) + check_number(number, 2, 1)
+check_number(number, 1, 1) + check_number(number, 2, 1)
end

Николай обнови решението на 15.10.2014 13:17 (преди над 9 години)

def calculate_number(number, first_value, second_value)
for i in 2...number
- if i%2 == 0
+ if i % 2 == 0
first_value = first_value + second_value
else second_value = first_value + second_value
end
end
(first_value > second_value) ? first_value : second_value
end
def check_number(number, first_value, second_value)
if number == 1
first_value
elsif number == 2
second_value
else
calculate_number(number, first_value, second_value)
end
end
def series(name, number)
if name == 'fibonacci'
return check_number(number, 1, 1)
elsif name == 'lucas'
return check_number(number, 2, 1)
end
check_number(number, 1, 1) + check_number(number, 2, 1)
end

Николай обнови решението на 15.10.2014 13:21 (преди над 9 години)

def calculate_number(number, first_value, second_value)
for i in 2...number
- if i % 2 == 0
+ if i%2 == 0
first_value = first_value + second_value
else second_value = first_value + second_value
end
end
(first_value > second_value) ? first_value : second_value
end
def check_number(number, first_value, second_value)
if number == 1
first_value
elsif number == 2
second_value
- else
- calculate_number(number, first_value, second_value)
end
+ calculate_number(number, first_value, second_value)
end
def series(name, number)
if name == 'fibonacci'
return check_number(number, 1, 1)
elsif name == 'lucas'
return check_number(number, 2, 1)
end
-check_number(number, 1, 1) + check_number(number, 2, 1)
+ check_number(number, 1, 1) + check_number(number, 2, 1)
end

Целия проблем около многото функции и че не използвам case е ограничението за 5 реда на функция(ако ползвам case стават 6). Целта на кода ми е производителност,а не четимост(причината,поради която не използвам рекурсия)

Николай обнови решението на 15.10.2014 13:27 (преди над 9 години)

def calculate_number(number, first_value, second_value)
for i in 2...number
- if i%2 == 0
+ if i % 2 == 0
first_value = first_value + second_value
else second_value = first_value + second_value
end
end
- (first_value > second_value) ? first_value : second_value
+ [first_value, second_value].max
end
def check_number(number, first_value, second_value)
if number == 1
first_value
elsif number == 2
second_value
end
calculate_number(number, first_value, second_value)
end
def series(name, number)
if name == 'fibonacci'
return check_number(number, 1, 1)
elsif name == 'lucas'
return check_number(number, 2, 1)
end
check_number(number, 1, 1) + check_number(number, 2, 1)
end

Тук не правим задачи от състезателно програмиране и целта не трябва да ти е производителността. Въпреки това съм съгласен, че експоненциална сложност си е доста гадно. Можеш да направиш нещата с линейна сложност и пак да са разбираеми и четими. Алгоритъмът е следния. Пресмяташ подред всички членове от редицата, като винаги пазиш последните две стойности. Ти правиш същото, но записваш последната стойност веднъж на едно място веднъж на друго, за да избегнеш едно swap-ване на променливи. Това усложнява нещата и ги прави нечетими, вкарва разни проверки за четност и максимална стойност и освен това не работи коректно за началните стойности на lucas, заради което правиш отделна функция, която да се справи с този проблем.

  • Премисли си алгоритъмa за calculate_number, така може би ще се оттървеш и от check_number.
  • Относно case, можеш да пишеш when something then anything така ще спестиш редове.