This commit is contained in:
Ingy döt Net 2013-10-27 22:24:23 +00:00
parent 6f050a029e
commit 776bba907c
3887 changed files with 59894 additions and 7280 deletions

View file

@ -0,0 +1,35 @@
10 INPUT "GIMME A NUMBER! "; N
20 GOSUB 100"NUMBER NAME
30 PRINT R$
40 END
100 REMNUMBER NAME
110 IF R$ = "" THEN FOR I = 0 TO 10 : READ S$(I), T$(I), U$(I), V$(I) : NEXT
120 IF N = 0 THEN R$ = "ZERO" : RETURN
130 R$ = "" : D = 10 : C = 100 : M = 1E3
140 A = ABS(N)
150 FOR U = 0 TO D
160 H = A - C * INT(A / C)
170 IF H > 0 AND H < D THEN R$ = S$(H) + " " + R$
180 IF H > 9 AND H < 20 THEN R$ = T$(H - D) + " " + R$
190 IF H > 19 AND H < C THEN S = H - D * INT(H / D) : R$ = U$(INT(H / D)) + MID$("-",1+(S=0),1) + S$(S) + " " + R$
200 H = A - M * INT(A / M)
210 H = INT (H / C)
220 IF H THEN R$ = S$(H) + " HUNDRED " + R$
230 A = INT(A / M)
240 IF A > 0 THEN H = A - M * INT(A / M) : IF H THEN R$ = V$(U) + " " + R$
250 IF A > 0 THEN NEXT U
260 IF N < 0 THEN R$ = "NEGATIVE " + R$
270 RETURN
280 DATA "", "TEN", "", "THOUSAND"
281 DATA "ONE", "ELEVEN", "", "MILLION"
282 DATA "TWO", "TWELVE", "TWENTY", "BILLION"
283 DATA "THREE", "THIRTEEN", "THIRTY", "TRILLION"
284 DATA "FOUR", "FOURTEEN", "FORTY", "QUADRILLION"
285 DATA "FIVE", "FIFTEEN", "FIFTY", "QUINTILLION"
286 DATA "SIX", "SIXTEEN", "SIXTY", "SEXTILLION"
287 DATA "SEVEN", "SEVENTEEN", "SEVENTY", "SEPTILLION"
288 DATA "EIGHT", "EIGHTEEN", "EIGHTY", "OCTILLION"
289 DATA "NINE", "NINETEEN", "NINETY", "NONILLION"
290 DATA "", "", "", "DECILLION"

View file

@ -0,0 +1,81 @@
SuperStrict
Framework BRL.StandardIO
spellIt( 99)
spellIt( 300)
spellIt( 310)
spellIt( 1501)
spellIt( 12609)
spellIt( 512609)
spellIt( 43112609)
spellIt(1234567890)
Type TSpell
Field smallNumbers:String[] = ["zero", "one", "two", "three", "four", "five", ..
"six", "seven", "eight", "nine", "ten", ..
"eleven", "twelve", "thirteen", "fourteen", "fifteen", ..
"sixteen", "seventeen", "eighteen", "nineteen" ]
Field decades:String[] = [ "", "", "twenty", "thirty", "forty", ..
"fifty", "sixty", "seventy", "eighty", "ninety" ]
Field thousandPowers:String[] = [ " billion", " million", " thousand", "" ]
Method spellHundreds:String(number:Int)
Local result:String
If number > 99 Then
result = smallNumbers[number / 100]
result :+ " hundred"
number = number Mod 100
If number Then
result :+ " and "
End If
End If
If number >= 20 Then
result :+ decades[number / 10]
number = number Mod 10
If number Then
result :+ "-"
End If
End If
If number > 0 And number < 20 Then
result :+ smallNumbers[number]
End If
Return result
End Method
Method spell:String(number:Long)
If number < 20 Then
Return smallNumbers[number]
End If
Local result:String
Local scaleIndex:Int = 0
Local scaleFactor:Long = 1000000000:Long ' 1 billion
While scaleFactor > 0
If number >= scaleFactor
Local h:Long = number / scaleFactor
result :+ spellHundreds(h) + thousandPowers[scaleIndex]
number = number Mod scaleFactor
If number Then
result :+ ", "
End If
End If
scaleFactor :/ 1000
scaleIndex :+ 1
Wend
Return result
End Method
End Type
Function spellIt(number:Long)
Local numberSpell:TSpell = New TSpell
Print number + " " + numberSpell.spell(number)
End Function

View file

@ -0,0 +1,3 @@
IN: scratchpad USE: math.text.english
IN: scratchpad 43112609 number>text print
forty-three million, one hundred and twelve thousand, six hundred and nine

View file

@ -0,0 +1,3 @@
l: [99, 300, 310, 1501, 12609, 512609, 43112609, 77000112609, 2000000000100,
999999999999999999, 0, -99, -1501, -77000112609, -123456789987654321];
map( lambda([n], printf(true, "~20d ~r~%", n, n)), l)$

View file

