| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Ruby: Общие вопросы > Задача на сложный цикл |
| Автор: Zann 6.12.2009, 16:00 | ||||
| Привет. В продолжении изучения Ruby столкнулся с задачей у Криса Пайна:
Даже не могу представить как это сделать. Либо это сложная задача, либо методов не хватает, но думаю, что рано он такую задачу дал. Приблизительно то, что думаю я:
Если кто-то видел книгу Пайна, может еще что-то посоветуете? Или начинать программировать с руби сложно? Или продолжить дальше читать или про алгоритмы что-то посмотреть? Подскажите. |
| Автор: Zann 6.12.2009, 17:29 |
| source777, огромное спасибо. Да, это мой первый язык программирования впринципе. Не считая конечно HTML, но это и не язык программирования конечно. Есть какое-нибудь хорошее руководство по псевдокоду или книга? зы Гугл наверняка поможет, но лучше услышать совет реальных специалистов. Не удержался и подсмотрел... y1 = (y1%4 == 0) ? y1 : (y1/4+1)*4 y2 = (y2%4 == 0) ? y2 : y2/4*4 y1.step(y2, 4) { |y| puts y if (y%100!=0 || y%400==0) } Методы в этих строках не были рассмотрены в книге (%, :, ||, ?, step). Все-таки, может этот пример был рановат |
| Автор: source777 6.12.2009, 21:46 | ||
А может их вообще в этой книге не будет рассмотрено? Книга то для новичков, поэтому оттуда много убрано того, что обычно присутствует в более сложных книгах, таких как "The Ruby Way" Фултона. В любом случае это не столь важно, тот же алгоритм можно записать десятками других способов. Тернарный условный оператор(условие ? если_истина : если_ложь) можно заменить на обычный (if(условие) если_истина else если_ложь end), это правда уже 5 строк вместо одной. Цикл step можно заменить на цикл while. || - сокращённое логическое "или" a%b - взятие остатка от деление a на b Навряд ли, псевдокод - это изложение алгоритма на натуральном языке(в нашем случае на русском), либо в условных обозначениях. С условными обозначениями тебе ещё рано возиться, а уж на русским языком, я думаю, ты должен справиться без всяких книг. Главное чтобы в записи алгоритма не было ничего лишнего, но было всё необходимое. Как говорил Эйнштейн, всё должно быть настолько просто насколько это возможно, но не проще. Попробуй всё-таки изложить алгоритм похода в булочную за хлебом, можно прямо в этой теме. |
| Автор: Zann 6.12.2009, 23:02 |
| Начало 1) Одеться 2) Взять деньги 3) Выйти из квартиры 4) Выйти из подъезда 5) Дойти до магазина 6) Войти в магазин 7) Дойти до хлебной полки 8) Взять хлеб 9) Дойти до кассы 10) Оплатить хлеб 11) Выйти из магазина 12) Дойти до дома 13) Войти в подъезд 14) Войти в квартиру 15) Положить хлеб на кухне 16) Раздеться Конец алгоритма Конечно еще можно было ответвления сделать. Например, посмотреть на градусник. Если больше 0 - одеть то, если меньше - одеть то. Также можно было подробнее расписать: одел левый носок, потом правый |
| Автор: source777 6.12.2009, 23:26 |
| Неплохо, один вопрос только, у тебя всегда дверь в квартиру открытой остаётся? Следующее задание: нарисовать блок-схему для решения задачи о високосных годах. |
| Автор: Zann 7.12.2009, 13:57 |
Получилось примерно следующее:![]() |
| Автор: source777 7.12.2009, 14:42 |
| 1) Что за A3, A4? 2) Пройди по блок-схеме с данными A1 = 1894, A2 = 1912. Что у тебя получится на выводе? Лично я чётко вижу бесконечный цикл в твоей блок-схеме. 3) Ты понял алгоритм, который подсмотрел в моём коде? 4) Не надо никаких "как-то", "что-то", алгоритмика такого не терпит. если надо вывести значение конкретной переменной, то так и надо написать. Запомнить значение можно только через присваивание, а не через "как-то". |
| Автор: Zann 8.12.2009, 22:01 | ||
Если честно, то почти весь алгоритм не понят, тк не знаю этих методов и как их использовать. y1 = gets.chomp.to_i # тут все понятно y1 = (y1%4 == 0) ? y1 : (y1/4+1)*4 # если y1%4 == 0, то присваиваем y1, если нет, то (y1/4+1)*4 (не понял зачем (y1/4+1)*4 ) y2 = gets.chomp.to_i y2 = (y2%4 == 0) ? y2 : y2/4*4 # также не понял зачем y2/4*4 y1.step(y2, 4) { |y| puts y if (y%100!=0 || y%400==0) } # понял только, что мы выводим все переменныу y если y%100!=0 или y%400==0 |
| Автор: source777 9.12.2009, 13:59 | ||
Год больший чем y1 и делящийся нацело на 4. Именно он является первым кандидатом в високосные, если y1 не делится нацело на 4. Т.е. данная строчка округляет до 4 значение y1 в большую сторону. Год меньший чем y2 и делящийся нацело на 4. Именно он является последним кандидатом в високосные, если y2 не делится нацело на 4. Т.е. данная строчка округляет до 4 значение y2 в меньшую сторону.
Ну собственно так и есть, осталось только добавить, что y принимает значения от y1 до y2 с шагом 4. |
| Автор: KiRiller2 11.6.2010, 10:25 |
| тоже застрял на этой задачке, только мне показалось проще применить произвольный массив. Правда что дальше делать с массивом не знаю, свойства есть но не срабатывает. У меня это выглядит так: puts 'input begin' # вводим начальный год first = gets.chomp puts 'input end' #вводим конечный год last = gets.chomp years = Array(first .. last) # задаем массив из введенных выше годов years.each {|x| x/4 } # каждый произвольный элемент массива делим на 4 *** не работает, дальше не могу сделать ветвление *** puts ' -calculating- ' # просто строка для красивости внешнего вида puts years # выводит високосные годы |
| Автор: KiRiller2 11.6.2010, 11:22 |
| помозговал, вот еще вариант puts 'input begin' # вводим начальный год first = gets.chomp puts 'input end' #вводим конечный год last = gets.chomp years = Array(first .. last) puts ' -calculating- ' if years.each {|x| x%4 ==0 and x%400 != 0} puts years else puts '--' end |
| Автор: source777 11.6.2010, 23:53 |
Когда кажется, креститься надо... Создавать массив, чтобы просто перебрать в цикле числовой диапазон, - это ни в какие ворота не лезет. А создавать массив, который заведомо как минимум на 75% состоит из совершенно ненужных значений, - это вообще полный аут. P.S. Задачи даются для развития алгоритмического мышления, а не для того чтобы решать их первым попавшимся способом. Решение должно быть в первую очередь красивым, тогда оно будет и простым и эффективным одновременно. Представь, что ты решаешь эту задачу вручную, тогда твой алгоритм будет выглядеть так: нарезать кучу бумажек, на каждой написать год, а потом перебирать все эти бумажки по одной. Однако более правильным будет экономить бумагу (оперативную память) и перебирать числа соответствующие годам(в компьютере это эквивалентно изменению значения http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80%D0%B0), а не реальные объекты (типа Fixnum), на которых эти числа написаны. |
| Автор: bilbobagginz 12.6.2010, 08:54 | ||
khm... наверное, в первую очередь оно должно быть правильным ;-] |
| Автор: source777 12.6.2010, 21:05 | ||
Правильные решения существуют только для примитивных задач, подобных рассматриваемой в данном топике. Причём даже для таких примитивных случаев критерии правильности довольно размыты, т.к. сама постановка задачи, как правило, содержит ошибки (к примеру в условии рассматриваемой задачи не сказано явно, что указанный алгоритм расчета високосности действует с 1582 года и может измениться в будущем, т.е. любое решение данной задачи, которое реализует описанный критерий и позволяет при этом вводить года менее 1582 и более 2010 является формально неправильным). Что уж говорить о не учебных задачах, для которых правильное решение - это недостижимая абстракция, если бы было возможно иначе, то багов в программах вообще не было, а профессии "тестировщик" и "QA-инженер" отсутствовали бы за ненадобностью, однако суровая реальность такова, что правильное решение недостижимо за конечный интервал времени для 99.99% практических задач. Так что на практике решение может удовлетворять только критерию корректности (согласованность программных элементов с заданной спецификацией), т.е. проходить формальное тестирование. Некорректное решение, строго говоря, не является законченным решением. |
| Автор: bilbobagginz 15.6.2010, 23:16 | ||
срочно рекомендую испробовать методологии agile (scrum, kanban) и ессно надо сработанный коллектив, и тогда - невозможное становится более возможным ;-) |
| Автор: source777 19.6.2010, 23:50 |
| bilbobagginz, по-моему ты невнимательно прочитал мой ответ. Правильность - недостижима даже теоретически(если речь идёт не об абстрактных задачах, типа математических), никакая методология тут не поможет. Да и вообще программы на императивных языках неверифицируемы по своей природе, поэтому в лучшем случае возможна только формальная верификация на основе спецификации, не имеющая никакого отношения к правильности, т.к. в самой спецификации в 99.9% случаев полно разнокалиберных ошибок. Что мы видим даже в этой теме: спецификация всего 6 строчек и то с ошибками, что уж говорить о спецификациях, к примеру, на 60 листов. |
| Автор: bilbobagginz 20.6.2010, 20:48 |
| вообщето данная задача плохо сформулирована не из-за того, что ея низзя сформулировать корректно. я надеюсь в этом ни у кого сомнения нет. понимаю, что жизненные задачи сложны, НО не все их аспекты интересны. инженер должен в кооперации с клиентом прийти к общему знаменателю наиболее важных клиенту свойств ПО, которые можно формально или полуформально изложить, т.е. написать под них ПО, по крайней мере это так как у нас делают (ну или пытаются). Да, source777, программ без багов не существует (по теории). но на практике нужен какой-то идеал... ;-) и если классифицировать свойства, то аджильной методологией наиболее важные с т.з. клиента свойства будут реализованы наиболее корректно. |
| Автор: source777 20.6.2010, 23:51 | ||||||
Конечно, учебные задачи возможно сформулировать без ошибок, однако на практике даже такое встречается крайне редко, несмотря на сравнительно лёгкую достижимость: где-то в 10000-100000 раз проще, чем для реальной задачи.
С позиции корректности - да, а с позиции правильности - все аспекты интересны и одинаково важны. В этом и заключается недостижимость правильности.
Я прекрасно знаком с Agile и даже практикую его, но повторюсь ещё раз, к правильности эти методологии никакого отношения не имеют. Спринты, приоритеты и даже митинги - всё это противоречит критерию правильности, т.к. правильность - понятие неделимое, безотносительное и объективное. P.S. Предлагаю закончить оффтопик, думаю мы друг друга поняли. |
| Автор: bilbobagginz 21.6.2010, 06:12 |
| Автор: mw17 30.4.2012, 12:40 | ||||||||
Тоже читаю сейчас эту книгу, мучал эту задачу дня два. Решение делал исходя из изложеного материала в предыдущих главах. Вот что вышло:
|
| Автор: mw17 30.4.2012, 14:15 | ||
| У меня вопрос другого характера по поводу этой книги. Там на 48 странице есть одно задание где нужно написать: "авайте напишем программу, которая просит нас ввести сколько угодно слов (по одному слову в строке до тех пор, пока мы не нажмём Enter на пустой строке) и которая затем повторяет нам эти слова в алфавитном порядке." Я ее написал так:
Но как я уже выше написал, на 48 странице просят еще: "Попробуйте написать указанную программу без использования метода sort. " Ума не приложу, как без sort отсортировать |
| Автор: k0rvin 1.5.2012, 19:32 | ||
Написать свой метод sort, очевидно же. |
| Автор: napcep 14.2.2013, 22:14 | ||||
Тоже читаю сейчас эту книгу, мучал эту задачу дня два. Решение делал исходя из изложеного материала в предыдущих главах. Вот что вышло:
mw17, в твоём алгоритме встречаются не високосные года, такие как 1800. В книге об этом сказано - «Однако, годы, нацело делящиеся на 100, — не високосные (как 1800 и 1900) если только они не делятся нацело на 400...»
Вот ещё один вариант кому интересно. |