2011-10-05 55 views
5

我試圖寫一個函數哈斯克爾列表理解0和1的

row :: Int -> Int -> [Int] 
row n v 

返回的n整數的列表,所有0的,除了v個元素,這需要一個1

例如,

row 0 0 = [] 
row 5 1 = [1,0,0,0,0] 
row 5 3 = [0,0,1,0,0] 

我是新來的Haskell和有很多的困難與此有關。特別是我不知道如何使它重複0的。我理解建立一個列表的概念,比如說[1..n],但我只是得到[1,2,3,4,5]

任何幫助,這將不勝感激。謝謝。

+0

謝謝大家! – Shabu

+2

嗨涮。如果您覺得您的問題已得到解答,請選擇其中一個答案作爲接受的答案。這樣,其他人可以快速找到適用於您的問題的解決方案,而無需通過所有答案。您通過單擊問題左側的複選標記來選擇答案。 – Boris

回答

0

一個簡單的遞歸循環,包含兩個臨時變量c和lst。 c用於計數,lst是我們必須返回的列表。

row :: Int -> Int -> [ Int ] 
row 0 0 = [] 
row n v = rowHelp n v 1 [] where 
    rowHelp n v c lst 
      | c > n = lst 
      | v == c = rowHelp n v (c + 1) (lst ++ [ 1 ]) 
      | otherwise = rowHelp n v (c + 1) (lst ++ [ 0 ]) 


0

哈斯克爾有趣的是,它讓你寫你的程序非常多,你會表達算法的方式。因此請嘗試:

row n v = [if (x `mod` v==0) then 1 else 0 | x <- [1..n] ] 

首先,您將創建一個列表,從1,2到n。 然後你檢查的數量由V整除,如果是,1插在輸出列表中,如果不是0

例子:

> row 0 0 
[] 
> row 5 1 
[1,0,0,0,0] 
> row 5 3 
[0,0,1,0,0] 
> row 15 3 
[0,0,1,0,0,1,0,0,1,0,0,1,0,0,1] 

HTH克里斯

+0

看起來'mod'部分是你的發明,我沒有在問題中看到每個*或*每個*。至少你的第二個例子是不正確的。 – Wolf

16

嘗試:

let row n v = map (\x -> if x == v then 1 else 0) [1..n] 
+0

+1爲巧妙 –

+4

甚至更​​短:'row nv = map(fromEnum。(== v))[1..n]' – Landei

+3

+1對於克羅內克三角洲 - 值得注意的片段 – epsilonhalbe

1

而另一種解決方案,遞歸地建立列表:

row :: Int -> Int -> [Int] 
row 0 _ = [] 
row n 1 = 1 : (row (n-1) 0) 
row n m = 0 : (row (n-1) (m-1)) 

和更可讀的一個,其中零 「取」:

row :: Int -> Int -> [Int] 
row 0 _ = [] 
row n m = take (m - 1) zeros ++ [1] ++ take (n - m) zeros 
    where zeros = (iterate id 0) 
8

有了一個全面的列表:

row n v = [if x == v then 1 else 0 | x <- [1..n]] 

或者使用fromEnum(感謝dave4420)

row n v = [fromEnum (x == v) | x <- [1..n]] 
+0

最短的路是'fromEnum'。 – dave4420

0

我喜歡根據Chris的解決方案演示一種自頂向下的方法:

row n v = result   
    where 
     result = take n numbers  -- our result will have a length of n 
     numbers = map trans [1,2,..] -- and is some transformation of 
             -- the list of natural numbers 
     trans e 
      | e `mod` v == 0 = 1  -- let every v-th element be 1 
      | otherwise  = 0  -- 0 otherwise 

這種風格強調了函數式編程的想法,一個寫下什麼樣的row n v一定值應該是,而不是試圖去寫下某個功能。在回憶一個衆所周知的笑話關於較少知道的pragramming語言薩特人可以說,在純功能編程功能沒什麼,他們只是

+0

創建一個無限列表,並採取它的開始似乎有點程序對我來說。你寫2條語句,它們都做了一些事情(計算無限列表,然後開始)。這完全不是(IMO)寫的,應該怎麼寫,但更多的是如何去做,這就是你說的不應該做的。地圖trans [1..n]似乎很容易閱讀,不是嗎? – mb14

+1

我很抱歉,您不喜歡它,我沒有說它是最有效或最短的源代碼方式。 – Ingo

11

這裏,「一元」的解決方案:

row n v = [(v-1, 0), (1, 1), (n-v, 0)] >>= (uncurry replicate) 

replicate函數重複一個給定的值的次數,例如replicate (v-1) 0給出了v-1個零的列表。 uncurry用於修改replicate以接受元組而不是兩個單一參數。有趣的運營商>>=是monad的核心;對於列表,它與帶有翻轉參數的concatMap相同。

+0

這也許是最好的解決方案,因爲它非常容易概括。 – leftaroundabout

+0

+1,非常非常聰明。 – missingfaktor

+0

也許最聰明的,但不是必須的,最簡單的閱讀 – mb14

3

這也應該工作:

row n v = replicate (v-1)­ 0 ++ [1] ++ repl­icate (n-v)­ 0