PDA

Просмотр полной версии : Почему програмисты не умеют програмировать?


wvxvw
26.06.2010, 19:04
http://www.codinghorror.com/blog/2007/02/why-cant-programmers-program.html

Понравилась статья. Если чесно, я с ходу не понял, в чем фишка, но когда понял, вобщем, у нас появилось два варианта:

private function runFizzBuzz():void
{
var result:String;
var threes:int = 3;
var fives:int = 5;

for (var i:int = 1; i <= 100; i++)
{
result = "";
if (i == threes)
{
result = "Fizz";
threes += 3;
}
if (i == fives)
{
result += "Buzz";
fives += 5;
}
if (!result) result = i.toString();
trace(result, i);
}
}

function runFizzBuzz():void
{
var result:String;
for (var i:int = 1; i <= 100; i++)
{
result = "";
if (!(i % 3)) result += "Fizz";
if (!(i % 5)) result += "Buzz";
if (!result) result = i.toString();
trace(result, i);
}
}

Ваши мысли по поводу, альтернативы? :)

E-mail
26.06.2010, 21:09
Аналогично второму сделал
Кстати, а в чём фишка?

koIIImarik
26.06.2010, 21:38
Бегло прочитал статью, если честно, не очень понятно, как связаны 2 участка кода с указанной статьёй. На сколько я понял, там просто рассказывалось о том, что многие программисты, которые пытаются устроиться на работу не в состоянии написать простую программу.

Что касается 2-х участков кода, которые вы представили: я против записей блоков if/while/for/case с участками кода, которые выполняются после них, в одну строку, например так:

if (!(i % 3)) result += "Fizz";

Поэтому, не могу сказать, что «альтернатива» гораздо лучше 1-го участка кода, хотя выглядит компактнее, согласен.

CrazyFlasher
26.06.2010, 22:03
которые выполняются после них, в одну строку, например так

поддерживаю...хотя иногда сам этим грешу :)

udaaff
26.06.2010, 22:21
Ваши мысли по поводу, альтернативы? :)
Число итераций можно примерно в два раза сократить :)

wvxvw
26.06.2010, 22:23
Я всегда пишу так, и мне так больше нравится, но суть не в этом.
В самом начале статьи было написано, что большинство програмистов не способны решить примитивную задачу, и как раз эта задача решается в этом банальном на первый взгляд коде :)
Кстати, по производительности первый вариант лучше второго т.как инкремент быстрее модуло, да и при этом инкремент происходит не каждую итерацию. Но фишка не в этом, а в том, что прочитав условие задачи появляется желание найти вариант где бы использовались только два if'a или взаимоисключающие условия, а вот не находится :)

TERRORist
26.06.2010, 23:46
Я всегда пишу так, и мне так больше нравится, но суть не в этом.
В самом начале статьи было написано, что большинство програмистов не способны решить примитивную задачу, и как раз эта задача решается в этом банальном на первый взгляд коде :)
Кстати, по производительности первый вариант лучше второго т.как инкремент быстрее модуло, да и при этом инкремент происходит не каждую итерацию. Но фишка не в этом, а в том, что прочитав условие задачи появляется желание найти вариант где бы использовались только два if'a или взаимоисключающие условия, а вот не находится :)


а почему вы пропустили одно из условий задачи "For numbers which are multiples of both three and five print "FizzBuzz"." ? я не наблюдаю такого трейса..

for (var i:uint = 1; i < 101; i++)
{
var fizz:Boolean = !(i % 5);
var buzz:Boolean = !(i % 3);
trace(buzz && fizz ? "FizzBuzz" : fizz ? "Fizz" : buzz ? "Buzz" : i)
}

некрасиво но работает

wvxvw
27.06.2010, 00:35
TERRORist:
там не = а +=

Но идея интересная, хотя тоже не ахти - тернарный оператор ни чем не лучше if-else ну только что запись немного короче, а с другой стороны - приходится использовать "FizzBuzz", которая явно собирается из двух компонентов, которые так же используются отдельно. + нужно считать модуло каждую итерацию (более накладно чем раз в несколько итераций проинкрементить). + дополнительная операция &&.

кстати, для Лиспа можно было бы по-другому и красивше решать, там есть натуральные дроби (или я не знаю, как это правильно называется), в смысле можно 1/3 + 1/3 + 1/3 = 1.

TERRORist
27.06.2010, 00:36
а, точно, не заметил, сорри

