用Shell脚本破解经典鸡兔同笼问题
提到"鸡兔同笼",想必大家都不陌生------这道经典的数学题,是很多人接触应用题的入门启蒙。题目说"30只鸡和兔的头,80只鸡和兔的脚,求鸡兔各几只",用数学方程求解很直接,但你有没有想过用Shell脚本来实现?
一、先明确问题:鸡兔同笼的核心逻辑
在写代码前,先把问题的核心逻辑理清楚,这是写好脚本的基础:
- 已知条件:总头数30(鸡和兔各1个头,所以总数量是30)、总脚数80(鸡2只脚,兔4只脚);
- 核心关系:鸡的数量 + 兔的数量 = 总头数;鸡的脚数×2 + 兔的脚数×4 = 总脚数;
- 解题思路:这里用"穷举法"------遍历所有可能的鸡的数量,计算对应的兔的数量和总脚数,直到匹配上已知的总脚数。
穷举法虽然不是最高效的,但胜在直观易懂,非常适合用来讲解基础脚本编写。
二、完整Shell脚本:带超详细注释
先上完整脚本,每一行都加了注释,后面会逐句拆解。把这段代码保存为 chicken_rabbit.sh,就能直接运行。
bash
#!/bin/bash
# 1. 指定脚本解释器:告诉系统用Bash来执行这个脚本
# 必须放在脚本第一行,#!是固定语法(称为shebang),/bin/bash是Bash解释器的路径
# 已知条件:定义总头数和总脚数变量
total_heads=30
# 2. 变量赋值:Shell变量无需声明类型,直接"变量名=值"(等号前后不能有空格)
# 这里用total_heads存储总头数,方便后续修改和复用
total_feet=80
# 3. 同上,用total_feet存储总脚数
# 遍历所有可能的鸡的数量(从0到总头数)
for ((chicken=0; chicken<=total_heads; chicken++)); do
# 4. 数值循环命令:按固定次数遍历,格式为for ((初始值; 循环条件; 步长)); do
# chicken=0:循环变量chicken初始化为0(鸡的数量从0开始尝试)
<=total_heads:循环条件(鸡的数量最多等于总头数,不可能超过)
# chicken++:每次循环后chicken自增1(依次尝试每一种可能)
# do:循环体开始的标记
# 计算兔子数量:总头数 - 鸡的数量
rabbit=$((total_heads - chicken))
# 5. 算术运算+变量赋值:$((...))是Shell内置的整数计算语法
# 逻辑:总头数是鸡和兔的总和,所以兔子数量=总头数-鸡的数量
# 注意:赋值时变量名前不加$,取值时才加;表达式内无需空格
# 计算当前鸡兔组合的总脚数
calc_feet=$((chicken * 2 + rabbit * 4))
# 6. 算术运算:鸡2只脚×数量 + 兔4只脚×数量,得到总脚数
# 判断计算的脚数是否等于已知总脚数,是则输出结果
if [ $calc_feet -eq $total_feet ]; then
# 7. 条件判断命令:格式为if [ 条件 ]; then
# [ ... ]:条件测试表达式,括号前后必须有空格(语法要求)
# $calc_feet:取变量值(当前计算的脚数)
# -eq:整数比较运算符,意为"等于"(还有-ne≠、-gt>、-<等)
# then:条件满足时执行的命令开始标记
echo "鸡的数量:$chicken 只"
# 8. 输出命令:echo用于在终端打印字符串
# $chicken:在双引号内嵌入变量值(单引号会原样输出$chicken)
echo "兔的数量:$rabbit 只"
# 9. 同上,输出兔子数量
exit 0
# 10. 退出脚本:exit是内置命令,0表示正常退出(非0为异常)
# 找到正确结果后立即退出,避免多余循环,提高效率
fi
# 11. fi:if判断的结束标记(与if成对出现)
done
# 12. done:for循环的结束标记(与for成对出现)
# 异常处理:若遍历完未找到结果(本题不会执行到这)
echo "未找到符合条件的数量组合"
# 13. 异常提示:应对极端情况,让脚本更健壮
三、脚本运行步骤:新手也能操作
Shell脚本的运行非常简单,只需3步,在Linux或macOS的终端中操作即可(Windows可通过WSL或Git Bash运行):
- 保存脚本 :把上面的代码复制到文本编辑器,保存为
chicken_rabbit.sh(比如保存在桌面); - 赋予执行权限 :打开终端,进入脚本所在目录(比如桌面目录用
cd ~/Desktop),然后执行命令chmod +x chicken_rabbit.sh。这一步是告诉系统"这个文件可以执行"; - 运行脚本 :执行命令
./chicken_rabbit.sh,终端会立即输出结果:
鸡的数量:20 只
兔的数量:10 只
四、核心原理:脚本为什么能跑通?
整个脚本的核心就是"穷举法"的逻辑落地,结合Shell的基础语法实现:
- 变量承载数据 :用
total_heads和total_feet存储已知条件,避免硬编码,让脚本更灵活------如果题目改成"40个头、100只脚",只需修改这两个变量的值即可。 - 循环遍历可能性 :通过
for循环遍历鸡的所有可能数量(0到30),确保不遗漏任何组合,这是穷举法的核心操作。 - 算术运算关联关系 :用
$((...))实现整数计算,将"鸡兔数量关系"和"脚数计算规则"转化为代码可执行的表达式,这是从数学逻辑到编程逻辑的关键转换。 - 条件判断筛选结果 :用
if判断语句对比"计算脚数"和"已知脚数",精准定位正确答案,找到后立即用exit 0退出,减少无效循环。
这些语法(变量、循环、算术运算、条件判断)是Shell编程的基础,掌握它们就能应对很多简单的自动化需求。
五、进阶优化:告别循环,用数学公式直接求解
穷举法适合教学,但效率不高(虽然30次循环几乎无感知)。如果想让脚本更高效,可以直接用数学公式计算,一步得出结果。
数学推导:设鸡为x,兔为y,根据题意可得:
- x + y = 30(总头数)
- 2x + 4y = 80(总脚数)
将公式1变形为x=30-y,代入公式2,解得y=10,x=20。
对应Shell脚本(无循环,更高效):
bash
#!/bin/bash
total_heads=30
total_feet=80
# 直接用数学公式计算:兔数=(总脚数-2×总头数)/2,鸡数=总头数-兔数
rabbit=$(((total_feet - 2 * total_heads) / 2))
chicken=$((total_heads - rabbit))
# 输出结果
echo "鸡的数量:$chicken 只"
echo "兔的数量:$rabbit 只"
这种方式跳过循环,直接通过算术运算得到结果,效率更高,也更贴近数学解题思路。
六、总结
鸡兔同笼问题看似简单,但通过Shell脚本实现的过程,却涵盖了变量定义、循环、算术运算、条件判断等核心基础语法。无论是穷举法还是公式法,核心都是"将数学逻辑转化为代码逻辑"。