diff --git a/package.json b/package.json index 6430d66..f72dd16 100644 --- a/package.json +++ b/package.json @@ -1,48 +1,266 @@ { - "name": "module-starter", - "version": "0.0.1", - "description": "module template", - "main": "lib/src/index.js", - "exports": { - ".": { - "types": "./@types/index.d.ts", - "default": "./lib/src/index.js" - } - }, - "scripts": { - "build": "node ./esbuild.js", - "prepare": "rm -rf @types && npm run typecheck && npm run build-declarations && npm run build", - "pretest": "npm run build", - "test": "node test.cjs", - "lint": "eslint src", - "build-declarations": "tsc --emitDeclarationOnly", - "typecheck": "tsc --noemit", - "clean-coverage": "rm -rf coverage .nyc_output .xunit", - "coverage": "npm run clean-coverage && nyc mocha", - "test-reports": "npm run clean-coverage && nyc --reporter clover mocha --reporter xunit --reporter-option output=.xunit", - "coverage-html": "npm run test-reports && nyc report --reporter lcov && xdg-open coverage/lcov-report/index.html" - }, - "type": "module", - "author": "", - "license": "ISC", - "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.2", - "@types/mocha": "^10.0.1", - "@typescript-eslint/eslint-plugin": "^5.58.0", - "@typescript-eslint/parser": "^5.58.0", - "esbuild": "^0.14.10", - "eslint": "^8.38.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^5.4.0", - "eslint-plugin-with-tsc-error": "^0.0.8", - "mocha": "^10.2.0", - "mri": "^1.2.0", - "nyc": "^15.1.0", - "prettier": "^3.5.3", - "source-map-support": "^0.5.21", - "tiny-glob": "^0.2.9", - "ts-node": "^10.9.1", - "typescript": "^5.0.4" - }, - "types": "./@types/index.d.ts" + "name": "module-starter", + "version": "0.0.1", + "description": "module template", + "main": "lib/src/index.js", + "exports": { + ".": { + "types": "./@types/index.d.ts", + "default": "./lib/src/index.js" + } + }, + "scripts": { + "build": "node ./esbuild.js", + "prepare": "rm -rf @types && npm run typecheck && npm run build-declarations && npm run build", + "pretest": "npm run build", + "test": "node test.cjs", + "lint": "eslint src", + "build-declarations": "tsc --emitDeclarationOnly", + "typecheck": "tsc --noemit", + "clean-coverage": "rm -rf coverage .nyc_output .xunit", + "coverage": "npm run clean-coverage && nyc mocha", + "test-reports": "npm run clean-coverage && nyc --reporter clover mocha --reporter xunit --reporter-option output=.xunit", + "coverage-html": "npm run test-reports && nyc report --reporter lcov && xdg-open coverage/lcov-report/index.html" + }, + "type": "module", + "author": "", + "license": "ISC", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.2", + "@types/mocha": "^10.0.1", + "@typescript-eslint/eslint-plugin": "^5.58.0", + "@typescript-eslint/parser": "^5.58.0", + "esbuild": "^0.14.10", + "eslint": "^8.38.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^5.4.0", + "eslint-plugin-with-tsc-error": "^0.0.8", + "mocha": "^10.2.0", + "mri": "^1.2.0", + "nyc": "^15.1.0", + "prettier": "^3.5.3", + "source-map-support": "^0.5.21", + "tiny-glob": "^0.2.9", + "ts-node": "^10.9.1", + "typescript": "^5.0.4" + }, + "types": "./@types/index.d.ts", + "directories": { + "lib": "lib" + }, + "dependencies": { + "acorn": "^8.8.2", + "acorn-jsx": "^5.3.2", + "acorn-walk": "^8.2.0", + "aggregate-error": "^3.1.0", + "ajv": "^6.12.6", + "ansi-regex": "^5.0.1", + "ansi-styles": "^4.3.0", + "anymatch": "^3.1.3", + "append-transform": "^2.0.0", + "archy": "^1.0.0", + "arg": "^4.1.3", + "argparse": "^1.0.10", + "array-union": "^2.1.0", + "balanced-match": "^1.0.2", + "binary-extensions": "^2.2.0", + "brace-expansion": "^1.1.11", + "braces": "^3.0.2", + "browser-stdout": "^1.3.1", + "browserslist": "^4.21.5", + "buffer-from": "^1.1.2", + "caching-transform": "^4.0.0", + "callsites": "^3.1.0", + "camelcase": "^5.3.1", + "caniuse-lite": "^1.0.30001478", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "clean-stack": "^2.2.0", + "cliui": "^7.0.4", + "color-convert": "^2.0.1", + "color-name": "^1.1.4", + "commondir": "^1.0.1", + "compare-versions": "^3.6.0", + "concat-map": "^0.0.1", + "convert-source-map": "^1.9.0", + "create-require": "^1.1.1", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "decamelize": "^1.2.0", + "deep-is": "^0.1.4", + "default-require-extensions": "^3.0.1", + "diff": "^5.0.0", + "dir-glob": "^3.0.1", + "doctrine": "^3.0.0", + "electron-to-chromium": "^1.4.363", + "emoji-regex": "^8.0.0", + "es6-error": "^4.1.1", + "esbuild-linux-64": "^0.14.54", + "escalade": "^3.1.1", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^2.1.0", + "espree": "^9.5.1", + "esprima": "^4.0.1", + "esquery": "^1.5.0", + "esrecurse": "^4.3.0", + "estraverse": "^4.3.0", + "esutils": "^2.0.3", + "fast-deep-equal": "^3.1.3", + "fast-diff": "^1.2.0", + "fast-glob": "^3.2.12", + "fast-json-stable-stringify": "^2.1.0", + "fast-levenshtein": "^2.0.6", + "fastq": "^1.15.0", + "file-entry-cache": "^6.0.1", + "fill-range": "^7.0.1", + "find-cache-dir": "^3.3.2", + "find-up": "^5.0.0", + "flat": "^5.0.2", + "flat-cache": "^3.0.4", + "flatted": "^3.2.7", + "foreground-child": "^2.0.0", + "fromentries": "^1.3.2", + "fs.realpath": "^1.0.0", + "gensync": "^1.0.0-beta.2", + "get-caller-file": "^2.0.5", + "get-package-type": "^0.1.0", + "glob": "^7.2.0", + "glob-parent": "^5.1.2", + "globals": "^13.20.0", + "globalyzer": "^0.1.0", + "globby": "^11.1.0", + "globrex": "^0.1.2", + "graceful-fs": "^4.2.11", + "grapheme-splitter": "^1.0.4", + "has-flag": "^4.0.0", + "hasha": "^5.2.2", + "he": "^1.2.0", + "html-escaper": "^2.0.2", + "ignore": "^5.2.4", + "import-fresh": "^3.3.0", + "imurmurhash": "^0.1.4", + "indent-string": "^4.0.0", + "inflight": "^1.0.6", + "inherits": "^2.0.4", + "is-binary-path": "^2.1.0", + "is-extglob": "^2.1.1", + "is-fullwidth-code-point": "^3.0.0", + "is-glob": "^4.0.3", + "is-number": "^7.0.0", + "is-path-inside": "^3.0.3", + "is-plain-obj": "^2.1.0", + "is-stream": "^2.0.1", + "is-typedarray": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "is-windows": "^1.0.2", + "isexe": "^2.0.0", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-processinfo": "^2.0.3", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.1.5", + "js-sdsl": "^4.4.0", + "js-tokens": "^4.0.0", + "js-yaml": "^3.14.1", + "jsesc": "^2.5.2", + "json-schema-traverse": "^0.4.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "json5": "^2.2.3", + "levn": "^0.4.1", + "locate-path": "^6.0.0", + "lodash.flattendeep": "^4.4.0", + "lodash.merge": "^4.6.2", + "log-symbols": "^4.1.0", + "lru-cache": "^5.1.1", + "make-dir": "^3.1.0", + "make-error": "^1.3.6", + "merge2": "^1.4.1", + "micromatch": "^4.0.5", + "minimatch": "^3.1.2", + "ms": "^2.1.2", + "nanoid": "^3.3.3", + "natural-compare": "^1.4.0", + "natural-compare-lite": "^1.4.0", + "node-preload": "^0.2.1", + "node-releases": "^2.0.10", + "normalize-path": "^3.0.0", + "once": "^1.4.0", + "optionator": "^0.9.1", + "p-limit": "^3.1.0", + "p-locate": "^5.0.0", + "p-map": "^3.0.0", + "p-try": "^2.2.0", + "package-hash": "^4.0.0", + "parent-module": "^1.0.1", + "path-exists": "^4.0.0", + "path-is-absolute": "^1.0.1", + "path-key": "^3.1.1", + "path-type": "^4.0.0", + "picocolors": "^1.0.0", + "picomatch": "^2.3.1", + "pkg-dir": "^4.2.0", + "prelude-ls": "^1.2.1", + "prettier-linter-helpers": "^1.0.0", + "process-on-spawn": "^1.0.0", + "punycode": "^2.3.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readdirp": "^3.6.0", + "release-zalgo": "^1.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "resolve-from": "^4.0.0", + "reusify": "^1.0.4", + "rimraf": "^3.0.2", + "run-parallel": "^1.2.0", + "safe-buffer": "^5.2.1", + "semver": "^7.4.0", + "serialize-javascript": "^6.0.0", + "set-blocking": "^2.0.0", + "shebang-command": "^2.0.0", + "shebang-regex": "^3.0.0", + "signal-exit": "^3.0.7", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "spawn-wrap": "^2.0.0", + "sprintf-js": "^1.0.3", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "strip-bom": "^4.0.0", + "strip-json-comments": "^3.1.1", + "supports-color": "^7.2.0", + "synckit": "^0.11.6", + "test-exclude": "^6.0.0", + "text-table": "^0.2.0", + "to-fast-properties": "^2.0.0", + "to-regex-range": "^5.0.1", + "tslib": "^1.14.1", + "tsutils": "^3.21.0", + "type-check": "^0.4.0", + "type-fest": "^0.20.2", + "typedarray-to-buffer": "^3.1.5", + "update-browserslist-db": "^1.0.10", + "uri-js": "^4.4.1", + "uuid": "^8.3.2", + "v8-compile-cache-lib": "^3.0.1", + "which": "^2.0.2", + "which-module": "^2.0.0", + "word-wrap": "^1.2.3", + "workerpool": "^6.2.1", + "wrap-ansi": "^7.0.0", + "wrappy": "^1.0.2", + "write-file-atomic": "^3.0.3", + "y18n": "^5.0.8", + "yallist": "^3.1.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.4", + "yargs-unparser": "^2.0.0", + "yn": "^3.1.1", + "yocto-queue": "^0.1.0" + }, + "keywords": [] } diff --git a/src/example.test.ts b/src/example.test.ts index 72ecaee..e69de29 100644 --- a/src/example.test.ts +++ b/src/example.test.ts @@ -1,11 +0,0 @@ -import { Example } from "src/index.js"; -import * as assert from "assert"; - -describe("Example", () => { - describe("example", () => { - it("should equal 'example'", () => { - const example = new Example(); - assert.equal(example.example(), "example"); - }); - }); -}); diff --git a/src/index.ts b/src/index.ts index dbf6a19..182fe3d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,185 @@ -export class Example { - example(): string { - return "example"; +import { getSubsets } from "./subsets.js"; + +abstract class Var { + public name: string; + + abstract getValue(): boolean | null; + + abstract hasValue(): boolean; + + abstract getCoreVar(): Var; +} + +class BoolVar extends Var { + private value: boolean | null = null; + private has_value = false; + + constructor(name: string) { + super(); + this.name = name; + } + + getValue() { + return this.value; + } + + hasValue() { + return this.has_value; + } + + setValue(value: boolean) { + this.value = value; + this.has_value = true; + } + + getCoreVar(): Var { + return this; + } + + toString() { + if (!this.hasValue()) { + return this.name.replaceAll("~~", ""); + } + return this.getValue() ? "1" : "0"; + } +} + +class NotVar extends BoolVar { + constructor(public boolvar: BoolVar) { + super("~" + boolvar.name); + } + + getValue() { + if (!this.boolvar.hasValue()) { + return null; + } + return !this.boolvar.getValue(); + } + + hasValue() { + return this.boolvar.hasValue(); + } + + setValue(value: boolean) { + this.boolvar.setValue(value); + } + + getCoreVar() { + return this.boolvar.getCoreVar(); + } +} + +class Or { + constructor(private vars: Var[]) {} + + getVars() { + return this.vars; + } + + valueIsKnown() { + return this.getVars().every((v) => v.hasValue()); + } + + isTrue() { + const result = this.getVars().some( + (variable) => variable.hasValue() && variable.getValue() + ); + return result; + } + + isFalse() { + return !this.isTrue(); + } + + toString() { + return `(${this.vars.map((e) => e.toString()).join(" v ")})`; + } +} + +// TODO: This is totally wrong +function And(...vars: BoolVar[]): Or[] { + const all_subsets = getSubsets(vars).slice(1); + return all_subsets + .filter((s) => s.length > 0) + .map( + (subset) => + new Or( + vars.map((v) => (subset.includes(v) ? v : new NotVar(v))) + ) + ); +} + +class CNF { + ors: Or[]; + constructor(...ors: Or[]) { + this.ors = ors; + } + + getVars() { + return this.ors.map((or) => or.getVars()).flat(); + } + + getCoreVars() { + return Array.from( + new Set(this.getVars().map((v) => v.getCoreVar())).values() + ); + } + + valueIsKnown() { + return ( + this.ors.some((or) => or.valueIsKnown() && or.isFalse()) || + this.ors.every((or) => or.valueIsKnown()) + ); + } + + getValue() { + if (!this.valueIsKnown()) { + throw new Error("Value is not yet known"); + } + for (const or of this.ors) { + if (or.isFalse()) { + return false; + } + } + return true; + } + + toString() { + return this.ors.map((or) => or.toString()).join(" & "); + } + + printAnswers() { + return this.getCoreVars() + .filter((v) => v.hasValue()) + .map((v) => `${v.name}: ${v.getValue()}`) + .join(", "); + } + + printState() { + console.log(this.printAnswers()); + console.log("Value is known?", this.valueIsKnown()); + if (this.valueIsKnown()) { + console.log("The result is", this.getValue()); + } } } + +const is_poznan = new BoolVar("is_poznan"); +const is_droga_wojewodzka = new BoolVar("is_droga_wojewodzka"); +const is_droga_powiatowa = new BoolVar("is_droga_powiatowa"); +const is_less_than_6m = new BoolVar("is_less_than_6m"); +const is_less_than_8m = new BoolVar("is_less_than_8m"); +const is_ekran = new BoolVar("is_ekran"); + +const is_legal = new CNF( + ...And(is_droga_wojewodzka, new NotVar(is_less_than_8m)), + ...And(is_droga_powiatowa, new NotVar(is_less_than_6m)), + ...And(is_poznan, new NotVar(is_ekran)) +); + +is_poznan.setValue(true); +is_ekran.setValue(false); +is_droga_wojewodzka.setValue(true); +is_less_than_8m.setValue(true); +console.log(is_legal.toString()); +is_legal.printState(); diff --git a/src/subsets.ts b/src/subsets.ts new file mode 100644 index 0000000..2d6c017 --- /dev/null +++ b/src/subsets.ts @@ -0,0 +1,10 @@ +export function getSubsets(arr: T[]) { + const subsets = [[]] as T[][]; // start with empty set + + for (const element of arr) { + const newSubsets = subsets.map((subset) => [...subset, element]); + subsets.push(...newSubsets); + } + + return subsets; +}