这是受英国著名电视游戏节目 Countdown 启发而来的任务。即使没有任何游戏知识,挑战也应该很清楚,但请随时提出澄清。
而且,如果您希望看到该游戏的片段,请查看YouTube片段。它以1997年出色的已故RichardWhitely为特色。
系统会为您提供6个数字,这些数字是从{1、2、3、4、5、6、8、9、10、25、50、75、100}集中随机选择的,并且有100到999之间的随机目标数字。目的是使用六个给定的数字和四个常见的算术运算(加法,减法,乘法,除法;遍及有理数)来生成目标- 或尽可能靠近任一侧。每个数字最多只能使用一次,而每个算术运算符可以使用任意次(包括零次)。请注意,使用多少个数字都没有关系。 编写一个函数,该函数采用目标数字和6个数字的集合(可以表示为列表/集合/数组/序列),并以任何标准数字符号(例如,中缀,前缀,后缀)返回解决方案。该功能必须 始终将最可能的结果返回给目标 ,并且必须在标准PC上最多运行1分钟。注意,在存在多个解决方案的情况下,任何一个解决方案都足够。
系统会为您提供6个数字,这些数字是从{1、2、3、4、5、6、8、9、10、25、50、75、100}集中随机选择的,并且有100到999之间的随机目标数字。目的是使用六个给定的数字和四个常见的算术运算(加法,减法,乘法,除法;遍及有理数)来生成目标- 或尽可能靠近任一侧。每个数字最多只能使用一次,而每个算术运算符可以使用任意次(包括零次)。请注意,使用多少个数字都没有关系。
编写一个函数,该函数采用目标数字和6个数字的集合(可以表示为列表/集合/数组/序列),并以任何标准数字符号(例如,中缀,前缀,后缀)返回解决方案。该功能必须 始终将最可能的结果返回给目标 ,并且必须在标准PC上最多运行1分钟。注意,在存在多个解决方案的情况下,任何一个解决方案都足够。
例子:
{50,100,4,2,2,2,4},目标203, 例如100 * 2 + 2 +(4/4) (精确), 例如(100 + 50)* 4 * 2 /(4 + 2) (精确)
{25、4、9、2、3、10},目标465, 例如(25 + 10-4 )*(9 * 2-3) (精确)
{9,8,10,5,9,7},目标241 例如(((10 + 9)* 9 * 7)+ 8)/ 5 (精确)
{3,7,6,2,1,1,7},目标824 例如(((7 * 3)-1) 6-2 ) 7 (= 826;偏离2)
除了问题陈述中提到的内容外,没有其他限制。您可以用任何标准语言编写该函数(不需要标准I / O)。一如既往的目标是用最少数量的代码字符解决任务。
话虽如此,我可能不会简单地接受使用最短代码的答案。我还将研究代码的优美性和算法的时间复杂性!
找到空闲时间后,我正在尝试F#解决方案-当我有空的时候将其张贴在这里!
为了便于比较,请以以下格式发布所有答案:
语言 字符数:??? 完全模糊的功能: (code here) 清除(理想注释)功能: (code here) 关于算法/智能快捷键的所有注释。
字符数:???
完全模糊的功能:
(code here)
清除(理想注释)功能:
关于算法/智能快捷键的所有注释。
字符数: 361 350 338 322
m=map f=toRational a%w=m(\(b,v)->(b,a:v))w p[]=[];p(a:w)=(a,w):a%p w q[]=[];q(a:w)=[((a,b),v)|(b,v)<-p w]++a%q w z(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 list onRemainder :: 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 list pick :: [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 list pick2 :: [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 computed type Item = (Rational, String) -- | a specification of a binary operation type OpSpec = (Rational -> Rational -> Rational, String) -- | a binary operation on Items type 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 /0 combine :: OpSpec -> Op combine (op,os) (ar,as) (br,bs) | br == 0 = Nothing | otherwise = Just (ar`op`br,"("++as++os++bs++")") -- | the operators we can use ops :: [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 items items :: (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 target countDown:: (Real a, Show a) => a -> [a] -> Item countDown t is = snd $ minimum $ map dist $ reduce $ items is where dist is = (abs . subtract t' . fst $ is, is) t' = toRational t
关于算法/智能快捷方式的任何注释:
z
Maybe
ops
reduce
y
Rational
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.213s user 2m22.063s sys 0m 0.913s