LINUX.ORG.RU

Анализ ГПСЧ на Haskell

 


0

3

Дан линейный конгруэнтный ГПСЧ:

x_n = (a*x_{n-1}+b*x_{n-2}) mod m

Где a, b, c, m - константы, заранее неизвестные.

gen :: Int -> Int -> Int -> Int -> Int -> Int -> Int

И для этого генератора надо вычислить период, т. е. написать функцию:

period :: (Int -> Int -> Int) -> Int

В принципе, рабочий вариант этой функции у меня уже был, но он использовал списки, а по заданию это запрещено. Как это более-менее красиво реализовать без списков? Пока в голову приходят только итеративные варианты, которые реализовывать не очень красиво.


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

Кстати да, у Вас ещё одна опечатка: забыли in Я так понимаю, должно быть что-то вроде этого:

recalc :: Builder -> IO ()                                                                                                                    
recalc bulder = do                                                                                                                            
    let parseText label = do                                                                                                                  
        entry <- builderGetObject builder castToEntry label                                                                                   
        text  <- entryGetText entry                                                                                                           
        return $ read text                                                                                                                    
        labels = ["a", "b", "c", "m", "x1", "x2"]                                                                                             
    in [a, b, c, m, x1, x2] <- mapM parseText ["entry" ++ l | l <- labels]                                                             area    <- builderGetObject builder castToDrawingArea "drawingarea1"                                                      w       <- widgetGetAllocatedWidth area                                                                h       <- widgetGetAllocatedHeight area                                                                putStrLn $ research (gen a b c m) (x1, x2) m                                                                   area `on` draw $ (drawHistogram w h (gen a b c m) (x1, x2) 100 m)                                                                  widgetQueueDraw area
Только оно не компилится :( Ругается на
entry <- builderGetObject builder castToEntry label
Мол, оно должно быть в do-блоке

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

Школьник с gentoo и fvwm, калякающий потиньку на haskell? ОК школьники нынче, одобряю.

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

В do-блоке let без in пишется. Как, например, вот здесь: https://en.wikibooks.org/wiki/Haskell/do_notation#Example:_user-interactive_p...

nameDo :: IO ()
nameDo = do putStr "What is your first name? "
            first <- getLine
            putStr "And your last name? "
            last <- getLine
            let full = first ++ " " ++ last
            putStrLn ("Pleased to meet you, " ++ full ++ "!")
nezamudich ★★
()
Ответ на: комментарий от SeTSeR

Ну да, правильно ругается, do-блок должен быть отступом выделен (а он на одном уровне с «labels = ...»). Это же объявление функции локальной:

parseText label = do
  entry <- builderGetObject builder castToEntry label
  text  <- entryGetText entry
  return $ read text

А значит её тело должно быть выделено отступом в сравнении с остальными объявлениями в let (из которых есть только labels).

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

И выделен, вроде бы:

let parseText label = do                                                                   entry <- builderGetObject builder castToEntry label                                                                text  <- entryGetText entry                                                                return $ read text                                                               labels = ["a", "b", "c", "m", "x1", "x2"]

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

Нет, не выделен :)

А вот так — выделен:

recalc :: Builder -> IO ()
recalc builder = do
    let parseText label = do
          entry <- builderGetObject builder castToEntry label
          text  <- entryGetText entry labels
          return $ read text
        labels = ["a", "b", "c", "m", "x1", "x2"]
    [a, b, c, m, x1, x2] <- mapM parseText ["entry" ++ l | l <- labels]
    ...

parseText и labels должны начинаться на одном уровне, чтобы быть разными объявлениями внутри let-блока. А текст самой функции parseText должен формировать свой блок кода, поэтому отступ у строчек entry, text и return больше.

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

Очень долго тупил над этим. Особенно над вашим постом, но сейчас вроде дошло. Спасибо большое.

SeTSeR
() автор топика
Ответ на: комментарий от nezamudich

Прощу прощения за всякие глупые вопросы, но у меня в очередной раз вопрос: что не так в функциях drawRHistogram и quality? Такое ощущение, что значения в массиве в процессе работы не меняются, то бишь в конце работы все нули: https://github.com/SeTSeR/HaskellRandom/blob/master/src/Main.hs https://github.com/SeTSeR/HaskellRandom/blob/master/src/Random.hs

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

Совсем очевидные ошибки я пофиксил, но массив всё так же не обновляется

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

У меня сегодня какой-то тупняк. Ошибка была примитивнейшей. Вместо

(arr // [((get x1 m), (arr!(get x1 m) + 1))])
Я писал
(arr // [((get x1 m), arr!(get x1 m))])
Как следствие массив не обновлялся

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

Молодец, чо. Рекомендую, кстати, пользоваться hlint'ом. Иногда он чушь подсказывает, но чаще всего по делу. Для примера:

(arr // [((get x1 m), (arr!(get x1 m) + 1))])

Здесь следует иметь в виду, что у применения функции приоритет всегда самый высокий, а у всех операторов он ниже, поэтому здесь аж в трёх местах скобки можно опустить. Получается:

(arr // [(get x1 m, arr ! get x1 m + 1)])

Что более читаемо.

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