/// <summary> /// Calculates the gematria value for all Hebrew letters in the given string. /// Ignores all characters that are not Hebrew letters. /// </summary> /// <param name="sourceString">String to evaluate</param> /// <param name="gematriaType"><see cref="T:EllisWeb.Gematria.GematriaType"/> to use for calculation (defaults to Absolute)</param> /// <returns></returns> public static long GetGematriaValue(string sourceString, GematriaType gematriaType = GematriaType.Absolute) { if (string.IsNullOrEmpty(sourceString)) { throw new ArgumentNullException("sourceString"); } long value = 0; var dict = LookupFactory.GetDictionary(gematriaType); foreach (char c in sourceString) { if (dict.ContainsKey(c)) { value += dict[c]; } } return(value); }
/// <summary> /// Gives the string representation of a number up between 1 and 999 /// </summary> /// <param name="number"></param> /// <returns></returns> private static string GetNumericString(int number) { if (number < 1 || number > 999) { throw new ArgumentException("Number not between 1 and 999"); } var dict = LookupFactory.GetDictionary(GematriaType.AbsoluteNoSofiyot); // Remove sofiyot letters to avoid dictionary collissions. These are never used in numeric strings var reverseDict = dict.ToDictionary(k => k.Value, v => v.Key); // create a dict looking up letter by value var valueList = dict.Select(x => x.Value).ToList(); // get list of all available values valueList.Sort(); valueList.Reverse(); // get value list in reverse order - highest number first. Speeds up evaluations. StringBuilder str = new StringBuilder(); while (number > 0) { // first handle special cases if (number == 15) { str.Append("טו"); break; } if (number == 16) { str.Append("טז"); break; } var nextValToUse = valueList.Where(x => x <= number).Max(); str.Append(reverseDict[nextValToUse]); number = number - nextValToUse; } return(str.ToString()); }
/// <summary> /// Calculates the gematria value for a string that is intended to represent a number (example: a year in the Hebrew calendar or page in a Hebrew book). /// This function expects that the given string will contain only one word, and will throw an error if more than one word is included /// (this is because a string of Hebrew characters representing a number will never consist of multiple words). /// Ignores non-Hebrew characters and punctuation in the given word. /// </summary> /// <param name="sourceString">The string to evaluate</param> /// <param name="gematriaType"><see cref="T:EllisWeb.Gematria.GematriaType"/> to use for calculation (defaults to Absolute)</param> /// <param name="isStrictMode"> /// Should the numeric gematria be evaluated with Strict Mode turned on. Defaults to the global setting /// defined in <see cref="ForceNumericStrictMode"/>. When true this will throw a <see cref="FormatException"/> whenever the numbers at /// the end of the string that are under 100 (ק) are not included in descending numeric order, and do not appear on the exceptions list. /// </param> /// <returns>Number equal to the numeric gematria value of the string provided</returns> /// <remarks> /// This function will infer the division between thousands-groupings of the number by using the following rule: /// Evaluate characters one at a time. It is expected that gematria values within a thousands-grouping will always be the same or equal to the previous value. /// If a value is encountered that is greater than the previous value, it signifies the start of a new thousands-grouping. /// </remarks> public static long GetNumericGematriaValue(string sourceString, GematriaType gematriaType = GematriaType.Absolute, bool?isStrictMode = null) { sourceString = sourceString.Trim(); bool currentStrictMode = isStrictMode ?? ForceNumericStrictMode; if (currentStrictMode) { var stripped = StripSeparatorCharacters(sourceString); if (KnownNumericValues.ContainsKey(stripped)) { return(KnownNumericValues[stripped]); } } if (Regex.IsMatch(sourceString, @"[\s]")) { throw new ArgumentException("Source string contains more than one word", "sourceString"); } var dict = LookupFactory.GetDictionary(gematriaType); List <List <int> > numberStacks = new List <List <int> >(); var currentStack = new List <int>(); numberStacks.Add(currentStack); int prevNum = 0; foreach (char c in sourceString) { if (dict.ContainsKey(c)) { int currentVal = dict[c]; if (currentVal > prevNum && currentStack.Any()) { currentStack = new List <int>(); numberStacks.Add(currentStack); } currentStack.Add(currentVal); prevNum = currentVal; } } // At this point, the first number stack is the highest thousands-grouping. Need to reverse them in order to go from lowest to highest when evaluating. numberStacks.Reverse(); // Go through the number stacks. Multiply the sum of each stack by 1000^X where X is the zero-index value of the current stack int currentStackIndex = 0; long value = 0; bool inHundreds = false; long maxStackSum = 0; foreach (List <int> numberStack in numberStacks) { long stackSum = numberStack.Sum(); if (currentStrictMode) { numberStack.Reverse(); // need to reverse the current stack, in order to preserve the order of items being evaluated foreach (var number in numberStack) { if (number >= 100) { inHundreds = true; } if (!inHundreds && number < maxStackSum) { throw new FormatException("In Strict Mode, trailing values less than 100 (ק) must appear in the proper order"); } maxStackSum = Math.Max(maxStackSum, number); } } var stackMultiplier = Math.Pow(1000, currentStackIndex++); var adjustedStackSum = Convert.ToInt64(stackSum * stackMultiplier); value += adjustedStackSum; } return(value); }