解小学一年级数学题
亲戚的儿子发来一道数学题,于是草稿打了很久也没解决,后面干脆直接用程序跑。分别用go和rust。跑出来有4种解。不得不说现在小学题已经不是当年那样的了。
package main
import "fmt"
func solve(nums []int, c chan []int) {
dfs(nums, 0, []int{}, c)
close(c)
}
func dfs(nums []int, depth int, res []int, c chan []int) {
if depth == len(nums) {
if res[0]+res[1] == 13 &&
res[1]+res[2]+res[3] == 13 &&
res[3]+res[4]+res[5] == 13 &&
res[5]+res[6]+res[7] == 13 &&
res[7]+res[8] == 13 {
c <- res
}
return
}
for i := 0; i < len(nums); i++ {
if !contains(res, nums[i]) {
dfs(nums, depth+1, append(res, nums[i]), c)
}
}
}
func contains(nums []int, n int) bool {
for _, num := range nums {
if num == n {
return true
}
}
return false
}
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
c := make(chan []int)
go solve(nums, c)
for res := range c {
fmt.Println(res)
}
}
fn solve(nums: &[i32], c: &mut std::sync::mpsc::Sender<Vec<i32>>) {
dfs(nums, 0, &mut vec![], c);
}
fn dfs(nums: &[i32], depth: usize, mut res: &mut Vec<i32>, c: &mut std::sync::mpsc::Sender<Vec<i32>>) {
if depth == nums.len() {
if res[0] + res[1] == 13 &&
res[1] + res[2] + res[3] == 13 &&
res[3] + res[4] + res[5] == 13 &&
res[5] + res[6] + res[7] == 13 &&
res[7] + res[8] == 13 {
c.send(res.clone()).expect("发送结果失败!");
}
return;
}
for i in nums {
if !res.contains(i) {
res.push(*i);
dfs(nums, depth + 1, &mut res, c);
res.pop();
}
}
}
fn main() {
let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let (mut tx, rx) = std::sync::mpsc::channel();
std::thread::spawn(move || {
solve(&nums, &mut tx);
drop(tx);
});
for res in rx.iter() {
println!("{:?}", res);
}
}
这个问题是小学生的题,不可能采用穷举法的。
左右两边需要两个数字组成13,就只有3种情况:9+4,8+5,7+6,所以也就只能组合成三种[[9,4],[8,5]],[[9,4],[7,6]],[[7,6],[8,5]].
左右两边弄完了,就该弄挨着两边的了,这两个数的和一定是两边数中的一个。
整道题其实是一个有条件的分组题,
第一个条件:从[[9,4],[8,5]],[[9,4],[7,6]],[[7,6],[8,5]]中任选一组作为最左右的两边。
从剩余数字中挑选数字使其和等于左右两边中的任意一个
剩余的最后一个数字可以与第二组中的任意一个可以相加成13
举例:左右两边 9+4,7+6。 中间两组1+3,2+5,其中1+3=4,2+5=7。剩余数为8,8+2+3=13。