![]() |
#1 |
Участник
|
axforum blogs: FizzBuzz
Источник: http://axforum.info/forums/blog.php?b=358
============== Навеяно статьей FizzBuzz, или почему программисты не умеют программировать Цитата:
Напишите программу, которая выводит на экран числа от 1 до 100. При этом вместо чисел, кратных трем, программа должна выводить слово «Fizz», а вместо чисел, кратных пяти — слово «Buzz». Если число кратно и 3, и 5, то программа должна выводить слово «FizzBuzz»
X++: #define.FIZZ(3) #define.BUZZ(5) static void FizzBuzzImpl(Args _args) { int i; ; for (i = 1; i <=100; i++) { switch(true) { case ((i mod #FIZZ) == 0) && ((i mod #BUZZ) == 0): info(strfmt("FizzBuzz %1", i)); break; case ((i mod #FIZZ) == 0): info(strfmt("Fizz (%1)", i)); break; case ((i mod #BUZZ) == 0): info(strfmt("Buzz (%1)", i)); break; default: info(strfmt("%1", i)); } } }
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
![]() |
#2 |
Участник
|
Цитата:
Сообщение от Blog bot
![]() Навеяно статьей FizzBuzz, или почему программисты не умеют программировать
Избыточное вычисление mod и куча лишнего кода. с точки зрения вычислений лучше уж так. X++: #define.FIZZ(3) #define.BUZZ(5) static void FizzBuzzImpl(Args _args) { int i; str fizz; str buzz; ; for (i = 1; i <=100; i++) { fizz = ((i mod #FIZZ) == 0) ? "Fizz" : ""; buzz = ((i mod #BUZZ) == 0) ? "Buzz" : ""; if( fizz || buzz ) { info(strfmt("%1%2 %3", fizz, buzz, i)); } } } |
|
![]() |
#3 |
Участник
|
Хмм, что-то у меня не компилируется код, ругается на строчку "fizz = (i mod #FIZZ) == 0) ? "Fizz" : "";" - Типы операнда не совместимы с оператором
![]() |
|
![]() |
#4 |
Участник
|
а вот объектно-ориентированная многословная реализация, если не лень заводить класс в AOT. Но зато тело цикла не содержит деталей реализации - детали в классе.
X++: class TestState { boolean state; str description; } void new(int i, int num, int _description) { state = i mod num; if( state ) description = _description; } boolean getState() { return state; } str getDescription() { return description; } ///////////////////////////////////////// #define.FIZZ(3) #define.BUZZ(5) static void FizzBuzzImpl(Args _args) { int i; TestState fizz, buzz; ; for (i = 1; i <=100; i++) { fizz = new TestState(i, #FIZZ, "Fizz"); buzz = new TestState(i, #BUZZ, "Buzz"); if( fizz.getState() || buzz.getState() ) { info(strfmt("%1%2 %3", fizz.getDescription(), buzz.getDescription(), i)); } } } ![]() вместо простой конкатенации строк FizzBuzz можно сделать класс, который формирует вывод... В любом случае, это будет лучше чудовищного switch. |
|
![]() |
#5 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: Lemming (1). |
![]() |
#6 |
Участник
|
кстати. в исходной задаче нужно было выводить все числа.
в процедурном коде можно убрать if. а объектно-ориентированный код становится еще короче. X++: class TestState { str description; } void new(boolean _state, int _description) { if( _state ) description = _description; } str getDescription() { return description; } ///////////////////////////////////////// #define.FIZZ(3) #define.BUZZ(5) static void FizzBuzzImpl(Args _args) { int i; TestState fizz, buzz; ; for (i = 1; i <=100; i++) { fizz = new TestState(((i mod #FIZZ) == 0), "Fizz"); buzz = new TestState(((i mod #BUZZ) == 0), "Buzz"); info(strfmt("%1%2 %3", fizz.getDescription(), buzz.getDescription(), i)); } } |
|
![]() |
#7 |
Участник
|
![]()
Все, я сдаюсь, тут опять две ошибки компиляции, одна в new, я ее вроде пофиксил, хотя не факт что правильно, т.к. не до конца понимаю задумку кода, а вторая в запускающем Job'е, снова путаница int/str...mazzy
upd: Джобик из второго поста запустил, да, работает. Спасибо! Последний раз редактировалось Lemming; 06.12.2012 в 23:04. Причина: upd |
|
![]() |
#8 |
Участник
|
можно сократить число внутренних переменных в необъектной реализации.
правда не уверен, что код станет быстрее из-за дополнительной сборки мусора. X++: #define.FIZZ(3) #define.BUZZ(5) static void FizzBuzzImpl(Args _args) { int i; str state; ; for (i = 1; i <=100; i++) { state = ""; if ((i mod #FIZZ) == 0) { state += "Fizz"; } if ((i mod #BUZZ) == 0) { state += "Buzz"; } info(strfmt("%1 %2", state, i)); } } Но как пример использования неконстант в case - очень даже ничего. |
|
![]() |
#9 |
Участник
|
Не очень понял что именно сложно найти, вроде все ветви в одном месте, хотя когда он становится большим, читать такой код не очень приятно, согласен.
|
|
![]() |
#10 |
Участник
|
|
|
![]() |
#11 |
Участник
|
Цитата:
X++: switch (noYesValue) { case NoYes::No : // ... break; case NoYes::Yes : // ... break; default : throw error(Error::unsupportedEnumValue(noYesValue)); } X++: public static LabelType unsupportedEnumValue(anytype _enumValue) { return strfmt(@"Значение %1 (%2) не поддерживается", _enumValue, any2int(_enumValue)); } |
|
|
За это сообщение автора поблагодарили: Stitch_MS (2). |
![]() |
#12 |
Участник
|
|
|
![]() |
#13 |
Участник
|
Цитата:
Из-за этого добавление нового условия к уже имеющимся может потребовать изменить и все остальные. Ещё как-то встречал P.S.: Для решения задачи из первого поста подходит паттерн цепочка декораторов ![]() |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
![]() |
#14 |
Участник
|
Например code conventions в java(во всяком случае я там про это прочел) предлагает помечать пропуски break'ов комментарием fall-through, что бы программисты читающие код были предупреждены что это не ошибка, а задумка.
|
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
![]() |
#15 |
Участник
|
Цитата:
Вспомнилось в legacy из 2.5, в которой не было полноценных абстрактных классов, Датские программисты похожим образом имитировали абстрактные методы, когда в теле метода принудительно выбрасывали исключение с сообщением что "Метод должен быть перекрыт". И ничего, как-то наверное жили со всем этим. |
|
![]() |
#16 |
Moderator
|
Хотя я уже лет 15 не программирую на C/C++, мне конструкции вида (i mod #FIZZ) == 0 режут глаз.
Я бы написал !(i mod #FIZZ). Я понимаю что это вопрос стиля, вкуса и вообще для интерпретируемого языка разница в производительности отсутствует. Но глаз все равно режет... |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
![]() |
#17 |
Участник
|
Можно и так (кода больше, но резь в глазах уменьшится
![]() X++: class Number { int number; public void new(int _number) { number = _number; } public boolean isDivisibleBy(int _denominator) { return (number mod _denominator) == 0; } } static void testFizzBuzz(Args _args) { str fullWord; Number number; int i; for (i = 1; i <= 100; i++) { fullWord = ''; number = new Number(i); if (number.isDivisibleBy(3)) { fullWord += "Fizz"; } if (number.isDivisibleBy(5)) { fullWord += "Buzz"; } if (fullWord != '') { info(strFmt("%1 %2", i, fullWord)); } } } |
|
![]() |
#18 |
Молодой, подающий надежды
|
Любители тернарных операторов видят это, наверное, так
![]() X++: #define.FIZZ(3) #define.BUZZ(5) static void FizzBuzzImpl(Args _args) { int i; ; for (i = 1; i <= 100; i++) { info(! (i mod (#FIZZ * #BUZZ)) ? "FizzBuzz" : ! (i mod #FIZZ) ? "Fizz" : ! (i mod #BUZZ) ? "Buzz" : int2str(i)); } } Последний раз редактировалось pedrozzz; 07.12.2012 в 22:15. |
|
![]() |
#19 |
Участник
|
По-моему самое простое это:
X++: for (i = 1; i <=100; i++) { if (i % 3 == 0 && i % 5 == 0) Console.WriteLine("BuzzFuzz"); else if ( i %3 ==0) Console.WriteLine("Fuzz"); else if(i%5 ==0) Console.WriteLine("Buzz"); else Console.WriteLine("{0}", i); } Последний раз редактировалось Bergman; 07.12.2012 в 23:28. |
|
![]() |
#20 |
Участник
|
Не, ребят.
1. Вы занимаетесь внешним видом, а не сутью. В ваших примерах (как и в изначальном) нахождение остатка от деления вычисляется несколько раз (до 4 вместо необходмых 2 вычислений). Представьте, что в реальной жизни это будет не нахождение остатка от деления, а вычисление остатка на некую дату на некоем складе и отдельно на складе пополнения. Вы и там тоже будете запускать процедуру расчета остатков лишние разы? 2. Чем плох if else if... тем что выражение внутри if вычисляется несколько раз. условие внутри switch всегда вычисляется только один раз. Именно для этого (ну, кроме формы записи) и вводился switch в процедурные языки. если в switch условие вычисляется один раз, а в case константы... то можно добиться существенной оптимизации. А не только внешнего вида. в исходном примере суть switch вывернута наизнанку - условие константа, а в case - выражения (вдобавок с избыточным количеством). Возврат к if else if... это возврат. примерно так. удивительно, что об этом приходится писать. |
|