如何获得更高效的haskell解决方案

时间:2017-05-13 19:45:05

标签: haskell

我一直试图在kattis问题上解决这个问题:https://open.kattis.com/problems/rijeci
我有下面的解决方案,但系统拒绝我的解决方案,因为完成更大的输入需要太长时间,我想知道是否有办法更有效地解决这个问题。请不要假设我知道某些方法,因为我刚刚开始学习haskell,以及针对此问题的函数式编程。

我的解决方案

convertString :: String -> String
convertString [] = []
convertString (x:xs)
  | x == 'A'  = 'B': convertString xs
  | otherwise = 'B':'A':convertString xs

finalString :: String -> Integer -> String
finalString letters numOfTimes
  | numOfTimes > 0   = finalString (convertString letters) (numOfTimes-1)
  | otherwise = letters

getNumA :: String -> Int
getNumB :: String -> Int

getNumA = length . filter(=='A')
getNumB = length . filter(=='B')

main = do
  inputLine <- getLine
  let numOfTimes = read (inputLine) :: Integer
  let convertedString = (finalString "A" numOfTimes)
  putStrLn ((show (getNumA convertedString)) ++ " " ++(show (getNumB convertedString)))

4 个答案:

答案 0 :(得分:1)

好的,让我们看看我们是否可以消除所有的装饰,并用原始递归来表达。我们只关心A和B的数量:它们的顺序与问题无关。此外,每次推送后A和B的数量仅取决于之前的A和B的数量。因此,让我们在步骤 n n )中调用A的数量,并在步骤 n 中调用B的数量 b'/ em>的(名词的)。

我们的基本情况是 a (0)= 1, b (0)= 0.

按下按钮后,前一个字符串中的每个A变为B,每个B变为BA。因此,新字符串中的每个A都是B→AB替换的结果,旧字符串的每个字母都会向新字符串添加一个B.

这意味着,当 n &gt; 0, a n )= b n -1)和 b n )= a n -1)+ b n - 1)。现在,对于 n &gt; 1,我们可以替换 a n -1)= b n -2)。这给了我们:

a (0)= 1, b (0)= 0

a (1)= 0, b (1)= 1

a n )= b n -1), b n )= b n -2)+ b n -1)| n &gt; 1

是否 b -zero的定义,然后是 b 的前两个值的总和 - 将你的任何其他数字序列都删除在编程类中遇到过?

答案 1 :(得分:0)

解决这个问题的诀窍与Haskell无关,而且与答案的格式有关。

问题的难点在于字符串的大小每次迭代大致加倍。所有'B' s加倍"BA",所有'A' s变为'B' s,最终加倍。在内存中为大数字构建此字符串是难以处理的。要快速解决问题,您需要找到一种方法来避免在内存中构建字符串。这是可能的,因为答案不要求字符串,它只要求两个数字:字母数'A'和字母数'B'

在执行任何步骤之前,字符串由1 'A'0 'B'组成。你能算出第一步之后有多少'A''B'

答案 2 :(得分:0)

问题不在Haskell中,而在于您对String类型的处理方式。问题出在使用 String类型。这个问题可以有效解决没有字符串。只需将K的答案从 1 写入 10

K = 1: 0, 1
K = 2: 1, 1
K = 3: 1, 2
K = 4: 2, 3
K = 5: 3, 5
K = 6: 5, 8
K = 7: 8, 13
K = 8: 13, 21
K = 9: 21, 34
K = 10: 34, 55

所以答案是这个序列中的两个连续数字:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...

这段数字对你来说是否熟悉? ;)

Haskell中有很多解决方案可以快速计算这个序列。

答案 3 :(得分:0)

你可以从一个更加数学的方面来思考这个问题:如果你有(As的数量,B的数量),你按下按钮,你会得到(B的数量,As的数量+ B的数量)

您可以在Haskell中将其写为:

step :: (Integer, Integer) -> (Integer,Integer)  
step (a,b) = (b,b+a)

applyStep :: Int -> (Integer, Integer) -> (Integer,Integer)
applyStep 0 (a,b) = (a,b)
applyStep n (a,b) = applyStep (n-1) (step (a,b))