gematry
Version:
Gematria calculator (Hebrew only)
151 lines (142 loc) • 3.5 kB
text/typescript
export function toNumber(
phrase: string,
options: Partial<ToNumberOptions> = DEFAULT_TO_NUMBER_OPTIONS
): number {
// fill missing options with defaults
options = { ...DEFAULT_TO_NUMBER_OPTIONS, ...options };
let sum = 0;
let i = phrase.length;
const dict = options.treatManzpachDifferently
? lettersValuesWithMantzpach
: lettersValues;
while (i--) {
if (phrase[i] >= "א" && phrase[i] <= "ת") {
const letter = phrase[i] as Letter;
sum += dict[letter];
} else if (options.throwIfNotLetter) {
throw new Error(`Character ${phrase[i]} is not a letter`);
}
}
return sum;
}
export function toLetters(
number: number,
options: Partial<ToLettersOptions> = DEFAULT_TO_LETTERS_OPTIONS
): string {
// fill missing options with defaults
options = { ...DEFAULT_TO_LETTERS_OPTIONS, ...options };
let result = "";
let thousandsPart = 0;
if (options.thousands) {
while (number > 1000) {
const numberOfThousands = Math.floor(number / 1000);
thousandsPart = numberOfThousands * 1000;
result += toLetters(numberOfThousands);
if (options.thousandsSeparator !== "" && thousandsPart !== number) {
result += options.thousandsSeparator;
}
number -= thousandsPart;
}
}
const unitsPart = number % 10;
const tensPart = (Math.floor(number / 10) % 10) * 10;
let rest = number - tensPart - unitsPart;
while (rest >= 400) {
result += "ת";
rest -= 400;
}
const hundredsPart = rest;
if (hundredsPart > 0) {
result += keyByValue(hundredsPart);
}
if (options.maskHashem && tensPart + unitsPart === 15) {
result += "טו";
} else if (options.maskHashem && tensPart + unitsPart === 16) {
result += "טז";
} else {
result += keyByValue(tensPart);
result += keyByValue(unitsPart);
}
if (
options.addQuotes &&
((thousandsPart == 0 && result.length >= 2) ||
(thousandsPart > 0 && result.length >= 3))
) {
result = result.slice(0, -1) + '"' + result.slice(-1);
}
return result;
}
const lettersValues = {
א: 1,
ב: 2,
ג: 3,
ד: 4,
ה: 5,
ו: 6,
ז: 7,
ח: 8,
ט: 9,
י: 10,
כ: 20,
ל: 30,
מ: 40,
נ: 50,
ס: 60,
ע: 70,
פ: 80,
צ: 90,
ק: 100,
ר: 200,
ש: 300,
ת: 400,
ך: 20,
ם: 40,
ן: 50,
ף: 80,
ץ: 90,
"": 0,
};
const lettersValuesWithMantzpach = {
...lettersValues,
ך: 500,
ם: 600,
ן: 700,
ף: 800,
ץ: 900,
};
interface ToNumberOptions {
treatManzpachDifferently: boolean;
throwIfNotLetter: boolean;
}
const DEFAULT_TO_NUMBER_OPTIONS: ToNumberOptions = {
treatManzpachDifferently: false,
throwIfNotLetter: false,
};
type Letter = keyof typeof lettersValuesWithMantzpach;
interface ToLettersOptions {
maskHashem: boolean;
thousands: boolean;
thousandsSeparator: string;
addQuotes: boolean;
}
const DEFAULT_TO_LETTERS_OPTIONS: ToLettersOptions = {
maskHashem: true,
thousands: false,
thousandsSeparator: "",
addQuotes: false,
};
function keyByValue(
value: number,
dict: { [key: string]: number } = lettersValues
): string {
const entries = Object.entries(dict);
let result = "";
for (const [key, val] of entries) {
if (val === value) {
result = key;
// not returning directly to not lose coverage
break;
}
}
return result;
}