题目一:【解数独】力扣——37
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。
一个数独。
答案被标成红色。
Note:
给定的数独序列只包含数字 1-9 和字符 '.' 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。
#!/bin/bash
#解数独
#author:yzt 2019-11-03
#
hangshu(){
case $1 in
1|2|3)
sed -n '1,3 p' tmp.txt >tmp1.txt;;
4|5|6)
sed -n '4,6 p' tmp.txt >tmp1.txt;;
7|8|9)
sed -n '7,9 p' tmp.txt >tmp1.txt;;
esac
}
lieshu(){
case $1 in
1|2|3)
lienums=`awk -F , '{print $1,$2,$3}' tmp1.txt|sed 's#\[\|\]##g'|sed 's#\.##g'`
for i in $lienums
do
echo "$i" >>count.txt
done;;
4|5|6)
lienums=`awk -F , '{print $4,$5,$6}' tmp1.txt|sed 's#\[\|\]##g'|sed 's#\.##g'`
for i in $lienums
do
echo "$i" >>count.txt
done;;
7|8|9)
lienums=`awk -F , '{print $7,$8,$9}' tmp1.txt|sed 's#\[\|\]##g'|sed 's#\.##g'`
for i in $lienums
do
echo "$i" >>count.txt
done;;
esac
}
##main_function#
while :
do
for((n1=1;n1<10;n1++))
do
cat /dev/null > count1.txt
sed -n "$n1 p" tmp.txt|sed 's#\[\|\]##g'|sed 's#,#\n#g'|sed 's#\.##g'|grep -v "^$" >> count1.txt
for((n2=1;n2<10;n2++))
do
cat count1.txt >count.txt
count=`awk -F , -v j=$n2 '{print $j}' tmp.txt|sed 's#\[\|\]##g'|sed -n "$n1 p"`
if [ $count = '.' ];then
awk -F , -v k=$n2 '{print $k}' tmp.txt|sed 's#\[\|\]##g'|sed 's#\.##g'|grep -v "^$" >>count.txt
hangshu $n1
lieshu $n2
shuzi_num=`cat count.txt|sort|uniq|wc -l`
if [ $shuzi_num -eq 8 ];then
sum=0
for i in `cat count.txt|sort|uniq`
do
sum=$[$sum+$i]
done
target_num=$[45-$sum]
n3=$[$n2*2]
sed -i "$n1 s#.#$target_num#$n3" tmp.txt #修改文档第n1行第n2列的数值
else
continue
fi
else
continue
fi
done
done
test_file=`grep "\." tmp.txt|head -n1`
if [ -z $test_file ];then
cat tmp.txt
exit 0
fi
done
心得:【此题真的可以说是将sed、awk、grep三大神器的灵活应用的典范】
脚本逻辑:
第一:根据题目意思,提供的数独具有唯一解,据笔者对题目的反复研究,终于在与女友通话过程中灵光一闪【略过】;解决的思路是数独中必定存在一个空缺位置,且此位置的行和列以及小正方形内的数字一定包括了1-9之间的8个数字,只剩余一个目标数字【此思路是解题的关键】
第二:找出存在唯一数字的空缺位置,并将目标数字填充到文档中,这步骤的难点是如何修改文档中某行某列位置的数值,方法在上面的shell脚本中有展现
第三:使用无限循环,使得脚本不断遍历并完善数独,直到数独中没有空缺位置,即没有字符"."
脚本效果: