哈斯克尔
字符数: 361 350 338 322
完全模糊的功能:
m=mapf=toRationala%w=m((b,v)->(b,a:v))wp[]=[];p(a:w)=(a,w):a%p wq[]=[];q(a:w)=[((a,b),v)|(b,v)<-p w]++a%q wz(o,p)(a,w)(b,v)=[(a`o`b,'(':w++p:v++")")|b/=0]y=m z(zip[(-),(/),(+),(*)]"-/+*")++m flip(take 2 y)r w=do{((a,b),v)<-q w;o<-y;c<-o a b;c:r(c:v)}c t=snd.minimum.m(a->(abs(fst a-f t),a)).r.m(a->(f a,show a))清除功能:
-- | add an element on to the front of the remainder listonRemainder :: a -> [(b,[a])] -> [(b,[a])]a`onRemainder`w = map ((b,as)->(b,a:as)) w-- | all ways to pick one item from a list, returns item and remainder of listpick :: [a] -> [(a,[a])]pick [] = []pick (a:as) = (a,as) : a `onRemainder` (pick as)-- | all ways to pick two items from a list, returns items and remainder of listpick2 :: [a] -> [((a,a),[a])]pick2 [] = []pick2 (a:as) = [((a,b),cs) | (b,cs) <- pick as] ++ a `onRemainder` (pick2 as)-- | a value, and how it was computedtype Item = (Rational, String)-- | a specification of a binary operationtype OpSpec = (Rational -> Rational -> Rational, String)-- | a binary operation on Itemstype Op = Item -> Item -> Maybe Item-- | turn an OpSpec into a operation-- applies the operator to the values, and builds up an expression string-- in this context there is no point to doing +0, -0, *0, or /0combine :: OpSpec -> Opcombine (op,os) (ar,as) (br,bs) | br == 0 = Nothing | otherwise = Just (ar`op`br,"("++as++os++bs++")")-- | the operators we can useops :: [Op]ops = map combine [ ((+),"+"), ((-), "-"), ((*), "*"), ((/), "/") ] ++ map (flip . combine) [((-), "-"), ((/), "/")]-- | recursive reduction of a list of items to a list of all possible values-- includes values that don't use all the items, includes multiple copies of-- some results reduce :: [Item] -> [Item]reduce is = do ((a,b),js) <- pick2 is op <- ops c <- maybe [] (:[]) $ op a b c : reduce (c : js)-- | convert a list of real numbers to a list of itemsitems :: (Real a, Show a) => [a] -> [Item]items = map (a -> (toRational a, show a))-- | return the first reduction of a list of real numbers closest to some targetcountDown:: (Real a, Show a) => a -> [a] -> ItemcountDown t is = snd $ minimum $ map dist $ reduce $ items is where dist is = (abs . subtract t' . fst $ is, is) t' = toRational t关于算法/智能快捷方式的任何注释:
- 在golf’d版本,
z
在列表单子的回报,而不是Maybe
为ops
做。 - 尽管这里的算法是蛮力的,但由于Haskell的惰性,它在较小的固定的线性空间中运行。我编写了很棒的@ keith-randall算法,但它同时运行,并在Haskell中接管了1.5G的内存。
reduce
多次生成一些答案,以便轻松包含术语更少的解决方案。- 在高尔夫球版中,
y
部分是根据自身定义的。 - 结果用
Rational
值计算。Golf的代码将缩短17个字符,如果使用进行计算,则将更快Double
。 - 请注意,函数是如何
onRemainder
排除pick
和之间结构相似性的pick2
。
高尔夫版驱动程序:
main = do print $ c 203 [50, 100, 4, 2, 2, 4] print $ c 465 [25, 4, 9, 2, 3, 10] print $ c 241 [9, 8, 10, 5, 9, 7] print $ c 824 [3, 7, 6, 2, 1, 7]
按时间运行(每个结果还不到一分钟):
[1076] : time ./Countdown(203 % 1,"(((((2*4)-2)/100)+4)*50)")(465 % 1,"(((((10-4)*25)+2)*3)+9)")(241 % 1,"(((((10*9)/5)+8)*9)+7)")(826 % 1,"(((((3*7)-1)*6)-2)*7)")real 2m24.213suser 2m22.063ssys 0m 0.913s



