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

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

Към профила на Светлозар Тодоров

Резултати

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

Код

def series(name, index)
case name
when 'fibonacci' then calculate_member(1, 1, index)
when 'lucas' then calculate_member(2, 1, index)
when 'summed' then series('fibonacci', index) + series('lucas', index)
end
end
def calculate_member(first_element, second_element, index)
sequence = [nil, first_element, second_element]
(3..index).each do |element|
sequence[element] = sequence[element - 2] + sequence[element - 1]
end
sequence[index]
end

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

............

Finished in 0.00924 seconds
12 examples, 0 failures

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

Светлозар обнови решението на 11.10.2014 17:04 (преди около 10 години)

+def series(name, index)
+ case name
+ when 'fibonacci' then fibonacci(index)
+ when 'lucas' then lucas(index)
+ when 'summed' then summed(index)
+ end
+end
+
+def fibonacci(index)
+ if (1..2).include? index then result = 1
+ else
+ first = 1
+ second = 1
+ result = fibonacci(index - 2) * first + fibonacci(index - 1) * second
+ end
+end
+
+def lucas(index)
+ if index == 1 then result = 2
+ elsif index == 2 then result = 1
+ else
+ first = 2
+ second = 1
+ result = fibonacci(index - 2) * first + fibonacci(index - 1) * second
+ end
+end
+
+def summed(index)
+ result = fibonacci(index) + lucas(index)
+end

Здрасти. Имам няколко забележки.

  • Виж как се форматира кода правилно. Много важно е кодът да е лесен и приятен за четене. :)

  • Променливата result навсякъде е излишна. Създаваш локална променлива, която не ползваш никъде. Може би си искал чрез нея да поясниш, че това е резултата от функцията, но това е ясно така, или иначе.

  • Логиката ти във функцията lucas e странна. Ти твърдиш, че

    lucas(n) = 2 * fibonacci(n-2) + fibonacci(n-1).

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

Светлозар обнови решението на 12.10.2014 10:26 (преди около 10 години)

def series(name, index)
- case name
- when 'fibonacci' then fibonacci(index)
- when 'lucas' then lucas(index)
- when 'summed' then summed(index)
- end
+ case name
+ when 'fibonacci' then fibonacci(index)
+ when 'lucas' then lucas(index)
+ when 'summed' then summed(index)
+ end
end
def fibonacci(index)
- if (1..2).include? index then result = 1
- else
- first = 1
- second = 1
- result = fibonacci(index - 2) * first + fibonacci(index - 1) * second
- end
+ if (1..2).include? index then result = 1
+ else
+ first = 1
+ second = 1
+ fibonacci(index - 2) * first + fibonacci(index - 1) * second
+ end
end
def lucas(index)
- if index == 1 then result = 2
- elsif index == 2 then result = 1
- else
- first = 2
- second = 1
- result = fibonacci(index - 2) * first + fibonacci(index - 1) * second
- end
+ if index == 1 then result = 2
+ elsif index == 2 then result = 1
+ else
+ first = 2
+ second = 1
+ fibonacci(index - 2) * first + fibonacci(index - 1) * second
+ end
end
def summed(index)
- result = fibonacci(index) + lucas(index)
+ result = fibonacci(index) + lucas(index)
end

Здравей и благодаря за коментара!

Относно форматирането на кода:

  • ще трябва да си поиграя малко с настройките на Sublime Text - въпреки че съм настроил табулация от два празни места, след като пейстна текста тук, излизаше по-голяма; за момента просто ръчно ги поставих в началото на всеки ред :anguished:, но ще опитам да се справя с проблема;
  • празните места, които оставям преди then, не се пействат по същия начин; още нещо, което е най-вероятно при мен; бих изпуснал then и пренесъл изразите на долен ред, но ограниченията... :wink:; отново, ще опитам да оправя и това.

Махнах променливата result - благодаря за забележката. Това е нещо, с което все още свиквам в Ruby. :smile:

Формулата открих ето тук. Преди това пробвах по-интуитивен начин с три променливи, но не се вмествам в изискването за дължина на метод :disappointed: Ще опитам отново да раздробя на още по-малки методи.

Поздрави!

Светлозар обнови решението на 12.10.2014 22:00 (преди около 10 години)

def series(name, index)
case name
when 'fibonacci' then fibonacci(index)
when 'lucas' then lucas(index)
when 'summed' then summed(index)
end
end
def fibonacci(index)
- if (1..2).include? index then result = 1
- else
- first = 1
- second = 1
- fibonacci(index - 2) * first + fibonacci(index - 1) * second
- end
+ calculate(1, 1, index)
end
def lucas(index)
- if index == 1 then result = 2
- elsif index == 2 then result = 1
- else
- first = 2
- second = 1
- fibonacci(index - 2) * first + fibonacci(index - 1) * second
- end
+ calculate(2, 1, index)
end
def summed(index)
result = fibonacci(index) + lucas(index)
-end
+end
+
+def calculate(first, second, index)
+ set = []
+ set[1] = first
+ set[2] = second
+ (3..index).each { |element| set[element] = set[element-2] + set[element-1] }
+ set[index]
+end

Така е доста по-добре :) Относно sublime text, ако не си го оправил все още, може да питаш във форума.

