project-euler

https://projecteuler.net/
Log | Files | Refs | README

commit ceee511b3377cbb5df7d76b87d976e7f18fdd839
parent 046e2fbcae54b35af2f014a8529de43d2dccf43d
Author: mpizzzle <m@michaelpercival.xyz>
Date:   Tue, 29 Sep 2020 20:01:28 +0100

safety commit...

Diffstat:
MEuler_96.cpp | 121+++++++++++++++++++++++++++++++++----------------------------------------------
1 file changed, 51 insertions(+), 70 deletions(-)

diff --git a/Euler_96.cpp b/Euler_96.cpp @@ -6,11 +6,11 @@ #include "Euler.h" typedef std::array<std::array<int, 9>, 9> sudoku; +typedef std::unordered_set<int> set; bool check(sudoku bifurcation) { for (int i = 0; i < 9; ++i) { - std::unordered_set<int> h; - std::unordered_set<int> v; + set h, v; for (int j = 0; j < 9; ++j) { h.insert(bifurcation[i][j]); @@ -24,15 +24,15 @@ bool check(sudoku bifurcation) { for (int l = 0; l < 3; ++l) { for (int k = 0; k < 3; ++k) { - std::unordered_set<int> subgroup_digits; + set subgroup; for (int i = l * 3; i < (l * 3) + 3; ++i) { for (int j = k * 3; j < (k * 3) + 3; ++j) { - subgroup_digits.insert(bifurcation[i][j]); + subgroup.insert(bifurcation[i][j]); } } - if (subgroup_digits.size() < 9) { + if (subgroup.size() < 9) { return false; } } @@ -41,7 +41,7 @@ bool check(sudoku bifurcation) { return true; } -void reset_hv(sudoku& puzzle, std::array<std::unordered_set<int>, 9>& h, std::array<std::unordered_set<int>, 9>& v) { +void reset_hv(sudoku& puzzle, std::array<set, 9>& h, std::array<set, 9>& v) { for (int i = 0; i < 9; ++i) { h[i].clear(); v[i].clear(); @@ -53,109 +53,89 @@ void reset_hv(sudoku& puzzle, std::array<std::unordered_set<int>, 9>& h, std::ar } } -void reset_subgroup(sudoku& puzzle, std::unordered_set<int>& s, int l, int k) { +void reset_subgroup(sudoku& puzzle, set& s, set& m, int l, int k) { s.clear(); + m.clear(); for (int i = l * 3; i < (l * 3) + 3; ++i) { for (int j = k * 3; j < (k * 3) + 3; ++j) { s.insert(puzzle[i][j]); } } + + for (int i = 1; i <= 9; ++i) { + if (s.find(i) == s.end()) { + m.insert(i); + } + } +} + +void found(sudoku& puzzle, int x, int i, int j, int k, int l, bool r, bool vert, std::array<set, 9>& h, std::array<set, 9>& v, set& s, set& m) { + puzzle[i][j] = x; + r = true; + vert = true; + std::cout << "reduced i: " << i + 1 << ", j: " << j + 1 << " = " << x << std::endl; + + reset_hv(puzzle, h, v); + reset_subgroup(puzzle, s, m, l, k); } sudoku reduce(sudoku puzzle) { - bool reduced; - bool vert = true; + bool reduced, vert = true; do { reduced = false; - std::array<std::unordered_set<int>, 9> h; - std::array<std::unordered_set<int>, 9> v; + std::array<set, 9> h, v; reset_hv(puzzle, h, v); for (int l = 0; l < 3; ++l) { for (int k = 0; k < 3; ++k) { - std::unordered_set<int> missing_digits; - std::unordered_set<int> subgroup_digits; - - reset_subgroup(puzzle, subgroup_digits, l, k); - - for (int i = 1; i <= 9; ++i) { - if (subgroup_digits.find(i) == subgroup_digits.end()) { - missing_digits.insert(i); - } - } - + set missing, subgroup; + reset_subgroup(puzzle, subgroup, missing, l, k); for (int i = l * 3; i < (l * 3) + 3; ++i) { for (int j = k * 3; j < (k * 3) + 3; ++j) { if (puzzle[i][j] <= 0) { - if (missing_digits.size() == 1) { - puzzle[i][j] = *missing_digits.begin(); - reduced = true; - vert = true; - std::cout << "reduced i: " << i + 1 << ", j: " << j + 1 << " = " << *missing_digits.begin() << std::endl; - - reset_hv(puzzle, h, v); - reset_subgroup(puzzle, subgroup_digits, l, k); - + if (missing.size() == 1) { + found(puzzle, *missing.begin(), i, j, k, l, reduced, vert, h, v, subgroup, missing); break; } - std::unordered_set<int> matches; + set matches; - for (int x : missing_digits) { - if (h[i].find(x) != h[i].end()) { - matches.insert(x); + for (int x : missing) { + if (subgroup.find(x) == subgroup.end()) { + if (((puzzle[(l * 3) + ((i + 1) % 3)][j] > 0 && !vert) + || h[(l * 3) + ((i + 1) % 3)].find(x) != h[(l * 3) + ((i + 1) % 3)].end()) + && ((puzzle[(l * 3) + ((i + 2) % 3)][j] > 0 && !vert) + || h[(l * 3) + ((i + 2) % 3)].find(x) != h[(l * 3) + ((i + 2) % 3)].end()) + && ((puzzle[i][(k * 3) + ((j + 1) % 3)] > 0 && vert) + || v[(k * 3) + ((j + 1) % 3)].find(x) != v[(k * 3) + ((j + 1) % 3)].end()) + && ((puzzle[i][(k * 3) + ((j + 2) % 3)] > 0 && vert) + || v[(k * 3) + ((j + 2) % 3)].find(x) != v[(k * 3) + ((j + 2) % 3)].end())) { + found(puzzle, x, i, j, k, l, reduced, vert, h, v, subgroup, missing); + break; + } } - if (v[j].find(x) != v[j].end()) { + if (h[i].find(x) != h[i].end() || v[j].find(x) != v[j].end()) { matches.insert(x); } } - std::unordered_set<int> match_matches; + set left_join; - for (int x : missing_digits) { + for (int x : missing) { if (matches.find(x) == matches.end()) { - match_matches.insert(x); + left_join.insert(x); } } - if (match_matches.size() == 1) { - puzzle[i][j] = *match_matches.begin(); - reduced = true; - vert = true; - std::cout << "reduced i: " << i + 1 << ", j: " << j + 1 << " = " << *match_matches.begin() << std::endl; - - reset_hv(puzzle, h, v); - reset_subgroup(puzzle, subgroup_digits, l, k); - + if (left_join.size() == 1) { + found(puzzle, *left_join.begin(), i, j, k, l, reduced, vert, h, v, subgroup, missing); break; } - for (int x : missing_digits) { - if (subgroup_digits.find(x) == subgroup_digits.end()) { - if (((puzzle[(l * 3) + ((i + 1) % 3)][j] > 0 && !vert) - || h[(l * 3) + ((i + 1) % 3)].find(x) != h[(l * 3) + ((i + 1) % 3)].end()) - && ((puzzle[(l * 3) + ((i + 2) % 3)][j] > 0 && !vert) - || h[(l * 3) + ((i + 2) % 3)].find(x) != h[(l * 3) + ((i + 2) % 3)].end()) - && ((puzzle[i][(k * 3) + ((j + 1) % 3)] > 0 && vert) - || v[(k * 3) + ((j + 1) % 3)].find(x) != v[(k * 3) + ((j + 1) % 3)].end()) - && ((puzzle[i][(k * 3) + ((j + 2) % 3)] > 0 && vert) - || v[(k * 3) + ((j + 2) % 3)].find(x) != v[(k * 3) + ((j + 2) % 3)].end())) { - puzzle[i][j] = x; - reduced = true; - vert = true; - std::cout << "reduced i: " << i + 1 << ", j: " << j + 1 << " = " << x << std::endl; - - reset_hv(puzzle, h, v); - reset_subgroup(puzzle, subgroup_digits, l, k); - - break; - } - } - } } } } @@ -209,6 +189,7 @@ void print(sudoku puzzle) { } std::cout << "-------------------" << std::endl << std::endl; } + int Euler::Sudoku() { std::array<sudoku, 50> sudokus;