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)

Ответ на: комментарий от naryl

Впрочем, и на Схеме такой код не нужен >.<

naryl ★★★★★
()

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

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 ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

я там рекурсию пропустил

это не рекурсия

jtootf ★★★★★
()
Ответ на: комментарий от 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

как тогда можно определить конструктор ++

ну собственно, ты сам и ответил на свой предыдущий вопрос :)

jtootf ★★★★★
()
Ответ на: комментарий от 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 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.