@turing-machine-js/library-binary-numbers 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [3.0.0] - 2026-04-30
8
+
9
+ ### Added
10
+
11
+ - **`minusOneFast`** — a direct borrow-propagation `minusOne` (10 nodes), an alternative to the existing `minusOne` (17 nodes via `~(~x + 1)`). Both kept side-by-side; the heavier composition-based version is pedagogically valuable.
12
+ - Auto-generated [`states.md`](states.md) — rendered Mermaid graph for every exported state, produced by `src/graphs.spec.ts`.
13
+ - Algorithm-explaining comments in `src/index.ts` (node count, intent, composition trade-offs).
14
+ - Tests for `goToNextNumber` and `goToPreviousNumber` (previously `test.todo`).
15
+
16
+ ### Changed
17
+
18
+ - **BREAKING** — `@turing-machine-js/machine` is now a `peerDependency` (was a regular `dependency`). With npm 7+ this is auto-installed; with older npm you may need to install it explicitly. The change ensures consumer and library share the same singleton sentinels (`haltState`, `ifOtherSymbol`, etc.) — duplicate copies would break `instanceof` checks and identity equality.
19
+ - Peer-dep range bumped to `^3.0.0` to require the v3 line of the engine.
20
+ - Internal source files now import the bare `@turing-machine-js/machine` (was `@turing-machine-js/machine/src`).
21
+
22
+ ### Migration
23
+
24
+ If you previously had:
25
+
26
+ ```json
27
+ { "dependencies": { "@turing-machine-js/library-binary-numbers": "^2.0.2" } }
28
+ ```
29
+
30
+ You should now have both as direct dependencies (npm 7+ does this automatically):
31
+
32
+ ```json
33
+ {
34
+ "dependencies": {
35
+ "@turing-machine-js/machine": "^3.0.0",
36
+ "@turing-machine-js/library-binary-numbers": "^3.0.0"
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## [2.0.2] - earlier
42
+
43
+ Initial public 2.x release.
package/README.md CHANGED
@@ -1,50 +1,97 @@
1
1
  # @turing-machine-js/library-binary-numbers
2
2
 
3
3
  [![build](https://github.com/mellonis/turing-machine-js/actions/workflows/main.yml/badge.svg)](https://github.com/mellonis/turing-machine-js/actions/workflows/main.yml)
4
- ![npm (tag)](https://img.shields.io/npm/v/@turing-machine-js/library-binary-numbers)
4
+ [![npm (tag)](https://img.shields.io/npm/v/@turing-machine-js/library-binary-numbers)](https://www.npmjs.com/package/@turing-machine-js/library-binary-numbers)
5
5
 
6
- A library for the turing-machine-js.
6
+ Binary arithmetic on a **5-symbol alphabet** (` `, `^`, `$`, `0`, `1`) supporting **multiple numbers per tape**. Numbers are delimited by `^…$` markers — the markers cost extra states per algorithm but enable inter-number navigation. Side-by-side with [`@turing-machine-js/library-binary-numbers-bare`](../library-binary-numbers-bare), which drops the markers for smaller graphs at the cost of single-number-only operation.
7
7
 
8
8
  ## Install
9
9
 
10
- Using npm:
11
-
12
10
  ```sh
13
- npm install @turing-machine-js/library-binary-numbers
11
+ npm install @turing-machine-js/machine @turing-machine-js/library-binary-numbers
14
12
  ```
15
13
 
16
- ## A concept
14
+ `@turing-machine-js/machine` is a peer dependency.
15
+
16
+ ## Concept
17
+
18
+ A number is a sequence of `0`/`1` cells delimited by `^` (start) and `$` (end). Several numbers can sit on one tape, separated by blanks.
17
19
 
18
- Binary numbers are represented as a sequence of symbols `0` and `1`.
20
+ ```
21
+ …blank ^101011$ blank ^110010$ blank…
22
+ ╰─ 43 ─╯ ╰─ 50 ─╯
23
+ ```
19
24
 
20
- A representation of a number starts with symbol `^` and ends with symbol `$`.
25
+ Examples:
26
+ - `^$` represents 0
27
+ - `^1$` represents 1
28
+ - `^10$` represents 2
29
+ - `^11$` represents 3
21
30
 
22
- For example:
23
- - `^$` stands for 0
24
- - `^1$` stands for 1
25
- - `^10$` stands for 2
26
- - `^11$` stands for 3
27
- - etc.
31
+ Negative numbers are not currently supported.
28
32
 
29
- There is no ability to work with negative numbers at this time.
33
+ ## Algorithms
30
34
 
31
- This library provides following objects to work with binary numbers:
32
- - `getTapeBlock` - this function returns a `TapeBlock` class instance. It has only one tape. An alphabet of the tape contains the following symbols: `space` as a blank symbol, `^`, `$`, `0` and `1`.
33
- - `states` - following `States` class instances which represent some algorithms:
34
- - `goToNumber` - move the head to the number's end
35
- - `goToNextNumber` - move the head to the next number (to the right)
36
- - `goToPreviousNumber` - move the head to the previous number (to the left)
37
- - `deleteNumber` - delete the current number
38
- - `goToNumbersStart` - move the head to the number's start
39
- - `invertNumber` - change every symbol in the number to it's opposite one (`0` to `1` and `1` to `0`)
40
- - `normalizeNumber` - delete leading zeros
41
- - `plusOne` - add 1 to the number
42
- - `minusOne` - subtract 1 from the number
35
+ | name | what it does |
36
+ |---|---|
37
+ | `goToNumber` | move the head to the current number's `$` |
38
+ | `goToNextNumber` | move the head to the next number (rightward) |
39
+ | `goToPreviousNumber` | move the head to the previous number (leftward) |
40
+ | `goToNumbersStart` | move the head to the current number's `^` |
41
+ | `deleteNumber` | erase the current number entirely |
42
+ | `invertNumber` | flip every bit (`0` `1`) |
43
+ | `normalizeNumber` | erase leading zeros (preserving `^$` for the value zero) |
44
+ | `plusOne` | add 1 to the number; extends leftward on overflow (`111 + 1 = 1000`) |
45
+ | `minusOne` | subtract 1, computed via `~(~x + 1)` — composes `invertNumber` → `plusOne` → `invertNumber` → `normalizeNumber` |
46
+ | `minusOneFast` | direct borrow propagation; smaller than `minusOne` and auto-normalizes |
43
47
 
44
- If you want to use states which were described earlier, you must use a tape block received from the `getTapeBlock` function.
48
+ To use these, the tape block **must** come from `getTapeBlock()` that's the one that interns the `^`/`$`/`01` patterns the states key against.
45
49
 
46
- ## Links
50
+ ## Usage
51
+
52
+ ```javascript
53
+ import { Tape, TuringMachine } from '@turing-machine-js/machine';
54
+ import binaryNumbers from '@turing-machine-js/library-binary-numbers';
55
+
56
+ const tapeBlock = binaryNumbers.getTapeBlock();
57
+ const tape = new Tape({
58
+ alphabet: tapeBlock.alphabets[0],
59
+ symbols: '^101$'.split(''), // binary 5
60
+ });
61
+
62
+ tapeBlock.replaceTape(tape);
63
+
64
+ const machine = new TuringMachine({ tapeBlock });
65
+
66
+ machine.run({ initialState: binaryNumbers.states.plusOne });
47
67
 
