标签:pen java led NPU 维数 out arrays output stringbu
代码
// 测试
public class SudoKu {
public static String sudokuString(BiFunction<Integer, Integer, Integer> supplier) {
StringBuilder str = new StringBuilder(" _0_1_2_3_4_5_6_7_8\n");
for (int r = 0; r < 9; r++) {
str.append(r).append(" | ");
for (int c = 0; c < 9; c++) {
int v = supplier.apply(r, c);
str.append(v).append(" ");
}
str.append(‘\n‘);
}
return str.toString();
}
public static void main(String[] args) {
List<Integer> inputs = Arrays.asList(821007900, 7000000, 400003000, 908040000, 000000001, 374201000, 160040, 60000000,
709008600);
int[][] cells = new int[9][9];
for (int rowIndex = 0; rowIndex < inputs.size(); rowIndex++) {
int input = inputs.get(rowIndex);
for (int ci = 8; input > 0; input /= 10, ci--) {
cells[rowIndex][ci] = input % 10;
}
}
SudoKuResolver rc = new SudoKuResolver(cells);
System.out.printf("Input >>\n%s", sudokuString(rc::getCellValue));
System.out.printf("resolving...\n");
long s = System.currentTimeMillis();
boolean resolved = rc.resolve();
long e = System.currentTimeMillis();
long cost = e - s;
System.out.printf("finished, cost: %s\n" , cost);
System.out.printf("Output >>\n%s", resolved ? sudokuString(rc::getCellValue) : "不可解");
}
}
// 解析
class SudoKuResolver {
public final static int[] MIN_INDEX = new int[] { 0, 0, 0, 3, 3, 3, 6, 6, 6 };
public final static int[] MAX_INDEX = new int[] { 2, 2, 2, 5, 5, 5, 8, 8, 8 };
private static final Logger LOGGER = LoggerFactory.getLogger(SudoKuResolver.class);
private final CellMaskBucket[][] cellBuckets;
private int depth;
public SudoKuResolver(int[][] cells) {
this.cellBuckets = new CellMaskBucket[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
cellBuckets[i][j] = new CellMaskBucket(i, j);
cellBuckets[i][j].setMask(0b111_111_111);
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int v = cells[i][j];
if (v != 0) {
CellMaskBucket bucket = cellBuckets[i][j];
bucket.setMask(toMask(cells[i][j]));
}
}
}
}
public boolean resolve() {
// 是否有效
if (!isValid()) {
return false;
}
// 选出格子
CellMaskBucket cell = pickCell();
if (cell == null) {
return true;
}
// 使用调用栈保存拆解步骤
int m = cell.getMask();
if (LOGGER.isDebugEnabled()) {
int trys[] = computeTrys(m);
LOGGER.debug("{}: try [ {} ]", cell, Strings.join(",", trys));
}
while (Integer.bitCount(m) > 0) {
int zc = Integer.numberOfTrailingZeros(m);
int tv = 1 << zc;
push();
setCellMask(cell, tv);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("{}: try {}\n{}", cell, zc + 1, SudoKu.sudokuString(this::getCellValue));
}
if (resolve()) {
return true;
} else {
m &= ~tv;
pop();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("{}: not {}", cell, zc + 1);
}
}
}
// 都不可解,返回 false
return false;
}
void push() {
if (++depth > 80) {
throw new ArrayIndexOutOfBoundsException(depth--);
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
cellBuckets[i][j].bucket[depth] = cellBuckets[i][j].bucket[depth - 1];
}
}
}
void pop() {
if (--depth < 0) {
throw new ArrayIndexOutOfBoundsException(depth++);
}
}
void setCellMask(CellMaskBucket bucket, int mask) {
bucket.setMask(mask);
rcbTravel(bucket.row, bucket.col, (i, j) -> {
int om = cellBuckets[i][j].getMask();
if (Integer.bitCount(om) > 1) {
this.cellBuckets[i][j].setMask(om & (~mask));
}
});
}
void rcbTravel(int r, int c, BiConsumer<Integer, Integer> act) {
// 行
for (int i = 0; i < 9; i++) {
if (i == c) {
continue;
}
act.accept(r, i);
}
// 列
for (int i = 0; i < 9; i++) {
if (i == r) {
continue;
}
act.accept(i, c);
}
// 区块
for (int i = MIN_INDEX[r]; i <= MAX_INDEX[r]; i++) {
for (int j = MIN_INDEX[c]; j <= MAX_INDEX[c]; j++) {
if (i == r || j == c) {
continue;
}
act.accept(i, j);
}
}
}
CellMaskBucket pickCell() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
CellMaskBucket cs = cellBuckets[i][j];
if (Integer.bitCount(cs.getMask()) > 1) {
return cs;
}
}
}
return null;
}
boolean isValid() {
int rms, cms, re, ce, bms, be;
for (int i = 0; i < 9; i++) {
rms = cms = re = ce = bms = be = 0;
for (int j = 0; j < 9; j++) {
// 行
int rm = cellBuckets[i][j].getMask();
if (Integer.bitCount(rm) == 1) {
re += 1;
rms += rm;
if (Integer.bitCount(rms) != re) {
return false;
}
}
// 列
int cm = cellBuckets[j][i].getMask();
if (Integer.bitCount(cm) == 1) {
ce += 1;
cms += cm;
if (Integer.bitCount(cms) != ce) {
return false;
}
}
// block
int r = (i / 3) * 3 + (j / 3);
int c = (i % 3) * 3 + (j % 3);
int bm = cellBuckets[r][c].getMask();
if (Integer.bitCount(bm) == 1) {
be += 1;
bms += bm;
if (Integer.bitCount(bms) != be) {
return false;
}
}
}
}
return true;
}
public int getCellValue(int r, int c) {
int m = this.cellBuckets[r][c].getMask();
return toDecimal(m);
}
class CellMaskBucket {
private final int row, col;
private final int[] bucket = new int[81];
CellMaskBucket(int row, int col) {
this.row = row;
this.col = col;
}
void setMask(int v) {
bucket[depth] = v;
}
int getMask() {
return bucket[depth];
}
@Override
public String toString() {
return "(" + row + ", " + col + ")";
}
}
static int toDecimal(int mask) {
if (Integer.bitCount(mask) == 1) {
return Integer.numberOfTrailingZeros(mask << 1);
}
return 0;
}
static int toMask(int dec) {
return dec == 0 ? 0b111_111_111 : 1 << (dec - 1);
}
static int[] computeTrys(int m) {
int[] r = new int[Integer.bitCount(m)];
for (int i = 0; i < r.length; i++) {
int z = Integer.numberOfTrailingZeros(m);
r[i] = z + 1;
m >>= r[i];
m <<= r[i];
}
return r;
}
}
标签:pen java led NPU 维数 out arrays output stringbu
原文地址:https://www.cnblogs.com/realhyx/p/10354368.html