wvxvw
27.06.2010, 01:19
Кстати, вот еще экстримальный вариант :)
function runFizzBuzz():void
{
var result:String;

for (var i:int = 1, state:int; i <= 100; i++, state++)
{
switch (state)
{
case 2: case 5: case 8: case 11:
result = "Fizz";
break;
case 4: case 9:
result = "Buzz";
break;
case 14:
result = "FizzBuzz";
state = -1;
break;
default: result = i.toString();
}
trace(result, i);
}
}

artcraft
27.06.2010, 02:20
cуть как в варинианте 2 но на пару символов короче:
/**
* Write a program that prints the numbers from 1 to 100. But for multiples of three print
* “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers
* which are multiples of both three and five print “FizzBuzz”.
*/
function runFizzBuzz():void{
var i:int=0, r:String;
while( i < 100 ){
i++;
r = i%3==0 ? "Fizz" : "";
if( i%5==0 ) r += "Buzz";
trace( r ? r : i );
}
}
runFizzBuzz();

Nirth
27.06.2010, 11:54
Программа пишется для пользователей, которые будут ее запускать на компьютерах.
Приоритеты из этого следуют:
Удобная для пользователя
Оптимальная нагрузка компьютера.
Красивый код.

Первый вариант показывает лучшую скорость – он самый правильный )

silin
27.06.2010, 12:21
такой еще
private function runFizzBuzz():void
{
var labels:Array = [null, "fizz", "buzz", "fizzbuzz"];
var i:int;
for (i = 1; i < 100; i ++)
{
var indx:int = int(!(i % 3)) + 2 * int(!(i % 5));
trace(labels[indx] || i);
}
}

Iv
28.06.2010, 14:34
Первый вариант показывает лучшую скорость – он самый правильный )
- я бы сказал, что первый вариант самый правильный из представленных потому, что он самый читабельный - в нем сложнее допустить ошибку.

wvxvw
28.06.2010, 17:05
Самое интересное, что в оригинальной статье все, без исключения использовали модуло (ну, из тех, кто пытался написать примеры). Правда, там больше VB / C# людей.

Iv
28.06.2010, 18:05
Да и по модулю нормально тоже. Просто все увлечения на тему вот таких выражений
var indx:int = int(!(i % 3)) + 2 * int(!(i % 5));
от лукавого.

Nirth
28.06.2010, 18:45
@Iv
Это чисто Flash и JS разработчики могут допустить ошубки в коде меньше 1000 строк ^_^

-De-
28.06.2010, 18:54
По-моему что-то типа второго наиболее читабельно. 0 == (i%n) - i кратно n. Понять, что за инкременты и вообще переменные в 1-м варианте не так просто. Может, кому как, конечно. Думаю в таких задачках решает именно читабельность (и скорость их написания).
Кстати, думаю проще замерить то, что 1-й вариант жрёт больше памяти, чем то, что он быстрее =)

Psycho Tiger
28.06.2010, 19:06
Nirth, а знаешь как правят ошибки на системах, на которых нельзя их допускать (ну, например система бортового управления или ещё чего?)
Пишут код, и считают количество строк. Они знают, что в n строчек в среднем m ошибок, и они сидят и ищут эти ошибки, пока не найдут =)
Идиотизм, но Россия.. непобедима.

Nirth
28.06.2010, 19:13
Psycho Tiger
Ну я последние полгода работал в телекоме. Там просто тест каждой версии идет в 3 фазы, по 3 недели каждый. Хотя метод с "есть ошибки" забавный да ^_^

wvxvw
28.06.2010, 21:47
А вот собственно, решение на божественном языке :)

#!/usr/bin/sbcl --script
(defun fizz-buzz (i threes fives)
(let (result)
(when (< i 100)
(setq result "")
(when (= i threes)
(setq result "Fizz")
(setq threes (+ threes 3))
)
(when (= i fives)
(setq result (concatenate 'string result "Buzz"))
(setq fives (+ fives 5))
)
(when (equal result "")
(setq result i)
)
(print result)
(fizz-buzz (1+ i) threes fives)
)
)
)

(fizz-buzz 1 3 5)

Nirth
28.06.2010, 22:02
Scheme или Common Lisp ))?

wvxvw
28.06.2010, 22:35
CLisp :)

lowka
29.06.2010, 01:10
val s = (1 to 100).foldLeft(""){(xs, x) => xs + (x match{
case a if x % 5 == 0 && x % 3 == 0 => "FizzBuzz"
case b if x % 5 == 0 => "Buzz"
case c if x % 3 == 0 => "Fizz"
case _ => x.toString
})
}

+++
это ничего не выводит. хм. :rolleyes:
тогда так

