LINUX.ORG.RU

Рекурсия против циклов

 


0

4

Есть г..код на Haskell и Ruby который просто перебирает комбинации - «aa», «ab», «ac» ... «az», «ba» ... «zz». При строке «aaaaaa» код на Haskell справился за 15 минут а на Ruby за 3. Почему Haskell так тормозит? Или скорость проявляется только при компиляции(код запускался в ghci)?

import Data.Char (ord, chr)

mut :: String -> String
mut s 
    | ch == 'z' = mut (init s) ++ "a"
    | otherwise = (init s) ++ [chr $ (+1) $ ord ch]
    where ch = last s

test :: String -> String
test s
    | s /= "zzzzzz" = test $ mut s
    | otherwise = s
def mut s
    if s[-1] == ?z then
        s = mut(s[0,s.length-1]) + ?a
    else
        s[-1] = s[-1].succ
    end
    s
end

def test s
    start = Time.now.to_i
    while (s != "zzzzzz")
        s = mut s
    end
    puts Time.now.to_i - start
end

Это хорошо, что подобные индивидуумы пробуют хаскель через написание кривых алгоритмов, а потом делают соответствующие выводы и оставляют его. Нужно же «избегать популярности любой ценой» (С) :)

al = ['a'..'z']

foo n = length $ iterate (\l -> l >>= \x -> map (:x) al) [[]] !! n

main = print $ foo 6
Успешно	time: 2.38 memory: 5724 signal:0
308915776
https://ideone.com/Go72q7 2 секунды, Карл.

Ivana
()
Ответ на: комментарий от Ivana

iterate (\l -> l >>= \x -> map (:x) al)

Интересно, илитные цацкелисты в принципе не умеют писать читабельный код, или делают это специально, из какирской гордости?

Esper
()
Ответ на: комментарий от Esper

Пожалуйста, для ТС-подобных можно написать и читабельнее :)

iterate (flip map al . flip (:) =<<)
ЗЫ элитные хаскелисты не озадачиваются проблемой «написать читабельно для полного нуля».

Ivana
()
Ответ на: комментарий от Ivana

Пожалуйста, для ТС-подобных можно написать и читабельнее :)

Типа чтобы ему страшно стало и он бросил это дело?

элитные хаскелисты не озадачиваются проблемой «написать читабельно для полного нуля»

По-моему, на нём для полного нуля и не напишешь. Просто мне, как частичному нулю, непонятно, нафига делать это через монады.

Esper
()
Ответ на: комментарий от Esper

Типа чтобы ему страшно стало и он бросил это дело?

Чтобы он увидел 2 секунды, понял, что он начал в хаскеле крайне неудачно, бросил и начал снова - но не втупую переписывая императивные алгоритмы, а по-нормальному. А то топик в высшей степени комичен - надевать штаны через голову и ругать их что они так «тормозят»...

По-моему, на нём для полного нуля и не напишешь. Просто мне, как частичному нулю, непонятно, нафига делать это через монады.

А почему бы не через листомонаду - если она здесь ложится на задачу как доктор прописал? К тому же она достаточно проста. Хотя конечно сделать можно и по-другому, разными способами. Но те же листокомпрехеншенсы (вышкприведенные) - это банальный сахар для все той же листомонады.

Ivana
()
Ответ на: комментарий от Ivana

не втупую переписывая императивные алгоритмы, а по-нормальному

Ваще-т сам алгоритм нормальный, проблема в непонимании, как работает список.

К тому же она достаточно проста.

Проще видали: iterate (concatMap $ \x -> map (:x) al).

Но те же листокомпрехеншенсы (вышкприведенные) - это банальный сахар для все той же листомонады.

Что, правда? А как они рассахариваются?

Esper
()
Ответ на: комментарий от Esper

Проще видали

так конкатмап и есть листомонадный бинт. Проще - вопрос привычки.

А как они рассахариваются?

Семантически эквивалентно - через дунотацию вот так:

x = [ (a,b) | a <- [1..3], b <- [1..3], a/=b ]

y = do
    a <- [1..3]
    b <- [1..3]
    guard $ a/=b
    return (a, b)

main = print $ x == y
Но и то и другое в коре на самом деле рассахаривается в последовательно вложенные монадные бинты с лямбдами. Детальнее надо у элитных хаскелистов (С) спрашивать.

Ivana
()
Ответ на: комментарий от Ivana

Но и то и другое в коре на самом деле рассахаривается в последовательно вложенные монадные бинты с лямбдами.

Как do-нотация рассахаривается, я в курсе. А вот про guard в первый раз услышал. И вообще, я думал, что листомонада - это дурацкая приблуда для кодгольфа в духе Applicative ((->) a), а оказалось, такая базовая вещь. Прикольно.

Кстати, а почему ты (>>=) называешь «бинтом»?

Esper
()
Ответ на: комментарий от Esper

Любая монада - это базовая вещь, на которой и строятся все сахарные дунотации и монад компрехеншенсы (не только листовые, такой же синтаксис применим к любой монаде)

Кстати, а почему ты (>>=) называешь «бинтом»?

потому же, почему и код называю котом :) Но в случае с бинтом еще и аналогия со «связыванием» добавляется.

Ivana
()
Ответ на: комментарий от anonymous

Неудачно выебнулся:

согласен. Ну так если не умеешь выебываться - не выебывайся :)

Код-то не работает!

Ога: https://ideone.com/Ib6BQN

ЗЫ Продолжай выебываеться, может следующие попытки будут более удачны.

Ivana
()
Ответ на: комментарий от anonymous

а, =<< же не в скобочках. тогда ок все

anonymous
()
Ответ на: комментарий от Ivana

подобные индивидуумы
ТС-подобных

предложу, что ты влаедешь функциональным программированием в общем и вчастности Haskell. Сверх знания возвышают тебя над простыми людьми(кто не родился со знанием Haskell) вызывая чувство превосходства над ними, осознание какие все ничтожные. А если кто из простых смертных пытается прикоснуться к Haskell ты заливаешься желчью и злобой, и только передергивание на свое отражение в зеркале возвращает тебя в состояния умиротворения и полета над людьми...

ругать их что они так «тормозят»

где я что то ругал? Или задание простого вопроса о работе Haskell это ругань?

С чего ты взял что мне нужно сгенирировать все возможные последовательности? Возможно это был просто тест работы функии которая начинает перебор отправля каждое новое значение в предикат? Ты как то много делаешь выводов...

RA
() автор топика
Ответ на: комментарий от Ivana
al = ['a'..'z']

foo n = length $ iterate (\l -> l >>= \x -> map (:x) al) [[]] !! n

main = print $ foo 6

И эти люди ещё говорят, что Perl это ужасный язык, код на котором не читаем?

WARNING ★★★★
()
Ответ на: комментарий от Miguel

Ну так-то, да, сразу всё понятно и читабельность на высоте.

WARNING ★★★★
()
Ответ на: комментарий от Miguel

Короче можно

Сокращать - так сокращать!

foo = length . (iterate (>>= \x -> map (:x) al) [[]] !!)
Esper
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.