Решение на Девета задача от Станимир Богданов

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

Към профила на Станимир Богданов

Резултати

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

Код

REPOSITORY = 'https://github.com/stamaniorec/ruby-retrospective-2015-1'
# Двадесет неща, които научих.
#
# 1. Има смисъл обектите, които остават константни, да бъдат дефинирани като константи (очевидно).
# 2. Още по-добре е такива обекти да бъдат замразявани.
# 3. Замразяването не работи рекурсивно.
# 4. Тази точка е спорна, но мисля, че trailing commas при дефинирането на многоредови литерали са хубаво нещо. Много по-лесно може да се разместват отделните редове.
# 5. Методът dup не работи рекурсивно. Ако ползвам само него и направя snake = [[2, 1], [2, 2]]; new_snake = snake.dup; snake[0][0] = 'WTF'; new_snake # => [["WTF", 1], [2, 2]] Опасна работа!
# 6. Има интересен начин да се генерира храна за змията, като идеята се базира на изваждане на множества. Тоест, прави се масив с всички позиции на полето, а после от тях се изваждат позициите, които заемат змията и храната, която вече съществува на полето, като накрая се взима произволен елемент от оставащите. Това не ми беше хрумвало и мисля, че е интересен подход. Също така обаче мисля, че за по-големи полета това не би било ефективно. Поради тази причина оставих своята имплементация, която не е най-красивата в момента, но един tap може да оправи нещата значително. Заради skeptic ограниченията обаче това не става.
# 7. Впрочем, самият метод tap. Много прост, но адски ефективен. Решава ми всички проблеми от типа result = 0; do_stuff_with_result(result); result
# 8. [1, 2, 3].map(&:to_s) е еквивалентно на [1, 2, 3].map { |el| el.to_s }. Това вече го знаех, но ровейки из интернет, попаднах на интересен ruby трик: [1, 2, 3].map(&method(:puts)). Това е еквивалентно на [1, 2, 3].each { |el| puts el }
# 9. Последното го намерих, опитвайки се да съкратя ситуация от типа arr.each { |el| yield el }. Уж знаех, ама явно бях забравил, че yield е ключова дума, а не метод.
# 10. При проверка дали едно число е просто с bruteforce алгоритъм, цикълът може да върти до sqrt(n), а не до n-1.
# 11. Вместо да правя нещо от типа на count = 0; while count < n; ...; count += 1; end мога да направя (0...n).each, а още по-добре - n.times
# 12. Бях забравил enum_for - много полезен метод, който връща yield-натите стойности.
# 13. При проверката за просто число по "ruby начина", вместо да слагам специален случай за единицата и да проверявам с none? за остатък 0 от 2 до числото, мога да го напиша на един ред с one?, като проверявам от 1.
# 14. Вместо да правя [].reduce(:*) or 1 (първото връща nil, взима се единицата), мога да задам първоначална стойност на reduce - [].reduce(1, :*)
# 15. Да не забравям да оставям празни редове между дефинициите на методите.
# 16. Вместо each_with_object([]), където да генерирам тесте, product ми върши много по-добра работа, защото може да направи комбинация на всяка стойност с всяка боя. По-идиоматично е, а и ми спестява 3-4 реда код.
# 17. Опитвайки се да подобря четвърта задача, пробвах да вкарам в играта метапрограмиране. Накрая се отказах, защото количеството код намаля твърде малко, за да си заслужава усложняването на кода. В опитите си обаче достигнах до един метод get_game_name в Deck, който може да връща името на играта - "War" или "Belote" и т.н. - self.class.to_s.match(/([^\/.]*)Deck/)[1]
# 18. Вместо [(2..10).to_a, :jack, ...].flatten мога да направя [*2.upto(10), :jack, ...] - не знаех, че * работи и върху енумератори.
# 19. Ако имам метод от типа на not_something?, по-добре е да инвертирам логиката, за да не се получават ситуации от типа if not not_something?, unless not_something, тъй като тези конструкции са по-трудно разбираеми от "положителната" посока на логиката.
# 20. Разгледах Rakefile-а в това хранилище и се разчетох в интернет за rake. Полезно нещо.

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

From https://github.com/fmi/ruby-retrospective-2015-1
 * branch            master     -> FETCH_HEAD
HEAD is now at 767dd8d Update the task name in the readme for clarity
Cloning into 'submission'...
HEAD is now at 1dace87 Task 4: Fixed the failing test! Made other small improvements.
From /tmp/ruby-retrospective-2015-1/checker
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> upstream/master

Changes URL:
https://github.com/stamaniorec/ruby-retrospective-2015-1/compare/767dd8dfe46...1dace871958

‘solutions/04.rb’ -> ‘/tmp/ruby-retrospective-2015-1/checker/solutions/04.rb’
‘solutions/02.rb’ -> ‘/tmp/ruby-retrospective-2015-1/checker/solutions/02.rb’
‘solutions/03.rb’ -> ‘/tmp/ruby-retrospective-2015-1/checker/solutions/03.rb’
‘solutions/01.rb’ -> ‘/tmp/ruby-retrospective-2015-1/checker/solutions/01.rb’
OK
........

