@turing-machine-js/library-binary-numbers 2.0.2 → 3.0.1

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,47 @@
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.1] - 2026-04-30
8
+
9
+ Released in lockstep with `@turing-machine-js/machine` 3.0.1. No source or behavior changes in this package.
10
+
11
+ ## [3.0.0] - 2026-04-30
12
+
13
+ ### Added
14
+
15
+ - **`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.
16
+ - Auto-generated [`states.md`](states.md) — rendered Mermaid graph for every exported state, produced by `src/graphs.spec.ts`.
17
+ - Algorithm-explaining comments in `src/index.ts` (node count, intent, composition trade-offs).
18
+ - Tests for `goToNextNumber` and `goToPreviousNumber` (previously `test.todo`).
19
+
20
+ ### Changed
21
+
22
+ - **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.
23
+ - Peer-dep range bumped to `^3.0.0` to require the v3 line of the engine.
24
+ - Internal source files now import the bare `@turing-machine-js/machine` (was `@turing-machine-js/machine/src`).
25
+
26
+ ### Migration
27
+
28
+ If you previously had:
29
+
30
+ ```json
31
+ { "dependencies": { "@turing-machine-js/library-binary-numbers": "^2.0.2" } }
32
+ ```
33
+
34
+ You should now have both as direct dependencies (npm 7+ does this automatically):
35
+
36
+ ```json
37
+ {
38
+ "dependencies": {
39
+ "@turing-machine-js/machine": "^3.0.0",
40
+ "@turing-machine-js/library-binary-numbers": "^3.0.0"
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## [2.0.2] - earlier
46
+
47
+ 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 CHANGED
@@ -1,109 +1,147 @@
1
1
  'use strict';
2
2
 
3
- var src = require('@turing-machine-js/machine/src');
3
+ var machine = require('@turing-machine-js/machine');
4
4
 
5
- const alphabet = new src.Alphabet(' ^$01'.split(''));
6
- const tapeBlock = src.TapeBlock.fromAlphabets([alphabet]);
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]);
7
15
  const { symbol } = tapeBlock;
