Решение на Първа задача от Ясен Трифонов

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

Към профила на Ясен Трифонов

Резултати

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

Код

def compute_series(previous_value, last_value, index)
series_value_at_index = 0
index.times do
series_value_at_index = previous_value + last_value
last_value, previous_value = series_value_at_index, last_value
end
series_value_at_index
end
def series(series_name, index)
initial_values = { 'fibonacci' => [1, 0, index],
'lucas' => [3, -1, index],
'summed' => [4, -1, index] }
compute_series(*initial_values[series_name])
end

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

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

Finished in 0.01579 seconds
12 examples, 0 failures

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

Ясен обнови решението на 12.10.2014 15:49 (преди над 9 години)

+def compute_series(previous_value, last_value, index)
+ series_value_at_index = 0
+ index.times do
+ series_value_at_index = previous_value + last_value
+ last_value, previous_value = series_value_at_index, last_value
+ end
+ return series_value_at_index
+end
+
+def series(series_name, index)
+ initial_values = { 'f' => [1, 0], 'l' => [3, -1], 's' => [4, -1] }
+ return compute_series(*initial_values[series_name[0]] << index)
+end

Здравей :)

Хубаво решение. Харесва ми, че не си сложил какви да е имена на променливите и функциите, а си помислил за по-добри такива.

Само няколко забележки:

  • return-ите са излишни. Когато израз е последен във функцията, той се return-ва винаги.
  • Хубаво е, че си се сетил да отделиш първоначалните стойности от функцията, която смята сумата. initial_values обаче не ми изглежда добре, поради три причини:
    • Съкратил си имената, може би с идеята да ги събереш на един ред, което обаче прави функцията по-трудна за разчитане.
    • Магията, която се случва на 12. ред ми отне време да я схвана, а това не е добър знак. Всичко трябва да е написано така, че от един поглед да е ясно какво се случва.
    • Първоначалните стойности са различни от тези на съответните редици. По-добре нагласи функцията, така че да работи с "истинските" първоначални стойности, отколкото да нагласяваш стойностите според функцията.

Ако смяташ, че с initial_values няма да могат да се оправят някои от нещата, може да използваш case .. when .. then .. в series.

Ясен обнови решението на 14.10.2014 10:43 (преди над 9 години)

def compute_series(previous_value, last_value, index)
series_value_at_index = 0
index.times do
series_value_at_index = previous_value + last_value
last_value, previous_value = series_value_at_index, last_value
end
- return series_value_at_index
+ series_value_at_index
end
def series(series_name, index)
- initial_values = { 'f' => [1, 0], 'l' => [3, -1], 's' => [4, -1] }
- return compute_series(*initial_values[series_name[0]] << index)
+ initial_values = { 'fibonacci' => [1, 0, index],
-end
+ 'lucas' => [3, -1, index],
+ 'summed' => [4, -1, index] }
+ compute_series(*initial_values[series_name])
+end

Здрасти :)

Изпратих нова версия:

1) Махнах return-ите. Мислех си, че е по-четимо с тях, но си прав, че са излишни.

2) Имената мога и да не ги съкращавам (в началото исках всичко да е 1 функция, но не ми достигаха ред-два), така изглежда по-добре.

3) "Магията" на ред 12 е проста комбинация на 2 сравнително често използвани ruby оператора. Единствената въпросителна е с приоритетите им, но се предполага, че ако имаш добър опит с ruby, това не трябва да е проблем.

Простото решение е просто да добавя index към всеки елемент от initial_values.

Не мисля да променям първите две стойности, въпреки че не са като оригиналните (иначе трябва да правя магии с индексацията -- (index-2).times не ми харесва и може да доведе то грешки или допълнителни условия) . Би трябвало key-ът на initial_values да дава добра ориентация за това :)

Поздрави, Ясен.

За 12. (вече 14.) ред: Ясно е, че работи. А щом работи, значи ако се замислиш, ще го разбереш рано или късно. Въпросът е, че трябва да е по-рано, отколкото по-късно. :)

WTFs/Minute

Тази картинка много добре описва нещата. Въпросният ред с *initial_values[series_name[0]] << index вкарва поне още едно допълнително WTF ( според мен 2 :) ). Както каза и самият ти, не е много ясен приоритетът на * спрямо <<. Казваш, че ако имаш добър опит с ruby ще го знаеш, но колко често реално ще ти се наложи да го разбереш? Освен това тези неща се натрупват и ако за всяко предполагаме перфектно знаене на езика, лесно достигаме до момент, в който половината от редовете съдържат нещо триково.

Ако ти се наложи да напишеш нещо толкова странно (a.k.a. за което трябва да се замислиш или да пробваш), помисли дали не си в грешна посока и дали няма по-добър начин. В почти всички случаи има. :)

compute_series(*initial_values[series_name], index)

ПП. Това с началните стойности, докато го прочитах, при мен породи още едно WTF. Най-лесният начин, за да проверя дали работи, беше да го пусна, и пак не бях убеден напълно. Избягването на подобни ситуации е същината на "четимостта" на кода.

Съгласен съм, че вариантът, който предложи, е най-чист и прегледен.

В ruby има доста захар и в много случаи е по-лесно да се намери кратко kinda-WTF решение, отколкото да се търси по-стандартна комбинация. Обикновенно преглеждам някоя документация преди да напиша решение и не винаги е тривиално да се прецени кое ще се възприеме за WTF момент, при положение, че всичко е в документацията. С други думи, очаквай още подобни WTF моменти от мен :)