Bash 简化数独
Bash simplified sudoku
所以,我必须编写一个 bash 脚本来检查 9x9 "sudoku" 解决方案是否有效,但简化是我不必将其分成 3x3,而只是检查行和列是否包含重复数字,有效数字只有1-9..
这就是我的想法,但无法实现:
#!/bin/bash
error="false"
count=0
#this would be for columns
#for i in 1 2 3 4 5 6 7 8 9
#do
#cat sudoku.txt | awk -F "\t" '{ print $'$i'}' | uniq -c | awk ' > 1 { count++ } END { print count }'
#done
#and this would be for rows
for i in 1 2 3 4 5 6 7 8 9
do
cat sudoku.txt | awk '{ print FNR=$'$i'}' | uniq -c |
awk ' > 1 { count++ } END { print count }' |
awk ' count > 0 { $error="true" } END { print $i }' |
awk '{ if ($error = "true") print "Wrong data!"; else print "Correct data!"; } '
done
$ awk '
function check(num) {
return num != 45 ? 1 : 0;
}
{
row = 0;
for (i = 1; i <= 9; i++) {
row += $i;
col[i] += $i;
}
if (check(row) > 0) {
errors[++error_len] = sprintf("error in line %s: %s", FNR, [=10=]);
}
}
END {
for (i = 1; i <= 9; i++) {
if (check(row) > 0) {
errors[++error_len] = sprintf("error in column %s: %s", i, col[i]);
}
}
if (error_len) {
for (i = 0; i <= error_len; i++) {
print(errors[i]);
}
}
else {
print("all good");
}
}
' sudoku
error in line 4: 6 7 1 4 8 2 6 9 3
$ cat sudoku
8 1 2 9 7 4 3 6 5
9 3 4 6 5 1 7 8 2
7 6 5 8 2 3 9 4 1
6 7 1 4 8 2 6 9 3 <-- see the 6 here thats an error:
2 8 9 3 6 5 4 1 7
6 4 3 7 1 9 2 5 8
1 9 6 5 3 7 8 2 4
3 2 8 1 4 6 5 7 9
4 5 7 2 9 8 1 3 6
如果您先使用 awk 转置矩阵,然后像处理列一样循环处理它,就很容易了。
file: transpose.awk
#! /bin/sh
# Transpose a matrix: assumes all lines have same number
# of fields
exec awk '
NR == 1 {
n = NF
for (i = 1; i <= NF; i++)
row[i] = $i
next
}
{
if (NF > n)
n = NF
for (i = 1; i <= NF; i++)
row[i] = row[i] " " $i
}
END {
for (i = 1; i <= n; i++)
print row[i]
}' ${1+"$@"}
for a in {1..9}; do var=$(cut -d ' ' -f ${a} sudoku.txt | sort -n | uniq -d); ((${var:-0} > 0)) && echo "Column $a is bad, duplicate ${var}'s."; done
for a in {1..9}; do var=$(transpose.awk sudoku.txt | cut -d ' ' -f ${a} | sort -n | uniq -d); ((${var:-0} > 0)) && echo "Row $a is bad, duplicate ${var}'s."; done
运行 示例文件 sudoku.txt
:
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 3 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 1 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 8
第 2 列错误,第 3 列重复。
第 4 列错误,重复 1。
第 9 列错误,重复 8。
第 3 行错误,重复 3。
第 7 行错误,重复 1。
第 9 行错误,重复 8。
所以,我必须编写一个 bash 脚本来检查 9x9 "sudoku" 解决方案是否有效,但简化是我不必将其分成 3x3,而只是检查行和列是否包含重复数字,有效数字只有1-9..
这就是我的想法,但无法实现:
#!/bin/bash
error="false"
count=0
#this would be for columns
#for i in 1 2 3 4 5 6 7 8 9
#do
#cat sudoku.txt | awk -F "\t" '{ print $'$i'}' | uniq -c | awk ' > 1 { count++ } END { print count }'
#done
#and this would be for rows
for i in 1 2 3 4 5 6 7 8 9
do
cat sudoku.txt | awk '{ print FNR=$'$i'}' | uniq -c |
awk ' > 1 { count++ } END { print count }' |
awk ' count > 0 { $error="true" } END { print $i }' |
awk '{ if ($error = "true") print "Wrong data!"; else print "Correct data!"; } '
done
$ awk '
function check(num) {
return num != 45 ? 1 : 0;
}
{
row = 0;
for (i = 1; i <= 9; i++) {
row += $i;
col[i] += $i;
}
if (check(row) > 0) {
errors[++error_len] = sprintf("error in line %s: %s", FNR, [=10=]);
}
}
END {
for (i = 1; i <= 9; i++) {
if (check(row) > 0) {
errors[++error_len] = sprintf("error in column %s: %s", i, col[i]);
}
}
if (error_len) {
for (i = 0; i <= error_len; i++) {
print(errors[i]);
}
}
else {
print("all good");
}
}
' sudoku
error in line 4: 6 7 1 4 8 2 6 9 3
$ cat sudoku
8 1 2 9 7 4 3 6 5
9 3 4 6 5 1 7 8 2
7 6 5 8 2 3 9 4 1
6 7 1 4 8 2 6 9 3 <-- see the 6 here thats an error:
2 8 9 3 6 5 4 1 7
6 4 3 7 1 9 2 5 8
1 9 6 5 3 7 8 2 4
3 2 8 1 4 6 5 7 9
4 5 7 2 9 8 1 3 6
如果您先使用 awk 转置矩阵,然后像处理列一样循环处理它,就很容易了。
file: transpose.awk
#! /bin/sh
# Transpose a matrix: assumes all lines have same number
# of fields
exec awk '
NR == 1 {
n = NF
for (i = 1; i <= NF; i++)
row[i] = $i
next
}
{
if (NF > n)
n = NF
for (i = 1; i <= NF; i++)
row[i] = row[i] " " $i
}
END {
for (i = 1; i <= n; i++)
print row[i]
}' ${1+"$@"}
for a in {1..9}; do var=$(cut -d ' ' -f ${a} sudoku.txt | sort -n | uniq -d); ((${var:-0} > 0)) && echo "Column $a is bad, duplicate ${var}'s."; done
for a in {1..9}; do var=$(transpose.awk sudoku.txt | cut -d ' ' -f ${a} | sort -n | uniq -d); ((${var:-0} > 0)) && echo "Row $a is bad, duplicate ${var}'s."; done
运行 示例文件 sudoku.txt
:
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 3 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 1 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 8
第 2 列错误,第 3 列重复。
第 4 列错误,重复 1。
第 9 列错误,重复 8。
第 3 行错误,重复 3。
第 7 行错误,重复 1。
第 9 行错误,重复 8。