Решение на Първа задача от Александър Попов

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

Към профила на Александър Попов

Резултати

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

Код

def series(type, index)
{fibonacci: nth(index, 1, 1, 1),
lucas: nth(index, 1, 2, 1),
summed: nth(index, 1, 1, 1) + nth(index, 1, 2, 1)}[type.to_sym]
end
def nth(index, counter, first, second)
index == counter ? first : nth(index, counter + 1, second, first + second)
end

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

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

Finished in 0.01262 seconds
12 examples, 0 failures

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

Александър обнови решението на 09.10.2014 16:33 (преди около 10 години)

+def series(type, i)
+ type == 'summed' ? nth('fibonacci', i) + nth('lucas', i) : nth(type, i)
+end
+
+def nth(type, i)
+ series = type == 'fibonacci' ? [1, 1] : [2, 1]
+ series << series[-1] + series[-2] until series.count > i - 1
+ series[i - 1]
+end

Това е първото решение с пълнене на масиви до момента, което да ми е харесало. :)

  • Дали беше добра идея да използваш i и nth, с единствена цел да спечелиш няколко символа?
  • Има по-ясни начини да получиш последния елемент на масив от series[i - 1]. Разгледай документацията на Array.
  • fibonacci и lucas са имена на редици, не типове. Това беше наша грешка. :)

:)

  • за i и nth - много ги мразя contraint-ите на skeptic и винаги ми къса нервите докато намеря баланса между брой редове и правилното наименоване на променливите. Две неща съм забелязал:

    • правилното наименоването наистина е адски важно и сравнително трудно, но има разни имена отрода на i, които са толкова утвърдени, че може да се преглътне на пръв поглед неясното значение.

    • Също така, не мисля, че е болка за умиране, ако даден код ред е 85 символа.

    • За nth съм съгласен, но това го видях в задачата nth-prime на exercism.io, така че си помислих, че не е толкова зле :)

  • последния елемент може да се достигне и с last или [-1], само че за индекс 1, т.е. първия елемент, не работи, така че трябваше да ползвам точен индекс.

  • знам, че са имена на редици, но щеше малко да се получи тафтология (или трябваше да ползвам някакво дълго име от рода на series_name, та затова е type.

Какви други начини има да се реши тази задача - с рекурсия? Моля дай няколко жокера без конкретните решения. Hint: не съм студент и не се боря за оценка. :)

  • Напълно съм съгласен, че това е може би един от много малкото контексти, където i, n или x_[index] са приемливи имена на променливи (не като индекси в масив, а като индекс на член на редицата). Не съм казал, че са лоши, само да си помислиш (малко са на кантар нещата). :)
  • Това за индекс 1 не го бях забелязал на първо четене.
  • А защо не нещо, което е също толкова кратко, колкото type и също толкова говоримо, колкото series_name? :)
  • Относно как иначе може да се реши задачата - да, с рекурсия. Но недей да си пренаписваш решението (освен ако ти самият не настояваш), както казах - така ми харесва.

Александър обнови решението на 09.10.2014 20:20 (преди около 10 години)

def series(type, i)
- type == 'summed' ? nth('fibonacci', i) + nth('lucas', i) : nth(type, i)
+ { fibonacci: nth(i, 1, 1, 1),
+ lucas: nth(i, 1, 2, 1),
+ summed: nth(i, 1, 1, 1) + nth(i, 1, 2, 1) }[type.to_sym]
end
-def nth(type, i)
- series = type == 'fibonacci' ? [1, 1] : [2, 1]
- series << series[-1] + series[-2] until series.count > i - 1
- series[i - 1]
+def nth(i, c, first, second)
+ i > c + 1 ? nth(i, c + 1, second, first + second) : [first, second][i <=> c]
end

Това е второто нестандартно (или поне различаващо се от другите, доколкото е възможно за толкова кратка задача) решение, което предаваш. :)

  • Имаш лек проблем с whitespace-овете при hash-a. Погледни style guide-а.
  • Индексирането на hash вместо if - elsif - else или case-ове е доста по-често използвано, отколкото повечето хора си мислят първия път. Според мен в случая е изцяло ok.
  • За жалост имплементацията ти на nth е "прекалено хитроумна" :) Предпочитай ясни и четими решения пред по-интересни или кратки такива. [first, second][i <=> c] е доста забавно, но не е моментално очевидно. Какво изобщо е тук c в контекста на числови редове? Не можех да разбера как става цялата магия преди да си извъртя няколко итерации наум.

Добре, ще се опитам нещо по-ясно да предам :) Иначе едно последно за обфускиране:

def series(type, i)
  types =  {f: nth(i, 1, 1, 1), l: nth(i, 1, 2, 1)}
  {f: types[:f], l: types[:l], s: types[:f] + types[:l]}[type[0].to_sym]
end

def nth(i, c, first, second)
  i > c + 1 ? nth(i, c + 1, second, first + second) : [first, second][i <=> c]
end

Александър обнови решението на 09.10.2014 21:13 (преди около 10 години)

-def series(type, i)
- { fibonacci: nth(i, 1, 1, 1),
- lucas: nth(i, 1, 2, 1),
- summed: nth(i, 1, 1, 1) + nth(i, 1, 2, 1) }[type.to_sym]
+def series(type, index)
+ {fibonacci: nth(index, 1, 1, 1),
+ lucas: nth(index, 1, 2, 1),
+ summed: nth(index, 1, 1, 1) + nth(index, 1, 2, 1)}[type.to_sym]
end
-def nth(i, c, first, second)
- i > c + 1 ? nth(i, c + 1, second, first + second) : [first, second][i <=> c]
+def nth(index, counter, first, second)
+ index == counter ? first : nth(index, counter + 1, second, first + second)
end

Здравей :)

Мен ме притеснява хеша в series. Помисли дали с него функцията ти не върши излишна работа. Вярно е, че не се стремим към бързодействие, но няма смисъл да се смятат излишни неща. Ще е доста по-четимо ако използваш if или case ... when.

Още няколко мнения:

  • Именуването на променливи и функции наистина понякога е доста предизвикателно. Опитай се да даваш по-добро описание чрез имената. Това не означава, че трябва да ги правиш много дълги. Например за функцията nth не става ясно какво прави, ако и прочетеш името. Казва, че е нещо n-то. Какво е n? Кое е това нещо, което е n-то? Това са въпроси, които може да си задаваш, когато имаш проблем с именуването.

  • Същото може да се каже и за first и second. first е първото. Първото какво? Число? Ако е число може да е first_number. А first и second всъщност не винаги са първото и второто число в твоята функция.

  • Има параметър counter, който единствено внася сложност във функцията. Можеш спокойно да го махнеш и вместо да го увеличаваш с 1, можеш да намаляваш index с 1.

  • Можеш да направиш по-лесна за разбиране функцията nth, като махнеш тернарния оператор и разделиш нещата на два реда. За дъно на рекурсията и други подобни условия, в които ти се налага да върнеш различна стойност от функция в определен случай, е напълно ОК да използваш return в комбинация с if.

Всъщност това, което прави функцията nth в момента се нарича опашкова рекурсия (tail recursion) и всъщност симулира решение с цикъл, чрез рекурсия. :) Можеш ли да се досетиш какъв е другият начин, отново с рекурсия? Той е дори по-лесен, ако погледнеш математическата дефиниция за числата на Фибоначи - веднага ще се сетиш. :)