@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 +47 -0
- package/README.md +78 -31
- package/dist/index.cjs +168 -65
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +104 -1
- package/package.json +5 -5
- package/states.md +266 -0
- package/dist/index.js +0 -227
- package/tsconfig.tsbuildinfo +0 -1
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
|
[](https://github.com/mellonis/turing-machine-js/actions/workflows/main.yml)
|
|
4
|
-

|
|
4
|
+
[](https://www.npmjs.com/package/@turing-machine-js/library-binary-numbers)
|
|
5
5
|
|
|
6
|
-
|
|
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
|
-
|
|
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
|
-
|
|
20
|
+
```
|
|
21
|
+
…blank ^101011$ blank ^110010$ blank…
|
|
22
|
+
╰─ 43 ─╯ ╰─ 50 ─╯
|
|
23
|
+
```
|
|
19
24
|
|
|
20
|
-
|
|
25
|
+
Examples:
|
|
26
|
+
- `^$` represents 0
|
|
27
|
+
- `^1$` represents 1
|
|
28
|
+
- `^10$` represents 2
|
|
29
|
+
- `^11$` represents 3
|
|
21
30
|
|
|
22
|
-
|
|
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
|
-
|
|
33
|
+
## Algorithms
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
49
|
-
|
|
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
|
|
3
|
+
var machine = require('@turing-machine-js/machine');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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:
|
|
21
|
+
nextState: machine.haltState,
|
|
11
22
|
},
|
|
12
|
-
[
|
|
23
|
+
[machine.ifOtherSymbol]: {
|
|
13
24
|
command: {
|
|
14
|
-
movement:
|
|
25
|
+
movement: machine.movements.right,
|
|
15
26
|
},
|
|
16
27
|
},
|
|
17
28
|
}, 'goToNumber');
|
|
18
|
-
|
|
19
|
-
|
|
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:
|
|
36
|
+
movement: machine.movements.right,
|
|
22
37
|
},
|
|
23
38
|
nextState: goToNumber,
|
|
24
39
|
},
|
|
25
40
|
}, 'goToNextNumber');
|
|
26
|
-
|
|
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:
|
|
46
|
+
nextState: machine.haltState,
|
|
29
47
|
},
|
|
30
|
-
[
|
|
48
|
+
[machine.ifOtherSymbol]: {
|
|
31
49
|
command: {
|
|
32
|
-
movement:
|
|
50
|
+
movement: machine.movements.left,
|
|
33
51
|
},
|
|
34
52
|
},
|
|
35
53
|
}, 'goToPreviousNumberInternal');
|
|
36
|
-
const goToPreviousNumber = new
|
|
37
|
-
[
|
|
54
|
+
const goToPreviousNumber = new machine.State({
|
|
55
|
+
[machine.ifOtherSymbol]: {
|
|
38
56
|
command: {
|
|
39
|
-
movement:
|
|
57
|
+
movement: machine.movements.left,
|
|
40
58
|
},
|
|
41
59
|
nextState: goToPreviousNumberInternal,
|
|
42
60
|
},
|
|
43
61
|
}, 'goToPreviousNumber');
|
|
44
|
-
|
|
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:
|
|
67
|
+
nextState: machine.haltState,
|
|
47
68
|
},
|
|
48
|
-
[
|
|
69
|
+
[machine.ifOtherSymbol]: {
|
|
49
70
|
command: {
|
|
50
|
-
movement:
|
|
71
|
+
movement: machine.movements.left,
|
|
51
72
|
},
|
|
52
73
|
},
|
|
53
74
|
}, 'goToNumberStart');
|
|
54
|
-
|
|
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:
|
|
84
|
+
symbol: machine.symbolCommands.erase,
|
|
58
85
|
},
|
|
59
|
-
nextState:
|
|
86
|
+
nextState: machine.haltState,
|
|
60
87
|
},
|
|
61
|
-
[
|
|
88
|
+
[machine.ifOtherSymbol]: {
|
|
62
89
|
command: {
|
|
63
|
-
symbol:
|
|
64
|
-
movement:
|
|
90
|
+
symbol: machine.symbolCommands.erase,
|
|
91
|
+
movement: machine.movements.right,
|
|
65
92
|
},
|
|
66
93
|
},
|
|
67
94
|
}, 'deleteNumberInternal');
|
|
68
|
-
const deleteNumber = new
|
|
95
|
+
const deleteNumber = new machine.State({
|
|
69
96
|
[symbol('^10$')]: {
|
|
70
97
|
nextState: goToNumbersStart.withOverrodeHaltState(deleteNumberInternal),
|
|
71
98
|
},
|
|
72
|
-
[
|
|
73
|
-
nextState:
|
|
99
|
+
[machine.ifOtherSymbol]: {
|
|
100
|
+
nextState: machine.haltState,
|
|
74
101
|
},
|
|
75
102
|
}, 'deleteNumber');
|
|
76
|
-
|
|
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:
|
|
111
|
+
movement: machine.movements.right,
|
|
80
112
|
},
|
|
81
113
|
},
|
|
82
114
|
[symbol('1')]: {
|
|
83
115
|
command: {
|
|
84
116
|
symbol: '0',
|
|
85
|
-
movement:
|
|
117
|
+
movement: machine.movements.right,
|
|
86
118
|
},
|
|
87
119
|
},
|
|
88
120
|
[symbol('0')]: {
|
|
89
121
|
command: {
|
|
90
122
|
symbol: '1',
|
|
91
|
-
movement:
|
|
123
|
+
movement: machine.movements.right,
|
|
92
124
|
},
|
|
93
125
|
},
|
|
94
126
|
[symbol('$')]: {
|
|
95
|
-
nextState:
|
|
127
|
+
nextState: machine.haltState,
|
|
96
128
|
},
|
|
97
129
|
}, 'invertNumberGoToNumberWithInversion');
|
|
98
|
-
const invertNumber = new
|
|
130
|
+
const invertNumber = new machine.State({
|
|
99
131
|
[symbol('^10$')]: {
|
|
100
132
|
nextState: goToNumbersStart.withOverrodeHaltState(invertNumberGoToNumberWithInversion),
|
|
101
133
|
},
|
|
102
|
-
[
|
|
103
|
-
nextState:
|
|
134
|
+
[machine.ifOtherSymbol]: {
|
|
135
|
+
nextState: machine.haltState,
|
|
104
136
|
},
|
|
105
137
|
}, 'invertNumber');
|
|
106
|
-
|
|
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
|
|
152
|
+
const normalizeNumberMoveNumberStart = new machine.State({
|
|
115
153
|
[symbol('^0')]: {
|
|
116
154
|
command: {
|
|
117
|
-
symbol:
|
|
118
|
-
movement:
|
|
155
|
+
symbol: machine.symbolCommands.erase,
|
|
156
|
+
movement: machine.movements.right,
|
|
119
157
|
},
|
|
120
158
|
},
|
|
121
159
|
[symbol('1$')]: {
|
|
122
160
|
command: {
|
|
123
|
-
movement:
|
|
161
|
+
movement: machine.movements.left,
|
|
124
162
|
},
|
|
125
163
|
nextState: normalizeNumberPutNewStartSymbol,
|
|
126
164
|
},
|
|
127
165
|
}, 'normalizeNumberMoveNumberStart');
|
|
128
|
-
const normalizeNumber = new
|
|
166
|
+
const normalizeNumber = new machine.State({
|
|
129
167
|
[symbol('^10$')]: {
|
|
130
168
|
nextState: goToNumbersStart.withOverrodeHaltState(normalizeNumberMoveNumberStart),
|
|
131
169
|
},
|
|
132
|
-
[
|
|
133
|
-
nextState:
|
|
170
|
+
[machine.ifOtherSymbol]: {
|
|
171
|
+
nextState: machine.haltState,
|
|
134
172
|
},
|
|
135
173
|
}, 'normalizeNumber');
|
|
136
|
-
|
|
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:
|
|
189
|
+
movement: machine.movements.right,
|
|
141
190
|
},
|
|
142
191
|
},
|
|
143
192
|
[symbol('$')]: {
|
|
144
|
-
nextState:
|
|
193
|
+
nextState: machine.haltState,
|
|
145
194
|
},
|
|
146
195
|
}, 'plusOneFillZeros');
|
|
147
|
-
const plusOneAddNumberStart = new
|
|
196
|
+
const plusOneAddNumberStart = new machine.State({
|
|
148
197
|
[symbol(alphabet.blankSymbol)]: {
|
|
149
198
|
command: {
|
|
150
199
|
symbol: '^',
|
|
151
|
-
movement:
|
|
200
|
+
movement: machine.movements.right,
|
|
152
201
|
},
|
|
153
202
|
},
|
|
154
203
|
[symbol('1')]: {
|
|
155
204
|
command: {
|
|
156
|
-
movement:
|
|
205
|
+
movement: machine.movements.right,
|
|
157
206
|
},
|
|
158
207
|
nextState: plusOneFillZeros,
|
|
159
208
|
},
|
|
160
209
|
}, 'plusOneAddNumberStart');
|
|
161
|
-
const plusOneCaryOne = new
|
|
210
|
+
const plusOneCaryOne = new machine.State({
|
|
162
211
|
[symbol('0')]: {
|
|
163
212
|
command: {
|
|
164
213
|
symbol: '1',
|
|
165
|
-
movement:
|
|
214
|
+
movement: machine.movements.right,
|
|
166
215
|
},
|
|
167
216
|
nextState: plusOneFillZeros,
|
|
168
217
|
},
|
|
169
218
|
[symbol('1')]: {
|
|
170
219
|
command: {
|
|
171
|
-
movement:
|
|
220
|
+
movement: machine.movements.left,
|
|
172
221
|
},
|
|
173
222
|
},
|
|
174
223
|
[symbol('^')]: {
|
|
175
224
|
command: {
|
|
176
225
|
symbol: '1',
|
|
177
|
-
movement:
|
|
226
|
+
movement: machine.movements.left,
|
|
178
227
|
},
|
|
179
228
|
nextState: plusOneAddNumberStart,
|
|
180
229
|
},
|
|
181
230
|
}, 'plusOneCaryOne');
|
|
182
|
-
const plusOne = new
|
|
231
|
+
const plusOne = new machine.State({
|
|
183
232
|
[symbol('^10')]: {
|
|
184
233
|
command: {
|
|
185
|
-
movement:
|
|
234
|
+
movement: machine.movements.right,
|
|
186
235
|
},
|
|
187
236
|
},
|
|
188
237
|
[symbol('$')]: {
|
|
189
238
|
command: {
|
|
190
|
-
movement:
|
|
239
|
+
movement: machine.movements.left,
|
|
191
240
|
},
|
|
192
241
|
nextState: plusOneCaryOne,
|
|
193
242
|
},
|
|
194
|
-
[
|
|
195
|
-
nextState:
|
|
243
|
+
[machine.ifOtherSymbol]: {
|
|
244
|
+
nextState: machine.haltState,
|
|
196
245
|
},
|
|
197
246
|
}, 'plusOne');
|
|
198
|
-
|
|
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:
|
|
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
|
-
[
|
|
211
|
-
nextState:
|
|
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
|
|
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
|
|
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": "
|
|
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
|
-
"
|
|
30
|
-
"@turing-machine-js/machine": "^
|
|
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": "
|
|
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
|
-
};
|
package/tsconfig.tsbuildinfo
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"root":["./src/index.ts"],"version":"5.9.3"}
|