Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
142
Task/Nonogram-solver/Java/nonogram-solver.java
Normal file
142
Task/Nonogram-solver/Java/nonogram-solver.java
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
import java.util.*;
|
||||
import static java.util.Arrays.*;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class NonogramSolver {
|
||||
|
||||
static String[] p1 = {"C BA CB BB F AE F A B", "AB CA AE GA E C D C"};
|
||||
|
||||
static String[] p2 = {"F CAC ACAC CN AAA AABB EBB EAA ECCC HCCC", "D D AE "
|
||||
+ "CD AE A DA BBB CC AAB BAA AAB DA AAB AAA BAB AAA CD BBA DA"};
|
||||
|
||||
static String[] p3 = {"CA BDA ACC BD CCAC CBBAC BBBBB BAABAA ABAD AABB BBH "
|
||||
+ "BBBD ABBAAA CCEA AACAAB BCACC ACBH DCH ADBE ADBB DBE ECE DAA DB CC",
|
||||
"BC CAC CBAB BDD CDBDE BEBDF ADCDFA DCCFB DBCFC ABDBA BBF AAF BADB DBF "
|
||||
+ "AAAAD BDG CEF CBDB BBB FC"};
|
||||
|
||||
static String[] p4 = {"E BCB BEA BH BEK AABAF ABAC BAA BFB OD JH BADCF Q Q "
|
||||
+ "R AN AAN EI H G", "E CB BAB AAA AAA AC BB ACC ACCA AGB AIA AJ AJ "
|
||||
+ "ACE AH BAF CAG DAG FAH FJ GJ ADK ABK BL CM"};
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (String[] puzzleData : new String[][]{p1, p2, p3, p4})
|
||||
newPuzzle(puzzleData);
|
||||
}
|
||||
|
||||
static void newPuzzle(String[] data) {
|
||||
String[] rowData = data[0].split("\\s");
|
||||
String[] colData = data[1].split("\\s");
|
||||
|
||||
List<List<BitSet>> cols, rows;
|
||||
rows = getCandidates(rowData, colData.length);
|
||||
cols = getCandidates(colData, rowData.length);
|
||||
|
||||
int numChanged;
|
||||
do {
|
||||
numChanged = reduceMutual(cols, rows);
|
||||
if (numChanged == -1) {
|
||||
System.out.println("No solution");
|
||||
return;
|
||||
}
|
||||
} while (numChanged > 0);
|
||||
|
||||
for (List<BitSet> row : rows) {
|
||||
for (int i = 0; i < cols.size(); i++)
|
||||
System.out.print(row.get(0).get(i) ? "# " : ". ");
|
||||
System.out.println();
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// collect all possible solutions for the given clues
|
||||
static List<List<BitSet>> getCandidates(String[] data, int len) {
|
||||
List<List<BitSet>> result = new ArrayList<>();
|
||||
|
||||
for (String s : data) {
|
||||
List<BitSet> lst = new LinkedList<>();
|
||||
|
||||
int sumChars = s.chars().map(c -> c - 'A' + 1).sum();
|
||||
List<String> prep = stream(s.split(""))
|
||||
.map(x -> repeat(x.charAt(0) - 'A' + 1, "1")).collect(toList());
|
||||
|
||||
for (String r : genSequence(prep, len - sumChars + 1)) {
|
||||
char[] bits = r.substring(1).toCharArray();
|
||||
BitSet bitset = new BitSet(bits.length);
|
||||
for (int i = 0; i < bits.length; i++)
|
||||
bitset.set(i, bits[i] == '1');
|
||||
lst.add(bitset);
|
||||
}
|
||||
result.add(lst);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// permutation generator, translated from Python via D
|
||||
static List<String> genSequence(List<String> ones, int numZeros) {
|
||||
if (ones.isEmpty())
|
||||
return asList(repeat(numZeros, "0"));
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
for (int x = 1; x < numZeros - ones.size() + 2; x++) {
|
||||
List<String> skipOne = ones.stream().skip(1).collect(toList());
|
||||
for (String tail : genSequence(skipOne, numZeros - x))
|
||||
result.add(repeat(x, "0") + ones.get(0) + tail);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static String repeat(int n, String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < n; i++)
|
||||
sb.append(s);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/* If all the candidates for a row have a value in common for a certain cell,
|
||||
then it's the only possible outcome, and all the candidates from the
|
||||
corresponding column need to have that value for that cell too. The ones
|
||||
that don't, are removed. The same for all columns. It goes back and forth,
|
||||
until no more candidates can be removed or a list is empty (failure). */
|
||||
|
||||
static int reduceMutual(List<List<BitSet>> cols, List<List<BitSet>> rows) {
|
||||
int countRemoved1 = reduce(cols, rows);
|
||||
if (countRemoved1 == -1)
|
||||
return -1;
|
||||
|
||||
int countRemoved2 = reduce(rows, cols);
|
||||
if (countRemoved2 == -1)
|
||||
return -1;
|
||||
|
||||
return countRemoved1 + countRemoved2;
|
||||
}
|
||||
|
||||
static int reduce(List<List<BitSet>> a, List<List<BitSet>> b) {
|
||||
int countRemoved = 0;
|
||||
|
||||
for (int i = 0; i < a.size(); i++) {
|
||||
|
||||
BitSet commonOn = new BitSet();
|
||||
commonOn.set(0, b.size());
|
||||
BitSet commonOff = new BitSet();
|
||||
|
||||
// determine which values all candidates of ai have in common
|
||||
for (BitSet candidate : a.get(i)) {
|
||||
commonOn.and(candidate);
|
||||
commonOff.or(candidate);
|
||||
}
|
||||
|
||||
// remove from bj all candidates that don't share the forced values
|
||||
for (int j = 0; j < b.size(); j++) {
|
||||
final int fi = i, fj = j;
|
||||
|
||||
if (b.get(j).removeIf(cnd -> (commonOn.get(fj) && !cnd.get(fi))
|
||||
|| (!commonOff.get(fj) && cnd.get(fi))))
|
||||
countRemoved++;
|
||||
|
||||
if (b.get(j).isEmpty())
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return countRemoved;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue