Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,106 @@
import scala.annotation.tailrec
import scala.collection.parallel.ParSeq
/** Spells an English numeral longhand. The numbers are expressed using words.
*
* The implementation goes up to 10<sup>69</sup>-1 and also supports negative and zero inputs.
*
* @example longhand( 1234 ) // results in: "one thousand two hundred thirty-four".
*/
trait LongHand {
/** Spells a number longhand
*
* Done by recursively process the triplets of decimal numbers.
* @param numeral the numeric value to be converted
* @param showAnd flag the output extra and in output, default off
* @param zeroString the word for 0, default to "zero"
* @param showHyphen hyphenate all compound numbers e.g. twenty-four, default is on
* @return the numeric value expressed in words
*/
def longhand(numeral: BigInt,
showAnd: Boolean = false,
zeroString: String = "zero",
showHyphen: Boolean = true): String = {
val condAndString = if (showAnd) "and " else ""
val condHyphenString = if (showHyphen) "-" else " "
// 234 Becomes "two hundred [and] thirty-four"
def composeScale(nnn: String, isLSDgroup: Boolean, strE3: String): String = {
nnn match { // Rare exceptions confirms the rule
case "000" => ""
case "100" => onesAndTeens(1) + hundredString + strE3 // Solves the faulty hundred AND thousand problem
case _ => {
val eval = (nnn.par.map(_.toString.toInt).reverse zip ParSeq('units, 'tens, 'hundreds)).reverse
eval.map {
case (d, 'units) if eval.seq.contains(1, 'tens) => onesAndTeens(d + 10)
case (d, 'units) if (isLSDgroup && nnn == "0") => zeroString
case (d, 'units) => onesAndTeens(d)
case (d, 'hundreds) if d > 0 => onesAndTeens(d) + hundredString + condAndString
case (d, 'tens) if d > 1 && eval.seq.contains(0, 'units) => tens(d)
case (d, 'tens) if d > 1 => tens(d) + condHyphenString //'
case _ => ""
}.mkString + strE3
}
}
} // def composeScale(
def compose(n: BigInt): String = {
// "1234" becomes List((1,"thousand"), (234, ""))
val decGroups = n.toString.reverse.grouped(3).map(_.reverse).toSeq.par // Group into powers of thousands
if (decGroups.size <= shortScale.size) // Detect overflow
{ // Send per group section to composeScale
@tailrec
def iter(elems: Seq[(String, String)], acc: String): String = {
elems match {
case (group, powers) :: tail => {
iter(tail, acc + composeScale(group, tail == Nil, powers))
}
case _ => acc
}
} // Group of decimals are accompanied with the short scale name.
iter(decGroups.zip(shortScale).reverse.toList, "").mkString.trim
} else "###.overflow.###"
} // def compose(
// Here starts def longhand(
if (numeral < 0) "minus " + compose(-numeral) else compose(numeral)
} // End def longhand(
private val onesAndTeens = {
def dozen = "one two three four five six seven eight nine ten eleven twelve".split(' ').map(_ + " ").par
def teens = "thir four fif six seven eigh nine".split(' ').map(_ + "teen ").par
ParSeq("") ++ dozen ++ teens
}
private val tens = ParSeq("", "") ++
("twen thir for fif six seven eigh nine".split(' ')).map(_ + "ty")
private final val hundredString = "hundred "
private val shortScale = {
def p1 = "m b tr quadr quint sext sept oct non dec".split(' ').map(_ + "illion ").par
def p2 = "un duo tre quattuor quin sex septen octo novem ".split(' ').map(_ + "decillion ").par
def p3 = "vigint cent".split(' ').map(_ + "illion ").par
ParSeq("", "thousand ") ++ p1 ++ p2 ++ p3
}
} // trait LongHand
object SpellNumber extends LongHand with App {
// Main entry A little test...
{ // Anonymous ordered list as test set
def testVal1 = BigInt("1" * 69)
def testVal9 = BigInt(10).pow(69) - 1
@tailrec // Series generator of 9, 98, 987, 9876
def inner(counter: Int, elem: BigInt, testList: ParSeq[BigInt]): ParSeq[BigInt] = {
if (counter < 20)
inner(counter + 1, elem * 10 + (9 - (counter % 10)), testList ++ ParSeq(elem))
else testList.par
}
inner(0, 0L, // Test values
ParSeq(-Long.MaxValue, -1000000000, 12, 13, 19, 20, 21, 112, 1001, 1012, 1013,
Long.MaxValue - 1, Long.MaxValue - 13, testVal1, testVal9)) ++
(for (z <- 0 to 69) yield BigInt(10).pow(z)) // powers of ten
}.seq.sorted.foreach(num => println(f"$num%+,80d -> ${longhand(numeral = num, showAnd = true)}"))
} // object SpellNumber @ line 110

View file

@ -0,0 +1,26 @@
import scala.collection.immutable.TreeMap
val NUMBERS = TreeMap(
1 -> "one", 2 -> "two", 3 -> "three", 4 -> "four", 5 -> "five", 6 -> "six", 7 -> "seven", 8 -> "eight", 9 -> "nine",
10 -> "ten", 11 -> "eleven", 12 -> "twelve", 13 -> "thirteen", 14 -> "fourteen", 15 -> "fifteen", 16 -> "sixteen",
17 -> "seventeen", 18 -> "eighteen", 19 -> "nineteen", 20 -> "twenty", 30 -> "thirty", 40 -> "forty",
50 -> "fifty", 60 -> "sixty", 70 -> "seventy", 80 -> "eighty", 90 -> "ninety"
)
val HUNDREDS = TreeMap(
100l -> "hundred", 1000l -> "thousand", 1000000l -> "million", 1000000000l -> "billion", 1000000000000l -> "trillion"
)
def numberToString(number: Long) : String = {
if (HUNDREDS.to(number).nonEmpty) {
val (h, hundreds) = HUNDREDS.to(number).last
val remainder = number % h
numberToString(number / h) + hundreds + {if (remainder > 0) {if (remainder < 100) " and " else ", "} + numberToString(remainder) else " "}
} else if (NUMBERS.to(number.toInt).nonEmpty) {
val (n, word) = NUMBERS.to(number.toInt).last
val remainder = number - n
word + {if (remainder > 0 && remainder < 10) "-" else " "} + numberToString(remainder)
} else {
""
}
}