我正在学习Haskell,我正在使用Advent of Code 2015进行练习。我试图用位表而不是坐标和状态列表来解决 Day06,但它没有计算正确的值,我无法理解逻辑或实现中是否存在错误。
代码如下:
module Day06 where
import Data.Bits
import Data.Ix
import Data.List
parse :: String -> [Int]
parse a =
let (c1,c2) = break (==',') a
in range (read c1, read (tail c2))
mFlatten :: String -> String -> [Int]
mFlatten x y =
[ a + b * 1000 | a <- parse x, b <- parse y]
action :: (Bits b, Num b) => b -> [[Char]] -> b
action state instruction = case instruction of
["toggle", a, _, b] -> foldl' complementBit state $ mFlatten a b
["turn","on", a, _, b] -> foldl' setBit state $ mFlatten a b
["turn","off", a, _, b] -> foldl' clearBit state $ mFlatten a b
main :: IO ()
main = do
input <- readFile "input"
print $ popCount $ (foldl ( acc x -> action acc $ words x) 0 (lines input) :: Integer)
我有几个问题:
- 有没有更惯用的方法来编写此代码?
- 如何提高性能?
最重要的是
- 我是否犯了任何会导致程序计算错误结果的错误?我正在考虑诸如类型转换之类的东西,但是我可能错过了一些非常明显的东西。
(为了避免必须登录查看输入,您可以在此处找到它(
-
确保由于溢出而不使用
Int
。请改用Integer
,它可以任意增大。 -
据我了解,该问题要求您打开/关闭相对角(a,b(,(A,B(之间的矩形区域。我认为您将两个元组解释为矩形 [a..b]x[A..B],但它应该是[a.。A]x[b..B](假设 a<=A, b<=B(
早就说对了,我这边有很大的疏忽。这是工作代码:
module Day06 where
import Data.Bits
import Data.List
parse :: String -> (Int,Int)
parse a =
let (c1,c2) = break (==',') a
in (read c1, read (tail c2))
mFlatten :: String -> String -> [Int]
mFlatten a b =
let (x1,y1) = parse a
(x2,y2) = parse b
in [ x + y * 1000 | x <- [x1..x2], y <- [y1..y2]]
action :: (Bits b, Num b) => b -> [[Char]] -> b
action state instruction = case instruction of
["toggle", a, _, b] -> foldl' complementBit state $ mFlatten a b
["turn","on", a, _, b] -> foldl' setBit state $ mFlatten a b
["turn","off", a, _, b] -> foldl' clearBit state $ mFlatten a b
main :: IO ()
main = do
input <- readFile "input"
print $ popCount $ (foldl ( acc x -> action acc $ words x) 0 (lines input) :: Integer)
非常感谢!