v.1.0.0 NDameModel setup
This commit is contained in:
22
apps/n-dame-problem/src/n-dame-backtracking.ts
Normal file
22
apps/n-dame-problem/src/n-dame-backtracking.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { NDameModel } from './n-dame-model';
|
||||
|
||||
export class NDameBacktracking {
|
||||
private model: NDameModel;
|
||||
|
||||
constructor(private readonly modelSize: number) {
|
||||
this.model = new NDameModel(modelSize);
|
||||
}
|
||||
|
||||
options = (): Array<number> => {
|
||||
// const optionsArray = Array.from(
|
||||
// { length: this.modelSize },
|
||||
// (value, index) => index,
|
||||
// );
|
||||
// wir können nur 1 Dame pro Feld platzieren !!!
|
||||
return [1];
|
||||
};
|
||||
|
||||
solved = (): boolean => {
|
||||
return this.model.solved();
|
||||
};
|
||||
}
|
||||
192
apps/n-dame-problem/src/n-dame-model.ts
Normal file
192
apps/n-dame-problem/src/n-dame-model.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import { IBacktracking } from '@app/backtracking-lib/backtracking.interface';
|
||||
import { MatrixPosition } from '@app/backtracking-lib/matrix-position';
|
||||
import { Logger } from '@nestjs/common';
|
||||
|
||||
enum EDiagonal {
|
||||
NW_SO = 1,
|
||||
NO_SW = -1,
|
||||
}
|
||||
|
||||
export class NDameModel implements IBacktracking {
|
||||
private readonly logger = new Logger(this.constructor.name);
|
||||
|
||||
private nDamesMatrix: boolean[][] = [];
|
||||
// Wert initial setzen, damit nextPosition beim ersten Schritt richtig platziert wird
|
||||
private modelPosition: MatrixPosition = new MatrixPosition(
|
||||
-1,
|
||||
this.modelSize - 1,
|
||||
);
|
||||
|
||||
constructor(private readonly modelSize: number) {
|
||||
this.initNDameField();
|
||||
}
|
||||
|
||||
private initNDameField() {
|
||||
for (var zeile = 0; zeile < this.modelSize; zeile++) {
|
||||
this.nDamesMatrix[zeile] = [];
|
||||
for (var spalte = 0; spalte < this.modelSize; spalte++) {
|
||||
this.nDamesMatrix[zeile].push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get matrix(): boolean[][] {
|
||||
return this.nDamesMatrix;
|
||||
}
|
||||
|
||||
// getter: Anzahl der gesetzten Damen
|
||||
private get dames(): number {
|
||||
const arrOfMatrix = this.nDamesMatrix.flat();
|
||||
const dames = arrOfMatrix.reduce((a, b: boolean) => (b ? a + 1 : a), 0);
|
||||
return dames;
|
||||
}
|
||||
|
||||
// sind alle N Damen auf dem Feld platziert ?
|
||||
public solved = (): boolean => {
|
||||
return this.dames == this.modelSize;
|
||||
};
|
||||
|
||||
options = (): Array<number> => {
|
||||
// wir können nur 1 Dame pro Feld platzieren !!!
|
||||
return [1];
|
||||
|
||||
// const optionsArray = Array.from(
|
||||
// { length: this.modelSize },
|
||||
// (value, index) => index,
|
||||
// );
|
||||
};
|
||||
|
||||
nextPosition = () => {
|
||||
this.modelPosition.col++;
|
||||
|
||||
if (this.modelPosition.col == this.modelSize) {
|
||||
this.modelPosition.row++;
|
||||
this.modelPosition.col = 0;
|
||||
}
|
||||
|
||||
if (this.modelPosition.row == this.modelSize)
|
||||
throw new Error(`model bounds crashed...\n${this.modelPosition}`);
|
||||
|
||||
return this.modelPosition;
|
||||
};
|
||||
|
||||
private rowProhibited = (): boolean => {
|
||||
const damesRow = this.nDamesMatrix[this.modelPosition.row];
|
||||
|
||||
// steht schon eine Dame in der selben Zeile ?
|
||||
const damesInRow = damesRow.reduce((acc, act) => (act ? ++acc : acc), 0);
|
||||
|
||||
if (damesInRow > 1)
|
||||
this.logger.error(`row occupied: ${this.modelPosition}`);
|
||||
|
||||
return damesInRow > 1;
|
||||
};
|
||||
|
||||
private colProhibited = (): boolean => {
|
||||
const damesCol = this.nDamesMatrix.reduce((acc, act) => {
|
||||
acc.push(act[this.modelPosition.col]);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
// steht schon eine Dame in der selben Spalte ?
|
||||
const damesInCol = damesCol.reduce((acc, act) => (act ? ++acc : acc), 0);
|
||||
|
||||
if (damesInCol > 1)
|
||||
this.logger.error(`col occupied: ${this.modelPosition}`);
|
||||
|
||||
return damesInCol > 1;
|
||||
};
|
||||
|
||||
private damesInDiagonal = (diagDirection: EDiagonal) => {
|
||||
this.logger.log(
|
||||
`diaginal ${diagDirection == EDiagonal.NW_SO ? 'NW_SO' : 'NO_SW'}`,
|
||||
);
|
||||
|
||||
// const startPos = { ...this.modelPosition };
|
||||
const startPos = new MatrixPosition(
|
||||
this.modelPosition.row,
|
||||
this.modelPosition.col,
|
||||
);
|
||||
const colSearchEndPos =
|
||||
diagDirection == EDiagonal.NW_SO ? 0 : this.modelSize - 1;
|
||||
|
||||
var found = false;
|
||||
|
||||
while (!found) {
|
||||
if (startPos.row == 0 || startPos.col == colSearchEndPos) found = true;
|
||||
else {
|
||||
--startPos.row;
|
||||
startPos.col += -diagDirection;
|
||||
}
|
||||
}
|
||||
|
||||
var diagReady = false;
|
||||
var diagPos = startPos;
|
||||
const diagCoords = [];
|
||||
const damesDiag = [];
|
||||
const colExitPos = diagDirection == EDiagonal.NW_SO ? this.modelSize : -1;
|
||||
while (!diagReady) {
|
||||
if (diagPos.row == this.modelSize || diagPos.col == colExitPos)
|
||||
diagReady = true;
|
||||
else {
|
||||
diagCoords.push(new MatrixPosition(diagPos.row, diagPos.col));
|
||||
damesDiag.push(this.nDamesMatrix[diagPos.row][diagPos.col]);
|
||||
++diagPos.row;
|
||||
diagPos.col += diagDirection;
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose(diagCoords.join());
|
||||
return damesDiag;
|
||||
};
|
||||
|
||||
private diagonalsProhibited = (): boolean => {
|
||||
const diagNW_SO = this.damesInDiagonal(EDiagonal.NW_SO);
|
||||
const diagNO_SW = this.damesInDiagonal(EDiagonal.NO_SW);
|
||||
|
||||
// steht schon eine Dame in der Diagonale NW_SO ?
|
||||
const damesInDiagonalNW_SO = diagNW_SO.reduce(
|
||||
(acc, act) => (act ? ++acc : acc),
|
||||
0,
|
||||
);
|
||||
|
||||
// steht schon eine Dame in der Diagonale NW_SO ?
|
||||
const damesInDiagonalNO_SW = diagNO_SW.reduce(
|
||||
(acc, act) => (act ? ++acc : acc),
|
||||
0,
|
||||
);
|
||||
|
||||
if (damesInDiagonalNW_SO > 1)
|
||||
this.logger.error(`diagNW_SO occupied: ${this.modelPosition}`);
|
||||
if (damesInDiagonalNO_SW > 1)
|
||||
this.logger.error(`diagNO_SW occupied: ${this.modelPosition}`);
|
||||
|
||||
return damesInDiagonalNW_SO > 1 || damesInDiagonalNO_SW > 1;
|
||||
};
|
||||
|
||||
// darf hier eine Dame stehen ?
|
||||
positionPossible = (): boolean => {
|
||||
const rp = this.rowProhibited();
|
||||
const cp = this.colProhibited();
|
||||
const dp = this.diagonalsProhibited();
|
||||
const positionOk = !rp && !cp && !dp;
|
||||
|
||||
if (positionOk)
|
||||
this.logger.log(`free: ${JSON.stringify(this.modelPosition)}`);
|
||||
|
||||
return positionOk;
|
||||
};
|
||||
|
||||
// Dame auf das Feld platzieren
|
||||
applyPosition = (): MatrixPosition => {
|
||||
this.logger.warn(`apply: ${JSON.stringify(this.modelPosition)}`);
|
||||
this.nDamesMatrix[this.modelPosition.row][this.modelPosition.col] = true;
|
||||
return this.modelPosition;
|
||||
};
|
||||
|
||||
// letzte Dame vom Feld nehmen
|
||||
discardPosition = (): MatrixPosition => {
|
||||
this.nDamesMatrix[this.modelPosition.row][this.modelPosition.col] = false;
|
||||
return this.modelPosition;
|
||||
};
|
||||
}
|
||||
@@ -1,12 +1,30 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import {
|
||||
Controller,
|
||||
DefaultValuePipe,
|
||||
Get,
|
||||
ParseIntPipe,
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { NDameProblemService } from './n-dame-problem.service';
|
||||
|
||||
@Controller()
|
||||
export class NDameProblemController {
|
||||
constructor(private readonly nDameProblemService: NDameProblemService) {}
|
||||
|
||||
@Get()
|
||||
@Get('/hello')
|
||||
getHello(): string {
|
||||
return this.nDameProblemService.getHello();
|
||||
}
|
||||
|
||||
@Get('/model')
|
||||
getModel(
|
||||
@Query('field', new DefaultValuePipe(-1), ParseIntPipe) field: number,
|
||||
): boolean[][] {
|
||||
return this.nDameProblemService.getModel(field);
|
||||
}
|
||||
|
||||
@Get('/backtracking')
|
||||
getBacktracking() {
|
||||
return this.nDameProblemService.getBacktracking();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,48 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { NDameModel } from './n-dame-model';
|
||||
import { NDameBacktracking } from './n-dame-backtracking';
|
||||
|
||||
@Injectable()
|
||||
export class NDameProblemService {
|
||||
private readonly logger = new Logger(this.constructor.name);
|
||||
private readonly MODEL_SIZE = 5;
|
||||
|
||||
getBacktracking(): NDameBacktracking {
|
||||
const backTracking = new NDameBacktracking(4);
|
||||
|
||||
this.logger.log(`${backTracking.options()}`);
|
||||
backTracking.solved();
|
||||
|
||||
return backTracking;
|
||||
}
|
||||
|
||||
getModel(field: number): boolean[][] {
|
||||
const model = new NDameModel(this.MODEL_SIZE);
|
||||
const modelFieldCount = this.MODEL_SIZE * this.MODEL_SIZE;
|
||||
const rndFields = [];
|
||||
|
||||
// geben wir keine FeldNr. an, dann die Zufallsreihe
|
||||
if (field === -1)
|
||||
for (var i = 0; i < this.MODEL_SIZE; i++)
|
||||
rndFields.push(Math.floor(Math.random() * modelFieldCount));
|
||||
else rndFields.push(field);
|
||||
|
||||
this.logger.fatal(`[${rndFields.toString()}]`);
|
||||
|
||||
for (var i = 0; i < modelFieldCount; i++) {
|
||||
const nxtPos = model.nextPosition();
|
||||
|
||||
if (rndFields.includes(i)) {
|
||||
model.applyPosition();
|
||||
model.positionPossible();
|
||||
}
|
||||
|
||||
// this.logger.verbose(`${i + 1} - ${JSON.stringify(nxtPos)}`);
|
||||
}
|
||||
|
||||
return model.matrix;
|
||||
}
|
||||
|
||||
getHello(): string {
|
||||
return 'Hello World!';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user