【小学一年级数学】在数字之间填上“+”或“-”号(位置相邻的两个数字可以组成一个数),使等式成立...

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 = do
        print $ 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 = do
        print $ 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 do
    def 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 
    end
    
    def sign(xs) do
        case xs do 
            [h | t]  -> Enum.map(isign(t), &[h|&1])
            _        -> [[]]
        end
    end

    defp isign(xs) do 
        case xs do 
            [h | t]  -> Enum.map(isign(t), &[h|&1]) ++ Enum.map(isign(t), &[-h|&1])
            _        -> [[]]
        end
    end
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]
]

转载于:https://my.oschina.net/jsk/blog/3071777

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值