@ -1,69 +1,110 @@
/**
* Spells a number longhand
package org.rosettacode
package numbernames
import annotation.tailrec
import collection.parallel.ParSeq
/** Spells a number longhand
*
* @example longhand( 1234 ) // results in: one thousand two hundred thirty-four
* 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".
*/
def longhand( v:Long, showAnd:Boolean = false, showHyphen:Boolean = true ) : String = {
// Based on a solution of Rex Kerr's
object SpellNumber extends App {
val onesAndTeens = {
val a1 = Array[String]("")
val a2 = "one two three four five six seven eight nine ten eleven twelve".split(' ').map(_ + " ")
val a3 = "thir four fif six seven eigh nine".split(' ').map(_ + "teen ")
a1 ++ a2 ++ a3
}
/** Spells a number longhand
*
* The solution is recursive by the triplets of decimal numbers.
* @param v 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 shows the hyphen e.g. twenty-four, default is on
* @return the numeric value in words
*/
def longhand(v: BigInt,
zeroString: String = "zero",
showAnd: Boolean = false,
showHyphen: Boolean = true): String = {
val tens = {
val a1 = Array[String]("","")
val a2 = "twen thir for fif six seven eigh nine".split(' ').map(_ + "ty")
a1 ++ a2
}
val hundredString = "hundred "
val andString = if( showAnd ) "and " else ""
val hyphenString = if( showHyphen ) "-" else " "
val powersOfThousands = {
val a1 = Array[String]("","thousand ")
val a2 = "m b tr quadr quint sext sept oct non dec".split(' ').map(_ + "illion ")
val a3 = "un duo tre quattuor quin sex septen octo novem ".split(' ').map(_ + "decillion ")
val a4 = "vigint cent".split(' ').map(_ + "illion ")
a1 ++ a2 ++ a3 ++ a4
}
// 234 becomes "two hundred [and] thirty-four"
def composeScale( v:String, isFirst:Boolean ) : String = {
val e1 = (v.map(_.toString.toInt).reverse zip List("","-","hundred")).reverse
e1.map {
case (d,"hundred") if d > 0 => onesAndTeens(d) + hundredString + andString
case (d,"-") if d > 1 && !e1.contains((0,"")) && isFirst => tens(d) + hyphenString
case (d,"-") if d > 1 && !e1.contains((0,"")) => tens(d) + " "
case (d,"-") if d > 1 => tens(d)
case (d,"") if e1.contains((1,"-")) => onesAndTeens(d+10)
case (d,"") => onesAndTeens(d)
case _ => ""
}.mkString
}
def compose( s:String ) : String = {
// "1234" becomes List(((1,false),"thousand"), ((234,true),""))
val thousands = {
def first( s:String ) = (true) #:: Stream.continually(false) // First element true others false
val e1 = s.reverse.grouped(3).map(_.reverse).toList // Group into powers of thousands
val e2 = e1 zip first(s) // Mark the first element
val e3 = e2 zip powersOfThousands // Name the powers of Thousands
e3.reverse // Put it back to most-significant first
val onesAndTeens = {
val a1 = "one two three four five six seven eight nine ten eleven twelve".split(' ').map(_ + " ")
val a2 = "thir four fif six seven eigh nine".split(' ').map(_ + "teen ")
(Array[String]("") ++ a1 ++ a2).par
}
thousands.map { case ((v,isFirst),s) => composeScale( v, isFirst ) + s }.mkString.trim
}
val tens = (Array[String]("", "") ++ ("twen thir for fif six seven eigh nine".split(' ')).
map(_ + "ty")).par
val hundredString = "hundred "
val condAndString = if (showAnd) "and " else ""
val condHyphenString = if (showHyphen) "-" else " "
val powersOfThousands = {
val p1 = "m b tr quadr quint sext sept oct non dec".split(' ').map(_ + "illion ").par
val p2 = "un duo tre quattuor quin sex septen octo novem ".split(' ').map(_ + "decillion ").par
val p3 = "vigint cent".split(' ').map(_ + "illion ") ++ Array("overflow trap").par
(Array("", "thousand ") ++ p1 ++ p2 ++ p3).par
}
if( v < 0 ) "minus " + compose((-v).toString) else compose(v.toString)
}
// 234 becomes "two hundred [and] thirty-four"
def tripletGroup(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
// A little test...
println( Long.MaxValue-13 + " is \"" + longhand( Long.MaxValue-13 ) + "\"" )
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 tripletGroup(
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
.zip(powersOfThousands) // // Name the powers of Thousands
.reverse // // Put it back to most-significant first
if (decGroups.size < 24) // Detect overflow trap
{ // Send per group sections to composeScale
@tailrec
def iter(elems: Seq[(String, String)], acc: String): String = {
elems match {
case (group, powers) :: tail => {
iter(tail, acc + tripletGroup(group, tail == Nil, powers))
}
case _ => acc
}
}
iter(decGroups.toList, "").mkString.trim
} else "###.overflow.###"
} // def compose(
// Here starts def longhand(
if (v < 0) "minus " + compose(-v) else compose(v)
} // End def longhand( @ 91 lines
// 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(v = num, showAnd = true)}"""))
} // object SpellNumber