За решението няколко забележки, главно свързани с именоване :

  • calculate е много общо име за функция. Конкретизирай го малко. Calculate какво ? Мисленето на имена си е трудна задача, но и много важна, защото чрез имената, които въвеждаш, си дефинираш езика, на който ще описваш даден проблем.

  • set също не е много добро име, защото е малко подвеждащо. Множество е математически обект с някакви свойства. Замисли се каква семантика има твоят масив. Той ти съхранява всички членове от редицата. Може би е добре да се нарича sequence.

  • first, second какво ? Членове на редица? Елементи?

  • Можеш да използваш литерала за масив така [first, second], но после внимавай с индексите.

  • Оставяй празно място около -.

  • Тъй като функциите fibonacci, lucas и summed са доста кратки вече, можеш да пробваш да ги махнеш и да видиш как ще изглеждат нещата.

Ако имаш някакви проблеми и скептикът не ти харесва решението, можеш да пишеш пак :)

Светлозар обнови решението на 13.10.2014 22:57 (преди около 10 години)

def series(name, index)
case name
- when 'fibonacci' then fibonacci(index)
- when 'lucas' then lucas(index)
- when 'summed' then summed(index)
+ when 'fibonacci' then find_item_by(1, 1, index)
+ when 'lucas' then find_item_by(2, 1, index)
+ when 'summed' then find_item_by(1, 1, index) + find_item_by(2, 1, index)
end
end
-def fibonacci(index)
- calculate(1, 1, index)
-end
-
-def lucas(index)
- calculate(2, 1, index)
-end
-
-def summed(index)
- result = fibonacci(index) + lucas(index)
-end
-
-def calculate(first, second, index)
- set = []
- set[1] = first
- set[2] = second
- (3..index).each { |element| set[element] = set[element-2] + set[element-1] }
+def find_item_by(first_element, second_element, index)
+ sequence = [0, first_element, second_element]
+ (3..index).each do |element|
+ sequence[element] = sequence[element - 2] + sequence[element - 1]
+ end
set[index]
end

Светлозар обнови решението на 13.10.2014 22:58 (преди около 10 години)

def series(name, index)
case name
when 'fibonacci' then find_item_by(1, 1, index)
when 'lucas' then find_item_by(2, 1, index)
when 'summed' then find_item_by(1, 1, index) + find_item_by(2, 1, index)
end
end
def find_item_by(first_element, second_element, index)
sequence = [0, first_element, second_element]
(3..index).each do |element|
sequence[element] = sequence[element - 2] + sequence[element - 1]
end
- set[index]
+ sequence[index]
end
  • Името find_item_by отново не е много добре. Трябваше да си запазиш calculate, защото наистина се пресмята нещо. Пресмята се n-тия член от редицата. calculate_member например е по-добре.

  • За началната 0 в sequence съм със смесени чувства. От една страна е добре, защото по-долу ти се запазват индексите и n-тия елемент от редицата ти е n-ти елемент от масива. От друга страна 0 не е валиден член на редицата и релацията sequence[2] = sequence[0] + sequence[1] не е изпълнена в случая при редицата на Лукас. Тази 0 не принадлежи на масива. Или я замени с nil, за да е напълно ясно, че е нещо спомагателно, или по-добре я махни и си коригирай индексите долу. Все пак програмистите сме свикнали да броим от 0 :smile:.

  • Подравни си when клаузите още два спейса навътре, а също можеш да подравниш then-овете един под друг, ето така :

    when 'happy'   then ..
    when 'hungry'  then ..
    when 'thirsty' then ..
    

Светлозар обнови решението на 14.10.2014 17:36 (преди около 10 години)

def series(name, index)
case name
- when 'fibonacci' then find_item_by(1, 1, index)
- when 'lucas' then find_item_by(2, 1, index)
- when 'summed' then find_item_by(1, 1, index) + find_item_by(2, 1, index)
+ when 'fibonacci' then calculate(1, 1, index)
+ when 'lucas' then calculate(2, 1, index)
+ when 'summed' then calculate(1, 1, index) + calculate(2, 1, index)
end
end
-def find_item_by(first_element, second_element, index)
- sequence = [0, first_element, second_element]
+def calculate(first_element, second_element, index)
+ sequence = [nil, first_element, second_element]
(3..index).each do |element|
sequence[element] = sequence[element - 2] + sequence[element - 1]
end
sequence[index]
end

Здравей!

И благодаря отново за подробните коментари! Опитвам да подравня then - овете, но щом ги пейстна в полето за код, подравняването се чупи доста сериозно. Не мога да разбера защо... Ще пиша във форума. Най-вероятно ще е най-добре да ги оставя с по едно празно място след изразите преди then.

За nil - разбрано. Още докато пишех 0, нещо не ми се стореше наред.

calculate става твърде дълъг при всички случаи. Мислех си за member и за item, но редът пак става повече от 80 символа... Ще помисля още малко до крайния срок. В краен случай ще го оставя така и ще си нося последствията :sweat:

Благодаря и поздрави!

Не се тревожи за последствията :smile:. then-овете ако не можеш да ги подравниш по този начин, наистина ги остави с по едно празно място.

А отностно дългия ред, помисли коя друга фунцкия можеш да викнеш там която смята това което ти трябва :grin:.

Светлозар обнови решението на 14.10.2014 23:16 (преди около 10 години)

def series(name, index)
case name
- when 'fibonacci' then calculate(1, 1, index)
- when 'lucas' then calculate(2, 1, index)
- when 'summed' then calculate(1, 1, index) + calculate(2, 1, index)
+ when 'fibonacci' then calculate_member(1, 1, index)
+ when 'lucas' then calculate_member(2, 1, index)
+ when 'summed' then series('fibonacci', index) + series('lucas', index)
end
end
-def calculate(first_element, second_element, index)
+def calculate_member(first_element, second_element, index)
sequence = [nil, first_element, second_element]
(3..index).each do |element|
sequence[element] = sequence[element - 2] + sequence[element - 1]
end
sequence[index]
end