UNPKG

grilops

Version:

A Grid Logic Puzzle Solver library, using Typescript and z3.

1,177 lines (1,114 loc) 47.4 kB
import { AnySort } from 'z3-solver'; import { Arith } from 'z3-solver'; import { Bool } from 'z3-solver'; import { Context } from 'z3-solver'; import { Expr } from 'z3-solver'; import { Optimize } from 'z3-solver'; import { Solver } from 'z3-solver'; import { Z3LowLevel } from 'z3-solver'; export declare function combinations<T>(choices: T[], length: number): Generator<T[]>; export declare type Constructor<T extends abstract new (...args: any) => any> = new (...args: ConstructorParameters<T>) => T; /** * Returns a count of cells along a sightline through a grid. * @param context The context in which to construct the constraints. * @param symbolGrid The grid to check against. * @param start The location of the cell where the sightline should begin. * This is the first cell checked. * @param direction The direction to advance to reach the next cell in the * sightline. * @param count A function that accepts a symbol as an argument and returns the * integer value to add to the count when this symbol is encountered. By * default, each symbol will count with a value of one. * @param stop A function that accepts a symbol as an argument and returns True * if we should stop following the sightline when this symbol is * encountered. By default, the sightline will continue to the edge of the * grid. * @returns An `Arith` for the count of cells along the sightline through the * grid. */ export declare function countCells<Name extends string>(context: GrilopsContext<Name>, symbolGrid: SymbolGrid<Name>, start: Point, direction: Direction, count?: (c: Arith<Name>) => Arith<Name>, stop?: (c: Arith<Name>) => Bool<Name>): Arith<Name>; export declare function createDefualtMap<T>(base: KeyedMapConstructor<T>): DefaultKeyedMapConstructor<T>; export declare function createDefualtMap(base: MapConstructor): DefaultMapConstructor; export declare function createStringMap<T, Key extends string>(toString: (item: T) => Key, fromString: (key: Key) => T): KeyedMapConstructor<T>; export declare function createStringSet<T, Key extends string>(toString: (item: T) => Key, fromString: (key: Key) => T): KeyedSetConstructor<T>; export declare const DefaultDirectionMap: DefaultKeyedMapConstructor<Direction>; export declare interface DefaultKeyedMapConstructor<T> extends DefaultMapConstructor, KeyedMapConstructor<T> { new <V>(defaultFunc: () => V, entries?: readonly (readonly [T, V])[] | null): DefaultMap<T, V>; readonly prototype: DefaultMap<T, any>; } export declare interface DefaultMap<K, V> extends Map<K, V> { get(key: K): V; } export declare interface DefaultMapConstructor { new <K, V>(defaultFunc: () => V, entries?: readonly (readonly [K, V])[] | null): DefaultMap<K, V>; readonly prototype: DefaultMap<any, any>; } export declare const DefaultPointMap: DefaultKeyedMapConstructor<Point>; export declare const DefaultVectorMap: DefaultKeyedMapConstructor<Vector>; /** * A named direction vector that offsets by one space in the grid. */ export declare class Direction { /** * The name of the direction. */ name: DirectionKey; /** * The vector of the direction. */ vector: Vector; constructor(name: DirectionKey, vector: Vector); toString(): DirectionString; static fromString(s: DirectionString): Direction; } export declare type DirectionKey = 'N' | 'S' | 'E' | 'W' | 'NE' | 'NW' | 'SE' | 'SW'; export declare const DirectionMap: KeyedMapConstructor<Direction>; export declare const DirectionSet: KeyedSetConstructor<Direction>; export declare type DirectionString = `D(${DirectionKey},${VectorString})`; /** * A quadtree for caching and aggregating z3 expressions. * * This class builds a quadtree data structure from a list of points, and * provides the ability to lazily construct and cache z3 expressions that * reference these points. */ export declare class ExpressionQuadTree<Name extends string, ExprKey extends string | number | symbol> { readonly ctx: GrilopsContext<Name>; private _exprs; private _exprFuncs; private _point; private _yMin; private _yMax; private _xMin; private _xMax; private _yMid; private _xMid; private _tl; private _tr; private _bl; private _br; private _quads; constructor(context: GrilopsContext<Name>, points: Point[], exprFuncs?: ExprFuncMap<Name, ExprKey> | undefined); /** * Returns true if the given point is within this tree node's bounds. */ coversPoint(p: Point): boolean; /** * Registers an expression constructor, to be called for each point. */ addExpr(key: ExprKey, exprFunc: (point: Point) => Bool<Name>): void; /** * Returns expressions for all points covered by this tree node. */ getExprs(key: ExprKey): Bool<Name>[]; /** * Returns the expression for the given point. */ getPointExpr(key: ExprKey, p: Point): Bool<Name>; /** * Returns the conjunction of all expressions, excluding given points. */ getOtherPointsExpr(key: ExprKey, points: Point[]): Bool<Name> | undefined; } export declare type ExprFuncMap<Name extends string, ExprKey> = Map<ExprKey, (point: Point) => Bool<Name>>; /** * A set of points forming a flat-topped hexagonal lattice. * * All points must lie on a hexagonal lattice in which each hexagon has * a flat top. We use the doubled coordinates scheme described at * https://www.redblobgames.com/grids/hexagons/. That is, y describes * the row and x describes the column, so hexagons that are vertically * adjacent have their y coordinates differ by 2. */ export declare class FlatToppedHexagonalLattice extends HexagonalLattice { static DIRECTIONS: { N: Direction; S: Direction; NE: Direction; NW: Direction; SE: Direction; SW: Direction; }; edgeSharingDirections(): Direction[]; transformationFunctions(allowRotations: boolean, allowReflections: boolean): ((vector: Vector) => Vector)[]; getInsideOutsideCheckDirections(): [Direction, Direction[]]; } declare namespace geometry { export { getRectangleLattice, getSquareLattice, VectorString, Vector, VectorMap, VectorSet, DefaultVectorMap, DirectionKey, DirectionString, Direction, DirectionMap, DirectionSet, DefaultDirectionMap, PointString, Point, PointMap, PointSet, DefaultPointMap, HookFunction, Neighbor, Lattice, RectangularLattice, HexagonalLattice, FlatToppedHexagonalLattice, PointyToppedHexagonalLattice } } /** * Returns a lattice of all points in a rectangle of the given dimensions. * @param height Height of the lattice. * @param width Width of the lattice. * @returns The lattice. */ export declare function getRectangleLattice(height: number, width: number): RectangularLattice; /** * Returns a lattice of all points in a square of the given height. * @param height Height of the lattice. * @returns The lattice. */ export declare function getSquareLattice(height: number): RectangularLattice; export declare function grilops<Name extends string>(context: GrilopsContext<Name>): { PathSymbolSet: typeof paths.PathSymbolSet; PathConstrainer: typeof paths.PathConstrainer; RegionConstrainer: new <const Core extends Solver<Name> | Optimize<Name> = Solver<Name> | Optimize<Name>>(lattice: geometry.Lattice, solver: Core | undefined, complete?: boolean | undefined, rectangular?: boolean | undefined, minRegionSize?: number | undefined, maxRegionSize?: number | undefined) => RegionConstrainer<Name, Core>; Shape: new <Payload extends Expr<Name, AnySort<Name>, unknown>>(offsets: Offset<Name, Payload>[]) => Shape<Name, Payload>; ShapeConstrainer: new <Payload_1 extends Expr<Name, AnySort<Name>, unknown>, const Core_1 extends Solver<Name> | Optimize<Name> = Solver<Name> | Optimize<Name>>(lattice: geometry.Lattice, shapes: Shape<Name, Payload_1>[], solver: Core_1 | undefined, complete: boolean, allowRotations: boolean, allowReflections: boolean, allowCopies: boolean) => ShapeConstrainer<Name, Payload_1, Core_1>; reduceCells: <Accumulator extends Arith<Name>>(symbolGrid: SymbolGrid<Name, Solver<Name> | Optimize<Name>>, start: geometry.Point, direction: geometry.Direction, initializer: Accumulator, accumulate: (a: Accumulator, c: Arith<Name>, p: geometry.Point) => Accumulator, stop?: (a: Accumulator, c: Arith<Name>, p: geometry.Point) => Bool<Name>) => Accumulator; countCells: (symbolGrid: SymbolGrid<Name, Solver<Name> | Optimize<Name>>, start: geometry.Point, direction: geometry.Direction, count?: (c: Arith<Name>) => Arith<Name>, stop?: (c: Arith<Name>) => Bool<Name>) => Arith<Name>; makeLetterRangeSymbolSet(minLetter: string, maxLetter: string): symbols.SymbolSet; makeNumberRangeSymbolSet(minNumber: number, maxNumber: number): symbols.SymbolSet; Symbol: typeof symbols.Symbol; SymbolSet: typeof symbols.SymbolSet; ExpressionQuadTree: new <ExprKey extends string | number | symbol>(points: geometry.Point[], exprFuncs?: ExprFuncMap<Name, ExprKey> | undefined) => ExpressionQuadTree<Name, ExprKey>; SymbolGrid: new <Core_2 extends Solver<Name> | Optimize<Name> = Solver<Name>>(lattice: geometry.Lattice, symbolSet: symbols.SymbolSet, solver?: Core_2 | undefined) => SymbolGrid<Name, Core_2>; getRectangleLattice(height: number, width: number): geometry.RectangularLattice; getSquareLattice(height: number): geometry.RectangularLattice; Vector: typeof geometry.Vector; VectorMap: KeyedMapConstructor<geometry.Vector>; VectorSet: KeyedSetConstructor<geometry.Vector>; DefaultVectorMap: DefaultKeyedMapConstructor<geometry.Vector>; Direction: typeof geometry.Direction; DirectionMap: KeyedMapConstructor<geometry.Direction>; DirectionSet: KeyedSetConstructor<geometry.Direction>; DefaultDirectionMap: DefaultKeyedMapConstructor<geometry.Direction>; Point: typeof geometry.Point; PointMap: KeyedMapConstructor<geometry.Point>; PointSet: KeyedSetConstructor<geometry.Point>; DefaultPointMap: DefaultKeyedMapConstructor<geometry.Point>; Neighbor: typeof geometry.Neighbor; Lattice: typeof geometry.Lattice; RectangularLattice: typeof geometry.RectangularLattice; HexagonalLattice: typeof geometry.HexagonalLattice; FlatToppedHexagonalLattice: typeof geometry.FlatToppedHexagonalLattice; PointyToppedHexagonalLattice: typeof geometry.PointyToppedHexagonalLattice; }; export declare interface GrilopsContext<Name extends string> { z3: Z3LowLevel['Z3']; context: Context<Name>; } export declare abstract class HexagonalLattice extends Lattice { private _points; private _pointIndices; private static _DIRECTION_LABELS; /** * A set of points forming a hexagonal lattice. * * This abstract class implements functions identical between * FlatToppedHexagonalLattice and PointyToppedHexagonalLattice. * * We use the doubled coordinates scheme described at * https://www.redblobgames.com/grids/hexagons/. That is, y describes * the row and x describes the column, so x + y is always even. */ constructor(points: Point[]); get points(): Point[]; pointToIndex(point: Point): number | undefined; vertexSharingDirections(): Direction[]; labelForDirection(direction: Direction): string; labelForDirectionPair(dir1: Direction, dir2: Direction): string; } export declare type HookFunction = (point: Point) => string | undefined; export declare interface KeyedMapConstructor<T> extends MapConstructor { new (): Map<T, any>; new <V>(entries?: readonly (readonly [T, V])[] | null): Map<T, V>; readonly prototype: Map<T, any>; readonly [KeyedMapContructorSymbol]?: undefined; } declare const KeyedMapContructorSymbol: unique symbol; export declare interface KeyedSetConstructor<T> { new (values?: readonly T[] | null): Set<T>; readonly prototype: Set<any>; } /** * A base class for defining the structure of a grid. */ export declare abstract class Lattice { private _vectorDirection; constructor(); /** * The points in the lattice, sorted. */ abstract get points(): Point[]; /** * Returns the index of a point in the lattice's ordered list. * @param point The `Point` to get the index of. * @returns The index of the point in the ordered list, or None if the point * is not in the list. */ abstract pointToIndex(point: Point): number | undefined; /** * A list of edge-sharing directions. * @returns A list of `Direction`s, each including the name of an edge-sharing * direction and the vector representing that direction. Edge sharing (also * known as orthogonal adjacency) is the relationship between grid cells * that share an edge. */ abstract edgeSharingDirections(): Direction[]; /** * A list of vertex-sharing directions. * @returns A list of `Direction`s, each including the name of a * vertex-sharing direction and the vector representing that * direction. Vertex sharing (also known as touching adjacency) is the * relationship between grid cells that share a vertex. */ abstract vertexSharingDirections(): Direction[]; /** * Given a direction, return the opposite direction. * @param direction The given `Direction`. * @returns The `Direction` opposite the given direction. */ oppositeDirection(direction: Direction): Direction; /** * Returns a list of points that share an edge with the given cell. * @param point The point of the given cell. * @returns A list of `Point`s in the lattice that correspond to cells that * share an edge with the given cell. */ edgeSharingPoints(point: Point): Point[]; /** * Returns a list of points that share a vertex with the given cell. * @param point The point of the given cell. * @returns A list of `Point`s in the lattice corresponding to cells that * share a vertex with the given cell. */ vertexSharingPoints(point: Point): Point[]; /** * Returns a list of neighbors in the given directions of the given cell. * @param cellMap A dictionary mapping points in the lattice to z3 constants. * @param p Point of the given cell. * @param directions The given list of directions to find neighbors with. * @returns A list of `Neighbor`s corresponding to the cells that are in the * given directions from the given cell. */ private static _getNeighbors; /** * Returns a list of neighbors sharing an edge with the given cell. * @param cellMap A dictionary mapping points in the lattice to z3 constants. * @param p Point of the given cell. * @returns A list of `Neighbor`s corresponding to the cells that share an * edge with the given cell. */ edgeSharingNeighbors<Name extends string>(cellMap: Map<Point, Arith<Name>>, p: Point): Neighbor<Name>[]; /** * Returns a list of neighbors sharing a vertex with the given cell. * @param cellMap A dictionary mapping points in the lattice to z3 constants. * @param p Point of the given cell. * @returns A list of `Neighbor`s corresponding to the cells that share a * vertex with the given cell. */ vertexSharingNeighbors<Name extends string>(cellMap: Map<Point, Arith<Name>>, p: Point): Neighbor<Name>[]; /** * Returns the label for a direction. * @param direction The direction to label. * @returns A label representing the direction. * @throws An error if there's no character defined for the direction. */ abstract labelForDirection(direction: Direction): string; /** * Returns the label for a pair of edge-sharing directions. * @param dir1 The first direction. * @param dir2 The second direction. * @returns A label representing both directions. * @throws An error if there's no character defined for the direction pair. */ abstract labelForDirectionPair(dir1: Direction, dir2: Direction): string; /** * Returns a list of `Vector` transformations. * * Each returned transformation is a function that transforms a * `Vector` into a `Vector`. The returned list always contains at least * one transformation: the identity function. The transformations * returned are all transformations satisfying the given constraints. * * @param allowRotations Whether rotation is an allowed transformation. * @param allowReflections Whether reflection is an allowed transformation. * @returns A list of `Vector` transformation functions. */ abstract transformationFunctions(allowRotations: boolean, allowReflections: boolean): ((vector: Vector) => Vector)[]; /** * Returns directions for use in a loop inside-outside check. * * The first direction returned is the direction to look, and the * remaining directions are the directions to check for crossings. * * For instance, on a rectangular grid, a valid return value would * be (north, [west]). This means that if you look north and count how many * west-going lines you cross, you can tell from its parity if you're inside * or outside the loop. * * @returns A tuple, the first component of which indicates the direction to * look, and the second component of which indicates what types of crossings * to count. */ abstract getInsideOutsideCheckDirections(): [Direction, Direction[]]; /** * Prints something for each of the given points. * @param hookFunction A function implementing per-location display * behavior. It will be called for each `Point` in the lattice. If the * returned string has embedded newlines, it will be treated as a multi-line * element. For best results, all elements should have the same number of * lines as each other and as blank (below). * @param ps The `Point`s to print something for. * @param blank What to print for `Point`s not in the lattice, or for when * the hook function returns None. Defaults to one space. If it has * embedded newlines, it will be treated as a multi-line element. */ private _pointsToString; /** * Prints something for each space in the lattice. * * Printing is done from top to bottom and left to right. * * @param hookFunction A function implementing per-location display * behavior. It will be called for each `Point` in the lattice. If the * returned string has embedded newlines, it will be treated as a multi-line * element. For best results, all elements should have the same number of * lines as each other and as blank (below). * @param blank What to print for `Point`s not in the lattice, or for when * the hook function returns None. Defaults to one space. If it has * embedded newlines, it will be treated as a multi-line element. */ toString(hookFunction: HookFunction, blank?: string): string; } /** * Returns a `SymbolSet` consisting of consecutive letters. * @param minLetter The lowest letter to include in the set. * @param maxLetter The highest letter to include in the set. * @returns A `SymbolSet` consisting of consecutive letters. */ export declare function makeLetterRangeSymbolSet(minLetter: string, maxLetter: string): SymbolSet; /** * Returns a `SymbolSet` consisting of consecutive numbers. * * The names of the symbols will be prefixed with S to be consistent with the * Python implementation. * * @param minNumber The lowest number to include in the set. * @param maxNumber The highest number to include in the set. * @returns A `SymbolSet` consisting of consecutive numbers. */ export declare function makeNumberRangeSymbolSet(minNumber: number, maxNumber: number): SymbolSet; /** * Properties of a cell that is a neighbor of another. */ export declare class Neighbor<Name extends string> { /** * The location of the cell. */ location: Point; /** * The direction from the original cell. */ direction: Direction; /** * The symbol constant of the cell. */ symbol: Arith<Name>; constructor(location: Point, direction: Direction, symbol: Arith<Name>); } export declare type Offset<Name extends string, Payload extends Expr<Name>> = Vector | [Vector, Payload?]; /** * Creates constraints for ensuring symbols form connected paths. */ export declare class PathConstrainer<Name extends string> { private static _instanceIndex; private readonly _symbolGrid; private readonly _complete; private readonly _allowTerminatedPaths; private readonly _allowLoops; private readonly _pathInstanceGrid; private readonly _pathOrderGrid; private _numPaths; /** * @param symbolGrid The grid to constrain. * @param complete If true, every cell must be part of a path. Defaults to * false. * @param allowTerminatedPaths If true, finds paths that are terminated * (not loops). Defaults to true. * @param allowLoops If true, finds paths that are loops. Defaults to true. */ constructor(symbolGrid: SymbolGrid<Name>, complete?: boolean, allowTerminatedPaths?: boolean, allowLoops?: boolean); private _addPathEdgeConstraints; private _addPathInstanceGridConstraints; private _allDirectionPairs; private _addPathOrderGridConstraints; private _addAllowTerminatedPathsConstraints; /** * A constant representing the number of distinct paths found. */ get numPaths(): Arith<Name>; /** * Constants of path instance identification. * * Each separate path will have a distinct instance number. The instance number * is -1 if the cell does not contain a path segment or terminal. */ get pathInstanceGrid(): Map<Point, Arith<Name>>; /** * Constants of path traversal orders. * * Each segment or terminal of a path will have a distinct order number. The * order number is -1 if the cell does not contain a path segment or terminal. */ get pathOrderGrid(): Map<Point, Arith<Name>>; /** * Prints the path instance and order for each path cell. * * Should be called only after the solver has been checked. */ pathNumberingToString(): string; } declare namespace paths { export { PathSymbolSet, PathConstrainer } } /** * A `SymbolSet` consisting of symbols that may form paths. * * Additional symbols (e.g. a `Symbol` representing an empty * space) may be added to this `SymbolSet` by calling * `SymbolSet.append` after it's constructed. */ export declare class PathSymbolSet extends SymbolSet { private readonly _includeTerminals; private readonly _symbolsForDirection; private readonly _symbolForDirectionPair; private readonly _terminalForDirection; private _maxPathSegmentSymbolIndex; private _maxPathTerminalSymbolIndex; /** * @param lattice The structure of the grid. * @param includeTerminals If true, create symbols for path terminals. * Defaults to true. */ constructor(lattice: Lattice, includeTerminals?: boolean); /** * Returns true if the given symbol represents part of a path. * @param symbol An `Arith` expression representing a symbol. * @returns A true `Bool` if the symbol represents part of a path. */ isPath<Name extends string>(symbol: Arith<Name>): Bool<Name>; /** * Returns true if the given symbol represents a non-terminal path segment. * @param symbol An `Arith` expression representing a symbol. * @returns A true `Bool` if the symbol represents a non-terminal path segment. */ isPathSegment<Name extends string>(symbol: Arith<Name>): Bool<Name>; /** * Returns true if the given symbol represents a path terminal. * @param symbol An `Arith` expression representing a symbol. * @returns A true `Bool` if the symbol represents a path terminal. */ isTerminal<Name extends string>(symbol: Arith<Name>): Bool<Name>; /** * Returns the symbols with one arm going in the given direction. * @param d The given direction. * @returns A `number[]` of symbol indices corresponding to symbols with one * arm going in the given direction. */ symbolsForDirection(d: Direction): number[]; /** * Returns the symbol with arms going in the two given directions. * @param d1 The first given direction. * @param d2 The second given direction. * @returns The symbol index for the symbol with one arm going in each of the * two given directions. */ symbolForDirectionPair(d1: Direction, d2: Direction): number; /** * Returns the symbol that terminates the path from the given direction. * @param d The given direction. * @returns The symbol index for the symbol that terminates the path from the * given direction. */ terminalForDirection(d: Direction): number | undefined; } /** * A point, generally corresponding to the center of a grid cell. */ export declare class Point { /** * The location in the y dimension. */ y: number; /** * The location in the x dimension. */ x: number; constructor(y: number, x: number); /** * Translates this point by the given `Vector` or `Direction`. */ translate(other: Vector | Direction): Point; toString(): PointString; static fromString(s: PointString): Point; equals(other: Point): boolean; static comparator(a: Point, b: Point): number; } export declare const PointMap: KeyedMapConstructor<Point>; export declare const PointSet: KeyedSetConstructor<Point>; export declare type PointString = `P(${string},${string})`; /** * A set of points forming a pointy-topped hexagonal lattice. * * All points must lie on a hexagonal lattice in which each hexagon has * a pointy top. We use the doubled coordinates scheme described at * https://www.redblobgames.com/grids/hexagons/. That is, y describes * the row and x describes the column, so hexagons that are horizontally * adjacent have their x coordinates differ by 2. */ export declare class PointyToppedHexagonalLattice extends HexagonalLattice { static DIRECTIONS: { E: Direction; W: Direction; NE: Direction; NW: Direction; SE: Direction; SW: Direction; }; edgeSharingDirections(): Direction[]; transformationFunctions(allowRotations: boolean, allowReflections: boolean): ((vector: Vector) => Vector)[]; getInsideOutsideCheckDirections(): [Direction, Direction[]]; } export declare class RectangularLattice extends Lattice { private _points; private _pointIndices; static EDGE_DIRECTIONS: { N: Direction; S: Direction; E: Direction; W: Direction; }; static VERTEX_DIRECTIONS: { NE: Direction; NW: Direction; SE: Direction; SW: Direction; N: Direction; S: Direction; E: Direction; W: Direction; }; /** * @param points A set of points corresponding to a rectangular lattice. * Note that these points need not fill a complete rectangle. */ constructor(points: Point[]); get points(): Point[]; pointToIndex(point: Point): number | undefined; edgeSharingDirections(): Direction[]; vertexSharingDirections(): Direction[]; labelForDirection(direction: Direction): string; labelForDirectionPair(dir1: Direction, dir2: Direction): string; transformationFunctions(allowRotations: boolean, allowReflections: boolean): ((vector: Vector) => Vector)[]; getInsideOutsideCheckDirections(): [Direction, Direction[]]; } /** * Returns a computation of a sightline through a grid. * @param context The context in which to construct the constraints. * @param symbolGrid The grid to check against. * @param start The location of the cell where the sightline should begin. * This is the first cell checked. * @param direction The direction to advance to reach the next cell in the * sightline. * @param initializer The initial value for the accumulator. * @param accumulate A function that accepts an accumulated value, a symbol, * and (optionally) a point as arguments, and returns a new accumulated * value. This function is used to determine a new accumulated value for * each cell along the sightline, based on the accumulated value from the * previously encountered cells as well as the point and/or symbol of the * current cell. * @param stop A function that accepts an accumulated value, a symbol, and * (optionally) a point as arguments, and returns True if we should stop * following the sightline when this symbol or point is encountered. By * default, the sightline will continue to the edge of the grid. * @returns The accumulated value. */ export declare function reduceCells<Name extends string, Accumulator extends Arith<Name>>(context: GrilopsContext<Name>, symbolGrid: SymbolGrid<Name>, start: Point, direction: Direction, initializer: Accumulator, accumulate: (a: Accumulator, c: Arith<Name>, p: Point) => Accumulator, stop?: (a: Accumulator, c: Arith<Name>, p: Point) => Bool<Name>): Accumulator; /** * Creates constraints for grouping cells into contiguous regions. */ export declare class RegionConstrainer<Name extends string, const Core extends Solver<Name> | Optimize<Name> = Solver<Name> | Optimize<Name>> { private static _instanceIndex; readonly ctx: GrilopsContext<Name>; private readonly _solver; private readonly _lattice; private readonly _complete; private readonly _minRegionSize; private readonly _maxRegionSize; private _edgeSharingDirectionToIndex; private _parentTypeToIndex; private _parentTypes; private _parentGrid; private _subtreeSizeGrid; private _regionIdGrid; private _regionSizeGrid; /** * @param lattice The structure of the grid. * @param solver A `Solver` object. If None, a `Solver` will be constructed. * @param complete If true, every cell must be part of a region. Defaults to * true. * @param rectangular If true, every region must be "rectangular"; for each * cell in a region, ensure that pairs of its neighbors that are part of * the same region each share an additional neighbor that's part of the * same region when possible. * @param minRegionSize The minimum possible size of a region. * @param maxRegionSize The maximum possible size of a region. */ constructor(context: GrilopsContext<Name>, lattice: Lattice, solver?: Core | undefined, complete?: boolean, rectangular?: boolean, minRegionSize?: number | undefined, maxRegionSize?: number | undefined); /** * Creates the structures used for managing edge-sharing directions. * * Creates the mapping between edge-sharing directions and the parent * indices corresponding to them. */ private _manageEdgeSharingDirections; /** * Create the grids used to model region constraints. */ private _createGrids; /** * Add constraints to the region modeling grids. */ private _addConstraints; private _addRectangularConstraints; /** * Returns the `RegionConstrainer.parent_grid` value for the direction. * * For instance, if direction is (-1, 0), return the index for N. * * @param direction The direction to an edge-sharing cell. * @returns The `RegionConstrainer.parent_grid` value that means that the * parent in its region's subtree is the cell offset by that direction. */ edgeSharingDirectionToIndex(direction: Direction): number; /** * Returns the `RegionConstrainer.parent_grid` value for the parent type. * * The parent_type may be a direction name (like "N") or name of a special * value like "R" or "X". * * @param parentType The parent type. * @returns The corresponding `RegionConstrainer.parent_grid` value. */ parentTypeToIndex(parentType: string): number; /** * The `Solver` associated with this `RegionConstrainer`. */ get solver(): Core; /** * A dictionary of numbers identifying regions. * * A region's identifier is the position in the grid (going in order from left * to right, top to bottom) of the root of that region's subtree. It is the * same as the index of the point in the lattice. */ get regionIdGrid(): Map<Point, Arith<Name>>; /** * A dictionary of region sizes. */ get regionSizeGrid(): Map<Point, Arith<Name>>; /** * A dictionary of region subtree parent pointers. */ get parentGrid(): Map<Point, Arith<Name>>; /** * A dictionary of cell subtree sizes. * * A cell's subtree size is one plus the number of cells that are descendents * of the cell in its region's subtree. */ get subtreeSizeGrid(): Map<Point, Arith<Name>>; /** * Prints the region parent assigned to each cell. * * Should be called only after the solver has been checked. */ treesToString(): string; /** * Prints the region subtree size of each cell. * * Should be called only after the solver has been checked. */ subtreeSizesToString(): string; /** * Prints a number identifying the region that owns each cell. * * Should be called only after the solver has been checked. */ regionIdsToString(): string; /** * Prints the size of the region that contains each cell. * * Should be called only after the solver has been checked. */ regionSizesToString(): string; } /** * A shape defined by a list of `Vector` offsets. * * Each offset may optionally have an associated payload value. */ export declare class Shape<Name extends string, Payload extends Expr<Name>> { readonly ctx: GrilopsContext<Name>; private _offsetTuples; /** * @param offsets A list of offsets that define the shape. An offset may be a * `Vector`; or, to optionally associate a payload value with the offset, it * may be a `[Vector, Payload]`. A payload may be any z3 expression. */ constructor(context: GrilopsContext<Name>, offsets: Offset<Name, Payload>[]); /** * The offset vectors that define this shape. */ get offsetVectors(): Vector[]; /** * The offset vector and payload value tuples for this shape. */ get offsetsWithPayloads(): [Vector, Payload | undefined][]; /** * Returns a new shape with each offset transformed by `f`. */ transform(f: (vector: Vector) => Vector): Shape<Name, Payload>; /** * Returns a new shape that's canonicalized. * * A canonicalized shape is in sorted order and its first offset is * `Vector`(0, 0). This helps with deduplication, since equivalent shapes * will be canonicalized identically. * * @returns A `Shape` of offsets defining the canonicalized version of the * shape, i.e., in sorted order and with first offset equal to * `Vector`(0, 0). */ canonicalize(): Shape<Name, Payload>; /** * Returns true iff the given shape is equivalent to this shape. */ equivalent(shape: Shape<Name, Payload>): boolean; } /** * Creates constraints for placing fixed shape regions into the grid. */ export declare class ShapeConstrainer<Name extends string, Payload extends Expr<Name>, const Core extends Solver<Name> | Optimize<Name> = Solver<Name> | Optimize<Name>> { private static _instanceIndex; readonly ctx: GrilopsContext<Name>; private readonly _solver; private readonly _lattice; private readonly _complete; private readonly _allowCopies; private readonly _shapes; private _variants; private _shapeTypeGrid; private _shapeInstanceGrid; private _shapePayloadGrid; /** * @param lattice The structure of the grid. * @param shapes A list of region shape definitions. The same region shape * definition may be included multiple times to indicate the number of times * that shape may appear (if allowCopies is false). * @param solver A `Solver` object. If undefined, a `Solver` will be constructed. * @param complete If true, every cell must be part of a shape region. * Defaults to false. * @param allowRotations If true, allow rotations of the shapes to be placed * in the grid. Defaults to false. * @param allowReflections If true, allow reflections of the shapes to be * placed in the grid. Defaults to false. * @param allowCopies If true, allow any number of copies of the shapes to * be placed in the grid. Defaults to false. */ constructor(context: GrilopsContext<Name>, lattice: Lattice, shapes: Shape<Name, Payload>[], solver?: Core | undefined, complete?: boolean, allowRotations?: boolean, allowReflections?: boolean, allowCopies?: boolean); private _makeVariants; /** * Create the grids used to model shape region constraints. */ private _createGrids; private _addConstraints; private _addGridAgreementConstraints; private _addShapeInstanceConstraints; private _addSingleCopyConstraints; /** * The `Solver` associated with this `ShapeConstrainer`. */ get solver(): Core; /** * A dictionary of z3 constants of shape types. * * Each cell contains the index of the shape type placed in that cell (as * indexed by the shapes list passed in to the `ShapeConstrainer` * constructor), or -1 if no shape is placed within that cell. */ get shapeTypeGrid(): Map<Point, Arith<Name>>; getShapeTypeAt(p: Point): Arith<Name>; /** * z3 constants of shape instance IDs. * * Each cell contains a number shared among all cells containing the same * instance of the shape, or -1 if no shape is placed within that cell. */ get shapeInstanceGrid(): Map<Point, Arith<Name>>; getShapeInstanceAt(p: Point): Arith<Name>; /** * z3 constants of the shape offset payloads initially provided. * * undefined if no payloads were provided during construction. */ get shapePayloadGrid(): Map<Point, Payload> | undefined; getShapePayloadAt(p: Point): Payload; /** * Prints the shape type assigned to each cell. * * Should be called only after the solver has been checked. */ shapeTypesToString(): string; /** * Prints the shape instance ID assigned to each cell. * * Should be called only after the solver has been checked. */ shapeInstancesToString(): string; } export declare enum ShapeExprKey { HAS_INSTANCE_ID = 0, NOT_HAS_INSTANCE_ID = 1, HAS_SHAPE_TYPE = 2 } /** * @module symbols This module supports defining symbols that may be filled into grid cells. */ /** * A marking that may be filled into a `grilops.grids.SymbolGrid` cell. */ declare class Symbol_2 { private _index; private _name; private _label; /** * @param index The index value assigned to the symbol. * @param name The code-safe name of the symbol. * @param label The printable label of the symbol. */ constructor(index: number, name?: string, label?: string); /** * The index value assigned to the symbol. */ get index(): number; /** * The code-safe name of the symbol. */ get name(): string; /** * The printable label of the symbol. */ get label(): string; toString(): string; } export { Symbol_2 as Symbol } /** * A grid of cells that can be solved to contain specific symbols. */ export declare class SymbolGrid<Name extends string, const Core extends Solver<Name> | Optimize<Name> = Solver<Name> | Optimize<Name>> { private static _instanceIndex; readonly ctx: GrilopsContext<Name>; private _lattice; private _symbolSet; private _solver; private _grid; /** * @param context The context in which to construct the grid. * @param lattice The structure of the grid. * @param symbolSet The set of symbols to be filled into the grid. * @param solver A `Solver` object. If undefined, a `Solver` will be constructed. */ constructor(context: GrilopsContext<Name>, lattice: Lattice, symbolSet: SymbolSet, solver?: Core | undefined); /** * The `Solver` object associated with this `SymbolGrid`. */ get solver(): Core; /** * The `grilops.symbols.SymbolSet` associated with this `SymbolGrid`. */ get symbolSet(): SymbolSet; /** * The grid of cells. */ get grid(): Map<Point, Arith<Name>>; /** * The lattice of points in the grid. */ get lattice(): Lattice; /** * Returns a list of cells that share an edge with the given cell. * @param p The location of the given cell. * @returns A `Neighbor[]` representing the cells sharing * an edge with the given cell. */ edgeSharingNeighbors(p: Point): Neighbor<Name>[]; /** * Returns the cells that share a vertex with the given cell. * * In other words, returns a list of cells orthogonally and diagonally * adjacent to the given cell. * @param p The location of the given cell. * @returns A `Neighbor[]` representing the cells sharing * a vertex with the given cell. */ vertexSharingNeighbors(p: Point): Neighbor<Name>[]; /** * Returns the cell at the given point. * @param p The location of the cell. * @returns The cell at the given point. */ cellAt(p: Point): Arith<Name>; /** * Returns an expression for whether this cell contains this value. * @param p The location of the given cell. * @param value The value to satisfy the expression. * @returns An expression that's true if and only if the cell at p contains * this value. */ cellIs(p: Point, value: number): Bool<Name>; /** * Returns an expression for whether this cell contains one of these values. * @param p The location of the given cell. * @param values The set of values to satisfy the expression. * @returns An expression that's true if and only if the cell at p contains * one of these values. */ cellIsOneOf(p: Point, values: number[]): Bool<Name>; /** * Returns true if the puzzle has a solution, false otherwise. */ solve(): Promise<boolean>; /** * Returns true if the solution to the puzzle is unique, false otherwise. * * Should be called only after `SymbolGrid.solve` has already completed * successfully. */ isUnique(): Promise<boolean>; /** * Returns the solved symbol grid. * * Should be called only after `SymbolGrid.solve` has already completed * successfully. */ solvedGrid(): Map<Point, number>; /** * Prints the solved grid using symbol labels. * * Should be called only after `SymbolGrid.solve` has already completed * successfully. * @param hookFunction A function implementing custom symbol display * behavior, or None. If this function is provided, it will be called for * each cell in the grid, with the arguments p (`Point`) * and the symbol index for that cell (`number`). It may return a string to * print for that cell, or None to keep the default behavior. */ toString(hookFunction?: ((p: Point, i: number) => string) | undefined): string; } declare namespace symbols { export { makeLetterRangeSymbolSet, makeNumberRangeSymbolSet, Symbol_2 as Symbol, SymbolSet } } /** * A set of markings that may be filled into a `grilops.grids.SymbolGrid`. */ export declare class SymbolSet { private _indexToSymbol; private _labelToSymbolIndex; readonly indices: Record<string, number>; /** * @param symbols A list of specifications for the symbols. Each specification * may be a code-safe name, a (code-safe name, printable label) tuple, or * a (code-safe name, printable label, index value) tuple. */ constructor(symbols: (string | [string, string] | [string, string, number])[]); private _nextUnusedIndex; /** * Appends an additional symbol to this symbol set. * @param name The code-safe name of the symbol. * @param label The printable label of the symbol. */ append(name?: string | undefined, label?: string | undefined): void; /** * Returns the minimum index value of all of the symbols. */ minIndex(): number; /** * Returns the maximum index value of all of the symbols. */ maxIndex(): number; /** * The map of all symbols. */ get symbols(): Map<number, Symbol_2>; toString(): string; } /** * A vector representing an offset in two dimensions. */ export declare class Vector { /** * The relative distance in the y dimension. */ dy: number; /** * The relative distance in the x dimension. */ dx: number; constructor(dy: number, dx: number); /** * Returns a vector that's the negation of this one. */ negate(): Vector; /** * Translates this vector's endpoint in the given direction. */ translate(other: Vector): Vector; toString(): VectorString; static fromString(s: VectorString): Vector; equals(other: Vector): boolean; static comparator(a: Vector, b: Vector): number; } export declare const VectorMap: KeyedMapConstructor<Vector>; export declare const VectorSet: KeyedSetConstructor<Vector>; export declare type VectorString = `V(${string},${string})`; export declare function zip<T1, T2>(a: T1[], b: T2[]): [T1, T2][]; export declare function zip<T1, T2, T3>(a: T1[], b: T2[], c: T3[]): [T1, T2, T3][]; export declare function zip<T>(...args: T[][]): T[][]; export { }