Finished in 0.04891 seconds
8 examples, 0 failures
OK
....................

Finished in 0.01092 seconds
20 examples, 0 failures
OK
....................

Finished in 0.39606 seconds
20 examples, 0 failures
OK
.........................................................

Finished in 0.02767 seconds
57 examples, 0 failures
From https://github.com/fmi/ruby-homework
 * branch            master     -> FETCH_HEAD
HEAD is now at 9dd040c Modify a test in task 8 to not include empty cells
.

Finished in 0.00157 seconds
1 example, 0 failures

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

Станимир обнови решението на 26.01.2016 23:39 (преди около 9 години)

+REPOSITORY = 'https://github.com/stamaniorec/ruby-retrospective-2015-1'
+
+# Двадесет неща, които научих.
+#
+# 1. Има смисъл обектите, които остават константни, да бъдат дефинирани като константи (очевидно).
+# 2. Още по-добре е такива обекти да бъдат замразявани.
+# 3. Замразяването не работи рекурсивно.
+# 4. Тази точка е спорна, но мисля, че trailing commas при дефинирането на многоредови литерали са хубаво нещо. Много по-лесно може да се разместват отделните редове.
+# 5. Методът dup не работи рекурсивно. Ако ползвам само него и направя snake = [[2, 1], [2, 2]]; new_snake = snake.dup; snake[0][0] = 'WTF'; new_snake # => [["WTF", 1], [2, 2]] Опасна работа!
+# 6. Има интересен начин да се генерира храна за змията, като идеята се базира на изваждане на множества. Тоест, прави се масив с всички позиции на полето, а после от тях се изваждат позициите, които заемат змията и храната, която вече съществува на полето, като накрая се взима произволен елемент от оставащите. Това не ми беше хрумвало и мисля, че е интересен подход. Също така обаче мисля, че за по-големи полета това не би било ефективно. Поради тази причина оставих своята имплементация, която не е най-красивата в момента, но един tap може да оправи нещата значително. Заради skeptic ограниченията обаче това не става.
+# 7. Впрочем, самият метод tap. Много прост, но адски ефективен. Решава ми всички проблеми от типа result = 0; do_stuff_with_result(result); result
+# 8. [1, 2, 3].map(&:to_s) е еквивалентно на [1, 2, 3].map { |el| el.to_s }. Това вече го знаех, но ровейки из интернет, попаднах на интересен ruby трик: [1, 2, 3].map(&method(:puts)). Това е еквивалентно на [1, 2, 3].each { |el| puts el }
+# 9. Последното го намерих, опитвайки се да съкратя ситуация от типа arr.each { |el| yield el }. Уж знаех, ама явно бях забравил, че yield е ключова дума, а не метод.
+# 10. При проверка дали едно число е просто с bruteforce алгоритъм, цикълът може да върти до sqrt(n), а не до n-1.
+# 11. Вместо да правя нещо от типа на count = 0; while count < n; ...; count += 1; end мога да направя (0...n).each, а още по-добре - n.times
+# 12. Бях забравил enum_for - много полезен метод, който връща yield-натите стойности.
+# 13. При проверката за просто число по "ruby начина", вместо да слагам специален случай за единицата и да проверявам с none? за остатък 0 от 2 до числото, мога да го напиша на един ред с one?, като проверявам от 1.
+# 14. Вместо да правя [].reduce(:*) or 1 (първото връща nil, взима се единицата), мога да задам първоначална стойност на reduce - [].reduce(1, :*)
+# 15. Да не забравям да оставям празни редове между дефинициите на методите.
+# 16. Вместо each_with_object([]), където да генерирам тесте, product ми върши много по-добра работа, защото може да направи комбинация на всяка стойност с всяка боя. По-идиоматично е, а и ми спестява 3-4 реда код.
+# 17. Опитвайки се да подобря четвърта задача, пробвах да вкарам в играта метапрограмиране. Накрая се отказах, защото количеството код намаля твърде малко, за да си заслужава усложняването на кода. В опитите си обаче достигнах до един метод get_game_name в Deck, който може да връща името на играта - "War" или "Belote" и т.н. - self.class.to_s.match(/([^\/.]*)Deck/)[1]
+# 18. Вместо [(2..10).to_a, :jack, ...].flatten мога да направя [*2.upto(10), :jack, ...] - не знаех, че * работи и върху енумератори.
+# 19. Ако имам метод от типа на not_something?, по-добре е да инвертирам логиката, за да не се получават ситуации от типа if not not_something?, unless not_something, тъй като тези конструкции са по-трудно разбираеми от "положителната" посока на логиката.
+# 20. Разгледах Rakefile-а в това хранилище и се разчетох в интернет за rake. Полезно нещо.