Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package qa6515385;
- import java.util.*;
- import java.util.Map.Entry;
- public class Main {
- @SuppressWarnings("resource")
- public static void main(String[] args) {
- Solver s = new Solver();
- StringBuilder sb = new StringBuilder();
- // http://ja.wikipedia.org/wiki/数独
- sb.append("5,3,0,0,7,0,0,0,0,");
- sb.append("6,0,0,1,9,5,0,0,0,");
- sb.append("0,9,8,0,0,0,0,6,0,");
- sb.append("8,0,0,0,6,0,0,0,3,");
- sb.append("4,0,0,8,0,3,0,0,1,");
- sb.append("7,0,0,0,2,0,0,0,6,");
- sb.append("0,6,0,0,0,0,2,8,0,");
- sb.append("0,0,0,4,1,9,0,0,5,");
- sb.append("0,0,0,0,8,0,0,7,9");
- Scanner in = new Scanner(sb.toString()).useDelimiter("\\s*,\\s*|\\s+");
- s.parse(in);
- in.close();
- s.solve();
- System.out.println(s);
- s = new Solver();
- sb = new StringBuilder();
- sb.append("0,0,6,0,0,1,9,0,0,");
- sb.append("0,0,2,0,0,3,0,1,0,");
- sb.append("0,1,5,0,9,0,0,0,0,");
- sb.append("0,0,4,0,7,2,0,9,0,");
- sb.append("0,9,1,0,0,0,5,2,0,");
- sb.append("0,2,0,5,1,0,3,0,0,");
- sb.append("0,0,0,0,2,0,6,4,0,");
- sb.append("0,4,0,7,0,0,2,0,0,");
- sb.append("0,0,8,9,0,0,1,0,0");
- in = new Scanner(sb.toString()).useDelimiter("\\s*,\\s*|\\s+");
- s.parse(in);
- in.close();
- s.solve();
- System.out.println(s);
- s = new Solver();
- sb = new StringBuilder();
- sb.append("5,0,0,1,0,9,4,0,0,");
- sb.append("2,0,4,7,0,0,9,0,0,");
- sb.append("0,8,3,0,0,2,0,7,0,");
- sb.append("0,4,0,0,0,0,3,0,0,");
- sb.append("0,0,0,8,0,4,0,0,0,");
- sb.append("0,0,6,0,0,0,0,8,0,");
- sb.append("0,9,0,3,0,0,7,2,0,");
- sb.append("0,0,1,0,0,8,6,0,9,");
- sb.append("0,0,2,9,0,6,0,0,3");
- in = new Scanner(sb.toString()).useDelimiter("\\s*,\\s*|\\s+");
- s.parse(in);
- in.close();
- s.solve();
- System.out.println(s);
- }
- }
- class Solver {
- private final Map<Coord, Cell> problem;
- public Solver() {
- problem = initCell();
- }
- public void parse(Scanner in) {
- for (int i = 1; i <= 9; i++)
- for (int j = 1; j <= 9; j++) {
- int k = new Integer(in.next());
- if (k == 0) continue;
- Coord coord = new Coord(Numeric.toNumeric(i), Numeric.toNumeric(j));
- problem().get(coord).number(Numeric.toNumeric(k));
- }
- }
- public Status solve() {
- while (fill8())
- ;
- Cell c = findMin();
- if (c == null) return checkConflict();
- switch (checkConflict()) {
- case False:
- for (Numeric n: c.candidate()) {
- Solver save = save();
- c.number(n);
- switch (solve()) {
- case True:
- return Status.True;
- case Conflict:
- reset(save);
- c.remove(n);
- return solve();
- default:
- break;
- }
- }
- default:
- return checkConflict();
- }
- }
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- int i = 0;
- for (Entry<Coord, Cell> e: problem().entrySet()) {
- Cell c = e.getValue();
- if (c.hasNumber()) sb.append(c.number());
- else sb.append(" ");
- i++;
- if (i > 9 - 1) {
- sb.append("\n");
- i = 0;
- }
- }
- return sb.toString();
- }
- protected Map<Coord, Cell> problem() {
- return problem;
- }
- static private Map<Coord, Cell> initCell() {
- Map<Coord, Cell> problem = new TreeMap<Coord, Cell>();
- for (Numeric i: Numeric.values())
- for (Numeric j: Numeric.values()) {
- Coord coord = new Coord(i, j);
- Cell cell = new Cell(coord);
- problem.put(coord, cell);
- }
- initEffect(problem);
- return problem;
- }
- static void initEffect(Map<Coord, Cell> problem) {
- for (Entry<Coord, Cell> a: problem.entrySet())
- for (Entry<Coord, Cell> b: problem.entrySet()) {
- if (a.getKey().equals(b.getKey())) continue;
- if (a.getKey().getRow() == b.getKey().getRow()) {
- a.getValue().effect(b.getValue());
- b.getValue().effect(a.getValue());
- }
- if (a.getKey().getColumn() == b.getKey().getColumn()) {
- a.getValue().effect(b.getValue());
- b.getValue().effect(a.getValue());
- }
- if (a.getKey().getBox() == b.getKey().getBox()) {
- a.getValue().effect(b.getValue());
- b.getValue().effect(a.getValue());
- }
- }
- }
- private Status checkConflict() {
- if (checkRow() == Status.Conflict) return Status.Conflict;
- if (checkColumn() == Status.Conflict) return Status.Conflict;
- if (checkBox() == Status.Conflict) return Status.Conflict;
- for (Entry<Coord, Cell> e: problem().entrySet()) {
- Cell c = e.getValue();
- if (!c.hasNumber()) return Status.False;
- }
- return Status.True;
- }
- private Status checkRow() {
- for (Numeric row: Numeric.values()) {
- Set<Numeric> all = EnumSet.noneOf(Numeric.class);
- for (Numeric column: Numeric.values()) {
- Coord coord = new Coord(row, column);
- Cell c = problem().get(coord);
- if (!c.hasNumber()) continue;
- if (all.contains(c.number())) return Status.Conflict;
- all.add(c.number());
- }
- Set<Numeric> rest = EnumSet.allOf(Numeric.class);
- rest.removeAll(all);
- for (Numeric column: Numeric.values()) {
- Coord coord = new Coord(row, column);
- Cell c = problem().get(coord);
- if (c.hasNumber()) continue;
- rest.removeAll(c.candidate());
- }
- if (!rest.isEmpty()) return Status.Conflict;
- }
- return Status.True;
- }
- private Status checkColumn() {
- for (Numeric column: Numeric.values()) {
- Set<Numeric> all = EnumSet.noneOf(Numeric.class);
- for (Numeric row: Numeric.values()) {
- Coord coord = new Coord(row, column);
- Cell c = problem().get(coord);
- if (!c.hasNumber()) continue;
- if (all.contains(c.number())) return Status.Conflict;
- all.add(c.number());
- }
- Set<Numeric> rest = EnumSet.allOf(Numeric.class);
- rest.removeAll(all);
- for (Numeric row: Numeric.values()) {
- Coord coord = new Coord(row, column);
- Cell c = problem().get(coord);
- if (c.hasNumber()) continue;
- rest.removeAll(c.candidate());
- }
- if (!rest.isEmpty()) return Status.Conflict;
- }
- return Status.True;
- }
- private Status checkBox() {
- for (Numeric box: Numeric.values()) {
- Set<Numeric> all = EnumSet.noneOf(Numeric.class);
- for (Numeric row: Numeric.values()) {
- for (Numeric column: Numeric.values()) {
- Coord coord = new Coord(row, column);
- if (coord.getBox() != box) continue;
- Cell c = problem().get(coord);
- if (!c.hasNumber()) continue;
- if (all.contains(c.number())) return Status.Conflict;
- all.add(c.number());
- }
- }
- Set<Numeric> rest = EnumSet.allOf(Numeric.class);
- rest.removeAll(all);
- for (Numeric row: Numeric.values()) {
- for (Numeric column: Numeric.values()) {
- Coord coord = new Coord(row, column);
- if (coord.getBox() != box) continue;
- Cell c = problem().get(coord);
- if (c.hasNumber()) continue;
- rest.removeAll(c.candidate());
- }
- }
- if (!rest.isEmpty()) return Status.Conflict;
- }
- return Status.True;
- }
- private Solver save() {
- Solver save = new Solver();
- for (Entry<Coord, Cell> e: problem().entrySet()) {
- Coord coord = e.getKey();
- Cell cell = e.getValue();
- save.problem().get(coord).candidate().clear();
- save.problem().get(coord).candidate().addAll(cell.candidate());
- save.problem().get(coord).number(cell.number());
- }
- return save;
- }
- private void reset(Solver save) {
- for (Entry<Coord, Cell> e: save.problem().entrySet()) {
- Coord coord = e.getKey();
- Cell cell = e.getValue();
- problem().get(coord).candidate().clear();
- problem().get(coord).candidate().addAll(cell.candidate());
- problem().get(coord).number(cell.number());
- }
- }
- private Cell find8() {
- for (Entry<Coord, Cell> e: problem().entrySet()) {
- Cell c = e.getValue();
- if (c.hasNumber()) continue;
- if (c.candidate().size() == 1) return c;
- }
- return null;
- }
- private boolean fill8() {
- boolean ret = false;
- for (Cell c = find8(); c != null; c = find8()) {
- c.number(c.candidate().iterator().next());
- ret = true;
- }
- return ret;
- }
- private Cell findMin() {
- Cell min = null;
- int min_size = Integer.MIN_VALUE;
- for (Entry<Coord, Cell> e: problem().entrySet()) {
- Cell c = e.getValue();
- if (c.hasNumber()) continue;
- if (min == null) {
- min = c;
- min_size = min.candidate().size();
- continue;
- }
- int c_size = c.candidate().size();
- if (c_size >= min_size) continue;
- min = c;
- min_size = min.candidate().size();
- }
- return min;
- }
- }
- class Cell implements Comparable<Cell> {
- private final Set<Cell> effect;
- private final Set<Numeric> candidate;
- private final Coord coord;
- private Numeric number;
- public Cell(Coord coord) {
- this.coord = coord;
- candidate = EnumSet.allOf(Numeric.class);
- effect = new TreeSet<Cell>();
- }
- public int compareTo(Cell o) {
- return coord().compareTo(o.coord());
- }
- public boolean effect(Cell c) {
- return effect.add(c);
- }
- public Coord coord() {
- return coord;
- }
- public Set<Numeric> candidate() {
- return candidate;
- }
- public Set<Cell> effect() {
- return effect;
- }
- public Numeric number() {
- return number;
- }
- public void number(Numeric n) {
- if (n == null) {
- number = null;
- return;
- }
- number = n;
- candidate().clear();
- candidate().add(n);
- for (Cell c: effect())
- c.remove(n);
- }
- protected void remove(Numeric n) {
- candidate().remove(n);
- }
- public boolean hasNumber() {
- return (number() != null) ? true : false;
- }
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("[" + coord());
- sb.append(", n = " + number());
- sb.append(", cand = " + candidate());
- sb.append("]");
- return sb.toString();
- }
- }
- class Coord implements Comparable<Coord> {
- private final Numeric row;
- private final Numeric column;
- private final Numeric box;
- public Coord(Numeric row, Numeric column) {
- this.row = row;
- this.column = column;
- box = decideBox(row.getVal(), column.getVal());
- }
- private Numeric decideBox(int row, int column) {
- if (row <= 3) {
- if (column <= 3) return Numeric.One;
- else if (column <= 6) return Numeric.Two;
- else return Numeric.Three;
- }
- else if (row <= 6) {
- if (column <= 3) return Numeric.Four;
- else if (column <= 6) return Numeric.Five;
- else return Numeric.Six;
- }
- else if (column <= 3) return Numeric.Seven;
- else if (column <= 6) return Numeric.Eight;
- else return Numeric.Nine;
- }
- public Numeric getBox() {
- return box;
- }
- public Numeric getColumn() {
- return column;
- }
- public Numeric getRow() {
- return row;
- }
- public boolean equals(Coord o) {
- if (this.box != o.box) return false;
- if (this.column != o.column) return false;
- if (this.row != o.row) return false;
- return true;
- }
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("[" + row);
- sb.append(", " + column);
- sb.append(", " + box);
- sb.append("]");
- return sb.toString();
- }
- public int compareTo(Coord o) {
- if (row.getVal() < o.row.getVal()) return -1;
- else if (row.getVal() > o.row.getVal()) return 1;
- else if (column.getVal() < o.column.getVal()) return -1;
- else if (column.getVal() > o.column.getVal()) return 1;
- else return 0;
- }
- }
- enum Numeric {
- One(1), Two(2), Three(3), Four(4), Five(5), Six(6), Seven(7), Eight(8), Nine(
- 9);
- private int val;
- private Numeric(int val) {
- this.val = val;
- }
- public int getVal() {
- return this.val;
- }
- @Override
- public String toString() {
- return Integer.toString(this.getVal());
- }
- public static Numeric toNumeric(int i) {
- Numeric ret = null;
- for (Numeric n: Numeric.values()) {
- if (n.getVal() == i) {
- ret = n;
- break;
- }
- }
- return ret;
- }
- }
- enum Status {
- True, False, Conflict
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement