diff -r 98adda6171d1 -r 2c8514b3891b test/gs/javatest.html
--- a/test/gs/javatest.html Sun Mar 02 12:47:31 2025 +0100
+++ b/test/gs/javatest.html Sun Mar 02 16:06:24 2025 +0100
@@ -33,6 +33,9 @@
span.c2html-string {
color: darkorange;
}
+ span.c2html-number {
+ color: dodgerblue;
+ }
span.c2html-comment {
color: grey;
}
@@ -44,181 +47,246 @@
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30 package de.uapcore.sigred.doc.base;
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27 package de.uapcore.sudoku;
+
28
+
29 import java.util.ArrayList;
+
30 import java.util.List;
31
-
32 import de.uapcore.sigred.doc.
Resources;
-
33 import de.uapcore.sigrapi.impl.
Digraph;
-
34 import de.uapcore.sigrapi.impl.
Graph;
-
35 import de.uapcore.sigrapi.
IGraph;
-
36 import java.io.
IOException;
-
37 import java.io.
InputStream;
-
38 import java.io.
OutputStream;
-
39 import java.util.concurrent.atomic.
AtomicBoolean;
-
40 import java.util.concurrent.atomic.
AtomicReference;
-
41 import org.apache.xerces.impl.
Constants;
-
42 import org.dom4j.
Document;
-
43 import org.dom4j.
DocumentException;
-
44 import org.dom4j.
DocumentHelper;
-
45 import org.dom4j.
Element;
-
46 import org.dom4j.
Namespace;
-
47 import org.dom4j.
QName;
-
48 import org.dom4j.io.
OutputFormat;
-
49 import org.dom4j.io.
SAXReader;
-
50 import org.dom4j.io.
XMLWriter;
-
51 import org.xml.sax.
ErrorHandler;
-
52 import org.xml.sax.
SAXException;
-
53 import org.xml.sax.
SAXParseException;
-
54
-
55 public abstract class AbstractGraphDocument<
T extends IGraph>
-
56 extends FileBackedDocument {
-
57
-
58 protected static final Namespace NAMESPACE =
Namespace.get(
"sigred",
-
59 "http://develop.uap-core.de/sigred/");
-
60
-
61 private static final
-
62 QName TAG_GRAPHDOC =
QName.get(
"graph-document",
NAMESPACE);
-
63 private static final
-
64 QName TAG_GRAPH =
QName.get(
"graph",
NAMESPACE);
-
65 private static final
-
66 QName TAG_DIGRAPH =
QName.get(
"digraph",
NAMESPACE);
-
67 private static final
-
68 QName TAG_METADATA =
QName.get(
"metadata",
NAMESPACE);
-
69
-
70 protected final T graph;
+
32
+
33
+
34
+
35 public final class Solver {
+
36
+
37 public static final int VERSION =
0x1000;
+
38
+
39 private Integer fillInCandidate(
Field f,
List<
Integer>[][] candidates,
int x,
int y) {
+
40 Integer c = candidates[x][y].remove(
0);
+
41 f.setCellValue(x, y, c);
+
42 f.setCellModified(x, y, true);
+
43 for (
int i =
0 ; i <
9 ; i++) {
+
44 candidates[x][i].remove(c);
+
45 candidates[i][y].remove(c);
+
46 }
+
47 for (
int i =
0 ; i <
3 ; i++) {
+
48 for (
int j =
0 ; j <
3 ; j++) {
+
49 candidates[x-x%
3+i][y-y%
3+j].remove(c);
+
50 }
+
51 }
+
52 return c;
+
53 }
+
54
+
55 private void makeBackup(
List<
Integer>[][] candidates,
List<
Integer>[][] candidatesBackup) {
+
56 for (
int x =
0 ; x <
9 ; x++) {
+
57 for (
int y =
0 ; y <
9 ; y++) {
+
58 candidatesBackup[x][y] =
new ArrayList<>(
9);
+
59 candidatesBackup[x][y].addAll(candidates[x][y]);
+
60 }
+
61 }
+
62 }
+
63
+
64 private void makeBackup(
Field f,
int[][] fieldBackup) {
+
65 for (
int x =
0 ; x <
9 ; x++) {
+
66 for (
int y =
0 ; y <
9 ; y++) {
+
67 fieldBackup[x][y] = f.getCellValue(x, y);
+
68 }
+
69 }
+
70 }
71
-
72 private final GraphDocumentMetadata metadata;
-
73
-
74 public AbstractGraphDocument(
Class<
T> graphType) {
-
75 T g;
-
76 try {
-
77 g = graphType.newInstance();
-
78 }
catch (
ReflectiveOperationException e) {
-
79 assert false;
-
80 g = null;
-
81 }
-
82 graph = g;
-
83 metadata =
new GraphDocumentMetadata();
-
84 }
-
85
-
86 public T getGraph() {
-
87 return graph;
-
88 }
-
89
-
90 public GraphDocumentMetadata getMetadata() {
-
91 return metadata;
-
92 }
-
93
-
94 protected abstract void writeGraph(
Element rootNode)
throws IOException;
-
95 protected abstract void readGraph(
Element rootNode)
throws IOException;
-
96
-
97 @Override
-
98 public void writeTo(
OutputStream out)
throws IOException {
-
99 Document doc =
DocumentHelper.createDocument();
-
100
-
101 Element rootNode = doc.addElement(
TAG_GRAPHDOC);
-
102
-
103 Element metadataNode = rootNode.addElement(
TAG_METADATA);
-
104
-
105 metadata.write(metadataNode);
-
106
-
107 if (graph
instanceof Graph) {
-
108 writeGraph(rootNode.addElement(
TAG_GRAPH));
-
109 }
else if (graph
instanceof Digraph) {
-
110 writeGraph(rootNode.addElement(
TAG_DIGRAPH));
-
111 }
else {
-
112 throw new IOException(
"unsupported graph type");
-
113 }
-
114
-
115 XMLWriter writer =
new XMLWriter(out,
OutputFormat.createPrettyPrint());
-
116 writer.write(doc);
-
117 writer.flush();
-
118 }
-
119
-
120 @Override
-
121 public void readFrom(
InputStream in)
throws IOException {
-
122 try {
-
123 SAXReader reader =
new SAXReader(true);
-
124 reader.setStripWhitespaceText(true);
-
125
-
126 reader.setFeature(
Constants.
XERCES_FEATURE_PREFIX+
-
127 Constants.
SCHEMA_VALIDATION_FEATURE, true);
-
128 reader.setProperty(
Constants.
XERCES_PROPERTY_PREFIX +
-
129 Constants.
SCHEMA_LOCATION,
String.format(
"%s %s",
-
130 NAMESPACE.getURI(),
Resources.
class.getResource(
-
131 "graph-document.xsd").toExternalForm()));
-
132
-
133 final AtomicBoolean passed =
new AtomicBoolean(true);
-
134 final AtomicReference<
SAXParseException> xmlerror =
new AtomicReference<>();
-
135
-
136 reader.setErrorHandler(
new ErrorHandler() {
-
137 @Override
-
138 public void warning(
SAXParseException exception)
throws SAXException {
-
139 }
-
140
-
141 @Override
-
142 public void error(
SAXParseException exception)
throws SAXException {
-
143 xmlerror.set(exception);
-
144 passed.set(false);
-
145 }
-
146
-
147 @Override
-
148 public void fatalError(
SAXParseException exception)
throws SAXException {
-
149 xmlerror.set(exception);
-
150 passed.set(false);
-
151 }
-
152
-
153 });
-
154 Document doc = reader.read(in);
-
155 if (!passed.get()) {
-
156
-
157 throw xmlerror.get();
-
158 }
-
159
-
160 doc.normalize();
-
161
-
162 Element root = doc.getRootElement();
-
163 metadata.read(root.element(
TAG_METADATA));
-
164
-
165 if (graph
instanceof Graph) {
-
166 readGraph(root.element(
TAG_GRAPH));
-
167 }
else if (graph
instanceof Digraph) {
-
168 readGraph(root.element(
TAG_DIGRAPH));
-
169 }
else {
-
170 throw new IOException(
"unsupported graph type");
-
171 }
-
172 }
catch (
DocumentException |
SAXException ex) {
-
173 throw new IOException(ex);
-
174 }
-
175 }
-
176 }
+
72 private void restoreBackup(
Field f,
int[][] fieldBackup) {
+
73 for (
int x =
0 ; x <
9 ; x++) {
+
74 for (
int y =
0 ; y <
9 ; y++) {
+
75 f.setCellValue(x, y, fieldBackup[x][y]);
+
76 }
+
77 }
+
78 }
+
79
+
80 private void restoreBackup(
List<
Integer>[][] candidates,
List<
Integer>[][] candidatesBackup) {
+
81 for (
int x =
0 ; x <
9 ; x++) {
+
82 for (
int y =
0 ; y <
9 ; y++) {
+
83 candidates[x][y].clear();
+
84 candidates[x][y].addAll(candidatesBackup[x][y]);
+
85 }
+
86 }
+
87 }
+
88
+
89 private boolean solve(
Field f,
List<
Integer>[][] candidates) {
+
90
+
91
+
92 List<
Integer>[][] candidatesBackup =
new List[
9][
9];
+
93 int[][] fieldBackup =
new int[
9][
9];
+
94 makeBackup(candidates, candidatesBackup);
+
95 makeBackup(f, fieldBackup);
+
96
+
97
+
98 boolean fillDistinct;
+
99 do {
+
100 fillDistinct = false;
+
101 for (
int x =
0 ; x <
9 ; x++) {
+
102 for (
int y =
0 ; y <
9 ; y++) {
+
103 if (f.isCellEmpty(x, y) && candidates[x][y].size() ==
1) {
+
104 fillInCandidate(f, candidates, x, y);
+
105 fillDistinct = true;
+
106 }
+
107 }
+
108 }
+
109 }
while (fillDistinct);
+
110
+
111
+
112 for (
int x =
0 ; x <
9 ; x++) {
+
113 for (
int y =
0 ; y <
9 ; y++) {
+
114 if (f.isCellEmpty(x, y)) {
+
115 while (candidates[x][y].size() >
0) {
+
116 List<
Integer>[][] cb =
new List[
9][
9];
+
117 makeBackup(candidates, cb);
+
118 Integer c = fillInCandidate(f, candidates, x, y);
+
119 if (solve(f, candidates)) {
+
120 break;
+
121 }
else {
+
122 f.clearCellValue(x, y);
+
123 restoreBackup(candidates, cb);
+
124
+
125 candidates[x][y].remove(c);
+
126 }
+
127 }
+
128 }
+
129 if (f.isCellEmpty(x, y)) {
+
130 restoreBackup(f, fieldBackup);
+
131 restoreBackup(candidates, candidatesBackup);
+
132 return false;
+
133 }
+
134 }
+
135 }
+
136
+
137 return true;
+
138 }
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150 public boolean solve(
Field f) {
+
151
+
152
+
153 List<
Integer>[][] candidates =
new List[
9][
9];
+
154 for (
int x =
0 ; x <
9 ; x++) {
+
155 for (
int y =
0 ; y <
9 ; y++) {
+
156 candidates[x][y] =
new ArrayList<>(
9);
+
157 if (f.getCellValue(x, y) ==
0) {
+
158
+
159 for (
int c =
1 ; c <=
9 ; c++) {
+
160 candidates[x][y].add(c);
+
161 }
+
162
+
163 int[] line = f.getRow(y);
+
164 for (
Integer c : line) {
+
165 candidates[x][y].remove(c);
+
166 }
+
167
+
168 line = f.getColumn(x);
+
169 for (
Integer c : line) {
+
170 candidates[x][y].remove(c);
+
171 }
+
172
+
173 int[][] square = f.getSquare(x/
3, y/
3);
+
174 for (
int[] sq : square) {
+
175 for (
Integer c : sq) {
+
176 candidates[x][y].remove(c);
+
177 }
+
178 }
+
179 }
+
180 }
+
181 }
+
182
+
183
+
184 return solve(f, candidates);
+
185 }
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193 public boolean check(
Field f) {
+
194 int[] line;
+
195 for (
int i =
0 ; i <
9 ; i++) {
+
196 line = f.getRow(i);
+
197 if (!valid(line)) {
+
198 return false;
+
199 }
+
200 line = f.getColumn(i);
+
201 if (!valid(line)) {
+
202 return false;
+
203 }
+
204 }
+
205
+
206 int[][] square;
+
207 for (
int x =
0 ; x <
3 ; x++) {
+
208 for (
int y =
0 ; y <
3 ; y++) {
+
209 square = f.getSquare(x, y);
+
210 if (!valid(square)) {
+
211 return false;
+
212 }
+
213 }
+
214 }
+
215
+
216 return true;
+
217 }
+
218
+
219 private boolean valid(
int[] line) {
+
220 int[] numbers;
+
221 numbers =
new int[
9];
+
222 for (
int i =
0 ; i <
9 ; i++) {
+
223 int l = line[i]
-1;
+
224 if (l >=
0) {
+
225 if ((++numbers[l]) >
1) {
+
226 return false;
+
227 }
+
228 }
+
229 }
+
230
+
231 return true;
+
232 }
+
233
+
234 private boolean valid(
int[][] square) {
+
235 int[] line =
new int[
9];
+
236 for (
int x =
0 ; x <
3 ; x++) {
+
237 System.arraycopy(square[x],
0, line,
3*x,
3);
+
238 }
+
239 return valid(line);
+
240 }
+
241 }