(1 to 100) foreach {x => println(x match{
case a if a % 5 == 0 && a % 3 == 0 => "FizzBuzz"
case b if b % 5 == 0 => "Buzz"
case c if c % 3 == 0 => "Fizz"
case _ => x.toString
})
}

wvxvw
29.06.2010, 05:04
Scala?

Nirth
29.06.2010, 18:42
Ага ))

Котяра
30.06.2010, 01:11
Раз уж пошли "божественные" языки..))
-module(test).
-export([fizzBuzz/0]).

fizzBuzz() ->
fizzBuzz(1).

fizzBuzz(101)->ok.

fizzBuzz(A)->
if
A rem 3 == 0 && A rem 5 == 0 ->
io:format("FizzBuzz~n", []);
A rem 3 == 0 ->
io:format("Fizz~n", []);
A rem 5 == 0 ->
io:format("Buzz~n", []);
true ->
io:format("~w~n", [A])
end,
fizzBuzz(A+1).


>test:fizzBuzz().
PS:Работоспособность не проверял - могут быть косяки).

Nirth
30.06.2010, 02:11
Prolog
shout( fizz, 3 ).
shout( buzz, 5 ).

fizz_buzz( Total, Total ) :- true.
fizz_buzz( Current, Total ) :-
shout( X, Current ),
shout( Y, Current ),
Current is Current + 1,
fizz_buzz( Current, Total),
X, Y.
Правда он не выводит данные как надо, я в Прологе со строками еще толком не работал ^_^, надо будет дописать как надо.

Добавлено через 23 минуты
Кстати, старый добрый ActionScript, тоже может тянутся на Олимп:

var fizzBuzz:Function = function( count:int = 0 ):void
{
var result:String = '';
if( !( count % 3 ) )
result += "Fizz";
if( !( count % 5 ) )
result += "Buzz";

trace( count, result );

tail( count );
}

var tail:Function = function( count:int ):void
{
if( ++count <= 100 )
fizzBuzz( count );
}

fizzBuzz();

Надо выспавшись подумать, как старину Curry сюда приделать, а то Tail-Recurssion не слишком уж божественно ^_^

Котяра
30.06.2010, 13:41
практически аналог эрланговского кода (http://www.flasher.ru/forum/showpost.php?p=918873&postcount=27) на AS3 :
function fizzBuzz(a:int=1,b:int=100):void
{
if (a > b) return;

if (a % 3 == 0 && a % 5 == 0)
trace ("FizzBuzz");
else if (a % 3 == 0)
trace ("Fizz");
else if (a % 5 == 0)
trace ("Buzz");
else
trace(a);
fizzBuzz(a + 1,b);
}


fizzBuzz();
только в отличии от эрланга может произойти переполнение стека рекурсий уже на
fizzBuzz(1,256);

UPD: странно..никакого переполнения не наблюдаю)))))

UPD2: таки наблюдаю на fizzBuzz(1,5552); :)
Error: Error #1023: Stack overflow occurred.

Nirth
30.06.2010, 16:29
Ну кстати, tail рекурсией, можно сделать вызов setTimeout ^_^ и обойти переполнение стэка

Котяра
30.06.2010, 17:37
Ну кстати, tail рекурсией, можно сделать вызов setTimeout ^_^ и обойти переполнение стэка
Ага. баловался уже так (http://www.flasher.ru/forum/showpost.php?p=907262&postcount=9))

wvxvw
01.07.2010, 17:01
Ну и еще немножко эзотерики :)
<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>

<xsl:template match="/">
<html lang="en" >
<head><title>FizzBuzz XSLT Example</title></head>
<body>
<h1>FizzBuzz!</h1>
<ul>
<xsl:call-template name="iterate">
<xsl:with-param name="start">1</xsl:with-param>
<xsl:with-param name="count">100</xsl:with-param>
</xsl:call-template>
</ul>
</body>
</html>
</xsl:template>

<xsl:template name="iterate">
<xsl:param name="start"/>
<xsl:param name="count"/>
<xsl:if test="$start &lt;= $count">
<li><xsl:call-template name="check">
<xsl:with-param name="start">
<xsl:value-of select="$start"/>
</xsl:with-param>
</xsl:call-template></li>
</xsl:if>
<xsl:if test="$start &lt;= $count">
<xsl:call-template name="iterate">
<xsl:with-param name="start">
<xsl:value-of select="$start + 1"/>
</xsl:with-param>
<xsl:with-param name="count">
<xsl:value-of select="$count"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>

