Proof of concept: https://numerology.mysticalriver.com
Using either Pythagorean or Chaldean number systems, this calculator does various common numerological name and date calculations:
- Destiny / Expression
- Soul's Urge / Heart's Desire
- Personality
- Hidden Passions
- Karmic Lessons
- Life Path
The truly unique aspect of this package, however, is that it also provides methods to search for either names or dates that satisfy various numerological criteria. This is useful if one is trying to find a name for a baby, or a wedding date that has the desirable numerological properties.
The way that it does this is using a precomputed table of names with corresponding numerological properties. This allows the table to be searched for specific names that satisfy given constraints. This method is surprisingly efficient. A database of 100,000 names with all the necessary pre-calculations is only 13.5 MB and searches take only hundredths of a second.
This calculator does not provide any numerological interpretations as part of the package. Just the raw numbers.
See additional documentation at pkg.go.dev.
go get "github.com/LanderTome/numerologyCalculator"
When doing a name calculation there are three properties that need to be specified that affect the calculation output:
- Number System
- Master Numbers
- Reduce Words
The Number System
is either one of the two most common systems that are used to assign numbers to the letters of
alphabet; Pythagorean and Chaldean.
The Master Numbers
are numbers that are considered to have special numerological importance, and are treated in
differently in calculations. The most commonly cited master numbers 11, 22, and 33. However, some consider ALL repeated
numbers to be special, ex. 44, 55, 66, etc. The master numbers that one wants to use can be customized.
When Reduce Words
is true, the calculation process sums and reduces each name individually before summing and reducing
those results. When it is false, all the parts of a name are summed and reduced together. The most common way is to sum
and reduce each name individually.
Start a name calculation with the Name
function.
package main
import "github.com/LanderTome/numerologyCalculator/numerology"
func main() {
numberSystem := numerology.Pythagorean
masterNumbers := []int{11, 22, 33}
reduceWords := true
name := numerology.Name("John Doe", numberSystem, masterNumbers, reduceWords)
}
The returned struct is now the basis for calculating the numerological properties of the given name.
Now the various numerological numbers can be calculated by calling the various methods.
result := name.Full()
destiny := name.Destiny() // alias for name.Full()
expression := name.Expression() // alias for name.Full()
result := name.Vowels()
soulsUrge := name.SoulsUrge() // alias for name.Vowels()
heartsDesire := name.HeartsDesire() // alias for name.Vowels()
result := name.Consonants()
personality := name.Personality() // alias for name.Consonants()
hiddenPassions := name.HiddenPassions()
karmicLessons := name.KarmicLessons()
Full, Vowels, and Consonants
are used instead of the common numerological terms because there are sometimes multiple
acceptable terms, and it can make is easier to understand which calculation is being done because you know what letters
of the name are being used.
Aliases for the above methods are provided for convenience.
The returned NumerologicalResult
struct contains information about the calculation. Value
is the final reduced
numerological number.
ReduceSteps
is a slice of numbers that are the numerological values at each stage of the final reducing. Breakdown
contains the calculated values for each letter and each name that are used as the basis of the calculations.
NumerologicalResult
has a method Debug()
that returns a multiline string that contains a simplistic breakdown of the
calculation steps. It can be used to visualize the conversion.
package main
import "github.com/LanderTome/numerologyCalculator/numerology"
func main() {
numberSystem := numerology.Pythagorean
masterNumbers := []int{11, 22, 33}
reduceWords := true
name := numerology.Name("Janet Audrey Doe", numberSystem, masterNumbers, reduceWords)
personality := name.Consonants()
println(personality.Debug())
}
Output:
J a n e t
1 · 5 · 2 = 8
A u d r e y
· · 4 9 · 7 = 20 = 2
D o e
4 · · = 4
Reduce: 14 = 5
Where this calculator stands apart from other ones is in its ability to search for names that match given numerological criteria. The idea is to scan a database of names, and find ones that, when combined with given names, have the numerological properties that are specified. This task can be done with brute force methods, but several tricks as utilized here to filter out names that we know won't work before actually querying the database.
package main
import "github.com/LanderTome/numerologyCalculator/numerology"
func main() {
numberSystem := numerology.Pythagorean
masterNumbers := []int{11, 22, 33}
reduceWords := true
name := numerology.Name("Jane ? Doe", numberSystem, masterNumbers, reduceWords)
searchOpts := numerology.NameSearchOpts{
Count: 10,
Offset: 0,
Seed: 0,
Database: "sqlite://test_names.db",
Dictionary: "usa_census",
Gender: numerology.Female,
Sort: numerology.CommonSort,
Full: []int{1, 8, -13},
Vowels: []int{4, 5, 6},
Consonants: []int{5},
HiddenPassions: nil,
KarmicLessons: nil,
}
results, offset, err := name.Search(searchOpts)
}
NameSearchOpts
contains the necessary information to do the search. Count
is the number of results to return in each
batch.
Offset
is used to return the next batch of results. Seed
is used for generating the "random" sort results. The seed
needs to be known if batching through random results in order to keep the results consistent. Dictionary
is the name
of the table in the database that will be searched. The included test files are from the US Census. Gender
allows
the names to be filtered by gender, so the results will be more male or female sounding. Database
is the database connection string that connects to the database that has the table to be searched.
Numerological properties: Full
, Vowels
, Consonants
,
HiddenPassions
, and KarmicLessons
. These are all slices of integers that specify what criteria we want. Positive
numbers are numbers that are acceptable. Negative numbers are numbers that are to be excluded. A common use for negative
numbers would be to exclude, what are referred to as, Karmic Debt numbers
(13, 14, 16, 17). By specifying []int{-13, -14, -16, -19}
, the search results will not include names with those
numbers.
The return consists of a slice of NameNumerology
results, an offset number that indicates where the next batch of
results should begin, and any errors messages that occur. To get the next batch use the given offset number in
the NameSearchOpts
.
Date calculation are done with the Date
function.
package main
import "github.com/LanderTome/numerologyCalculator/numerology"
func main() {
dt := numerology.NewDate(2021, 1, 1)
masterNumbers := []int{11, 22, 33}
date := numerology.Date(dt, masterNumbers)
}
The available methods for date numerology are Event()
and
LifePath()
.
event := name.Event()
lifePath := name.LifePath()
The only real difference between an event calculation and a life path calculation is that life path takes master numbers
into account. The returned NumerologicalResult
similar to that which is returned by the Name
methods.
The calculator is able to search for dates with specific numerological criteria. Unlike the name search, there are no clever optimizations to this process. It simply loops through each date, and checks that it meets the criteria. Usually, the search space for dates is only a few hundred days, so this does not significantly impact performance.
Life Path numbers have to do with one's date of birth so searching does not make a lot of sense because it is quite difficult to control when someone is born. Searching dates is better suited for finding ideal wedding or event dates.
package main
import "github.com/LanderTome/numerologyCalculator/numerology"
func main() {
dt := numerology.NewDate(2021, 1, 1)
masterNumbers := []int{11, 22, 33}
date := numerology.Date(dt, masterNumbers)
searchOpts := numerology.DateSearchOpts{
Count: 10,
Offset: 0,
Match: []int{3, 6},
MonthsForward: 12,
Dow: []int{numerology.Friday, numerology.Saturday},
LifePath: false,
}
results, offset := date.Search(searchOpts)
}
DateSearchOpts
contains the necessary information to do the search. Count
is the number of results to return in each
batch.
Offset
is used to return the next batch of results. Match
contains the numerological numbers to find. Positive numbers indicate numbers that are acceptable, and Negative numbers
indicate numbers that will be avoided. MonthsForward
is the number of months to search. It does not necessarily make
sense to search 5 years out for a wedding that you want to have in 1 or 2 years.
Dow
are days of the week that you want results on. This helps if you are only interested in events that occur on
particular days; like weekends. LifePath
indicates whether the dates should take Master Numbers into account.
Before using the name search functionality, a database needs to be created and populated.
package main
import "github.com/LanderTome/numerologyCalculator/numerology"
func main() {
dsn := "sqlite://file::memory:" // Example for testing
namesDir := "test_names"
if err := numerology.CreateDatabase(dsn, namesDir); err != nil {
println(err.Error())
}
}
DSN (data source name) is the connection string for the database to use. This library uses Gorm for the database connection. It currently supports MySQL, PostgreSQL, and SQLite, however it is anticipated that SQLite would be the most common backend used. Go package xo/dburl is used for dsn validation, so it is useful to look at the documentation there to see acceptable connection string formats.
The database connection is exposed in a package var numerology.DB
. It could theoretically be used to manually attach
a custom Gorm backend, although this feature is untested.
Each csv file needs to have three columns, however NO HEADERS.
The columns are name, gender, popularity.
Mary,F,100
Michael,M,98
John,M,95
Susan,F,94
The popularity field is used so that names are sorted by how common they are. Often census compilations include information like this. It is useful to be able to sort by how common a name is because some names that people give their children are simply bizarre, and it becomes hard to sift through quality names without some control of that.
In order to save space in the database, the raw popularity numbers are not stored. They are simply used to order the names before putting them in the database. Once there, the inserted order of the database is used to establish popularity.
The database is populated by names coming from one or more CSV files based on a particular directory layout.
baseDir\
├── table1\
│ ├── file1.csv
│ └── file2.csv
└── table2\
├── file1.csv
└── file2.csv
The folder names within the baseDir
will be used as table names in the database. The names in each csv file in the
table directory will be iterated in ascending order and aggregated before being added to the database.
Multiple csv files can be used when inserting into the database. The original source of names was a yearly compilation of USA Census names. They consisted of the popularity of each name for each year from past to present. The names are weighted so that current popularity is valued higher than older popularity. As the CSV files are iterated, the popularity is summed up with a weighted scale based on how many files there are.
One problem that often comes up when doing name numerology is that sometimes the letter 'Y' is treated as a consonant, and sometimes it is treated like a vowel. How to handle these situations is, unfortunately, not so straightforward for an algorithm. The obvious answer is that 'Y' is a consonant when it is used as a consonant in a word, and a vowel when used as a vowel. But how does one know the difference?
In the English language, every word can be broken down in to syllables. The rule is that each syllable must have a vowel. That means that when there is a syllable with no obvious vowels, but there is a 'Y', the 'Y' is treated like a vowel.
Take a name like Sydney. The syllables would be Syd
and ney
. In
Syd
, there is no vowel, so the 'Y' functions as a vowel. However, in
ney
, the 'E' is the vowel, so the 'Y' defaults to a consonant.
This idea is pretty easy to grasp, but turns out it is hard to program because there is no good algorithm for separating words (especially names) into syllables. You essentially need a dictionary of the English language (and perhaps others, as well) because there are different ways to pronounce similarly written words. This is even more difficult for names because great liberties are often taken with their pronunciation.
One route is the use machine learning, and train it to deduce the syllable structure of words. This is a lot of work and overhead for a solution that won't really even be 100% accurate anyway.
Some numerology calculators allow for special characters to signify when to treat 'Y' differently. Something
like S*yndey
would use the * symbol to denote that the following 'Y' should be a vowel instead of a consonant. This is
difficult for this library because in order to search it needs to precompute a table of names. In order to do that, the
value of 'Y' needs to be picked ahead of time and in a consistent way. Arbitrarily choosing the value of a 'Y' could
lead to inconsistent name results.
Luckily, the 'Y' situation does not come up very often, and there are several rules-of-thumb that can be used to pick the right value most of the time. This is what this library does, however, it does mean that names with 'Y' ought to be looked at with extra scrutiny.
The Pythagorean and Chaldean numbers systems are defined for the Latin alphabet A-Z. Of course, some languages have characters that do not fit into this alphabet. The general consensus is to transliterate those characters to Latin equivalent characters. This is easy for some characters such as ä, é, or ñ. However, some others are not so easy or obvious; ex. 张.
Most calculators just ignore these characters, but we can do better. This library includes a Go
package mozillazg/go-unidecode
that is inspired by a Python port of a well-known Perl package Text::Unidecode
. The author of the Perl package has
some excellent information
on the difficulties of transliterating languages. It is worth the read in order to understand the limitations of the
automatic conversion.
When in doubt, manual transliteration to ASCII characters is recommended.
Even with transliteration of alphabetic characters, it is inevitable that names pop up that have symbols or emojis or other weird characters. What should a calculator do in this situation? Symbols do not have numerological value, so it seems like there are two solutions: 1) Error on unknown characters or 2) Give them a zero value.
Returning an error does not seem quite appropriate because sometimes you want to use strange characters in a name, and purposefully ignore them. Commonly occurring characters of this sort are spaces, dashes, apostrophes, and periods. It is not unusual to have a hyphenated name or to include an apostrophe in a name like in A'isha.
If someone had a name like 'Crazy! Smith', we could force them to drop the exclamation point to do the calculation, or we could allow it and just give it no value. That way it calculates with no extra work, and the symbols are reflected as part of the name.
The problem with just zeroing out characters is that if someone does not know that a character is being interpreted as
an unknown character then they won't be able to know if the numerological calculation is what they expect. Perhaps
someone expects that
$amuel $mith
is similar enough to Samuel Smith
that it is automatically converted.
The compromise used here is that unknown characters are processed just fine, albeit with a zero value, and all unknown
characters are stored with the name and can be checked with the UnknownCharacters()
method.