shell编程实例
1.整除问题
read a b
if [ $[$a%$b] -eq 0 ]
then
echo YES
else
echo NO
fi
2.7的奇倍数
read n
if [[ $[$n%7] -eq 0 && $[$n%2] -ne 0 ]]; then
echo YES
else
echo NO
fi
3.一个月有几天
read y m
cal_days_in_month()
{
n_year=`expr $y + 0`
n_month=`expr $m + 0`
n_day=0;
case $n_month in 1|3|5|7|8|10|12) #这里使用case in ) 的表达式可以简化代码量,十分方便,下边的就是正常的if elif 和else
n_day=31;;
4|6|9|11)
n_day=30;;
2)
if [ `expr $n_year % 4` -eq 0 ];then
if [ `expr $n_year % 400` -eq 0 ];then
n_day=29;
elif [ `expr $n_year % 100` -eq 0 ];then
n_day=28;
else
n_day=29;
fi
else
n_day=28;
fi
;;
esac
echo ${n_day};
}
cal_days_in_month
4.买文具
read a b
A=`expr $a \* 10`
C=`expr $A + $b`
B=`expr $C / 26` #这里相当于统一了一个26进制
echo $B
5.计数问题
#!/bin/bash
read num target
sum=0
for ((i=1;i<=$num;i++))
do
t=$i
ans=0
while [ $t -ne 0 ] #这里使用了很多expr表达式,这一题存在时间要求,这个方法最后没法通过所有测试
do
A=`expr $t % 10`
if [[ $A -eq $target ]]; then
sum=`expr $sum + 1`
fi
t=`expr $t / 10`
done
done
echo $sum
#这个方法没有使用expr,同时通过一个数组换取了时间上的提升
read n x
function appear_num() {
k=0
for ((i=1; i<=$n; i++)); do
a=$[$i/1000000] #百万位
b=$[($i/100000)%10] #十万位
c=$[($i/10000)%10] #万位
d=$[($i/1000)%10] #千位
e=$[($i/100)%10] #百位
f=$[($i/10)%10] #十位
g=$[$i%10] #个位
bit=($g $f $e $d $c $b $a)
if [[ $i -lt 10 ]]; then
N=1
elif [[ $i -gt 9 && $i -lt 100 ]]; then
N=2
elif [[ $i -gt 99 && $i -lt 1000 ]]; then
N=3
elif [[ $i -gt 999 && $i -lt 10000 ]]; then
N=4
elif [[ $i -gt 9999 && $i -lt 100000 ]]; then
N=5
elif [[ $i -gt 99999 && $i -lt 1000000 ]]; then
N=6
elif [[ $i -gt 999999 && $i -lt 10000000 ]]; then
N=7
fi
for ((j=0; j<N; j++)); do
if [[ ${bit[j]} -eq $x ]]; then
k=$[$k+1]
fi
done
done
echo $k
}
6.校门口的树
read L num
arrtarget=(0)
sum=0
for ((i = 1; i <= $num; i++))
do
read left right
for ((j = $left; j < $[$right+1]; j++))
do
if [[ ${arrtarget[$j]} -eq 1 ]];then
continue
fi
arrtarget[$j]=1 #将所有有树的地方进行标记,然后每标记成功一次就将计数器加一
sum=$[ $sum+1 ]
done
done
A=$[ $L-$sum ]
A=`expr $A + 1`
echo $A
7.插队
#!/bin/bash
#思路很简单,就是数组的修改,过程类似链表的增加节点,只不过要把数组末尾临时保存起来
arr=(0)
read n
read -a arr #直接读入一行数据到数组中
temp=${arr[$[ $n - 1 ]]}
read target
for ((j = $[ $n - 1 ]; j >= $[ $target - 1 ]; j--))
do
arr[$j]=${arr[$[ $j - 1 ]]}
done
arr[$[ $target - 1 ]]=$temp
for((i = 0; i <= $[ $n - 1 ] ; i++))
do
echo -n ${arr[$i]} # echo -n 表示不换行
echo -n " "
done
8.走楼梯
#!/bin/bash
#本质上类似于斐波那契数列,所以就模拟那个过程就行了
declare -a arr#声明一个数组
read n
arr[1]=1 # 斐波那契数列
arr[2]=2
for ((i=3; i <= $n; i++))
do
arr[$i]=$[${arr[$[$i - 1]]} + ${arr[$[$i - 2]]}]
done
for ((i = 1; i <= $n; i++)); do
echo -n ${arr[$i]}" " #不换行输出带空格,这个是通过 -n 来实现的
done
9.比身高
#!/bin/bash
declare -a arr
read n
sum=0
for ((i = 1; i <= $n; i++)); do
read num
arr[$i]=$num
done
#正常模拟,将所有的数据进行遍历分别统计选定数字前后两部分的数组进行great比较
for ((i=1; i <= $n; i++)); do
t1=0
t2=0
for ((j=1; j < $i; j++));do
if [[ ${arr[$j]} -gt ${arr[$i]} ]];then
t1=$[ $t1 + 1 ]
fi
done
for ((k=$[ $i + 1 ]; k <= $n; k++)); do
if [[ ${arr[$k]} -gt ${arr[$i]} ]];then
t2=$[ $t2 + 1 ]
fi
done
if [[ $t1 -eq $t2 ]];then
sum=$[ $sum + 1 ]
fi
done
echo $sum
10.爬楼梯
#!/bin/bash
declare -a arr
read n
arr[1]=0
arr[2]=1
arr[3]=1
for((i=4;i<=$n;i++))
do
#有点像是分治法,但是过程还是斐波那契,只不过需要将每次的结果保存下来用于之后的计算,因为它的相隔个数不是1
arr[$i]=$[${arr[$[$i - 2]]}+${arr[$[$i - 3]]}]
done
echo $[arr[$n]]
11.斐波那契数列
read n
list=(0 1)
for i in `seq 2 30`
do
list[$i]=`expr ${list[-1]} + ${list[-2]}`
done
echo ${list[$n]}
出现了很多次斐波那契数列的变形,思路基本一样,但是参考了其他人的代码,不过还是尽量不要用expr