From 26f0d38d5731e7aea796889eecbcf333aefb0548 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Sun, 6 Oct 2024 20:50:56 -0700 Subject: [PATCH] [alg] Add a way to serialize to string using LGN. --- src/cubing/alg/Alg.ts | 9 ++- src/cubing/alg/Serializable.ts | 22 ------- src/cubing/alg/SerializationOptions.ts | 6 ++ .../alg/alg-nodes/containers/Commutator.ts | 7 ++- .../alg/alg-nodes/containers/Conjugate.ts | 7 ++- .../alg/alg-nodes/containers/Grouping.ts | 29 +++++++-- .../alg/alg-nodes/leaves/LineComment.ts | 5 +- src/cubing/alg/alg-nodes/leaves/Move.ts | 63 ++++++++++++------- src/cubing/alg/alg-nodes/leaves/Newline.ts | 5 +- src/cubing/alg/alg-nodes/leaves/Pause.ts | 5 +- src/cubing/alg/common.ts | 7 ++- 11 files changed, 101 insertions(+), 64 deletions(-) delete mode 100644 src/cubing/alg/Serializable.ts create mode 100644 src/cubing/alg/SerializationOptions.ts diff --git a/src/cubing/alg/Alg.ts b/src/cubing/alg/Alg.ts index 20a2ad2b0..de6808b57 100644 --- a/src/cubing/alg/Alg.ts +++ b/src/cubing/alg/Alg.ts @@ -9,6 +9,7 @@ import { AlgCommon, type Comparable } from "./common"; import { experimentalIs, experimentalIsAlgNode } from "./is"; import { IterationDirection, direct, reverse } from "./iteration"; import { parseAlg } from "./parseAlg"; +import type { ExperimentalSerializationOptions } from "./SerializationOptions"; import { simplify, type SimplifyOptions } from "./simplify"; import { warnOnce } from "./warnOnce"; @@ -247,7 +248,9 @@ export class Alg extends AlgCommon { * // R U2 L * console.log(alg.toString()) */ - toString(): string { + toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { let output = ""; let previousVisibleAlgNode: AlgNode | null = null; for (const algNode of this.#algNodes) { @@ -259,11 +262,11 @@ export class Alg extends AlgCommon { if (nissGrouping.amount !== -1) { throw new Error("Invalid NISS Grouping amount!"); } - output += `^(${nissGrouping.alg.toString()})`; + output += `^(${nissGrouping.alg.toString(experimentalSerializationOptions)})`; } else if (algNode.as(Grouping)?.experimentalNISSPlaceholder) { // do not serialize (rely on the placeholder instead) } else { - output += algNode.toString(); + output += algNode.toString(experimentalSerializationOptions); } previousVisibleAlgNode = algNode; } diff --git a/src/cubing/alg/Serializable.ts b/src/cubing/alg/Serializable.ts deleted file mode 100644 index 1d5f44b74..000000000 --- a/src/cubing/alg/Serializable.ts +++ /dev/null @@ -1,22 +0,0 @@ -// export interface MoveJSON { -// type: "move"; -// family: string; -// innerLayer?: number; -// outerLayer?: number; -// } - -// export interface GroupingJSON { -// type: "grouping"; -// alg: AlgJSON; -// } - -// export interface LineCommentJSON { -// type: "comment"; -// text: string; -// } - -// export interface CommutatorJSON { -// type: "commutator"; -// A: AlgJSON; -// B: AlgJSON; -// } diff --git a/src/cubing/alg/SerializationOptions.ts b/src/cubing/alg/SerializationOptions.ts new file mode 100644 index 000000000..96dea1f9a --- /dev/null +++ b/src/cubing/alg/SerializationOptions.ts @@ -0,0 +1,6 @@ +type notation = "auto" | "LGN"; + +export interface ExperimentalSerializationOptions { + // TODO: this will still serialize caret NISS notation as normal. + notation?: notation; +} diff --git a/src/cubing/alg/alg-nodes/containers/Commutator.ts b/src/cubing/alg/alg-nodes/containers/Commutator.ts index 5885280a0..311255ea1 100644 --- a/src/cubing/alg/alg-nodes/containers/Commutator.ts +++ b/src/cubing/alg/alg-nodes/containers/Commutator.ts @@ -1,3 +1,4 @@ +import type { ExperimentalSerializationOptions } from "cubing/alg/SerializationOptions"; import { experimentalEnsureAlg, type Alg, @@ -84,7 +85,9 @@ export class Commutator extends AlgCommon { } } - toString(): string { - return `[${this.#A.toString()}, ${this.#B.toString()}]`; + toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { + return `[${this.#A.toString(experimentalSerializationOptions)}, ${this.#B.toString(experimentalSerializationOptions)}]`; } } diff --git a/src/cubing/alg/alg-nodes/containers/Conjugate.ts b/src/cubing/alg/alg-nodes/containers/Conjugate.ts index aaaf43d46..16f948502 100644 --- a/src/cubing/alg/alg-nodes/containers/Conjugate.ts +++ b/src/cubing/alg/alg-nodes/containers/Conjugate.ts @@ -1,3 +1,4 @@ +import type { ExperimentalSerializationOptions } from "cubing/alg/SerializationOptions"; import { experimentalEnsureAlg, type Alg, @@ -52,7 +53,9 @@ export class Conjugate extends AlgCommon { } } - toString(): string { - return `[${this.A}: ${this.B}]`; + toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { + return `[${this.A.toString(experimentalSerializationOptions)}: ${this.B.toString(experimentalSerializationOptions)}]`; } } diff --git a/src/cubing/alg/alg-nodes/containers/Grouping.ts b/src/cubing/alg/alg-nodes/containers/Grouping.ts index 9e5c66acf..c50654cfc 100644 --- a/src/cubing/alg/alg-nodes/containers/Grouping.ts +++ b/src/cubing/alg/alg-nodes/containers/Grouping.ts @@ -1,3 +1,4 @@ +import type { ExperimentalSerializationOptions } from "cubing/alg/SerializationOptions"; import { Commutator, Conjugate } from ".."; import { Alg, experimentalEnsureAlg, type FlexibleAlgSource } from "../../Alg"; import { AlgCommon, type Comparable } from "../../common"; @@ -13,7 +14,14 @@ class Square1TupleFormatter { quantumU_SQ_: QuantumMove | null = null; quantumD_SQ_: QuantumMove | null = null; - format(grouping: Grouping): string | null { + format( + grouping: Grouping, + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string | null { + if (experimentalSerializationOptions?.notation === "LGN") { + return null; + } + if (grouping.amount !== 1) { return null; } @@ -107,8 +115,12 @@ export class Grouping extends AlgCommon { throw new Error("unimplemented"); } - #unrepeatedString(): string | null { - const insideString = this.#quantumWithAmount.quantum.toString(); + #unrepeatedString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string | null { + const insideString = this.#quantumWithAmount.quantum.toString( + experimentalSerializationOptions, + ); const iter = this.alg.childAlgNodes(); const { value } = iter.next() as { value: AlgNode; @@ -120,10 +132,15 @@ export class Grouping extends AlgCommon { return `(${insideString})`; } - toString(): string { + toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { return ( - square1TupleFormatterInstance.format(this) ?? - `${this.#unrepeatedString()}${this.#quantumWithAmount.suffix()}` + square1TupleFormatterInstance.format( + this, + experimentalSerializationOptions, + ) ?? + `${this.#unrepeatedString(experimentalSerializationOptions)}${this.#quantumWithAmount.suffix()}` ); } diff --git a/src/cubing/alg/alg-nodes/leaves/LineComment.ts b/src/cubing/alg/alg-nodes/leaves/LineComment.ts index 148528c5b..e486cb4ce 100644 --- a/src/cubing/alg/alg-nodes/leaves/LineComment.ts +++ b/src/cubing/alg/alg-nodes/leaves/LineComment.ts @@ -1,3 +1,4 @@ +import type { ExperimentalSerializationOptions } from "cubing/alg/SerializationOptions"; import { AlgCommon, type Comparable } from "../../common"; import { IterationDirection } from "../../iteration"; import type { AlgLeaf } from "../AlgNode"; @@ -36,7 +37,9 @@ export class LineComment extends AlgCommon { yield this; } - toString(): string { + toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { return `//${this.#text}`; } // toJSON(): LineCommentJSON { diff --git a/src/cubing/alg/alg-nodes/leaves/Move.ts b/src/cubing/alg/alg-nodes/leaves/Move.ts index 4a8f64fbb..c4b57b60f 100644 --- a/src/cubing/alg/alg-nodes/leaves/Move.ts +++ b/src/cubing/alg/alg-nodes/leaves/Move.ts @@ -1,10 +1,11 @@ +import type { ExperimentalSerializationOptions } from "cubing/alg/SerializationOptions"; import { AlgCommon, Comparable } from "../../common"; import { IterationDirection } from "../../iteration"; import { MAX_INT, MAX_INT_DESCRIPTION } from "../../limits"; import { parseMove, parseQuantumMove, transferCharIndex } from "../../parseAlg"; import { warnOnce } from "../../warnOnce"; -import { QuantumWithAmount } from "../QuantumWithAmount"; import type { AlgLeaf } from "../AlgNode"; +import { QuantumWithAmount } from "../QuantumWithAmount"; interface QuantumMoveModifications { outerLayer?: number; @@ -114,7 +115,9 @@ export class QuantumMove extends Comparable { ); } - override toString(): string { + override toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { let s = this.#family; if (this.#innerLayer !== null) { s = String(this.#innerLayer) + s; @@ -171,7 +174,10 @@ export class Move extends AlgCommon { // TODO: handle char indices more consistently among alg nodes. return transferCharIndex( this, - new Move(this.#quantumWithAmount.quantum, -this.amount), + new Move( + this.#quantumWithAmount.quantum, + this.#isSlash() ? this.amount : -this.amount, + ), ); } @@ -229,29 +235,38 @@ export class Move extends AlgCommon { return this.#quantumWithAmount.quantum.innerLayer ?? undefined; } - toString(): string { - if (this.family === "_SLASH_") { - return "/"; // TODO: validate no amount - } - if (this.family.endsWith("_PLUS_")) { - return ( - this.#quantumWithAmount.quantum.toString().slice(0, -6) + - Math.abs(this.amount) + - (this.amount < 0 ? "-" : "+") - ); // TODO - } - if (this.family.endsWith("_PLUSPLUS_")) { - const absAmount = Math.abs(this.amount); - return ( - this.#quantumWithAmount.quantum.toString().slice(0, -10) + - (absAmount === 1 ? "" : absAmount) + - (this.amount < 0 ? "--" : "++") - ); // TODO - } + #cachedSlashMove: Move | undefined; + #isSlash(): boolean { + return this.isIdentical((this.#cachedSlashMove ??= new Move("_SLASH_"))); + } + toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { + if (experimentalSerializationOptions?.notation !== "LGN") { + if (this.#isSlash()) { + return "/"; // TODO: validate no amount + } + if (this.family.endsWith("_PLUS_")) { + return ( + this.#quantumWithAmount.quantum.toString().slice(0, -6) + + Math.abs(this.amount) + + (this.amount < 0 ? "-" : "+") + ); // TODO + } + if (this.family.endsWith("_PLUSPLUS_")) { + const absAmount = Math.abs(this.amount); + return ( + this.#quantumWithAmount.quantum.toString().slice(0, -10) + + (absAmount === 1 ? "" : absAmount) + + (this.amount < 0 ? "--" : "++") + ); // TODO + } + } return ( - this.#quantumWithAmount.quantum.toString() + - this.#quantumWithAmount.suffix() + this.#quantumWithAmount.quantum.toString( + experimentalSerializationOptions, + ) + this.#quantumWithAmount.suffix() ); } // // TODO: Serialize as a string? diff --git a/src/cubing/alg/alg-nodes/leaves/Newline.ts b/src/cubing/alg/alg-nodes/leaves/Newline.ts index 80ce779c6..48653ff14 100644 --- a/src/cubing/alg/alg-nodes/leaves/Newline.ts +++ b/src/cubing/alg/alg-nodes/leaves/Newline.ts @@ -1,10 +1,13 @@ +import type { ExperimentalSerializationOptions } from "cubing/alg/SerializationOptions"; import { AlgCommon, type Comparable } from "../../common"; import { IterationDirection } from "../../iteration"; import type { AlgLeaf } from "../AlgNode"; /** @category Alg Nodes */ export class Newline extends AlgCommon { - toString(): string { + toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { return "\n"; } diff --git a/src/cubing/alg/alg-nodes/leaves/Pause.ts b/src/cubing/alg/alg-nodes/leaves/Pause.ts index 9fcc56440..d2ed57224 100644 --- a/src/cubing/alg/alg-nodes/leaves/Pause.ts +++ b/src/cubing/alg/alg-nodes/leaves/Pause.ts @@ -1,3 +1,4 @@ +import type { ExperimentalSerializationOptions } from "cubing/alg/SerializationOptions"; import { AlgCommon, type Comparable } from "../../common"; import { IterationDirection } from "../../iteration"; import type { AlgLeaf } from "../AlgNode"; @@ -7,7 +8,9 @@ import type { Grouping } from "../containers/Grouping"; export class Pause extends AlgCommon { experimentalNISSGrouping?: Grouping; // TODO: tie this to the alg - toString(): string { + toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string { return "."; } diff --git a/src/cubing/alg/common.ts b/src/cubing/alg/common.ts index 09b452fc6..9f66eccbc 100644 --- a/src/cubing/alg/common.ts +++ b/src/cubing/alg/common.ts @@ -1,6 +1,7 @@ import type { Alg } from "./Alg"; -import type { IterationDirection } from "./iteration"; import type { AlgLeaf, AlgNode } from "./alg-nodes/AlgNode"; +import type { IterationDirection } from "./iteration"; +import type { ExperimentalSerializationOptions } from "./SerializationOptions"; let writeAlgDebugField = false; export function setAlgDebugField(debug: boolean): void { @@ -50,7 +51,9 @@ export abstract class AlgCommon ) => void; } - abstract override toString(): string; + abstract override toString( + experimentalSerializationOptions?: ExperimentalSerializationOptions, + ): string; abstract invert(): T;