2017-09-24 71 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不推薦。