<xsl:template name="check">
<xsl:param name="start"/>
<xsl:variable name="value" >
<xsl:if test="number($start) mod 3 = 0">Fizz</xsl:if>
<xsl:if test="number($start) mod 5 = 0">Buzz</xsl:if>
</xsl:variable>
<xsl:choose>
<xsl:when test="string-length($value) = 0">
<xsl:value-of select="$start"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

silin
01.07.2010, 19:32
о, е
где-то читал/слышал, что полиглолты мыслят гораздо свободнее/складнее, чем моноглоты (сори - нет наверное такого термина, но это такой перец, который дальше того, что сам знает не думает..)
wvxvw для нас в этом смысле просто удача
удача в том смысле, что он есть и свои мысли сюда трансрутует

Nirth
01.07.2010, 21:00
ну справедливости ради я скажу, что Lisp и Prolog используются в индустрии. На лиспе часто прототипируют ИИ. Пролог используется активно в биологии.
Доля Эрланга растет. Это я к тому, что если уж говорить об изотерике – нужно вспомнить про Whitespace !

Psycho Tiger
01.07.2010, 21:46
ну справедливости ради я скажу, что Lisp и Prolog используются в индустрии. На лиспе часто прототипируют ИИ. Пролог используется активно в биологии.
Доля Эрланга растет. Это я к тому, что если уж говорить об изотерике – нужно вспомнить про Whitespace !
А ведь у тебя тоже всё начиналось с Hello World...

wvxvw
01.07.2010, 22:41
Ну, на Whitespace я не смогу :) Да и запостить его на форум тяжко будет :) А вообще, ну так же по жизни приходится, можно подумать, что никому не приходилось BAT файлы писать, а это вообще по идеологии очень далеко от AS3. Ну и в том числе со всякими серверными языками разбираться, тот же SQL, который тоже вобщем-то почти ни на что не похож.

Сайлас
01.07.2010, 23:05
Ну первое что приходит в голову на SQL
CREATE DEFINER=`root`@`localhost` PROCEDURE `loopFizzBuzz`()
BEGIN

DECLARE i INTEGER;
DECLARE s TEXT;
DECLARE ls TEXT;
DECLARE comma VARCHAR(1);
SET comma = '';
SET i = 1;
SET s = '';
WHILE i < 101 DO
SET ls = '';
IF (i % 3) = 0 THEN
SET ls = 'Fizz';
END IF;
IF (i % 5) = 0 THEN
SET ls = CONCAT(ls,'Buzz');
ELSEIF ls = '' THEN
SET ls = i;
END IF;
SET s = CONCAT(s,comma,ls);
IF comma = '' THEN
SET comma = ',';
END IF;
SET i = i + 1;
END WHILE;
SELECT s;
END


PS - это на скорую руку, так можно некоторые вещи по-разному сделать. Здесь все выводится в одну строку, а не каждое значение в row

Котяра
01.07.2010, 23:56
где-то читал/слышал, что полиглолты мыслят гораздо свободнее/складнее, чем моноглоты
Многия знания - многия печали )))
А вообще расширенный кругозор - это расширенный кругозор)
Ничуть не жалею о выученном в детстве фортран (учил без компа по случайно найденному отцовскому учебнику)
также Basic а -ля спектрум, и всяким страшным из института: форт, asm, pascal, c++ итп.. - реально на них не приходилось кодить (кроме плюсов) а фан хороший)

хороший сайтик есть:
http://progopedia.ru
там на каждом языке - хелловорд, алгоритм вычисления фибоначчи и факториала - очень интересно посмотреть.
Кстати там ни слова о Нашем - зарегился даже чтоб статью там написать - руки не доходят.. может у кого дойдут?

PS: я вот как-то застрял последние лет пять на ас.. надоел жутко - сейчас срочно осваиваю эрланг и c#.
java почему то не пошла - язык в принципе выучил и даже кое-что серьёзное на нём делал, но как -то душа не лежит.
попробовал плюсы вспомнить - забил, споткнувшись об сложность всяких дефайнов и кучу библиотек.
сами языки вообще выучить легко. самое сложное - это обвязки, исключения из правил, парадигмы итп, осознание которых приходит только с реальным опытом работы.
сорри за такой личностный оффтоп - просто накипело)))))))

Nirth
20.07.2010, 13:09
Пытался попроывать собать на Ruby в одну строчку, но получился клон Erlang ( Котяры ), но не удалять же не засветив ^_^
#!/usr/bin/env ruby

1.upto( 100 ){
|i|
case
when i % 3 == 0 && i % 5 == 0 : print "Fizz-Buzz", "\n"
when i % 3 == 0 : print "Fizz", "\n"
when i % 5 == 0 : print "Buzz", "\n"
else print i.to_s, "\n"
end
}