Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package nudoku for openSUSE:Factory checked 
in at 2026-01-22 15:13:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/nudoku (Old)
 and      /work/SRC/openSUSE:Factory/.nudoku.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "nudoku"

Thu Jan 22 15:13:30 2026 rev:12 rq:1328240 version:7.0.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/nudoku/nudoku.changes    2025-08-20 
13:28:57.745521713 +0200
+++ /work/SRC/openSUSE:Factory/.nudoku.new.1928/nudoku.changes  2026-01-22 
15:13:33.272676389 +0100
@@ -1,0 +2,6 @@
+Tue Jan 20 10:19:59 UTC 2026 - Michael Vetter <[email protected]>
+
+- Update to 7.0.0:
+  * Implement better sudoku solver (pr #78)
+
+-------------------------------------------------------------------

Old:
----
  nudoku-6.0.0.tar.gz

New:
----
  nudoku-7.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ nudoku.spec ++++++
--- /var/tmp/diff_new_pack.ZQcMlu/_old  2026-01-22 15:13:34.104711062 +0100
+++ /var/tmp/diff_new_pack.ZQcMlu/_new  2026-01-22 15:13:34.104711062 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package nudoku
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           nudoku
-Version:        6.0.0
+Version:        7.0.0
 Release:        0
 Summary:        Ncurses based sudoku game
 License:        GPL-3.0-only

++++++ nudoku-6.0.0.tar.gz -> nudoku-7.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nudoku-6.0.0/ChangeLog new/nudoku-7.0.0/ChangeLog
--- old/nudoku-6.0.0/ChangeLog  2025-08-20 11:59:01.000000000 +0200
+++ new/nudoku-7.0.0/ChangeLog  2026-01-20 11:15:55.000000000 +0100
@@ -1,3 +1,6 @@
+6.0.0 to 7.0.0 (2026-01-20)
+  * Implement better sudoku solver (pr #78)
+
 5.0.0 to 6.0.0 (2025-08-20)
   * Wrap around board edges when navigating with arrow keys (pr #68)
   * Update Turkish translation (pr #69)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nudoku-6.0.0/configure.ac 
new/nudoku-7.0.0/configure.ac
--- old/nudoku-6.0.0/configure.ac       2025-08-20 11:59:01.000000000 +0200
+++ new/nudoku-7.0.0/configure.ac       2026-01-20 11:15:55.000000000 +0100
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.69])
-AC_INIT([nudoku], [6.0.0], [[email protected]])
+AC_INIT([nudoku], [7.0.0], [[email protected]])
 AC_CONFIG_SRCDIR([src/main.c])
 AC_CONFIG_MACRO_DIRS([m4])
 AM_INIT_AUTOMAKE([foreign])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nudoku-6.0.0/man/nudoku.6 
new/nudoku-7.0.0/man/nudoku.6
--- old/nudoku-6.0.0/man/nudoku.6       2025-08-20 11:59:01.000000000 +0200
+++ new/nudoku-7.0.0/man/nudoku.6       2026-01-20 11:15:55.000000000 +0100
@@ -1,5 +1,5 @@
 .\" Manpage for nudoku.
-.TH man 6 "20 August 2025" "6.0.0" "nudoku man page"
+.TH man 6 "20 January 2026" "7.0.0" "nudoku man page"
 .SH NAME
 nudoku \- ncurses based sudoku game
 .SH SYNOPSIS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nudoku-6.0.0/src/sudoku.c 
new/nudoku-7.0.0/src/sudoku.c
--- old/nudoku-6.0.0/src/sudoku.c       2025-08-20 11:59:01.000000000 +0200
+++ new/nudoku-7.0.0/src/sudoku.c       2026-01-20 11:15:55.000000000 +0100
@@ -77,61 +77,91 @@
        return true;
 }
 
-/* solver code is influenced by sb0rg: 
https://codereview.stackexchange.com/questions/37430/sudoku-solver-in-c */
-static bool is_available(char puzzle[STREAM_LENGTH], int row, int col, int num)
-{
-       int i;
-       int rowStart = (row/3) * 3;
-       int colStart = (col/3) * 3;
-
-       num += 48;
-
-       for (i=0; i<9; i++)
-       {
-               if (puzzle[row * 9 + i] == num)
-                       return false;
-               if (puzzle[i * 9 + col] == num)
-                       return false;
-               if (puzzle[(rowStart + (i % 3)) * 9 + (colStart + (i / 3))] == 
num)
-                       return false;
-       }
-       return true;
+static int get_candidates(char puzzle[STREAM_LENGTH], int pos) {
+    int row = pos / 9, col = pos % 9;
+    int box_row = (row / 3) * 3, box_col = (col / 3) * 3;
+    int mask = 0;
+
+    for (int i = 0; i < 9; i++) {
+        if (puzzle[row * 9 + i] != '.') mask |= 1 << (puzzle[row * 9 + i] - 
'1');
+        if (puzzle[i * 9 + col] != '.') mask |= 1 << (puzzle[i * 9 + col] - 
'1');
+        if (puzzle[(box_row + i / 3) * 9 + box_col + i % 3] != '.')
+            mask |= 1 << (puzzle[(box_row + i / 3) * 9 + box_col + i % 3] - 
'1');
+    }
+    return 0x1FF & ~mask;
+}
+
+static int find_best_cell(char puzzle[STREAM_LENGTH], int *cand_out) {
+    int best_pos = -1, best_count = 10;
+
+    for (int pos = 0; pos < 81; pos++) {
+        if (puzzle[pos] != '.') continue;
+
+        int candidates = get_candidates(puzzle, pos);
+        int n = __builtin_popcount(candidates); // single CPU instruction
+
+        if (n == 0) { *cand_out = 0; return -2; } // dead end
+        if (n < best_count) {
+            best_count = n;
+            best_pos = pos;
+            *cand_out = candidates;
+            if (n == 1) break;
+        }
+    }
+    return best_pos; // -1 if solved
+}
+
+// counts solutions (always backtracks)
+static int count_solutions(char puzzle[STREAM_LENGTH], int count) {
+    int candidates;
+    int pos = find_best_cell(puzzle, &candidates);
+
+    if (pos == -2) return count;     // dead end
+    if (pos == -1) return count + 1; // solved
+
+    for (int num = 0; num < 9 && count < 2; num++) {
+        if (candidates & (1 << num)) {
+            puzzle[pos] = '1' + num;
+            count = count_solutions(puzzle, count);
+            puzzle[pos] = '.'; // always reset
+        }
+    }
+    return count;
 }
 
-/* solve_recursively function influenced by CMPS: 
https://stackoverflow.com/questions/24343214/determine-whether-a-sudoku-has-a-unique-solution
 */
-static int solve_recursively(char puzzle[STREAM_LENGTH], int row, int col, int 
count)
-{
-       int i;
-       if (row == 9)
-       {
-               row = 0;
-               if (++col == 9)
-                       return 1+count;
-       }
-       if (puzzle[row * 9 + col] != '.')  // skip filled cells
-               return solve_recursively(puzzle, row + 1, col, count);
-       for (i = 0; i < 9 && count < 2; ++i)
-       {
-               if (is_available(puzzle, row, col, i + 1))
-               {
-                       puzzle[row * 9 + col] = i + 1 + 48;
-                       count = solve_recursively(puzzle, row + 1, col, count);
-               }
-               else
-                       puzzle[row * 9 + col] = '.'; // reset on backtrack
-       }
-       return count;
-}
-
-int solve(char puzzle[STREAM_LENGTH])
-{
-       int count = 0;
-       if (is_valid_puzzle(puzzle))
-               return solve_recursively(puzzle, 0, 0, count);
-       else
-               return 0;
+// Fills puzzle with first solution (keeps values)
+static bool fill_puzzle(char puzzle[STREAM_LENGTH]) {
+    int candidates;
+    int pos = find_best_cell(puzzle, &candidates);
+
+    if (pos == -2) return false; // dead end
+    if (pos == -1) return true;  // solved
+
+    for (int num = 0; num < 9; num++) {
+        if (candidates & (1 << num)) {
+            puzzle[pos] = '1' + num;
+            if (fill_puzzle(puzzle)) return true; // keep solution
+            puzzle[pos] = '.';
+        }
+    }
+    return false;
 }
 
+int solve(char puzzle[STREAM_LENGTH]) {
+    if (!is_valid_puzzle(puzzle))
+        return 0;
+
+    // count solutions on a copy
+    char copy[STREAM_LENGTH];
+    strncpy(copy, puzzle, STREAM_LENGTH);
+    int count = count_solutions(copy, 0);
+
+    // fill original if solvable
+    if (count >= 1)
+        fill_puzzle(puzzle);
+
+    return count;
+}
 /* GENERATOR */
 /* Generator code is influenced by: 
http://rubyquiz.strd6.com/quizzes/182-sudoku-generator */
 static int rand_int(int n)

Reply via email to