48
- - The information about `TapeBlock` and `State` classes is [here](https://github.com/mellonis/turing-machine-js/tree/master/packages/machine)
49
- - [Turing Machine](https://en.wikipedia.org/wiki/Turing_machine) on the Wikipedia
68
+ console.log(tape.symbols.join('').trim()); // "^110$" (binary 6)
69
+ ```
70
+
71
+ To run several algorithms in sequence on the same value, reuse the same `TapeBlock` across `machine.run(...)` calls — every state in `binaryNumbers.states` halts cleanly with the head positioned for the next algorithm to pick up.
72
+
73
+ ## How it compares to the bare library
74
+
75
+ Both libraries solve the same arithmetic problem; the trade is **alphabet symbols** vs **state-graph size**.
76
+
77
+ | algorithm | this library (5-symbol) | bare library (3-symbol) |
78
+ |---|---|---|
79
+ | `plusOne` | 5 states | **3** states |
80
+ | `minusOne` | 17 / 10 (`minusOne` / `minusOneFast`) | **3** states |
81
+ | `invertNumber` | 5 states | **2** states |
82
+ | `normalizeNumber` | 7 states | **2** states |
83
+ | **multi-number on tape?** | yes — `goToNumber`, `goToNextNumber`, etc. | no |
84
+ | **head-position flexibility** | anywhere on the number | leftmost digit |
85
+ | **`minusOne` auto-normalizes?** | yes — `minusOneFast` chains into `normalizeNumber` | no — leading `0` kept |
86
+
87
+ The extra states this library spends are mostly bookkeeping for the `^`/`$` markers (planting `^` on left-overflow, sweeping past it on entry, etc.). The pay-off is multi-number-per-tape support and head-position flexibility — `goToNumber` / `goToNextNumber` / `goToPreviousNumber` / `deleteNumber` / `goToNumbersStart` have no counterpart in the bare library.
88
+
89
+ For a teaching context, both libraries shipping in parallel makes the cost of representation choices tangible.
90
+
91
+ See the rendered Mermaid graphs for every state in [`states.md`](states.md) (auto-generated by `src/graphs.spec.ts`).
92
+
93
+ ## Links
50
94
 
95
+ - [`@turing-machine-js/machine`](../machine) — the core engine
96
+ - [`@turing-machine-js/library-binary-numbers-bare`](../library-binary-numbers-bare) — the 3-symbol counterpart
97
+ - [Turing Machine](https://en.wikipedia.org/wiki/Turing_machine) on Wikipedia
package/dist/index.cjs ADDED
@@ -0,0 +1,335 @@
1
+ 'use strict';
2
+
3
+ var machine = require('@turing-machine-js/machine');
4
+
5
+ // 5-symbol alphabet: blank (' '), '^' (number start), '$' (number end), '0', '1'.
6
+ // A tape can hold many numbers, each delimited by '^...$', with blanks between.
7
+ //
8
+ // Compared with @turing-machine-js/library-binary-numbers-bare (3-symbol alphabet,
9
+ // single-number-per-tape), the explicit '^'/'$' markers cost extra states per
10
+ // algorithm but enable safe multi-number navigation (goToNumber / goToNextNumber /
11
+ // goToPreviousNumber). Both libraries exist side-by-side so the trade-off between
12
+ // alphabet size and state-graph size is visible — see ../states.md for diagrams.
13
+ const alphabet = new machine.Alphabet(' ^$01'.split(''));
14
+ const tapeBlock = machine.TapeBlock.fromAlphabets([alphabet]);
15
+ const { symbol } = tapeBlock;
16
+ // goToNumber — 2 nodes
17
+ //
18
+ // Walks the head right until '$'. Used as a "go to current number's end" primitive.
19
+ const goToNumber = new machine.State({
20
+ [symbol('$')]: {
21
+ nextState: machine.haltState,
22
+ },
23
+ [machine.ifOtherSymbol]: {
24
+ command: {
25
+ movement: machine.movements.right,
26
+ },
27
+ },
28
+ }, 'goToNumber');
29
+ // goToNextNumber — 3 nodes (composes goToNumber)
30
+ //
31
+ // Steps right one cell (out of the current '$' / blank gap), then hands off to
32
+ // goToNumber to land on the next number's '$'.
33
+ const goToNextNumber = new machine.State({
34
+ [machine.ifOtherSymbol]: {
35
+ command: {
36
+ movement: machine.movements.right,
37
+ },
38
+ nextState: goToNumber,
39
+ },
40
+ }, 'goToNextNumber');
41
+ // goToPreviousNumber — 3 nodes (uses an internal mirror of goToNumber)
42
+ //
43
+ // Steps left one cell, then walks left until '$' of the previous number.
44
+ const goToPreviousNumberInternal = new machine.State({
45
+ [symbol('$')]: {
46
+ nextState: machine.haltState,
47
+ },
48
+ [machine.ifOtherSymbol]: {
49
+ command: {
50
+ movement: machine.movements.left,
51
+ },
52
+ },
53
+ }, 'goToPreviousNumberInternal');
54
+ const goToPreviousNumber = new machine.State({
55
+ [machine.ifOtherSymbol]: {
56
+ command: {
57
+ movement: machine.movements.left,
58
+ },
59
+ nextState: goToPreviousNumberInternal,
60
+ },
61
+ }, 'goToPreviousNumber');
62
+ // goToNumbersStart — 2 nodes
63
+ //
64
+ // Walks the head left until '^'. Mirror of goToNumber for the start marker.
65
+ const goToNumbersStart = new machine.State({
66
+ [symbol('^')]: {
67
+ nextState: machine.haltState,
68
+ },
69
+ [machine.ifOtherSymbol]: {
70
+ command: {
71
+ movement: machine.movements.left,
72
+ },
73
+ },
74
+ }, 'goToNumberStart');
75
+ // deleteNumber — 5 nodes
76
+ //
77
+ // Composition: go to the number's '^', then sweep right erasing every cell
78
+ // (digits, '^', '$') until the number is gone. Implemented as
79
+ // goToNumbersStart.withOverrodeHaltState(deleteNumberInternal): when
80
+ // goToNumbersStart would halt at '^', it falls through to the eraser instead.
81
+ const deleteNumberInternal = new machine.State({
82
+ [symbol('$')]: {
83
+ command: {
84
+ symbol: machine.symbolCommands.erase,
85
+ },
86
+ nextState: machine.haltState,
87
+ },
88
+ [machine.ifOtherSymbol]: {
89
+ command: {
90
+ symbol: machine.symbolCommands.erase,
91
+ movement: machine.movements.right,
92
+ },
93
+ },
94
+ }, 'deleteNumberInternal');
95
+ const deleteNumber = new machine.State({
96
+ [symbol('^10$')]: {
97
+ nextState: goToNumbersStart.withOverrodeHaltState(deleteNumberInternal),
98
+ },
99
+ [machine.ifOtherSymbol]: {
100
+ nextState: machine.haltState,
101
+ },
102
+ }, 'deleteNumber');
103
+ // invertNumber — 5 nodes
104
+ //
105
+ // Composition: go to '^', then sweep right flipping each bit until '$'.
106
+ // Same shape as deleteNumber (goToNumbersStart.withOverrodeHaltState(...)) but
107
+ // the inner state writes the complement instead of erasing.
108
+ const invertNumberGoToNumberWithInversion = new machine.State({
109
+ [symbol('^')]: {
110
+ command: {
111
+ movement: machine.movements.right,
112
+ },
113
+ },
114
+ [symbol('1')]: {
115
+ command: {
116
+ symbol: '0',
117
+ movement: machine.movements.right,
118
+ },
119
+ },
120
+ [symbol('0')]: {
121
+ command: {
122
+ symbol: '1',
123
+ movement: machine.movements.right,
124
+ },
125
+ },
126
+ [symbol('$')]: {
127
+ nextState: machine.haltState,
128
+ },
129
+ }, 'invertNumberGoToNumberWithInversion');
130
+ const invertNumber = new machine.State({
131
+ [symbol('^10$')]: {
132
+ nextState: goToNumbersStart.withOverrodeHaltState(invertNumberGoToNumberWithInversion),
133
+ },
134
+ [machine.ifOtherSymbol]: {
135
+ nextState: machine.haltState,
136
+ },
137
+ }, 'invertNumber');
138
+ // normalizeNumber — 7 nodes
139
+ //
140
+ // Strips leading zeros by erasing them and re-planting '^' just before the first
141
+ // '1' (or before '$' if the entire number was zero — preserving "0" as "^$").
142
+ // Composition: go to '^', then move-start sweeps right erasing '^' and leading
143
+ // '0's; on first '1' or '$' it backs up one cell and writes a fresh '^' there.
144
+ const normalizeNumberPutNewStartSymbol = new machine.State({
145
+ [symbol(alphabet.blankSymbol)]: {
146
+ command: {
147
+ symbol: '^',
148
+ },
149
+ nextState: goToNumber,
150
+ },
151
+ }, 'normalizeNumberPutNewStartSymbol');
152
+ const normalizeNumberMoveNumberStart = new machine.State({
153
+ [symbol('^0')]: {
154
+ command: {
155
+ symbol: machine.symbolCommands.erase,
156
+ movement: machine.movements.right,
157
+ },
158
+ },
159
+ [symbol('1$')]: {
160
+ command: {
161
+ movement: machine.movements.left,
162
+ },
163
+ nextState: normalizeNumberPutNewStartSymbol,
164
+ },
165
+ }, 'normalizeNumberMoveNumberStart');
166
+ const normalizeNumber = new machine.State({
167
+ [symbol('^10$')]: {
168
+ nextState: goToNumbersStart.withOverrodeHaltState(normalizeNumberMoveNumberStart),
169
+ },
170
+ [machine.ifOtherSymbol]: {
171
+ nextState: machine.haltState,
172
+ },
173
+ }, 'normalizeNumber');
174
+ // plusOne — 5 nodes
175
+ //
176
+ // Walk to '$', step left into the LSB, then carry from the LSB:
177
+ // 1 → 0 (carry continues left)
178
+ // 0 → 1, then fill any 1s to the right with 0s (already done by the chain) and halt at '$'
179
+ // ^ → 1 (carry overflows the MSB) — write 1, step into the new blank cell on the
180
+ // left, plant a fresh '^' there, then sweep right turning the old leading 1s
181
+ // into 0s. This is what plusOneAddNumberStart and plusOneFillZeros handle.
182
+ //
183
+ // The bare-alphabet variant in @turing-machine-js/library-binary-numbers-bare
184
+ // drops to 3 nodes for the same operation by skipping the '^' relocation.
185
+ const plusOneFillZeros = new machine.State({
186
+ [symbol('1')]: {
187
+ command: {
188
+ symbol: '0',
189
+ movement: machine.movements.right,
190
+ },
191
+ },
192
+ [symbol('$')]: {
193
+ nextState: machine.haltState,
194
+ },
195
+ }, 'plusOneFillZeros');
196
+ const plusOneAddNumberStart = new machine.State({
197
+ [symbol(alphabet.blankSymbol)]: {
198
+ command: {
199
+ symbol: '^',
200
+ movement: machine.movements.right,
201
+ },
202
+ },
203
+ [symbol('1')]: {
204
+ command: {
205
+ movement: machine.movements.right,
206
+ },
207
+ nextState: plusOneFillZeros,
208
+ },
209
+ }, 'plusOneAddNumberStart');
210
+ const plusOneCaryOne = new machine.State({
211
+ [symbol('0')]: {
212
+ command: {
213
+ symbol: '1',
214
+ movement: machine.movements.right,
215
+ },
216
+ nextState: plusOneFillZeros,
217
+ },
218
+ [symbol('1')]: {
219
+ command: {
220
+ movement: machine.movements.left,
221
+ },
222
+ },
223
+ [symbol('^')]: {
224
+ command: {
225
+ symbol: '1',
226
+ movement: machine.movements.left,
227
+ },
228
+ nextState: plusOneAddNumberStart,
229
+ },
230
+ }, 'plusOneCaryOne');
231
+ const plusOne = new machine.State({
232
+ [symbol('^10')]: {
233
+ command: {
234
+ movement: machine.movements.right,
235
+ },
236
+ },
237
+ [symbol('$')]: {
238
+ command: {
239
+ movement: machine.movements.left,
240
+ },
241
+ nextState: plusOneCaryOne,
242
+ },
243
+ [machine.ifOtherSymbol]: {
244
+ nextState: machine.haltState,
245
+ },
246
+ }, 'plusOne');
247
+ // minusOne — 17 nodes (the largest in this library)
248
+ //
249
+ // Computes x − 1 via the two's-complement identity: x − 1 == ~(~x + 1)
250
+ // (every step is a state we already have), composed with three nested
251
+ // withOverrodeHaltState calls to chain invert → plusOne → invert → normalize.
252
+ //
253
+ // This is *deliberately* the heavy version. It exists side-by-side with
254
+ // minusOneFast (10 nodes, direct borrow) to make the cost of "compose existing
255
+ // pieces" vs "write a dedicated algorithm" visible. See ../states.md for the
256
+ // dotted onHalt edges that show the four-deep subroutine chain.
257
+ const minusOne = new machine.State({
258
+ [symbol('^10')]: {
259
+ command: {
260
+ movement: machine.movements.right,
261
+ },
262
+ },
263
+ [symbol('$')]: {
264
+ nextState: invertNumber
265
+ .withOverrodeHaltState(plusOne
266
+ .withOverrodeHaltState(invertNumber
267
+ .withOverrodeHaltState(normalizeNumber))),
268
+ },
269
+ [machine.ifOtherSymbol]: {
270
+ nextState: machine.haltState,
271
+ },
272
+ }, 'minusOne');
273
+ // minusOneFast — 10 nodes (direct borrow propagation)
274
+ //
275
+ // Walks left from the LSB: 0→1 keeps borrowing; 1→0 stops; ^ is underflow.
276
+ // Falls through to normalizeNumber to strip the leading zero introduced when the
277
+ // borrow chain reaches the MSB (e.g. ^1000$ - 1 = ^0111$ → ^111$).
278
+ //
279
+ // Same algorithm as minusOne in @turing-machine-js/library-binary-numbers-bare
280
+ // (which is 3 nodes there). The extra 7 nodes here are the cost of: scanning
281
+ // past '^' on entry, the goToNumberStart path and its withOverrodeHaltState
282
+ // wrapper for normalize, and normalizeNumber's own marker-relocation chain.
283
+ const minusOneFastBorrow = new machine.State({
284
+ [symbol('1')]: {
285
+ command: {
286
+ symbol: '0',
287
+ },
288
+ nextState: machine.haltState,
289
+ },
290
+ [symbol('0')]: {
291
+ command: {
292
+ symbol: '1',
293
+ movement: machine.movements.left,
294
+ },
295
+ },
296
+ [symbol('^')]: {
297
+ nextState: machine.haltState,
298
+ },
299
+ }, 'minusOneFastBorrow');
300
+ const minusOneFast = new machine.State({
301
+ [symbol('^10')]: {
302
+ command: {
303
+ movement: machine.movements.right,
304
+ },
305
+ },
306
+ [symbol('$')]: {
307
+ command: {
308
+ movement: machine.movements.left,
309
+ },
310
+ nextState: minusOneFastBorrow.withOverrodeHaltState(normalizeNumber),
311
+ },
312
+ [machine.ifOtherSymbol]: {
313
+ nextState: machine.haltState,
314
+ },
315
+ }, 'minusOneFast');
316
+ function getTapeBlock() {
317
+ return tapeBlock.clone();
318
+ }
319
+ var index = {
320
+ getTapeBlock,
321
+ states: {
322
+ goToNumber,
323
+ goToNextNumber,
324
+ goToPreviousNumber,
325
+ deleteNumber,
326
+ goToNumbersStart,
327
+ invertNumber,
328
+ normalizeNumber,
329
+ plusOne,
330
+ minusOne,
331
+ minusOneFast,
332
+ },
333
+ };
334
+
335
+ module.exports = index;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { State, TapeBlock } from '@turing-machine-js/machine/src';
1
+ import { State, TapeBlock } from '@turing-machine-js/machine';
2
2
  declare function getTapeBlock(): TapeBlock;
3
3
  declare const _default: {
4
4
  getTapeBlock: typeof getTapeBlock;
@@ -12,6 +12,7 @@ declare const _default: {
12
12
  normalizeNumber: State;
13
13
  plusOne: State;
14
14
  minusOne: State;
15
+ minusOneFast: State;
15
16
  };
16
17
  };
17
18
  export default _default;
package/dist/index.js CHANGED
@@ -1,7 +1,18 @@
1
- import { Alphabet, haltState, ifOtherSymbol, movements, State, symbolCommands, TapeBlock, } from '@turing-machine-js/machine/src';
1
+ import { Alphabet, haltState, ifOtherSymbol, movements, State, symbolCommands, TapeBlock, } from '@turing-machine-js/machine';
2
+ // 5-symbol alphabet: blank (' '), '^' (number start), '$' (number end), '0', '1'.
3
+ // A tape can hold many numbers, each delimited by '^...$', with blanks between.
4
+ //
5
+ // Compared with @turing-machine-js/library-binary-numbers-bare (3-symbol alphabet,
6
+ // single-number-per-tape), the explicit '^'/'$' markers cost extra states per
7
+ // algorithm but enable safe multi-number navigation (goToNumber / goToNextNumber /
8
+ // goToPreviousNumber). Both libraries exist side-by-side so the trade-off between
9
+ // alphabet size and state-graph size is visible — see ../states.md for diagrams.
2
10
  const alphabet = new Alphabet(' ^$01'.split(''));
3
11
  const tapeBlock = TapeBlock.fromAlphabets([alphabet]);
4
12
  const { symbol } = tapeBlock;
13
+ // goToNumber — 2 nodes
14
+ //
15
+ // Walks the head right until '$'. Used as a "go to current number's end" primitive.
5
16
  const goToNumber = new State({
6
17
  [symbol('$')]: {
7
18
  nextState: haltState,
@@ -12,6 +23,10 @@ const goToNumber = new State({
12
23
  },
13
24
  },
14
25
  }, 'goToNumber');
26
+ // goToNextNumber — 3 nodes (composes goToNumber)
27
+ //
28
+ // Steps right one cell (out of the current '$' / blank gap), then hands off to
29
+ // goToNumber to land on the next number's '$'.
15
30
  const goToNextNumber = new State({
16
31
  [ifOtherSymbol]: {
17
32
  command: {
@@ -20,6 +35,9 @@ const goToNextNumber = new State({
20
35
  nextState: goToNumber,
21
36
  },
22
37
  }, 'goToNextNumber');
38
+ // goToPreviousNumber — 3 nodes (uses an internal mirror of goToNumber)
39
+ //
40
+ // Steps left one cell, then walks left until '$' of the previous number.
23
41
  const goToPreviousNumberInternal = new State({
24
42
  [symbol('$')]: {
25
43
  nextState: haltState,
@@ -38,6 +56,9 @@ const goToPreviousNumber = new State({
38
56
  nextState: goToPreviousNumberInternal,
39
57
  },
40
58
  }, 'goToPreviousNumber');
59
+ // goToNumbersStart — 2 nodes
60
+ //
61
+ // Walks the head left until '^'. Mirror of goToNumber for the start marker.
41
62
  const goToNumbersStart = new State({
42
63
  [symbol('^')]: {
43
64
  nextState: haltState,
@@ -48,6 +69,12 @@ const goToNumbersStart = new State({
48
69
  },
49
70
  },
50
71
  }, 'goToNumberStart');
72
+ // deleteNumber — 5 nodes
73
+ //
74
+ // Composition: go to the number's '^', then sweep right erasing every cell
75
+ // (digits, '^', '$') until the number is gone. Implemented as
76
+ // goToNumbersStart.withOverrodeHaltState(deleteNumberInternal): when
77
+ // goToNumbersStart would halt at '^', it falls through to the eraser instead.
51
78
  const deleteNumberInternal = new State({
52
79
  [symbol('$')]: {
53
80
  command: {
@@ -70,6 +97,11 @@ const deleteNumber = new State({
70
97
  nextState: haltState,
71
98
  },
72
99
  }, 'deleteNumber');
100
+ // invertNumber — 5 nodes
101
+ //
102
+ // Composition: go to '^', then sweep right flipping each bit until '$'.
103
+ // Same shape as deleteNumber (goToNumbersStart.withOverrodeHaltState(...)) but
104
+ // the inner state writes the complement instead of erasing.
73
105
  const invertNumberGoToNumberWithInversion = new State({
74
106
  [symbol('^')]: {
75
107
  command: {
@@ -100,6 +132,12 @@ const invertNumber = new State({
100
132
  nextState: haltState,
101
133
  },
102
134
  }, 'invertNumber');
135
+ // normalizeNumber — 7 nodes
136
+ //
137
+ // Strips leading zeros by erasing them and re-planting '^' just before the first
138
+ // '1' (or before '$' if the entire number was zero — preserving "0" as "^$").
139
+ // Composition: go to '^', then move-start sweeps right erasing '^' and leading
140
+ // '0's; on first '1' or '$' it backs up one cell and writes a fresh '^' there.
103
141
  const normalizeNumberPutNewStartSymbol = new State({
104
142
  [symbol(alphabet.blankSymbol)]: {
105
143
  command: {
@@ -130,6 +168,17 @@ const normalizeNumber = new State({
130
168
  nextState: haltState,
131
169
  },
132
170
  }, 'normalizeNumber');
171
+ // plusOne — 5 nodes
172
+ //
173
+ // Walk to '$', step left into the LSB, then carry from the LSB:
174
+ // 1 → 0 (carry continues left)
175
+ // 0 → 1, then fill any 1s to the right with 0s (already done by the chain) and halt at '$'
176
+ // ^ → 1 (carry overflows the MSB) — write 1, step into the new blank cell on the
177
+ // left, plant a fresh '^' there, then sweep right turning the old leading 1s
178
+ // into 0s. This is what plusOneAddNumberStart and plusOneFillZeros handle.
179
+ //
180
+ // The bare-alphabet variant in @turing-machine-js/library-binary-numbers-bare
181
+ // drops to 3 nodes for the same operation by skipping the '^' relocation.
133
182
  const plusOneFillZeros = new State({
134
183
  [symbol('1')]: {
135
184
  command: {
@@ -192,6 +241,16 @@ const plusOne = new State({
192
241
  nextState: haltState,
193
242
  },
194
243
  }, 'plusOne');
244
+ // minusOne — 17 nodes (the largest in this library)
245
+ //
246
+ // Computes x − 1 via the two's-complement identity: x − 1 == ~(~x + 1)
247
+ // (every step is a state we already have), composed with three nested
248
+ // withOverrodeHaltState calls to chain invert → plusOne → invert → normalize.
249
+ //
250
+ // This is *deliberately* the heavy version. It exists side-by-side with
251
+ // minusOneFast (10 nodes, direct borrow) to make the cost of "compose existing
252
+ // pieces" vs "write a dedicated algorithm" visible. See ../states.md for the
253
+ // dotted onHalt edges that show the four-deep subroutine chain.
195
254
  const minusOne = new State({
196
255
  [symbol('^10')]: {
197
256
  command: {
@@ -208,6 +267,49 @@ const minusOne = new State({
208
267
  nextState: haltState,
209
268
  },
210
269
  }, 'minusOne');
270
+ // minusOneFast — 10 nodes (direct borrow propagation)
271
+ //
272
+ // Walks left from the LSB: 0→1 keeps borrowing; 1→0 stops; ^ is underflow.
273
+ // Falls through to normalizeNumber to strip the leading zero introduced when the
274
+ // borrow chain reaches the MSB (e.g. ^1000$ - 1 = ^0111$ → ^111$).
275
+ //
276
+ // Same algorithm as minusOne in @turing-machine-js/library-binary-numbers-bare
277
+ // (which is 3 nodes there). The extra 7 nodes here are the cost of: scanning
278
+ // past '^' on entry, the goToNumberStart path and its withOverrodeHaltState
279
+ // wrapper for normalize, and normalizeNumber's own marker-relocation chain.
280
+ const minusOneFastBorrow = new State({
281
+ [symbol('1')]: {
282
+ command: {
283
+ symbol: '0',
284
+ },
285
+ nextState: haltState,
286
+ },
287
+ [symbol('0')]: {
288
+ command: {
289
+ symbol: '1',
290
+ movement: movements.left,
291
+ },
292
+ },
293
+ [symbol('^')]: {
294
+ nextState: haltState,
295
+ },
296
+ }, 'minusOneFastBorrow');
297
+ const minusOneFast = new State({
298
+ [symbol('^10')]: {
299
+ command: {
300
+ movement: movements.right,
301
+ },
302
+ },
303
+ [symbol('$')]: {
304
+ command: {
305
+ movement: movements.left,
306
+ },
307
+ nextState: minusOneFastBorrow.withOverrodeHaltState(normalizeNumber),
308
+ },
309
+ [ifOtherSymbol]: {
310
+ nextState: haltState,
311
+ },
312
+ }, 'minusOneFast');
211
313
  function getTapeBlock() {
212
314
  return tapeBlock.clone();
213
315
  }
@@ -223,5 +325,6 @@ export default {
223
325
  normalizeNumber,
224
326
  plusOne,
225
327
  minusOne,
328
+ minusOneFast,
226
329
  },
227
330
  };
package/dist/index.mjs ADDED
@@ -0,0 +1,333 @@
1
+ import { Alphabet, TapeBlock, State, movements, haltState, ifOtherSymbol, symbolCommands } from '@turing-machine-js/machine';
2
+
3
+ // 5-symbol alphabet: blank (' '), '^' (number start), '$' (number end), '0', '1'.
4
+ // A tape can hold many numbers, each delimited by '^...$', with blanks between.
5
+ //
6
+ // Compared with @turing-machine-js/library-binary-numbers-bare (3-symbol alphabet,
7
+ // single-number-per-tape), the explicit '^'/'$' markers cost extra states per
8
+ // algorithm but enable safe multi-number navigation (goToNumber / goToNextNumber /
9
+ // goToPreviousNumber). Both libraries exist side-by-side so the trade-off between
10
+ // alphabet size and state-graph size is visible — see ../states.md for diagrams.
11
+ const alphabet = new Alphabet(' ^$01'.split(''));
12
+ const tapeBlock = TapeBlock.fromAlphabets([alphabet]);
13
+ const { symbol } = tapeBlock;
14
+ // goToNumber — 2 nodes
15
+ //
16
+ // Walks the head right until '$'. Used as a "go to current number's end" primitive.
17
+ const goToNumber = new State({
18
+ [symbol('$')]: {
19
+ nextState: haltState,
20
+ },
21
+ [ifOtherSymbol]: {
22
+ command: {
23
+ movement: movements.right,
24
+ },
25
+ },
26
+ }, 'goToNumber');
27
+ // goToNextNumber — 3 nodes (composes goToNumber)
28
+ //
29
+ // Steps right one cell (out of the current '$' / blank gap), then hands off to
30
+ // goToNumber to land on the next number's '$'.
31
+ const goToNextNumber = new State({
32
+ [ifOtherSymbol]: {
33
+ command: {
34
+ movement: movements.right,
35
+ },
36
+ nextState: goToNumber,
37
+ },
38
+ }, 'goToNextNumber');
39
+ // goToPreviousNumber — 3 nodes (uses an internal mirror of goToNumber)
40
+ //
41
+ // Steps left one cell, then walks left until '$' of the previous number.
42
+ const goToPreviousNumberInternal = new State({
43
+ [symbol('$')]: {
44
+ nextState: haltState,
45
+ },
46
+ [ifOtherSymbol]: {
47
+ command: {
48
+ movement: movements.left,
49
+ },
50
+ },
51
+ }, 'goToPreviousNumberInternal');
52
+ const goToPreviousNumber = new State({
53
+ [ifOtherSymbol]: {
54
+ command: {
55
+ movement: movements.left,
56
+ },
57
+ nextState: goToPreviousNumberInternal,
58
+ },
59
+ }, 'goToPreviousNumber');
60
+ // goToNumbersStart — 2 nodes
61
+ //
62
+ // Walks the head left until '^'. Mirror of goToNumber for the start marker.
63
+ const goToNumbersStart = new State({
64
+ [symbol('^')]: {
65
+ nextState: haltState,
66
+ },
67
+ [ifOtherSymbol]: {
68
+ command: {
69
+ movement: movements.left,
70
+ },
71
+ },
72
+ }, 'goToNumberStart');
73
+ // deleteNumber — 5 nodes
74
+ //
75
+ // Composition: go to the number's '^', then sweep right erasing every cell
76
+ // (digits, '^', '$') until the number is gone. Implemented as
77
+ // goToNumbersStart.withOverrodeHaltState(deleteNumberInternal): when
78
+ // goToNumbersStart would halt at '^', it falls through to the eraser instead.
79
+ const deleteNumberInternal = new State({
80
+ [symbol('$')]: {
81
+ command: {
82
+ symbol: symbolCommands.erase,
83
+ },
84
+ nextState: haltState,
85
+ },
86
+ [ifOtherSymbol]: {
87
+ command: {
88
+ symbol: symbolCommands.erase,
89
+ movement: movements.right,
90
+ },
91
+ },
92
+ }, 'deleteNumberInternal');
93
+ const deleteNumber = new State({
94
+ [symbol('^10$')]: {
95
+ nextState: goToNumbersStart.withOverrodeHaltState(deleteNumberInternal),
96
+ },
97
+ [ifOtherSymbol]: {
98
+ nextState: haltState,
99
+ },
100
+ }, 'deleteNumber');
101
+ // invertNumber — 5 nodes
102
+ //
103
+ // Composition: go to '^', then sweep right flipping each bit until '$'.
104
+ // Same shape as deleteNumber (goToNumbersStart.withOverrodeHaltState(...)) but
105
+ // the inner state writes the complement instead of erasing.
106
+ const invertNumberGoToNumberWithInversion = new State({
107
+ [symbol('^')]: {
108
+ command: {
109
+ movement: movements.right,
110
+ },
111
+ },
112
+ [symbol('1')]: {
113
+ command: {
114
+ symbol: '0',
115
+ movement: movements.right,
116
+ },
117
+ },
118
+ [symbol('0')]: {
119
+ command: {
120
+ symbol: '1',
121
+ movement: movements.right,
122
+ },
123
+ },
124
+ [symbol('$')]: {
125
+ nextState: haltState,
126
+ },
127
+ }, 'invertNumberGoToNumberWithInversion');
128
+ const invertNumber = new State({
129
+ [symbol('^10$')]: {
130
+ nextState: goToNumbersStart.withOverrodeHaltState(invertNumberGoToNumberWithInversion),
131
+ },
132
+ [ifOtherSymbol]: {
133
+ nextState: haltState,
134
+ },
135
+ }, 'invertNumber');
136
+ // normalizeNumber — 7 nodes
137
+ //
138
+ // Strips leading zeros by erasing them and re-planting '^' just before the first
139
+ // '1' (or before '$' if the entire number was zero — preserving "0" as "^$").
140
+ // Composition: go to '^', then move-start sweeps right erasing '^' and leading
141
+ // '0's; on first '1' or '$' it backs up one cell and writes a fresh '^' there.
142
+ const normalizeNumberPutNewStartSymbol = new State({
143
+ [symbol(alphabet.blankSymbol)]: {
144
+ command: {
145
+ symbol: '^',
146
+ },
147
+ nextState: goToNumber,
148
+ },
149
+ }, 'normalizeNumberPutNewStartSymbol');
150
+ const normalizeNumberMoveNumberStart = new State({
151
+ [symbol('^0')]: {
152
+ command: {
153
+ symbol: symbolCommands.erase,
154
+ movement: movements.right,
155
+ },
156
+ },
157
+ [symbol('1$')]: {
158
+ command: {
159
+ movement: movements.left,
160
+ },
161
+ nextState: normalizeNumberPutNewStartSymbol,
162
+ },
163
+ }, 'normalizeNumberMoveNumberStart');
164
+ const normalizeNumber = new State({
165
+ [symbol('^10$')]: {
166
+ nextState: goToNumbersStart.withOverrodeHaltState(normalizeNumberMoveNumberStart),
167
+ },
168
+ [ifOtherSymbol]: {
169
+ nextState: haltState,
170
+ },
171
+ }, 'normalizeNumber');
172
+ // plusOne — 5 nodes
173
+ //
174
+ // Walk to '$', step left into the LSB, then carry from the LSB:
175
+ // 1 → 0 (carry continues left)
176
+ // 0 → 1, then fill any 1s to the right with 0s (already done by the chain) and halt at '$'
177
+ // ^ → 1 (carry overflows the MSB) — write 1, step into the new blank cell on the
178
+ // left, plant a fresh '^' there, then sweep right turning the old leading 1s
179
+ // into 0s. This is what plusOneAddNumberStart and plusOneFillZeros handle.
180
+ //
181
+ // The bare-alphabet variant in @turing-machine-js/library-binary-numbers-bare
182
+ // drops to 3 nodes for the same operation by skipping the '^' relocation.
183
+ const plusOneFillZeros = new State({
184
+ [symbol('1')]: {
185
+ command: {
186
+ symbol: '0',
187
+ movement: movements.right,
188
+ },
189
+ },
190
+ [symbol('$')]: {
191
+ nextState: haltState,
192
+ },
193
+ }, 'plusOneFillZeros');
194
+ const plusOneAddNumberStart = new State({
195
+ [symbol(alphabet.blankSymbol)]: {
196
+ command: {
197
+ symbol: '^',
198
+ movement: movements.right,
199
+ },
200
+ },
201
+ [symbol('1')]: {
202
+ command: {
203
+ movement: movements.right,
204
+ },
205
+ nextState: plusOneFillZeros,
206
+ },
207
+ }, 'plusOneAddNumberStart');
208
+ const plusOneCaryOne = new State({
209
+ [symbol('0')]: {
210
+ command: {
211
+ symbol: '1',
212
+ movement: movements.right,
213
+ },
214
+ nextState: plusOneFillZeros,
215
+ },
216
+ [symbol('1')]: {
217
+ command: {
218
+ movement: movements.left,
219
+ },
220
+ },
221
+ [symbol('^')]: {
222
+ command: {
223
+ symbol: '1',
224
+ movement: movements.left,
225
+ },
226
+ nextState: plusOneAddNumberStart,
227
+ },
228
+ }, 'plusOneCaryOne');
229
+ const plusOne = new State({
230
+ [symbol('^10')]: {
231
+ command: {
232
+ movement: movements.right,
233
+ },
234
+ },
235
+ [symbol('$')]: {
236
+ command: {
237
+ movement: movements.left,
238
+ },
239
+ nextState: plusOneCaryOne,
240
+ },
241
+ [ifOtherSymbol]: {
242
+ nextState: haltState,
243
+ },
244
+ }, 'plusOne');
245
+ // minusOne — 17 nodes (the largest in this library)
246
+ //
247
+ // Computes x − 1 via the two's-complement identity: x − 1 == ~(~x + 1)
248
+ // (every step is a state we already have), composed with three nested
249
+ // withOverrodeHaltState calls to chain invert → plusOne → invert → normalize.
250
+ //
251
+ // This is *deliberately* the heavy version. It exists side-by-side with
252
+ // minusOneFast (10 nodes, direct borrow) to make the cost of "compose existing
253
+ // pieces" vs "write a dedicated algorithm" visible. See ../states.md for the
254
+ // dotted onHalt edges that show the four-deep subroutine chain.
255
+ const minusOne = new State({
256
+ [symbol('^10')]: {
257
+ command: {
258
+ movement: movements.right,
259
+ },
260
+ },
261
+ [symbol('$')]: {
262
+ nextState: invertNumber
263
+ .withOverrodeHaltState(plusOne
264
+ .withOverrodeHaltState(invertNumber
265
+ .withOverrodeHaltState(normalizeNumber))),
266
+ },
267
+ [ifOtherSymbol]: {
268
+ nextState: haltState,
269
+ },
270
+ }, 'minusOne');
271
+ // minusOneFast — 10 nodes (direct borrow propagation)
272
+ //
273
+ // Walks left from the LSB: 0→1 keeps borrowing; 1→0 stops; ^ is underflow.
274
+ // Falls through to normalizeNumber to strip the leading zero introduced when the
275
+ // borrow chain reaches the MSB (e.g. ^1000$ - 1 = ^0111$ → ^111$).
276
+ //
277
+ // Same algorithm as minusOne in @turing-machine-js/library-binary-numbers-bare
278
+ // (which is 3 nodes there). The extra 7 nodes here are the cost of: scanning
279
+ // past '^' on entry, the goToNumberStart path and its withOverrodeHaltState
280
+ // wrapper for normalize, and normalizeNumber's own marker-relocation chain.
281
+ const minusOneFastBorrow = new State({
282
+ [symbol('1')]: {
283
+ command: {
284
+ symbol: '0',
285
+ },
286
+ nextState: haltState,
287
+ },
288
+ [symbol('0')]: {
289
+ command: {
290
+ symbol: '1',
291
+ movement: movements.left,
292
+ },
293
+ },
294
+ [symbol('^')]: {
295
+ nextState: haltState,
296
+ },
297
+ }, 'minusOneFastBorrow');
298
+ const minusOneFast = new State({
299
+ [symbol('^10')]: {
300
+ command: {
301
+ movement: movements.right,
302
+ },
303
+ },
304
+ [symbol('$')]: {
305
+ command: {
306
+ movement: movements.left,
307
+ },
308
+ nextState: minusOneFastBorrow.withOverrodeHaltState(normalizeNumber),
309
+ },
310
+ [ifOtherSymbol]: {
311
+ nextState: haltState,
312
+ },
313
+ }, 'minusOneFast');
314
+ function getTapeBlock() {
315
+ return tapeBlock.clone();
316
+ }
317
+ var index = {
318
+ getTapeBlock,
319
+ states: {
320
+ goToNumber,
321
+ goToNextNumber,
322
+ goToPreviousNumber,
323
+ deleteNumber,
324
+ goToNumbersStart,
325
+ invertNumber,
326
+ normalizeNumber,
327
+ plusOne,
328
+ minusOne,
329
+ minusOneFast,
330
+ },
331
+ };
332
+
333
+ export { index as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turing-machine-js/library-binary-numbers",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "A standard library for working with binary numbers",
5
5
  "engines": {
6
6
  "npm": ">=7.0.0"
@@ -17,7 +17,7 @@
17
17
  "directory": "packages/library-binary-numbers"
18
18
  },
19
19
  "bugs": {
20
- "url": "https://github.com/mellonis/turing-machine-js/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3A%22pkg%3A+library-binary-numbers%22+label%3Abug+"
20
+ "url": "https://github.com/mellonis/turing-machine-js/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3A%22pkg%3A+library-binary-numbers%22+label%3Abug"
21
21
  },
22
22
  "keywords": [
23
23
  "turing",
@@ -26,18 +26,19 @@
26
26
  "binary",
27
27
  "numbers"
28
28
  ],
29
- "dependencies": {
30
- "@turing-machine-js/machine": "^2.0.1"
29
+ "peerDependencies": {
30
+ "@turing-machine-js/machine": "^3.0.0"
31
31
  },
32
- "main": "index.js",
33
- "module": "index.js",
34
- "types": "index.d.ts",
32
+ "main": "dist/index.cjs",
33
+ "module": "dist/index.mjs",
34
+ "types": "dist/index.d.ts",
35
35
  "exports": {
36
36
  ".": {
37
- "types": "./index.d.ts",
38
- "import": "./index.js",
39
- "default": "./index.js"
37
+ "types": "./dist/index.d.ts",
38
+ "import": "./dist/index.mjs",
39
+ "require": "./dist/index.cjs",
40
+ "default": "./dist/index.mjs"
40
41
  }
41
42
  },
42
- "gitHead": "18d8a7388cea7372a9e262452797699cea7b61dd"
43
+ "gitHead": "98decf323129d528febafac1bec581a9ee3800ff"
43
44
  }
package/states.md ADDED
@@ -0,0 +1,266 @@
1
+ # library-binary-numbers — state graphs
2
+
3
+ ## goToNumber
4
+
5
+ *2 states (including `haltState`)*
6
+
7
+ ```mermaid
8
+ flowchart TD
9
+ %% alphabets: [[" ","^","$","0","1"]]
10
+ s0(((halt)))
11
+ s1(("goToNumber"))
12
+ s1 -- "$ → ·/S" --> s0
13
+ s1 -- "* → ·/R" --> s1
14
+ ```
15
+
16
+ ## goToNextNumber
17
+
18
+ *3 states (including `haltState`)*
19
+
20
+ ```mermaid
21
+ flowchart TD
22
+ %% alphabets: [[" ","^","$","0","1"]]
23
+ s0(((halt)))
24
+ s1["goToNumber"]
25
+ s2(("goToNextNumber"))
26
+ s1 -- "$ → ·/S" --> s0
27
+ s1 -- "* → ·/R" --> s1
28
+ s2 -- "* → ·/R" --> s1
29
+ ```
30
+
31
+ ## goToPreviousNumber
32
+
33
+ *3 states (including `haltState`)*
34
+
35
+ ```mermaid
36
+ flowchart TD
37
+ %% alphabets: [[" ","^","$","0","1"]]
38
+ s0(((halt)))
39
+ s3["goToPreviousNumberInternal"]
40
+ s4(("goToPreviousNumber"))
41
+ s3 -- "$ → ·/S" --> s0
42
+ s3 -- "* → ·/L" --> s3
43
+ s4 -- "* → ·/L" --> s3
44
+ ```
45
+
46
+ ## deleteNumber
47
+
48
+ *5 states (including `haltState`)*
49
+
50
+ ```mermaid
51
+ flowchart TD
52
+ %% alphabets: [[" ","^","$","0","1"]]
53
+ s0(((halt)))
54
+ s5["goToNumberStart"]
55
+ s6["deleteNumberInternal"]
56
+ s7["goToNumberStart>deleteNumberInternal"]
57
+ s8(("deleteNumber"))
58
+ s5 -- "^ → ·/S" --> s0
59
+ s5 -- "* → ·/L" --> s5
60
+ s6 -- "$ → ⌫/S" --> s0
61
+ s6 -- "* → ⌫/R" --> s6
62
+ s7 -- "^ → ·/S" --> s0
63
+ s7 -- "* → ·/L" --> s5
64
+ s7 -. onHalt .-> s6
65
+ s8 -- "^|1|0|$ → ·/S" --> s7
66
+ s8 -- "* → ·/S" --> s0
67
+ ```
68
+
69
+ ## goToNumbersStart
70
+
71
+ *2 states (including `haltState`)*
72
+
73
+ ```mermaid
74
+ flowchart TD
75
+ %% alphabets: [[" ","^","$","0","1"]]
76
+ s0(((halt)))
77
+ s5(("goToNumberStart"))
78
+ s5 -- "^ → ·/S" --> s0
79
+ s5 -- "* → ·/L" --> s5
80
+ ```
81
+
82
+ ## invertNumber
83
+
84
+ *5 states (including `haltState`)*
85
+
86
+ ```mermaid
87
+ flowchart TD
88
+ %% alphabets: [[" ","^","$","0","1"]]
89
+ s0(((halt)))
90
+ s5["goToNumberStart"]
91
+ s9["invertNumberGoToNumberWithInversion"]
92
+ s10["goToNumberStart>invertNumberGoToNumberWithInversion"]
93
+ s11(("invertNumber"))
94
+ s5 -- "^ → ·/S" --> s0
95
+ s5 -- "* → ·/L" --> s5
96
+ s9 -- "^ → ·/R" --> s9
97
+ s9 -- "1 → 0/R" --> s9
98
+ s9 -- "0 → 1/R" --> s9
99
+ s9 -- "$ → ·/S" --> s0
100
+ s10 -- "^ → ·/S" --> s0
101
+ s10 -- "* → ·/L" --> s5
102
+ s10 -. onHalt .-> s9
103
+ s11 -- "^|1|0|$ → ·/S" --> s10
104
+ s11 -- "* → ·/S" --> s0
105
+ ```
106
+
107
+ ## normalizeNumber
108
+
109
+ *7 states (including `haltState`)*
110
+
111
+ ```mermaid
112
+ flowchart TD
113
+ %% alphabets: [[" ","^","$","0","1"]]
114
+ s0(((halt)))
115
+ s1["goToNumber"]
116
+ s5["goToNumberStart"]
117
+ s12["normalizeNumberPutNewStartSymbol"]
118
+ s13["normalizeNumberMoveNumberStart"]
119
+ s14["goToNumberStart>normalizeNumberMoveNumberStart"]
120
+ s15(("normalizeNumber"))
121
+ s1 -- "$ → ·/S" --> s0
122
+ s1 -- "* → ·/R" --> s1
123
+ s5 -- "^ → ·/S" --> s0
124
+ s5 -- "* → ·/L" --> s5
125
+ s12 -- "- → ^/S" --> s1
126
+ s13 -- "^|0 → ⌫/R" --> s13
127
+ s13 -- "1|$ → ·/L" --> s12
128
+ s14 -- "^ → ·/S" --> s0
129
+ s14 -- "* → ·/L" --> s5
130
+ s14 -. onHalt .-> s13
131
+ s15 -- "^|1|0|$ → ·/S" --> s14
132
+ s15 -- "* → ·/S" --> s0
133
+ ```
134
+
135
+ ## plusOne
136
+
137
+ *5 states (including `haltState`)*
138
+
139
+ ```mermaid
140
+ flowchart TD
141
+ %% alphabets: [[" ","^","$","0","1"]]
142
+ s0(((halt)))
143
+ s16["plusOneFillZeros"]
144
+ s17["plusOneAddNumberStart"]
145
+ s18["plusOneCaryOne"]
146
+ s19(("plusOne"))
147
+ s16 -- "1 → 0/R" --> s16
148
+ s16 -- "$ → ·/S" --> s0
149
+ s17 -- "- → ^/R" --> s17
150
+ s17 -- "1 → ·/R" --> s16
151
+ s18 -- "0 → 1/R" --> s16
152
+ s18 -- "1 → ·/L" --> s18
153
+ s18 -- "^ → 1/L" --> s17
154
+ s19 -- "^|1|0 → ·/R" --> s19
155
+ s19 -- "$ → ·/L" --> s18
156
+ s19 -- "* → ·/S" --> s0
157
+ ```
158
+
159
+ ## minusOne
160
+
161
+ *17 states (including `haltState`)*
162
+
163
+ ```mermaid
164
+ flowchart TD
165
+ %% alphabets: [[" ","^","$","0","1"]]
166
+ s0(((halt)))
167
+ s1["goToNumber"]
168
+ s5["goToNumberStart"]
169
+ s9["invertNumberGoToNumberWithInversion"]
170
+ s10["goToNumberStart>invertNumberGoToNumberWithInversion"]
171
+ s12["normalizeNumberPutNewStartSymbol"]
172
+ s13["normalizeNumberMoveNumberStart"]
173
+ s14["goToNumberStart>normalizeNumberMoveNumberStart"]
174
+ s15["normalizeNumber"]
175
+ s16["plusOneFillZeros"]
176
+ s17["plusOneAddNumberStart"]
177
+ s18["plusOneCaryOne"]
178
+ s19["plusOne"]
179
+ s20["invertNumber>normalizeNumber"]
180
+ s21["plusOne>invertNumber>normalizeNumber"]
181
+ s22["invertNumber>plusOne>invertNumber>normalizeNumber"]
182
+ s23(("minusOne"))
183
+ s1 -- "$ → ·/S" --> s0
184
+ s1 -- "* → ·/R" --> s1
185
+ s5 -- "^ → ·/S" --> s0
186
+ s5 -- "* → ·/L" --> s5
187
+ s9 -- "^ → ·/R" --> s9
188
+ s9 -- "1 → 0/R" --> s9
189
+ s9 -- "0 → 1/R" --> s9
190
+ s9 -- "$ → ·/S" --> s0
191
+ s10 -- "^ → ·/S" --> s0
192
+ s10 -- "* → ·/L" --> s5
193
+ s10 -. onHalt .-> s9
194
+ s12 -- "- → ^/S" --> s1
195
+ s13 -- "^|0 → ⌫/R" --> s13
196
+ s13 -- "1|$ → ·/L" --> s12
197
+ s14 -- "^ → ·/S" --> s0
198
+ s14 -- "* → ·/L" --> s5
199
+ s14 -. onHalt .-> s13
200
+ s15 -- "^|1|0|$ → ·/S" --> s14
201
+ s15 -- "* → ·/S" --> s0
202
+ s16 -- "1 → 0/R" --> s16
203
+ s16 -- "$ → ·/S" --> s0
204
+ s17 -- "- → ^/R" --> s17
205
+ s17 -- "1 → ·/R" --> s16
206
+ s18 -- "0 → 1/R" --> s16
207
+ s18 -- "1 → ·/L" --> s18
208
+ s18 -- "^ → 1/L" --> s17
209
+ s19 -- "^|1|0 → ·/R" --> s19
210
+ s19 -- "$ → ·/L" --> s18
211
+ s19 -- "* → ·/S" --> s0
212
+ s20 -- "^|1|0|$ → ·/S" --> s10
213
+ s20 -- "* → ·/S" --> s0
214
+ s20 -. onHalt .-> s15
215
+ s21 -- "^|1|0 → ·/R" --> s19
216
+ s21 -- "$ → ·/L" --> s18
217
+ s21 -- "* → ·/S" --> s0
218
+ s21 -. onHalt .-> s20
219
+ s22 -- "^|1|0|$ → ·/S" --> s10
220
+ s22 -- "* → ·/S" --> s0
221
+ s22 -. onHalt .-> s21
222
+ s23 -- "^|1|0 → ·/R" --> s23
223
+ s23 -- "$ → ·/S" --> s22
224
+ s23 -- "* → ·/S" --> s0
225
+ ```
226
+
227
+ ## minusOneFast
228
+
229
+ *10 states (including `haltState`)*
230
+
231
+ ```mermaid
232
+ flowchart TD
233
+ %% alphabets: [[" ","^","$","0","1"]]
234
+ s0(((halt)))
235
+ s1["goToNumber"]
236
+ s5["goToNumberStart"]
237
+ s12["normalizeNumberPutNewStartSymbol"]
238
+ s13["normalizeNumberMoveNumberStart"]
239
+ s14["goToNumberStart>normalizeNumberMoveNumberStart"]
240
+ s15["normalizeNumber"]
241
+ s24["minusOneFastBorrow"]
242
+ s25["minusOneFastBorrow>normalizeNumber"]
243
+ s26(("minusOneFast"))
244
+ s1 -- "$ → ·/S" --> s0
245
+ s1 -- "* → ·/R" --> s1
246
+ s5 -- "^ → ·/S" --> s0
247
+ s5 -- "* → ·/L" --> s5
248
+ s12 -- "- → ^/S" --> s1
249
+ s13 -- "^|0 → ⌫/R" --> s13
250
+ s13 -- "1|$ → ·/L" --> s12
251
+ s14 -- "^ → ·/S" --> s0
252
+ s14 -- "* → ·/L" --> s5
253
+ s14 -. onHalt .-> s13
254
+ s15 -- "^|1|0|$ → ·/S" --> s14
255
+ s15 -- "* → ·/S" --> s0
256
+ s24 -- "1 → 0/S" --> s0
257
+ s24 -- "0 → 1/L" --> s24
258
+ s24 -- "^ → ·/S" --> s0
259
+ s25 -- "1 → 0/S" --> s0
260
+ s25 -- "0 → 1/L" --> s24
261
+ s25 -- "^ → ·/S" --> s0
262
+ s25 -. onHalt .-> s15
263
+ s26 -- "^|1|0 → ·/R" --> s26
264
+ s26 -- "$ → ·/L" --> s25
265
+ s26 -- "* → ·/S" --> s0
266
+ ```
@@ -1 +0,0 @@
1
- {"root":["./src/index.ts"],"version":"5.9.3"}