1 ☐ 2 ☐ 3 ☐ 4 ☐ 5 ☐ 6 ☐ 7 ☐ 8 ☐ 9 = 100
拿笔试,大概能试出一组解,为了知道究竟有多少组解,我用Haskell解答如下:
先准备一个函数,给定列表,获取所有可能的组合,根据题目要求,可以将相邻两个数字组合成一个数字,如 1, 2, 3 这三个数字列表,将会得到如下几个列表: [[1,2,3],[1,23],[12,3]]
代码:
comb (x:y:xs) = [x:v | v <- comb (y:xs)] ++ [(x*10+y):v | v <- comb xs]
comb (x:xs) = map (x:) (comb xs)
comb _ = [[]]
不仅仅是加,还有减号,所以准备另外一个函数,将正负号打入:
sign (x:xs) = map (x:) (isign xs) where isign (y:ys) = map (y:) (isign ys) ++ map (-y:) (isign ys)isign _ = [[]]
sign _ = [[]]
验证一下:
main = doprint $ comb [1,2,3]print $ concatMap sign $ comb [1,2,3]
结果:
[[1,2,3],[1,23],[12,3]]
[[1,2,3],[1,2,-3],[1,-2,3],[1,-2,-3],[1,23],[1,-23],[12,3],[12,-3]]
好下面解答就很简单了,直接过滤得到和为100的:
main = doprint $ filter( (==100) . sum ) $ concatMap sign $ comb [1..9]
结果:
[[1,2,3,-4,5,6,78,9],[1,2,34,-5,67,-8,9],[1,23,-4,5,6,78,-9],[1,23,-4,56,7,8,9],[12,3,4,5,-6,-7,89],[12,-3,-4,5,-6,7,89],[12,3,-4,5,67,8,9]
]
共7组解,之前的sign函数有问题,漏掉了连续负号情况,改正后的sign函数将首位提出来不打入负号,尾巴部分由子函数isign挨个打入正负号。
-- 之前的sign函数,刚好漏掉了连续负号情况,所以忽略掉了89的两组解
sign (x:y:xs) = map (\v-> x:v) (sign (y:xs)) ++ map (\v ->x:(-y):v) (sign xs)
sign (x:xs) = map (x:) (sign xs)
sign _ = [[]]
最近在研究Elixir,所以用Elixir也解答了一下,附上Elixir的代码,基本上是参考Haskell直译。
defmodule Num dodef comb(xs) do case xs do[x | [ y | xs]] -> Enum.map(comb([y|xs]), &[x|&1]) ++ Enum.map(comb(xs), &[x*10+y|&1])[h | t] -> Enum.map(comb(t), fn v -> [h|v] end)_ -> [[]]end enddef sign(xs) docase xs do [h | t] -> Enum.map(isign(t), &[h|&1])_ -> [[]]endenddefp isign(xs) do case xs do [h | t] -> Enum.map(isign(t), &[h|&1]) ++ Enum.map(isign(t), &[-h|&1])_ -> [[]]endend
end# test IEx.configure(inspect: [charlists: :as_lists])
# Enum.map([[1,2], [1,2,3], [1,2,3,4]], &IO.inspect(&1 ++ Num.comb(&1), charlists: :as_lists))
Enum.map([[1,2], [1,2,3], [1,2,3,4]], &IO.puts("#{inspect(&1, charlists: :as_lists)} : #{inspect(Num.comb(&1), charlists: :as_lists)}"))
IO.puts "[1,2,3] to comb & sign: "
IO.inspect(Enum.flat_map(Num.comb([1,2,3]), &Num.sign(&1)), charlists: :as_lists)
# result
IO.puts "\nResult Of: 1 ☐ 2 ☐ 3 ☐ 4 ☐ 5 ☐ 6 ☐ 7 ☐ 8 ☐ 9 = 100"
#IO.inspect(Enum.filter(Enum.flat_map(Num.comb(Enum.to_list(1..9)), &Num.sign(&1)), fn x -> 100 == Enum.sum(x) end), charlists: :as_lists)
1..9 |> Enum.to_list |> Num.comb |> Enum.flat_map(&Num.sign(&1)) |> Enum.filter(&Enum.sum(&1)==100) |> IO.inspect(charlists: :as_lists)
输出结果:
[1, 2] : [[1, 2], [12]]
[1, 2, 3] : [[1, 2, 3], [1, 23], [12, 3]]
[1, 2, 3, 4] : [[1, 2, 3, 4], [1, 2, 34], [1, 23, 4], [12, 3, 4], [12, 34]]
[1,2,3] to comb & sign:
[[1, 2, 3],[1, 2, -3],[1, -2, 3],[1, -2, -3],[1, 23],[1, -23],[12, 3],[12, -3]
]Result Of: 1 ☐ 2 ☐ 3 ☐ 4 ☐ 5 ☐ 6 ☐ 7 ☐ 8 ☐ 9 = 100
[[1, 2, 3, -4, 5, 6, 78, 9],[1, 2, 34, -5, 67, -8, 9],[1, 23, -4, 5, 6, 78, -9],[1, 23, -4, 56, 7, 8, 9],[12, 3, 4, 5, -6, -7, 89],[12, -3, -4, 5, -6, 7, 89],[12, 3, -4, 5, 67, 8, 9]
]