LINUX.ORG.RU

[haskell] покритикуйте программу

 


0

0

Только не спрашивайте, зачем она :-)

Задаётся натуральное число n. Если оно нечётное, то n = 3n+1, если оно чётное, то n = n/2. И так до тех пор, пока n ≠ 1.

Как результат интересны все промежуточные числа.

geblist :: [Integer] -> [Integer]
geblist (n:ns)
    | n == 1 = (n:ns)
    | otherwise = geblist (geb n : (n:ns))


geb :: Integer -> Integer
geb n
    | n == 1 = 1
    | odd n  = 3*n + 1
    | otherwise = n `div` 2

gebseq :: Integer -> [Integer]
gebseq n = reverse (geblist [n])

main = print (gebseq 27)

Вывод:

[27,82,41,124,62,31,94,47,142,71,214,107,322,161,484,242,121,364,182,91,274,137,412,206,103,310,155,466,233,700,350,175,526,263,790,395,1186,593,1780,890,445,1336,668,334,167,502,251,754,377,1132,566,283,850,425,1276,638,319,958,479,1438,719,2158,1079,3238,1619,4858,2429,7288,3644,1822,911,2734,1367,4102,2051,6154,3077,9232,4616,2308,1154,577,1732,866,433,1300,650,325,976,488,244,122,61,184,92,46,23,70,35,106,53,160,80,40,20,10,5,16,8,4,2,1]



Последнее исправление: ip1981 (всего исправлений: 3)

Для случайно зашедших в этот тред: все вышеотписавшиеся упоротые донским табаком. Не вздумайте брать их пример!

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

> Для случайно зашедших в этот тред: все вышеотписавшиеся упоротые донским табаком. Не вздумайте брать их пример!

Как это? Отличные примеры, на любой вкус и цвет

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

Love5an, харе так толсто троллить.

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

Waterlaz
()

так создавалась рисовась.... так создавался совершенный алгоритм сжатия freearc!

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

>Более того, т.к. CL может менять семантику и синтаксис до неузнаваемости, и в этом собственно его суть, спорить о читаемости кода на нем - просто глупо.

В том то и дело, что это как раз я бы сказал вредит читаемости. Перед тем, как распарсить, что же тут записано, нужно поизучать все макры, что там натыкали.

Waterlaz
()

Приведенные примеры показывают только убогость языка Хаскель.

Приведенные примеры показывают только убогость языка Хаскель. Кто-нить сможет написать на нем код примерно так:

collatz_sequence (nn :. n) = nn :. n :. ( if (odd n) then (3*n+1) else (n `div` 2) )
main = print $ takeWhile (/=1) $ collatz_sequence [27]

или так:

collatz_sequence (nn++[n]) = nn ++ [n] ++ [ if (odd n) then (3*n+1) else (n `div` 2) ]
main = print $ takeWhile (/=1) $ collatz_sequence [27]
www_linux_org_ru
()
(define (geb n res)
	(if (= n 1)
		(cons 1 res)
		(geb (if (odd? n)
			(+ 1 (* 3 n))
			(/ n 2)) (cons n res))))

