2011-10-05 46 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