2017-09-24 73 views
1

我想,给定一个列表,创建于哈斯克尔的元素的随机排列。我已经尝试在Javascript中的算法,它的工作。我对Haskell很新,所以我可能没有看到什么。我非常肯定,我只接收单个元素而不是列表,只有一个元素,这使得我的程序崩溃。我在之前的练习中遇到过这个问题,但仍不知道如何解决。随机化列表在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

您键入签名不正确'randomizeList ::公式A => A - > [一]'接受一个元素并返回一个列表,你可能想''a] - > [a]'。我也不明白为什么需要'Eq' – puhlen

回答

2

夫妇与你的代码,大多是微不足道的失误问题:

  1. 签名错误,应该是randomizeList :: Eq a => [a] -> [a] (从列表中的列出,而不是从元素列表)上的开始
  2. 虚假do块(只删除)
  3. 列表中串联起来++,不与:(后者将元素添加到列表)
  4. 在您需要的最后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 
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不推荐。