8
- const goToNumber = new src.State({
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({
9
20
  [symbol('$')]: {
10
- nextState: src.haltState,
21
+ nextState: machine.haltState,
11
22
  },
12
- [src.ifOtherSymbol]: {
23
+ [machine.ifOtherSymbol]: {
13
24
  command: {
14
- movement: src.movements.right,
25
+ movement: machine.movements.right,
15
26
  },
16
27
  },
17
28
  }, 'goToNumber');
18
- const goToNextNumber = new src.State({
19
- [src.ifOtherSymbol]: {
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]: {
20
35
  command: {
21
- movement: src.movements.right,
36
+ movement: machine.movements.right,
22
37
  },
23
38
  nextState: goToNumber,
24
39
  },
25
40
  }, 'goToNextNumber');
26
- const goToPreviousNumberInternal = new src.State({
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({
27
45
  [symbol('$')]: {
28
- nextState: src.haltState,
46
+ nextState: machine.haltState,
29
47
  },
30
- [src.ifOtherSymbol]: {
48
+ [machine.ifOtherSymbol]: {
31
49
  command: {
32
- movement: src.movements.left,
50
+ movement: machine.movements.left,
33
51
  },
34
52
  },
35
53
  }, 'goToPreviousNumberInternal');
36
- const goToPreviousNumber = new src.State({
37
- [src.ifOtherSymbol]: {
54
+ const goToPreviousNumber = new machine.State({
55
+ [machine.ifOtherSymbol]: {
38
56
  command: {
39
- movement: src.movements.left,
57
+ movement: machine.movements.left,
40
58
  },
41
59
  nextState: goToPreviousNumberInternal,
42
60
  },
43
61
  }, 'goToPreviousNumber');
44
- const goToNumbersStart = new src.State({
62
+ // goToNumbersStart 2 nodes
63
+ //
64
+ // Walks the head left until '^'. Mirror of goToNumber for the start marker.
65
+ const goToNumbersStart = new machine.State({
45
66
  [symbol('^')]: {
46
- nextState: src.haltState,
67
+ nextState: machine.haltState,
47
68
  },
48
- [src.ifOtherSymbol]: {
69
+ [machine.ifOtherSymbol]: {
49
70
  command: {
50
- movement: src.movements.left,
71
+ movement: machine.movements.left,
51
72
  },
52
73
  },
53
74
  }, 'goToNumberStart');
54
- const deleteNumberInternal = new src.State({
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({
55
82
  [symbol('$')]: {
56
83
  command: {
57
- symbol: src.symbolCommands.erase,
84
+ symbol: machine.symbolCommands.erase,
58
85
  },
59
- nextState: src.haltState,
86
+ nextState: machine.haltState,
60
87
  },
61
- [src.ifOtherSymbol]: {
88
+ [machine.ifOtherSymbol]: {
62
89
  command: {
63
- symbol: src.symbolCommands.erase,
64
- movement: src.movements.right,
90
+ symbol: machine.symbolCommands.erase,
91
+ movement: machine.movements.right,
65
92
  },
66
93
  },
67
94
  }, 'deleteNumberInternal');
68
- const deleteNumber = new src.State({
95
+ const deleteNumber = new machine.State({
69
96
  [symbol('^10$')]: {
70
97
  nextState: goToNumbersStart.withOverrodeHaltState(deleteNumberInternal),
71
98
  },
72
- [src.ifOtherSymbol]: {
73
- nextState: src.haltState,
99
+ [machine.ifOtherSymbol]: {
100
+ nextState: machine.haltState,
74
101
  },
75
102
  }, 'deleteNumber');
76
- const invertNumberGoToNumberWithInversion = new src.State({
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({
77
109
  [symbol('^')]: {
78
110
  command: {
79
- movement: src.movements.right,
111
+ movement: machine.movements.right,
80
112
  },
81
113
  },
82
114
  [symbol('1')]: {
83
115
  command: {
84
116
  symbol: '0',
85
- movement: src.movements.right,
117
+ movement: machine.movements.right,
86
118
  },
87
119
  },
88
120
  [symbol('0')]: {
89
121
  command: {
90
122
  symbol: '1',
91
- movement: src.movements.right,
123
+ movement: machine.movements.right,
92
124
  },
93
125
  },
94
126
  [symbol('$')]: {
95
- nextState: src.haltState,
127
+ nextState: machine.haltState,
96
128
  },
97
129
  }, 'invertNumberGoToNumberWithInversion');
98
- const invertNumber = new src.State({
130
+ const invertNumber = new machine.State({
99
131
  [symbol('^10$')]: {
100
132
  nextState: goToNumbersStart.withOverrodeHaltState(invertNumberGoToNumberWithInversion),
101
133
  },
102
- [src.ifOtherSymbol]: {
103
- nextState: src.haltState,
134
+ [machine.ifOtherSymbol]: {
135
+ nextState: machine.haltState,
104
136
  },
105
137
  }, 'invertNumber');
106
- const normalizeNumberPutNewStartSymbol = new src.State({
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({
107
145
  [symbol(alphabet.blankSymbol)]: {
108
146
  command: {
109
147
  symbol: '^',
@@ -111,94 +149,115 @@ const normalizeNumberPutNewStartSymbol = new src.State({
111
149
  nextState: goToNumber,
112
150
  },
113
151
  }, 'normalizeNumberPutNewStartSymbol');
114
- const normalizeNumberMoveNumberStart = new src.State({
152
+ const normalizeNumberMoveNumberStart = new machine.State({
115
153
  [symbol('^0')]: {
116
154
  command: {
117
- symbol: src.symbolCommands.erase,
118
- movement: src.movements.right,
155
+ symbol: machine.symbolCommands.erase,
156
+ movement: machine.movements.right,
119
157
  },
120
158
  },
121
159
  [symbol('1$')]: {
122
160
  command: {
123
- movement: src.movements.left,
161
+ movement: machine.movements.left,
124
162
  },
125
163
  nextState: normalizeNumberPutNewStartSymbol,
126
164
  },
127
165
  }, 'normalizeNumberMoveNumberStart');
128
- const normalizeNumber = new src.State({
166
+ const normalizeNumber = new machine.State({
129
167
  [symbol('^10$')]: {
130
168
  nextState: goToNumbersStart.withOverrodeHaltState(normalizeNumberMoveNumberStart),
131
169
  },
132
- [src.ifOtherSymbol]: {
133
- nextState: src.haltState,
170
+ [machine.ifOtherSymbol]: {
171
+ nextState: machine.haltState,
134
172
  },
135
173
  }, 'normalizeNumber');
136
- const plusOneFillZeros = new src.State({
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({
137
186
  [symbol('1')]: {
138
187
  command: {
139
188
  symbol: '0',
140
- movement: src.movements.right,
189
+ movement: machine.movements.right,
141
190
  },
142
191
  },
143
192
  [symbol('$')]: {
144
- nextState: src.haltState,
193
+ nextState: machine.haltState,
145
194
  },
146
195
  }, 'plusOneFillZeros');
147
- const plusOneAddNumberStart = new src.State({
196
+ const plusOneAddNumberStart = new machine.State({
148
197
  [symbol(alphabet.blankSymbol)]: {
149
198
  command: {
150
199
  symbol: '^',
151
- movement: src.movements.right,
200
+ movement: machine.movements.right,
152
201
  },
153
202
  },
154
203
  [symbol('1')]: {
155
204
  command: {
156
- movement: src.movements.right,
205
+ movement: machine.movements.right,
157
206
  },
158
207
  nextState: plusOneFillZeros,
159
208
  },
160
209
  }, 'plusOneAddNumberStart');
161
- const plusOneCaryOne = new src.State({
210
+ const plusOneCaryOne = new machine.State({
162
211
  [symbol('0')]: {
163
212
  command: {
164
213
  symbol: '1',
165
- movement: src.movements.right,
214
+ movement: machine.movements.right,
166
215
  },
167
216
  nextState: plusOneFillZeros,
168
217
  },
169
218
  [symbol('1')]: {
170
219
  command: {
171
- movement: src.movements.left,
220
+ movement: machine.movements.left,
172
221
  },
173
222
  },
174
223
  [symbol('^')]: {
175
224
  command: {
176
225
  symbol: '1',
177
- movement: src.movements.left,
226
+ movement: machine.movements.left,
178
227
  },
179
228
  nextState: plusOneAddNumberStart,
180
229
  },
181
230
  }, 'plusOneCaryOne');
182
- const plusOne = new src.State({
231
+ const plusOne = new machine.State({
183
232
  [symbol('^10')]: {
184
233
  command: {
185
- movement: src.movements.right,
234
+ movement: machine.movements.right,
186
235
  },
187
236
  },
188
237
  [symbol('$')]: {
189
238
  command: {
190
- movement: src.movements.left,
239
+ movement: machine.movements.left,
191
240
  },
192
241
  nextState: plusOneCaryOne,
193
242
  },
194
- [src.ifOtherSymbol]: {
195
- nextState: src.haltState,
243
+ [machine.ifOtherSymbol]: {
244
+ nextState: machine.haltState,
196
245
  },
197
246
  }, 'plusOne');
198
- const minusOne = new src.State({
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({
199
258
  [symbol('^10')]: {
200
259
  command: {
201
- movement: src.movements.right,
260
+ movement: machine.movements.right,
202
261
  },
203
262
  },
204
263
  [symbol('$')]: {
@@ -207,10 +266,53 @@ const minusOne = new src.State({
207
266
  .withOverrodeHaltState(invertNumber
208
267
  .withOverrodeHaltState(normalizeNumber))),
209
268
  },
210
- [src.ifOtherSymbol]: {
211
- nextState: src.haltState,
269
+ [machine.ifOtherSymbol]: {
270
+ nextState: machine.haltState,
212
271
  },
213
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');
214
316
  function getTapeBlock() {
215
317
  return tapeBlock.clone();
216
318
  }
@@ -226,6 +328,7 @@ var index = {
226
328
  normalizeNumber,
227
329
  plusOne,
228
330
  minusOne,
331
+ minusOneFast,
229
332
  },
230
333
  };
231
334
 
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.mjs CHANGED
@@ -1,8 +1,19 @@
1
- import { Alphabet, TapeBlock, State, movements, haltState, ifOtherSymbol, symbolCommands } from '@turing-machine-js/machine/src';
1
+ import { Alphabet, TapeBlock, State, movements, haltState, ifOtherSymbol, symbolCommands } from '@turing-machine-js/machine';
2
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.
3
11
  const alphabet = new Alphabet(' ^$01'.split(''));
4
12
  const tapeBlock = TapeBlock.fromAlphabets([alphabet]);
5
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.
6
17
  const goToNumber = new State({
7
18
  [symbol('$')]: {
8
19
  nextState: haltState,
@@ -13,6 +24,10 @@ const goToNumber = new State({
13
24
  },
14
25
  },
15
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 '$'.
16
31
  const goToNextNumber = new State({
17
32
  [ifOtherSymbol]: {
18
33
  command: {
@@ -21,6 +36,9 @@ const goToNextNumber = new State({
21
36
  nextState: goToNumber,
22
37
  },
23
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.
24
42
  const goToPreviousNumberInternal = new State({
25
43
  [symbol('$')]: {
26
44
  nextState: haltState,
@@ -39,6 +57,9 @@ const goToPreviousNumber = new State({
39
57
  nextState: goToPreviousNumberInternal,
40
58
  },
41
59
  }, 'goToPreviousNumber');
60
+ // goToNumbersStart — 2 nodes
61
+ //
62
+ // Walks the head left until '^'. Mirror of goToNumber for the start marker.
42
63
  const goToNumbersStart = new State({
43
64
  [symbol('^')]: {
44
65
  nextState: haltState,
@@ -49,6 +70,12 @@ const goToNumbersStart = new State({
49
70
  },
50
71
  },
51
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.
52
79
  const deleteNumberInternal = new State({
53
80
  [symbol('$')]: {
54
81
  command: {
@@ -71,6 +98,11 @@ const deleteNumber = new State({
71
98
  nextState: haltState,
72
99
  },
73
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.
74
106
  const invertNumberGoToNumberWithInversion = new State({
75
107
  [symbol('^')]: {
76
108
  command: {
@@ -101,6 +133,12 @@ const invertNumber = new State({
101
133
  nextState: haltState,
102
134
  },
103
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.
104
142
  const normalizeNumberPutNewStartSymbol = new State({
105
143
  [symbol(alphabet.blankSymbol)]: {
106
144
  command: {
@@ -131,6 +169,17 @@ const normalizeNumber = new State({
131
169
  nextState: haltState,
132
170
  },
133
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.
134
183
  const plusOneFillZeros = new State({
135
184
  [symbol('1')]: {
136
185
  command: {
@@ -193,6 +242,16 @@ const plusOne = new State({
193
242
  nextState: haltState,
194
243
  },
195
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.
196
255
  const minusOne = new State({
197
256
  [symbol('^10')]: {
198
257
  command: {
@@ -209,6 +268,49 @@ const minusOne = new State({
209
268
  nextState: haltState,
210
269
  },
211
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');
212
314
  function getTapeBlock() {
213
315
  return tapeBlock.clone();
214
316
  }
@@ -224,6 +326,7 @@ var index = {
224
326
  normalizeNumber,
225
327
  plusOne,
226
328
  minusOne,
329
+ minusOneFast,
227
330
  },
228
331
  };
229
332
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turing-machine-js/library-binary-numbers",
3
- "version": "2.0.2",
3
+ "version": "3.0.1",
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,8 +26,8 @@
26
26
  "binary",
27
27
  "numbers"
28
28
  ],
29
- "dependencies": {
30
- "@turing-machine-js/machine": "^2.0.2"
29
+ "peerDependencies": {
30
+ "@turing-machine-js/machine": "^3.0.0"
31
31
  },
32
32
  "main": "dist/index.cjs",
33
33
  "module": "dist/index.mjs",
@@ -40,5 +40,5 @@
40
40
  "default": "./dist/index.mjs"
41
41
  }
42
42
  },
43
- "gitHead": "54da1870a45fd78496c6ba56ce1de728d766470b"
43
+ "gitHead": "0a8d7ff87a3a73ea7ee1844f7f4602cbb23d20fe"
44
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
+ ```
package/dist/index.js DELETED
@@ -1,227 +0,0 @@
1
- import { Alphabet, haltState, ifOtherSymbol, movements, State, symbolCommands, TapeBlock, } from '@turing-machine-js/machine/src';
2
- const alphabet = new Alphabet(' ^$01'.split(''));
3
- const tapeBlock = TapeBlock.fromAlphabets([alphabet]);
4
- const { symbol } = tapeBlock;
5
- const goToNumber = new State({
6
- [symbol('$')]: {
7
- nextState: haltState,
8
- },
9
- [ifOtherSymbol]: {
10
- command: {
11
- movement: movements.right,
12
- },
13
- },
14
- }, 'goToNumber');
15
- const goToNextNumber = new State({
16
- [ifOtherSymbol]: {
17
- command: {
18
- movement: movements.right,
19
- },
20
- nextState: goToNumber,
21
- },
22
- }, 'goToNextNumber');
23
- const goToPreviousNumberInternal = new State({
24
- [symbol('$')]: {
25
- nextState: haltState,
26
- },
27
- [ifOtherSymbol]: {
28
- command: {
29
- movement: movements.left,
30
- },
31
- },
32
- }, 'goToPreviousNumberInternal');
33
- const goToPreviousNumber = new State({
34
- [ifOtherSymbol]: {
35
- command: {
36
- movement: movements.left,
37
- },
38
- nextState: goToPreviousNumberInternal,
39
- },
40
- }, 'goToPreviousNumber');
41
- const goToNumbersStart = new State({
42
- [symbol('^')]: {
43
- nextState: haltState,
44
- },
45
- [ifOtherSymbol]: {
46
- command: {
47
- movement: movements.left,
48
- },
49
- },
50
- }, 'goToNumberStart');
51
- const deleteNumberInternal = new State({
52
- [symbol('$')]: {
53
- command: {
54
- symbol: symbolCommands.erase,
55
- },
56
- nextState: haltState,
57
- },
58
- [ifOtherSymbol]: {
59
- command: {
60
- symbol: symbolCommands.erase,
61
- movement: movements.right,
62
- },
63
- },
64
- }, 'deleteNumberInternal');
65
- const deleteNumber = new State({
66
- [symbol('^10$')]: {
67
- nextState: goToNumbersStart.withOverrodeHaltState(deleteNumberInternal),
68
- },
69
- [ifOtherSymbol]: {
70
- nextState: haltState,
71
- },
72
- }, 'deleteNumber');
73
- const invertNumberGoToNumberWithInversion = new State({
74
- [symbol('^')]: {
75
- command: {
76
- movement: movements.right,
77
- },
78
- },
79
- [symbol('1')]: {
80
- command: {
81
- symbol: '0',
82
- movement: movements.right,
83
- },
84
- },
85
- [symbol('0')]: {
86
- command: {
87
- symbol: '1',
88
- movement: movements.right,
89
- },
90
- },
91
- [symbol('$')]: {
92
- nextState: haltState,
93
- },
94
- }, 'invertNumberGoToNumberWithInversion');
95
- const invertNumber = new State({
96
- [symbol('^10$')]: {
97
- nextState: goToNumbersStart.withOverrodeHaltState(invertNumberGoToNumberWithInversion),
98
- },
99
- [ifOtherSymbol]: {
100
- nextState: haltState,
101
- },
102
- }, 'invertNumber');
103
- const normalizeNumberPutNewStartSymbol = new State({
104
- [symbol(alphabet.blankSymbol)]: {
105
- command: {
106
- symbol: '^',
107
- },
108
- nextState: goToNumber,
109
- },
110
- }, 'normalizeNumberPutNewStartSymbol');
111
- const normalizeNumberMoveNumberStart = new State({
112
- [symbol('^0')]: {
113
- command: {
114
- symbol: symbolCommands.erase,
115
- movement: movements.right,
116
- },
117
- },
118
- [symbol('1$')]: {
119
- command: {
120
- movement: movements.left,
121
- },
122
- nextState: normalizeNumberPutNewStartSymbol,
123
- },
124
- }, 'normalizeNumberMoveNumberStart');
125
- const normalizeNumber = new State({
126
- [symbol('^10$')]: {
127
- nextState: goToNumbersStart.withOverrodeHaltState(normalizeNumberMoveNumberStart),
128
- },
129
- [ifOtherSymbol]: {
130
- nextState: haltState,
131
- },
132
- }, 'normalizeNumber');
133
- const plusOneFillZeros = new State({
134
- [symbol('1')]: {
135
- command: {
136
- symbol: '0',
137
- movement: movements.right,
138
- },
139
- },
140
- [symbol('$')]: {
141
- nextState: haltState,
142
- },
143
- }, 'plusOneFillZeros');
144
- const plusOneAddNumberStart = new State({
145
- [symbol(alphabet.blankSymbol)]: {
146
- command: {
147
- symbol: '^',
148
- movement: movements.right,
149
- },
150
- },
151
- [symbol('1')]: {
152
- command: {
153
- movement: movements.right,
154
- },
155
- nextState: plusOneFillZeros,
156
- },
157
- }, 'plusOneAddNumberStart');
158
- const plusOneCaryOne = new State({
159
- [symbol('0')]: {
160
- command: {
161
- symbol: '1',
162
- movement: movements.right,
163
- },
164
- nextState: plusOneFillZeros,
165
- },
166
- [symbol('1')]: {
167
- command: {
168
- movement: movements.left,
169
- },
170
- },
171
- [symbol('^')]: {
172
- command: {
173
- symbol: '1',
174
- movement: movements.left,
175
- },
176
- nextState: plusOneAddNumberStart,
177
- },
178
- }, 'plusOneCaryOne');
179
- const plusOne = new State({
180
- [symbol('^10')]: {
181
- command: {
182
- movement: movements.right,
183
- },
184
- },
185
- [symbol('$')]: {
186
- command: {
187
- movement: movements.left,
188
- },
189
- nextState: plusOneCaryOne,
190
- },
191
- [ifOtherSymbol]: {
192
- nextState: haltState,
193
- },
194
- }, 'plusOne');
195
- const minusOne = new State({
196
- [symbol('^10')]: {
197
- command: {
198
- movement: movements.right,
199
- },
200
- },
201
- [symbol('$')]: {
202
- nextState: invertNumber
203
- .withOverrodeHaltState(plusOne
204
- .withOverrodeHaltState(invertNumber
205
- .withOverrodeHaltState(normalizeNumber))),
206
- },
207
- [ifOtherSymbol]: {
208
- nextState: haltState,
209
- },
210
- }, 'minusOne');
211
- function getTapeBlock() {
212
- return tapeBlock.clone();
213
- }
214
- export default {
215
- getTapeBlock,
216
- states: {
217
- goToNumber,
218
- goToNextNumber,
219
- goToPreviousNumber,
220
- deleteNumber,
221
- goToNumbersStart,
222
- invertNumber,
223
- normalizeNumber,
224
- plusOne,
225
- minusOne,
226
- },
227
- };
@@ -1 +0,0 @@
1
- {"root":["./src/index.ts"],"version":"5.9.3"}