我正在尝试,给出一个列表,在Haskell中创建这些元素的随机排列。我已经在Javascript中尝试了这个算法并且它有效。我对Haskell很新,所以我可能没有看到任何东西。我很确定我收到单个元素而不是只包含一个元素的列表,这会让我的程序崩溃。我在以前的练习中遇到过这个问题,但仍然不知道如何解决。
算法将列表分开,直到获得一个元素。然后有50%的可能性,如果合并列表,另一个50%,以相反的方式合并。
这是代码:
-- A randomly chosen, program-scoped constant from the range [1 .. 10]
randomInt :: Int
randomInt = unsafePerformIO (getStdRandom (randomR (1, 10)))
-- Divides the list in half
divideList :: [a] -> ([a], [a])
divideList list = splitAt ((length list) `div` 2) list
-- Given a list, it creates a new one with the elements of said list
randomizeList :: Eq a => a -> [a]
randomizeList list = do
let lists = (divideList list) in
if (length list) > 1
then if (randomInt > 5)
then (randomizeList (fst lists) : randomizeList (snd lists))
else (randomizeList (snd lists) : randomizeList (fst lists))
else [list]
以下是Javascript代码,以防它有用:
function divideList(list){
const length = list.length / 2;
return {fst: list.splice(0, length), snd: list};
}
function randomizeList(list) {
if(list.length == 1) return list;
const lists = divideList(list);
if(Math.random() > 0.5) return randomizeList(lists.fst).concat(randomizeList(lists.snd));
else return randomizeList(lists.snd).concat(randomizeList(lists.fst));
}
提前致谢
答案 0 :(得分:3)
随机化列表的快捷方式是:
module Main where
import Control.Monad (replicateM)
import Data.Function (on)
import Data.List (sortBy)
import System.Random (randomRIO)
main :: IO ()
main = do
putStrLn "not randomized"
let nums = [1..10]
print nums
putStrLn "randomized"
print =<< randomize nums
randomize :: [a] -> IO [a]
randomize xs = do
ys <- replicateM (length xs) $ randomRIO (1 :: Int, 100000)
pure $ map fst $ sortBy (compare `on` snd) (zip xs ys)
此代码生成一个随机的数字列表,用原始列表将它们拉开,然后按生成的随机数对这些对进行排序。然后我们剥离随机数(map fst
)并留下原始元素列表,但随机化。
通常,不建议使用unsafePerformIO
。
答案 1 :(得分:2)
您的代码存在一些问题,主要是琐碎的错误:
randomizeList :: Eq a => [a] -> [a]
(从列表到列表,而不是从列表到列表)do
在块的开头(只需删除)++
连接,而不与:
连接(后者在列表中添加元素)else
中,您需要返回list
而不是[list]
(后者是列表清单)以下内容应该有效:
randomizeList :: Eq a => [a] -> [a]
randomizeList list =
let lists = (divideList list) in
if (length list) > 1
then if (randomInt > 5)
then (randomizeList (fst lists) ++ randomizeList (snd lists))
else (randomizeList (snd lists) ++ randomizeList (fst lists))
else list