如何使用 C++ 迭代数独子网格?
Posted
技术标签:
【中文标题】如何使用 C++ 迭代数独子网格?【英文标题】:How to iterate over Sudoku sub-grid using c++? 【发布时间】:2019-01-07 05:55:31 【问题描述】:我正在尝试做一个在线数独 c++ 测试题。
我需要确定 9x9 数独板是否有效。只有填充的单元格需要根据以下规则进行验证(有些单元格有'.'表示它们没有填写):
-
每行必须包含数字 1-9,不得重复。
每列必须包含数字 1-9,不得重复。
网格的 9 个 3x3 子框中的每一个都必须包含数字 1-9,不得重复。
对于我的解决方案,我正在遍历每一行、每一列和每一个子框网格。将这些数字添加到地图中。并检查该地图是否有任何重复。
我很确定我已经解决了 1
和 2
的标准,但我无法想象如何循环通过子框 3x3 网格。所以我改编了some code found here,老实说,我仍然无法完全理解。我认为这部分可能会导致问题。
如何解决标准 3?
示例输入,正确答案应该返回 False,但我的代码返回 True:
[
[".",".","4",".",".",".","6","3","."],
[".",".",".",".",".",".",".",".","."],
["5",".",".",".",".",".",".","9","."],
[".",".",".","5","6",".",".",".","."],
["4",".","3",".",".",".",".",".","1"],
[".",".",".","7",".",".",".",".","."],
[".",".",".","5",".",".",".",".","."],
[".",".",".",".",".",".",".",".","."],
[".",".",".",".",".",".",".",".","."]
]
我的(损坏的)解决方案:
class Solution
public:
bool isValidSudoku(vector<vector<char>>& board)
//Iterate over each row
for (int x = 0; x < 9; x++)
//Add row numbers to map
map<char, int> row_nums ;
for (int i = 0; i < 9; i++)
if (board[x][i] != '.')
row_nums[board[x][i]]++;
//Return false if duplicates found in row map
for (auto it = row_nums.begin(); it != row_nums.end(); ++it)
if (it->second > 1)
return false;
//Iterate over columns
for (int i = 0; i < 9; i++)
//Add column numbers to map
map<char, int> col_nums ;
for (int y = 0; y < 9; y++)
if (board[i][y] != '.')
col_nums[board[i][y]]++;
//Return false if duplicates found in column map
for (auto it = col_nums.begin(); it != col_nums.end(); it++)
if (it->second > 1)
return false;
//Iterate over the 3x3 sub-boxes and add numbers to a map
//I think this is where I am stuck
for (int x = 0; x < 9; x++)
for (int y = 0; y < 9; y++)
map<char, int> box_nums ;
for (int bx = (x/3)*3; bx < (x/3)*3 + 3; bx++)
for (int by = (y/3)*3; by < (y/3)*3 + 3; by++)
if (board[bx][by] != '.')
box_nums[board[bx][by]]++;
//Return false if duplicates found in column map
for (auto it = box_nums.begin(); it != box_nums.end(); it++)
if (it->second > 1)
return false;
//Else return true
return true;
;
【问题讨论】:
你不是在问问题。请阅读How to Ask。另外,如果您对某些代码有问题,请先提取minimal reproducible example。 添加了一个明确的问题,以防它不够清楚。所有代码都是查看我的解决方案所必需的,答案基于我提供的内容。 【参考方案1】:首先,您不需要std::map
并使用第二个循环来验证是否有任何计数大于1,只需使用std::set
,如果插入操作返回false,则表示找到重复项。其次,您可以只拥有 3 个 std::set
数组,并一次遍历所有行和列,然后为每个项目找到合适的 std::set
:
const size_t size = 9;
using cset = std::set<char>;
using sets = std::array<cset,size>;
sets columns, rows, squares;
for( size_t i = 0; i < size; ++i )
for( size_t j = 0; j < size; ++j )
char n = board[i][j];
if( not checkSet( columns[i], n ) ) return false;
if( not checkSet( rows[j], n ) ) return false;
if( not checkSet( squares[i/3 + j/3*3], n ) ) return false;
return true;
checkSet()
可以这么简单:
bool checkSet( cset &s, char n )
return s.insert( n ).second;
注意:如果您关心效率,您应该使用std::array<bool,size>
而不是std::set
,将您的字符转换为数字 0-8 并将其用作该数组中的索引。
【讨论】:
我想我一直在关注这个直到squares[i%3 + (j%3) * 3]
。你介意解释一下这部分是如何工作的吗?我很难想象这在 2D 平面上是如何工作的。
@TinyTiger 其实是我弄错了,应该是i/3 + j/3*3
你可以看这里ideone.com/zlzWhZ【参考方案2】:
您分享的示例是有效的 Sudoku w.r.t 子框。第 4 列存在两个5
的问题。必须更改列检查中的逻辑以遍历每一行以保持列固定。
//Iterate over columns
for (int i = 0; i < 9; i++)
//Add column numbers to map
map<char, int> col_nums ;
for (int y = 0; y < 9; y++)
if (board[y][i] != '.')
col_nums[board[y][i]]++;
//Return false if duplicates found in column map
for (auto it = col_nums.begin(); it != col_nums.end(); it++)
if (it->second > 1)
return false;
这应该可以解决您的问题。
不确定您的子框问题,但这是另一种无需执行(bx/3)*3
等即可获取子框的方法
for (int x = 0; x < 9; x+=3)
for (int y = 0; y < 9; y+=3)
map<char, int> box_nums;
for (int bx = x; bx < x + 3; bx++)
for (int by = y; by < y + 3; by++)
if (board[bx][by] != '.')
box_nums[board[bx][by]]++;
//Return false if duplicates found in column map
for (auto it = box_nums.begin(); it != box_nums.end(); it++)
if (it->second > 1)
return false;
【讨论】:
谢谢,这对我帮助很大。但现在我看到line 3: 4863 Segmentation fault (core dumped) $command
错误。我将我的代码粘贴到一个在线编译器,它工作正常:cpp.sh/3v6l。知道有什么问题吗?谷歌搜索错误消息,显然这意味着我指向的是分配之外的内存区域。我不知道这是怎么回事。
在链接中,条件应该是by < y + 3;
它显示为by < by + 3
,它永远不会中断。更改它应该可以解决问题以上是关于如何使用 C++ 迭代数独子网格?的主要内容,如果未能解决你的问题,请参考以下文章