(geb 27 `())
Puzan
()
Ответ на: комментарий от Miguel

> Что-то я не вполне понимаю, как оно должно работать.

да, я там рекурсию пропустил, через час-два приду и напишу как оно должно работать

collatz_seq (nn++[n]) = nn ++ [n] ++ collatz_seq [ if (odd n) then (3*n+1) else (n `div` 2) ]

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

>Это же псевдокод практически, чуть ли не литературный английский.
этот код совершенно нечитабелен сторонним человеком. Единственные литературноподобные языки - это ява и си и родственные

(* 3 n)

ну какому нормальному челоеку придет в голову, что это 3 умножить на n? Никакому.

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

>Единственные литературноподобные языки - это ява и си и родственные
Упоролся?

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

> Единственные литературноподобные языки - это ява и си и родственные

Да ты, видать, сурово болен. Паскаль уж всяко человечнее. Какие шансы, что сиподобную многоскобочную ерунду сможет понять не знающий языка человек? А паскалеподобные читаются как псевдокод.

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

этот код совершенно нечитабелен сторонним человеком.

Выучи, наконец: нет языков, читабельных для стороннего человека.

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

Как это называется и как включается?

[code] Prelude> let collatz_seq (nn++[n]) = (nn,n)

<interactive>:1:17: Parse error in pattern [/code]

Хотел посмотреть, что оно матчит - не получилось

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

Как это называется и как включается?

никак. это паттерн-матчинг некоего абстрактного типа, конструируемого из значения и одноэлементного списка. поскольку объявления конструктора (++) в коде нет, сложно сказать - что же именно имел в виду автор. скорее всего, просто написал от балды

Хотел посмотреть, что оно матчит - не получилось

логично

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

Так ведь определяемые инфиксные конструкторы должны начинаться с двоеточия, как тогда можно определить конструктор ++?

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

В общем ждём линукс_орг_р и его исправленную запись корекурсии с ++ или объяснений и признания в некомпетентности :)

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

> В общем ждём линукс_орг_р и его исправленную запись корекурсии с ++ или объяснений и признания в некомпетентности :)

Я с самого начала четко и ясно сказал, что это не хаскель. Хаскелеподобная запись была выбрана для иллюстрации идеи. Кроме того, тот, кто считает, что хаскель не убог, может попытаться реализовать подобное на нем.

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

> Хотел посмотреть, что оно матчит - не получилось

а догадаться не судьба? рассмотрим уравнение [1,2,3] = (nn++[n]) решение существует и единственно

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

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

а неубогим считается язык, который умеет через libastral интерпретировать ошибочные определения?

для иллюстрации идеи

и в чём же заключается идея?

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

Ну не так уж чётко и ясно. А что именно реализовать? (я не очень понял то, что ты имел ввиду).

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

рассмотрим уравнение [1,2,3] = (nn++[n]) решение существует и единственно

подобный паттерн-матчинг есть, емнип, только в РЕФАЛе (для двунаправленных строк); зачем он в этой задаче - непонятно

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

рассмотрим уравнение [1,2,3] = (nn++[n]) решение существует и единственно

В хаскеле такое можно матчить либо так:

fun [a,b,c] = undefined

Либо так:

fun a:b:c:[] = undefined

Я правильно понял?

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

В хаскеле такое можно матчить

в хаскеле такое можно матчить только лениво, поскольку список может быть бесконечным. по той же причине практического смысла это не имеет

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

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

Вообще говоря, подобная запись убога сама по себе.

Miguel
()
Ответ на: комментарий от Miguel
collatz_seq (nn++[n]) = nn ++ [n] ++ collatz_seq [ if (odd n) then (3*n+1) else (n `div` 2) ]

а работать оно могло бы так (показан процесс вычислений, когда нам требуются все новые значения из списка):

collatz_seq [27]
nn ++ [n] ++ collatz_seq [ if (odd n) then (3*n+1) else (n `div` 2) ] where nn=[] where n=[27]
[] ++ [27] ++ collatz_seq [81]
[27] ++ collatz_seq [81]
[27] ++ nn ++ [n] ++ collatz_seq [ if (odd n) then (3*n+1) else (n `div` 2) ] where nn=[] where n=[81]
[27] ++ [] ++ [81] ++ collatz_seq [42]
[27, 81] ++ collatz_seq [42]
www_linux_org_ru
()
Ответ на: комментарий от www_linux_org_ru

Глупо. collatz_seq в любом случае применяется только к одному числу, так что писать функцию, принимающую список - бессмысленно.

collatz_seq n = n : collatz_seq (if odd n then 3 * n + 1 else n `div` 2)

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

> Вообще говоря, подобная запись убога сама по себе.

Отдельно взятая запись не может быть убога. Убог может быть язык, не позволяющий сделать чего-то. Например, позволяющий паттерн матчинг только по конструкторам, в то время как он возможен по более широкому классу.

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

> в хаскеле такое можно матчить только лениво, поскольку список может быть бесконечным

Если предположить, что нам нужно заматчить список ровно из трёх элементов - то всё отлично получается и матчится.

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

Если предположить, что нам нужно заматчить список ровно из трёх элементов - то всё отлично получается и матчится.

я про его задачу с матчингом последнего элемента. количество в паттерне там не оговорено

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

> Например, позволяющий паттерн матчинг только по конструкторам, в то время как он возможен по более широкому классу.

Не только, (раньше был) ещё есть паттерны вида n + k

А болшее широкий класс - это как?

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

> а неубогим считается язык, который умеет через libastral интерпретировать ошибочные определения?

неубогим считается язык, который не ставит ненужных ограничений (т.е. в котором все ограничения оправданы)

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

> например, выстрелить себе в ногу ?

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

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

не ставит ненужных ограничений

на вопрос про бесконечный список ответишь?

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

хаскель выстрелить себе в ногу позволяет

к счастью, в меньшей степени, чем тебе бы того хотелось

задача генерации потенциально бесконечного списка по некоторому правилу решается корекурсией - либо явно, либо через всякие unfold и iterate. ты же хочешь решать эту задачу, мягко говоря, через задницу

а плохой хаскель тебе не позволяет этого сделать. ужасный язык, ужасный

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

тот же, что и другие способы задать бесконечный цикл

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

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

Ну, вообще говоря, расширение ViewPatterns подобные фокусы делать позволяет, ЕМНИМЭ.

Miguel
()

Всё можно, всё можно, но не всё нужно. Во первых collatz_sequence вычисляет только 1 элемент последовательности, никокой рекурсией здесь и не пахнет. Во вторых зачем-то таскает за собой список, а добавление в конец O(n) операция.

Используя view patterns:

{-# LANGUAGE ViewPatterns #-}
import Control.Arrow

collatz_sequence (init &&& last -> (nn,n)) =
    nn ++ [n] ++ [ if (odd n) then (3*n+1) else (n `div` 2) ] 

go = print $ takeWhile (/=1) $ collatz_sequence [27] 

Код с iterate куда проще и идиоматичней

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

> Глупо. collatz_seq в любом случае применяется только к одному числу, так что писать функцию, принимающую список - бессмысленно.

collatz_seq n = n : collatz_seq (if odd n then 3 * n + 1 else n `div` 2)


Для этой задачи — да.

А вот тут думаю список придется таскать:

reverse [] = []
reverse (nn++[n]) = n : reverse nn

www_linux_org_ru
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.