Files
zitsbit/zitsbit.js
T
z8tekandCommandCodeBot f1c2cc2a24 Add Gematria mode 10 (v1.3.0)
Port gematria logic from gematria.py: Hebrew/Arabic/English letter
values with --lang flag (hebrew|arabic|english|all). Added to both
bin/zitsbit and distributed zitsbit.js. Version bumped to 1.3.0.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
2026-07-16 15:20:10 +04:00

451 lines
16 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// ── Zitsbit mapping (conditional on next digit) ───────────────────
const ZITSBIT_MAP = {
'1': nd => nd > 5 ? '7' : '4',
'2': () => '5', '3': () => '8',
'4': nd => nd > 5 ? '7' : '1',
'5': () => '2', '6': () => '9',
'7': nd => nd > 5 ? '1' : '4',
'8': () => '3', '9': () => '6',
'0': () => '0',
};
// ── Static mirror (no conditional) ───────────────────────────────
function mirrorDigit(d) {
const map = { '0':'0','1':'1','2':'5','3':'Ɛ','4':'4','5':'2','6':'9','7':'7','8':'8','9':'6' };
return map[d] || d;
}
function mirrorString(s) {
return s.split('').map(c => mirrorDigit(c)).reverse().join('');
}
// ── Glyph mapping (symbolic digit glyphs) ───────────────────────
const GLYPH_MAP = { '0':'Ø','1':'','2':'Ƨ','3':'Ɛ','4':'ᔭ','5':'Ƽ','6':'9','7':'ᒣ','8':'∞','9':'6' };
function applyGlyphs(s) {
return [...s].map(c => GLYPH_MAP[c] || c).join('');
}
// ── Zero rules (pair-based, matches z8tek.net) ───────────────────
function applyZeroTail(digits) {
if (digits.length < 2 || digits[digits.length-1] !== '0') return digits;
const pair = parseInt(digits[digits.length-2] + digits[digits.length-1], 10);
const result = (pair - 1).toString().padStart(2, '0');
const d = [...digits];
d[d.length-2] = result[0];
d[d.length-1] = result[1];
return d;
}
function applyZeroMiddle(digits) {
let result = [...digits];
let i = 0;
while (i < result.length) {
if (result[i] === '0' && i > 0) {
const pair = parseInt(result[i-1] + result[i], 10);
const pairStr = (pair - 1).toString().padStart(2, '0');
const swapped = pairStr[1] + pairStr[0];
result[i-1] = swapped[0];
result[i] = swapped[1];
result[i-1] = '';
result = result.filter(x => x !== '');
}
i++;
}
return result;
}
function processZeros(str) {
let digits = [...str];
digits = applyZeroTail(digits);
digits = applyZeroMiddle(digits);
return digits.join('');
}
// ── Zitsbit transform (passes letters through, maps digits) ─────
function zitsbitTransform(s) {
const chars = [...s];
// Find next digit for each position
const nextDigit = (i) => {
for (let j = i + 1; j < chars.length; j++) {
if (/\d/.test(chars[j])) return parseInt(chars[j], 10);
}
return 0;
};
return chars.map((c, i) => {
if (!/\d/.test(c)) return c;
if (c === '0') return '0';
return ZITSBIT_MAP[c](nextDigit(i));
}).join('');
}
// ── Solar cycle (digit phase mapping) ────────────────────────────
function solarCycle(input) {
const steps = [`Input: ${input}`];
const digits = [...input].filter(c => /\d/.test(c)).map(Number);
const phases = [];
for (const d of digits) {
const deg = (d / 9) * 202.5;
let label;
if (deg < 90) label = 'Growth (0-90°)';
else if (deg < 180) label = 'Mirror (90-180°)';
else if (deg < 270) label = 'Infinity (180-270°)';
else label = 'Unity/Return (270-360°)';
phases.push({ digit: d, degrees: deg.toFixed(1), phase: label });
steps.push(` ${d}${deg.toFixed(1)}° → ${label}`);
}
return { result: digits.map(d => ((d/9)*202.5).toFixed(0) + '°').join(' '), steps, phases };
}
// ── Retrograde (each digit -1) ───────────────────────────────────
function retrograde(input) {
const steps = [`Input: ${input}`];
const result = [...input].map(c => {
if (/\d/.test(c)) {
const r = (parseInt(c, 10) - 1 + 10) % 10;
steps.push(` ${c}${r}`);
return String(r);
}
if (/[a-z]/.test(c)) {
const r = String.fromCharCode(((c.charCodeAt(0) - 97 - 1 + 26) % 26) + 97);
steps.push(` ${c}${r}`);
return r;
}
if (/[A-Z]/.test(c)) {
const r = String.fromCharCode(((c.charCodeAt(0) - 65 - 1 + 26) % 26) + 65);
steps.push(` ${c}${r}`);
return r;
}
return c;
}).join('');
return { result, steps };
}
// ── Block Cycle (rotate-left N → static map → detect cycle) ─────
const BLOCK_MAP = { '0':'3','1':'3','2':'4','3':'2','4':'1','5':'5','6':'6','7':'7','8':'3','9':'6' };
function blockCycle(input, shift = 3, alignTo) {
const steps = [`Input: ${input}`, '', ' Step Value'];
const sep = ' ──── ─────────';
steps.push(sep);
const seen = {};
let state = String(input);
const block = [];
let iter = 1;
while (iter <= 21) {
if (state in seen) {
const first = seen[state];
const cycle = block.slice(first);
steps.push(` It${String(iter).padEnd(4)} ${state} ← cycle`);
steps.push('');
steps.push(` ✓ Cycle ${cycle.length} (starts at step ${first+1}):`);
steps.push(` ${cycle.join(' → ')}`);
return { result: cycle.join(' → '), steps, iterations: iter, cycleLen: cycle.length };
}
seen[state] = block.length;
block.push(state);
steps.push(` It${String(iter).padEnd(4)} ${state}`);
let rotated;
if (alignTo && iter === 1) {
const idx = state.indexOf(alignTo);
if (idx > 0) {
rotated = state[idx] + state[idx-1] + state.slice(0, idx-1) + state.slice(idx+1);
} else if (idx === 0) {
rotated = state;
} else {
rotated = state;
}
} else {
rotated = state.slice(shift) + state.slice(0, shift);
}
state = [...rotated].map(c => BLOCK_MAP[c] || c).join('');
iter++;
}
return { result: state, steps, iterations: iter-1 };
}
// ── Scenarios ────────────────────────────────────────────────────
function scenario1(input, maxIter = 21) {
const parts = input.split('.');
let left = parts[0], right = parts[1] || '';
const seen = { [input]: 0 }, steps = []; steps.push(`Input: ${input}`, '', ' Step Value');
const sep = ' ──── ─────────';
steps.push(sep);
let iter = 1;
let usedFallback = false;
while (iter <= maxIter) {
const revL = [...left].reverse().join(''),
revR = right ? [...right].reverse().join('') : '';
let out = zitsbitTransform(revL) + (right ? '.'+zitsbitTransform(revR) : '');
// Fallback once: if rev→zb is seen, try zb-direct to break out of 2-cycle
if ((out in seen) && !usedFallback) {
const direct = zitsbitTransform(left) + (right ? '.'+zitsbitTransform(right) : '');
if (!(direct in seen)) {
out = direct;
usedFallback = true;
}
}
steps.push(` It${String(iter).padEnd(4)} ${out}`);
if (out in seen) {
const cycleStart = seen[out];
const cycleLen = iter - cycleStart;
steps.push('');
steps.push(` ✓ Cycle ${cycleLen} (starts at step ${cycleStart+1}): ${out}`);
return { result: out, steps, iterations: iter, cycleStart, cycleLen };
}
seen[out] = iter;
left = out.split('.')[0]; right = out.includes('.') ? out.split('.')[1] : '';
iter++;
}
return { result: left + (right ? '.'+right : ''), steps, iterations: iter-1 };
}
function scenario2(input, maxIter = 20) {
const parts = input.split('.');
let left = parts[0], right = parts[1] || '';
const seen = [], steps = []; steps.push(`Input: ${input}`);
let iter = 1;
while (iter <= maxIter) {
const mirL = mirrorString(left),
mirR = right ? mirrorString(right) : '';
const zbL = zitsbitTransform(mirL),
zbR = right ? zitsbitTransform(mirR) : '';
const revL = [...zbL].reverse().join(''),
revR = right ? [...zbR].reverse().join('') : '';
const out = revL + (right ? '.'+revR : '');
steps.push(` It${iter}: mirror(${mirL}${right ? '/'+mirR : ''}) → zitsbit(${zbL}${right ? '/'+zbR : ''}) → reverse(${out})`);
if (seen.slice(-2).includes(out)) {
steps.push(` ✓ Stable/2-cycle at iteration ${iter}: ${out}`);
return { result: out, steps, iterations: iter };
}
seen.push(out);
left = out.split('.')[0];
right = out.includes('.') ? out.split('.')[1] : '';
iter++;
}
return { result: left + (right ? '.'+right : ''), steps, iterations: iter-1 };
}
function scenario3(input, _offset = 0) {
return solarCycle(input);
}
function scenario6(input) {
return retrograde(input);
}
function scenario7(input) {
const steps = [`Input: ${input}`];
const mir = mirrorString(input);
steps.push(`Mirror: ${mir}`);
return { result: mir, steps };
}
function scenario8(input) {
const steps = [`Input: ${input}`];
const rev = [...input].reverse().join('');
steps.push(`Reversed: ${rev}`);
const mir = mirrorString(rev);
steps.push(`Mirror: ${mir}`);
return { result: mir, steps };
}
function scenario9(input) {
const steps = [`Input: ${input}`];
const mir = mirrorString(input);
steps.push(`Mirror: ${mir}`);
const rev = [...mir].reverse().join('');
steps.push(`Reversed: ${rev}`);
return { result: rev, steps };
}
// ── Rotation digit mapping (perspective number rule) ────────────
// After orbit rotation, digits may need remapping based on their
// rotated readability. Same conditional pattern as zitsbit map.
const ROTATION_MAP = {
'0': () => '0',
'1': nd => nd > 5 ? '7' : '1',
'2': nd => nd > 5 ? '5' : '2',
'3': nd => nd > 5 ? '8' : '3',
'4': () => '4',
'5': nd => nd > 5 ? '2' : '5',
'6': () => '9',
'7': nd => nd > 5 ? '1' : '7',
'8': nd => nd > 5 ? '3' : '8',
'9': () => '6',
};
function applyRotationMap(str) {
const digits = [...str].filter(c => /\d/.test(c));
return digits.map((d, i) => {
const nd = i + 1 < digits.length ? parseInt(digits[i+1], 10) : 0;
return ROTATION_MAP[d](nd);
}).join('');
}
// ── Orbit rotation (position shift only) ─────────────────────────
// Then applies rotation digit mapping.
function orbitTransform(str, angle) {
if (!angle) return null; // no perspective, skip
const steps = (angle / 90) % str.length;
if (!steps) return str;
const out = new Array(str.length);
[...str].forEach((c, i) => { out[(i + steps) % str.length] = c; });
const shifted = out.join('');
return applyRotationMap(shifted);
}
// ── Reverse helper ───────────────────────────────────────────────
function reverse(s) { return [...s].reverse().join(''); }
// ── Gematria (letter → numeric value, multi-language) ──────────
const GEMATRIA_MAPS = {
hebrew: {
'א':1,'ב':2,'ג':3,'ד':4,'ה':5,'ו':6,'ז':7,'ח':8,'ט':9,
'י':10,'כ':20,'ך':20,'ל':30,'מ':40,'ם':40,'נ':50,'ן':50,
'ס':60,'ע':70,'פ':80,'ף':80,'צ':90,'ץ':90,'ק':100,'ר':200,
'ש':300,'ת':400,
},
arabic: {
'ا':1,'أ':1,'إ':1,'آ':1,'ب':2,'ج':3,'د':4,'ه':5,'ة':5,
'و':6,'ز':7,'ح':8,'ط':9,'ي':10,'ى':10,'ك':20,'ل':30,
'م':40,'ن':50,'س':60,'ع':70,'ف':80,'ص':90,'ق':100,
'ر':200,'ش':300,'ت':400,'ث':500,'خ':600,'ذ':700,'ض':800,
'ظ':900,'غ':1000,
},
english: (() => { const m = {}; const A = 'A'.charCodeAt(0); for (let i = 0; i < 26; i++) m[String.fromCharCode(A + i)] = i + 1; return m; })(),
};
function gematria(input, lang = 'all') {
const steps = [`Input: ${input}`, `Language: ${lang}`];
const langs = lang === 'all' ? Object.keys(GEMATRIA_MAPS) : [lang];
const results = {};
for (const L of langs) {
const map = GEMATRIA_MAPS[L];
let total = 0;
const breakdown = [];
for (const ch of [...input]) {
const uc = ch.toUpperCase();
const v = map[ch] ?? map[uc] ?? 0;
if (v) { breakdown.push(`${ch}=${v}`); total += v; }
}
results[L] = total;
steps.push(` ${L.toUpperCase()}: ${total}`);
if (breakdown.length) steps.push(` ${breakdown.join(' + ')}`);
else steps.push(` none`);
}
const summary = Object.entries(results).map(([k, v]) => `${k}:${v}`).join(' ');
return { result: summary, steps, totals: results };
}
// ── Transform dispatcher ─────────────────────────────────────────
function splitDecimal(s) {
const i = s.indexOf('.');
if (i === -1) return [s, null];
return [s.slice(0, i), s.slice(i+1)];
}
function joinDecimal(left, right) {
return right !== null ? left + '.' + right : left;
}
function preprocess(input) {
// Always apply zero + decimal rules before the mode transform
const [left, right] = splitDecimal(input);
const zL = processZeros(left);
const zR = right !== null ? processZeros(right) : null;
return joinDecimal(zL, zR);
}
function transform(input, mode, align, lang = 'all') {
input = preprocess(input);
switch (mode) {
case 1: return scenario1(input);
case 2: { const r = zitsbitTransform(input); return { result: r, steps: [`Input: ${input}`, `Zitsbit: ${r}`] }; }
case 3: return scenario3(input);
case 5: { const r = blockCycle(input, 3, align); return r; }
case 6: return scenario6(input);
case 7: return scenario7(input);
case 8: return scenario8(input);
case 9: return scenario9(input);
case 10: return gematria(input, lang);
default: return scenario1(input);
}
}
// ── CLI ──────────────────────────────────────────────────────────
const VERSION = '1.3.0';
const args = process.argv.slice(2);
if (args.includes('--version') || args.includes('-v')) {
console.log(`zitsbit v${VERSION}`); process.exit(0);
}
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
console.log(`Usage: zitsbit [-m <n>] [-a <char>] [--glyph] [--perspective <angle>] <value>
Flags:
-m, --mode <n> Scenario mode (default: 1)
-a, --align <char> Align block cycle to start with this character (mode 5)
-g, --glyph Convert digits to symbolic glyphs
-p, --perspective <deg> Orbit rotation angle (0|90|180|270)
-l, --lang <lang> Gematria language: hebrew|arabic|english|all (mode 10)
-v, --version Show version
-h, --help Show help
Modes:
1 Reverse Cycle (rev → zitsbit, iterative with fallback) (default)
2 Direct Rule (zitsbit only, no reverse)
3 Solar Cycle (digit phase mapping)
5 Block Cycle (rotate-left 3 → static map → cycle detect)
6 Retrograde only (each digit -1)
7 Normal Mirror (reverse + static glyph map)
9 Mirror then Reverse (static glyph → reverse)
10 Gematria (letter → numeric value, hebrew/arabic/english)
Zero & decimal rules applied automatically.`);
process.exit(0);
}
let mode = 1, perspective = 0, glyph = false, align = '', lang = 'all', value;
const modeIdx = args.indexOf('--mode');
const modeShort = args.indexOf('-m');
const modeFinal = modeIdx !== -1 ? modeIdx : modeShort;
if (modeFinal !== -1 && modeFinal+1 < args.length) {
mode = parseInt(args[modeFinal+1], 10); args.splice(modeFinal, 2);
}
const glyphIdx = args.indexOf('--glyph');
if (glyphIdx !== -1) { glyph = true; args.splice(glyphIdx, 1); }
const gIdx = args.indexOf('-g');
if (gIdx !== -1) { glyph = true; args.splice(gIdx, 1); }
const alignIdx = args.indexOf('--align');
if (alignIdx !== -1 && alignIdx+1 < args.length) { align = args[alignIdx+1]; args.splice(alignIdx, 2); }
const aIdx = args.indexOf('-a');
if (aIdx !== -1 && aIdx+1 < args.length) { align = args[aIdx+1]; args.splice(aIdx, 2); }
const langIdx = args.indexOf('--lang');
const lIdx = args.indexOf('-l');
const li = langIdx !== -1 ? langIdx : lIdx;
if (li !== -1 && li+1 < args.length) { lang = args[li+1]; args.splice(li, 2); }
const perspIdx = args.indexOf('--perspective');
const pIdx = args.indexOf('-p');
const pi = perspIdx !== -1 ? perspIdx : pIdx;
if (pi !== -1 && pi+1 < args.length) {
perspective = parseInt(args[pi+1], 10); args.splice(pi, 2);
}
value = args.join(' ');
if (!value) { console.error('Error: no value provided.'); process.exit(1); }
// Perspective pre-processes, then mode runs on the rotated result
const orb = orbitTransform(value, perspective);
const input = orb !== null ? orb : value;
let output = transform(input, mode, align, lang);
let result = output.result;
if (glyph) result = applyGlyphs(result);
console.log(`\nResult: ${result}\n`);
console.log(output.steps.join('\n'));