Skip to content

Instantly share code, notes, and snippets.

Created July 12, 2017 21:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/8d783fc1fb3f1c87de7a7722599a24ba to your computer and use it in GitHub Desktop.
Save anonymous/8d783fc1fb3f1c87de7a7722599a24ba to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Numerals
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(Numeral(1234567));
Console.Read();
}
private static Dictionary<int, string> BasicNumerals = new Dictionary<int, string>
{
[0] = "",
[1] = "en",
[2] = "to",
[3] = "tre",
[4] = "fire",
[5] = "fem",
[6] = "seks",
[7] = "syv",
[8] = "åtte",
[9] = "ni",
[10] = "ti",
[11] = "elleve",
[12] = "tolv",
[13] = "tretten",
[14] = "fjorten",
[15] = "femten",
[16] = "seksten",
[17] = "sytten",
[18] = "atten",
[19] = "nitten",
[20] = "tjue",
[30] = "tretti",
[40] = "førti",
[50] = "femti",
[60] = "seksti",
[70] = "sytti",
[80] = "åtti",
[90] = "nitti",
};
private static Dictionary<int, string> LogNumerals = new Dictionary<int, string>()
{
[0] = "",
[2] = "hundre",
[3] = "tusen",
[6] = "million",
[9] = "milliard",
[12] = "billion",
};
public static string Numeral(long n)
{
string numeral = "";
if (n < 0)
{
numeral = "minus ";
n = -n;
}
Queue<string> output = new Queue<string>();
Stack<NumeralUnit> units = new Stack<NumeralUnit>();
int logarithm = 0;
while (n > 0)
{
int digitValue = (int)(n % 10);
units.Push(new NumeralUnit(digitValue, logarithm));
n /= 10;
logarithm++;
}
NumeralUnit? previousUnit = null;
while (units.Any())
{
NumeralUnit unit = units.Pop();
NumeralUnit? nextUnit = null;
if (units.Any())
nextUnit = units.Peek();
string unitNumeral = BasicNumerals[unit.DigitValue];
if (unit.IsTens)
{
unit.DigitValue *= 10;
unit.Log--;
units.Pop();
if (unit.DigitValue <= 10)
{
unit.DigitValue += (nextUnit?.DigitValue ?? 0);
unitNumeral = BasicNumerals[unit.DigitValue];
}
else
unitNumeral = BasicNumerals[unit.DigitValue] + BasicNumerals[nextUnit.Value.DigitValue];
if (units.Any())
nextUnit = units.Peek();
}
int tmpLog = -1;
if (unit.IsHundred)
tmpLog = 2;
else if (unit.IsThousands)
tmpLog = unit.Log;
AppendSeparatingWord(output, previousUnit, unit, tmpLog);
if (unit.DigitValue == 1 && (unit.IsHundred || unit.Log == 3))
unitNumeral = "ett";
output.Enqueue(unitNumeral);
if (tmpLog >= 0 && (unit.DigitValue != 0 || previousUnit?.IsHundred == true))
{
unitNumeral = LogNumerals[tmpLog];
if (tmpLog > 3 && (unit.DigitValue > 1 || previousUnit?.IsHundred == true))
unitNumeral += "er";
output.Enqueue(unitNumeral);
previousUnit = unit;
}
if (unit.DigitValue != 0)
previousUnit = unit;
}
while (output.Any())
{
string token = output.Dequeue();
if (token == ",")
numeral = numeral.Substring(0, numeral.Length - 1);
numeral += token;
if (token != "")
numeral += " ";
}
numeral = numeral.TrimEnd(' ');
return numeral == "" ? "null" : numeral;
}
private static void AppendSeparatingWord(Queue<string> output, NumeralUnit? previousUnit, NumeralUnit unit, int tmpLog)
{
if (tmpLog >= 0 && unit.DigitValue != 0 && previousUnit.HasValue
&& (previousUnit?.IsHundred == false))
output.Enqueue(",");
else if (unit.DigitValue != 0 && unit.IsSmall && output.Any())
output.Enqueue("og");
}
public struct NumeralUnit
{
public int DigitValue;
public int Log;
public NumeralUnit(int value, int log)
{
this.DigitValue = value;
this.Log = log;
}
public bool IsTens => Log % 3 == 1;
public bool IsHundred => Log % 3 == 2;
public bool IsThousands => Log % 3 == 0 && Log > 0;
public bool IsSmall => Log % 3 <= 1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment