将一段Java代码翻译成Haskell

时间:2016-11-30 19:14:06

标签: java haskell

我正在解决Baby Blocks问题。我有一些java代码,我想将其转换为Haskell:

爪哇:

for (int i = 1; i <optHeight.length ; i++) {
    int maxHeightIndex = 0;
        for (int j = i-1; j >=0 ; j--) {
            // Need help from here
            if(boxes[j].width>boxes[i-1].width && boxes[j].depth>boxes[i-1].depth) {
                if(optHeight[maxHeightIndex]<optHeight[j+1]) { <-- How do I write this condition
                    maxHeightIndex = j+1;
                }
            }
        }
        optHeight[i]=optHeight[maxHeightIndex] + boxes[i-1].height;
}

其中optHeight是一维数组,boxes是一个由height, width, depth作为数据成员的对象。在Haskell中,它只是一个列表列表。由于缺少可变阵列/变量,我完全无能为力。

Haskell中:

b list = do
 forM_ [1..length list] $ \i -> do
  let maxHeight = 0
  forM_ [0..(i-1)] $ \j  -> do
   if list!!j!!1 > list!!i-1!!1 && list!!j!!2 > list !!j!!2 then
    maxHeight = j + 1

PS:我完全是Haskell的初学者

1 个答案:

答案 0 :(得分:-1)

解决这个问题的方法(我认为)是考虑每个盒子的每次旋转(所以你有3n个总旋转)。然后,您根据其基数的增加来订购这些。那么问题就是选择“#34; fit&#34;”框中最长的子序列。彼此之间(你不必担心两次挑选相同的盒子,因为盒子永远不适合自己)。这听起来很像规范的longest increasing subsequence问题,这表明我们需要一个动态的编程解决方案。我们将有一个长度为3n的数组,其中第i个元素表示您可以使用顶部的第i个框创建的堆栈的最大高度。

maxHeight(i) = { height(i) + max[ maxHeight(j) ] such that
                 width(j) > width(i), depth(j) > depth(i), 0 <= j < i }

现在,让我们开始使用Haskell解决方案。我假设您的输入是维度列表。请注意代码与我描述的解决方案有多接近 - 诀窍是以声明方式编写内容。

   
import Data.List (sortOn)
import Data.Vector (fromList, (!), generate)
import Data.Ord (Down(..))

babyBlocks :: [(Int,Int,Int)] -> Int
babyBlocks blocks = maxHeights ! (3*n - 1)
  where
    -- get the number of blocks
    n = length blocks

    -- generate the `3n` blocks formed by rotating the existing blocks,
    -- sort them by their base size, and store them in a vector for
    -- fast retrieval
    sortedBlocks = fromList
                 . sortOn (\(x,y,z) -> Down (x*y))
                 . concatMap (\(x,y,z) -> [(x,y,z),(y,z,x),(z,x,y)])
                 $ blocks

    -- we'll make ourselves a couple helper functions, just so
    -- our translation of the recurrence relation looks better
    height n    = let (_,_,z) = sortedBlocks ! n in z
    width n     = let (_,y,_) = sortedBlocks ! n in y
    depth n     = let (x,_,_) = sortedBlocks ! n in x
    maxHeight n = maxHeights ! n

    -- state the dynamic programming
    maxHeights = generate (3*n) (\i ->
                   height i + maximum (0 : [ maxHeight j | j<-[0..(i-1)]
                                                         , width j > width i
                                                         , depth j > depth i ]))

你似乎遇到麻烦的部分是最后一部分的动态编程。因为Haskell是懒惰的,所以在定义maxHeight时使用maxHeights实际上是完全可以的,即使我不知道我的向量将被初始化为什么顺序!