Lazy word problems












15














Summary



A teacher was told to prepare word problems for the students. She is given a list of equations and told to write them as the corresponding word problem. However, she is very lazy, so she doesn't put much creativity into it. Instead, she simply writes it literally. For example, when she reads 1+1, she writes one plus one, 47 * 2 would turn into forty seven times two, and 56.2 / 7.4 would become fifty six point two divided by seven point four.



Write some code to help this lazy teacher out.



Details




  • Numbers may include a decimal point and a negative sign.

  • Numbers should be written in the short scale. (i.e., 1,000,000,000 is one billion)

  • Numbers can go up to 999,999,999,999,999,999 (nine hundred ninety nine quadrillion...nine hundred ninety nine).

  • Groups of zeros must be left out. e.g. 1,000,000 is one million not one million zero thousand zero hundred.

  • There can be arbitrarily many digits past the decimal point.

  • Digits after the decimal point must be listed digit by digit. e.g. 12.34 is twelve point three four not twelve point thirty four.

  • Two numbers are always separated by an operator.

  • The valid operators are plus (+), minus (-), times (*), and divided by (/).

  • There are no parentheses.

  • Numbers such as 1234 may optionally include an and in their output, as in one thousand two hundred *and* thirty four.

  • Commas and whitespace on the input may be ignored.


Examples



Input: 24 + 65

Output: twenty four plus sixty five



Input: 3.33333 - 0

Output: three point three three three three three minus zero



Input: 3.6 * 18.18 / 999.0

Output: three point six times eighteen point one eight divided by nine hundred ninety nine point zero



Input: 1-1

Output: one minus one



Input: 1+-1

Output: one plus negative one



Input: 1,000,000,000 + 0.2

Output: one billion plus zero point two



Input: 123,000,456,789,012,345.6789

Output: one hundred twenty three quadrillion four hundred fifty six billion seven hundred eighty nine million twelve thousand three hundred forty five point six seven eight nine



Input: -4.3 * 7

Output: negative four point three times seven



Input: -1-1--1

Output: negative one minus one minus negative one










share|improve this question




















  • 1




    Could you add something like 123,456,789,012,345.6789 to the examples? It should cover a lot of test cases.
    – maxb
    Nov 27 '18 at 10:42






  • 2




    Can we use minus instead of negative?
    – Jo King
    Nov 27 '18 at 10:55






  • 3




    For Mathematica: again there is a builtin, but / is over and negative number is minus, so it needs some manipulation.
    – user202729
    Nov 27 '18 at 11:21








  • 2




    @user202729 Amazing... why am I not surprised Mathematica has a builtin for this? :)
    – Daffy
    Nov 27 '18 at 11:25






  • 3




    Converting integers to English words
    – user202729
    Nov 27 '18 at 11:27
















15














Summary



A teacher was told to prepare word problems for the students. She is given a list of equations and told to write them as the corresponding word problem. However, she is very lazy, so she doesn't put much creativity into it. Instead, she simply writes it literally. For example, when she reads 1+1, she writes one plus one, 47 * 2 would turn into forty seven times two, and 56.2 / 7.4 would become fifty six point two divided by seven point four.



Write some code to help this lazy teacher out.



Details




  • Numbers may include a decimal point and a negative sign.

  • Numbers should be written in the short scale. (i.e., 1,000,000,000 is one billion)

  • Numbers can go up to 999,999,999,999,999,999 (nine hundred ninety nine quadrillion...nine hundred ninety nine).

  • Groups of zeros must be left out. e.g. 1,000,000 is one million not one million zero thousand zero hundred.

  • There can be arbitrarily many digits past the decimal point.

  • Digits after the decimal point must be listed digit by digit. e.g. 12.34 is twelve point three four not twelve point thirty four.

  • Two numbers are always separated by an operator.

  • The valid operators are plus (+), minus (-), times (*), and divided by (/).

  • There are no parentheses.

  • Numbers such as 1234 may optionally include an and in their output, as in one thousand two hundred *and* thirty four.

  • Commas and whitespace on the input may be ignored.


Examples



Input: 24 + 65

Output: twenty four plus sixty five



Input: 3.33333 - 0

Output: three point three three three three three minus zero



Input: 3.6 * 18.18 / 999.0

Output: three point six times eighteen point one eight divided by nine hundred ninety nine point zero



Input: 1-1

Output: one minus one



Input: 1+-1

Output: one plus negative one



Input: 1,000,000,000 + 0.2

Output: one billion plus zero point two



Input: 123,000,456,789,012,345.6789

Output: one hundred twenty three quadrillion four hundred fifty six billion seven hundred eighty nine million twelve thousand three hundred forty five point six seven eight nine



Input: -4.3 * 7

Output: negative four point three times seven



Input: -1-1--1

Output: negative one minus one minus negative one










share|improve this question




















  • 1




    Could you add something like 123,456,789,012,345.6789 to the examples? It should cover a lot of test cases.
    – maxb
    Nov 27 '18 at 10:42






  • 2




    Can we use minus instead of negative?
    – Jo King
    Nov 27 '18 at 10:55






  • 3




    For Mathematica: again there is a builtin, but / is over and negative number is minus, so it needs some manipulation.
    – user202729
    Nov 27 '18 at 11:21








  • 2




    @user202729 Amazing... why am I not surprised Mathematica has a builtin for this? :)
    – Daffy
    Nov 27 '18 at 11:25






  • 3




    Converting integers to English words
    – user202729
    Nov 27 '18 at 11:27














15












15








15


3





Summary



A teacher was told to prepare word problems for the students. She is given a list of equations and told to write them as the corresponding word problem. However, she is very lazy, so she doesn't put much creativity into it. Instead, she simply writes it literally. For example, when she reads 1+1, she writes one plus one, 47 * 2 would turn into forty seven times two, and 56.2 / 7.4 would become fifty six point two divided by seven point four.



Write some code to help this lazy teacher out.



Details




  • Numbers may include a decimal point and a negative sign.

  • Numbers should be written in the short scale. (i.e., 1,000,000,000 is one billion)

  • Numbers can go up to 999,999,999,999,999,999 (nine hundred ninety nine quadrillion...nine hundred ninety nine).

  • Groups of zeros must be left out. e.g. 1,000,000 is one million not one million zero thousand zero hundred.

  • There can be arbitrarily many digits past the decimal point.

  • Digits after the decimal point must be listed digit by digit. e.g. 12.34 is twelve point three four not twelve point thirty four.

  • Two numbers are always separated by an operator.

  • The valid operators are plus (+), minus (-), times (*), and divided by (/).

  • There are no parentheses.

  • Numbers such as 1234 may optionally include an and in their output, as in one thousand two hundred *and* thirty four.

  • Commas and whitespace on the input may be ignored.


Examples



Input: 24 + 65

Output: twenty four plus sixty five



Input: 3.33333 - 0

Output: three point three three three three three minus zero



Input: 3.6 * 18.18 / 999.0

Output: three point six times eighteen point one eight divided by nine hundred ninety nine point zero



Input: 1-1

Output: one minus one



Input: 1+-1

Output: one plus negative one



Input: 1,000,000,000 + 0.2

Output: one billion plus zero point two



Input: 123,000,456,789,012,345.6789

Output: one hundred twenty three quadrillion four hundred fifty six billion seven hundred eighty nine million twelve thousand three hundred forty five point six seven eight nine



Input: -4.3 * 7

Output: negative four point three times seven



Input: -1-1--1

Output: negative one minus one minus negative one










share|improve this question















Summary



A teacher was told to prepare word problems for the students. She is given a list of equations and told to write them as the corresponding word problem. However, she is very lazy, so she doesn't put much creativity into it. Instead, she simply writes it literally. For example, when she reads 1+1, she writes one plus one, 47 * 2 would turn into forty seven times two, and 56.2 / 7.4 would become fifty six point two divided by seven point four.



Write some code to help this lazy teacher out.



Details




  • Numbers may include a decimal point and a negative sign.

  • Numbers should be written in the short scale. (i.e., 1,000,000,000 is one billion)

  • Numbers can go up to 999,999,999,999,999,999 (nine hundred ninety nine quadrillion...nine hundred ninety nine).

  • Groups of zeros must be left out. e.g. 1,000,000 is one million not one million zero thousand zero hundred.

  • There can be arbitrarily many digits past the decimal point.

  • Digits after the decimal point must be listed digit by digit. e.g. 12.34 is twelve point three four not twelve point thirty four.

  • Two numbers are always separated by an operator.

  • The valid operators are plus (+), minus (-), times (*), and divided by (/).

  • There are no parentheses.

  • Numbers such as 1234 may optionally include an and in their output, as in one thousand two hundred *and* thirty four.

  • Commas and whitespace on the input may be ignored.


Examples



Input: 24 + 65

Output: twenty four plus sixty five



Input: 3.33333 - 0

Output: three point three three three three three minus zero



Input: 3.6 * 18.18 / 999.0

Output: three point six times eighteen point one eight divided by nine hundred ninety nine point zero



Input: 1-1

Output: one minus one



Input: 1+-1

Output: one plus negative one



Input: 1,000,000,000 + 0.2

Output: one billion plus zero point two



Input: 123,000,456,789,012,345.6789

Output: one hundred twenty three quadrillion four hundred fifty six billion seven hundred eighty nine million twelve thousand three hundred forty five point six seven eight nine



Input: -4.3 * 7

Output: negative four point three times seven



Input: -1-1--1

Output: negative one minus one minus negative one







code-golf string






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 27 '18 at 21:22

























asked Nov 27 '18 at 10:30









Daffy

558410




558410








  • 1




    Could you add something like 123,456,789,012,345.6789 to the examples? It should cover a lot of test cases.
    – maxb
    Nov 27 '18 at 10:42






  • 2




    Can we use minus instead of negative?
    – Jo King
    Nov 27 '18 at 10:55






  • 3




    For Mathematica: again there is a builtin, but / is over and negative number is minus, so it needs some manipulation.
    – user202729
    Nov 27 '18 at 11:21








  • 2




    @user202729 Amazing... why am I not surprised Mathematica has a builtin for this? :)
    – Daffy
    Nov 27 '18 at 11:25






  • 3




    Converting integers to English words
    – user202729
    Nov 27 '18 at 11:27














  • 1




    Could you add something like 123,456,789,012,345.6789 to the examples? It should cover a lot of test cases.
    – maxb
    Nov 27 '18 at 10:42






  • 2




    Can we use minus instead of negative?
    – Jo King
    Nov 27 '18 at 10:55






  • 3




    For Mathematica: again there is a builtin, but / is over and negative number is minus, so it needs some manipulation.
    – user202729
    Nov 27 '18 at 11:21








  • 2




    @user202729 Amazing... why am I not surprised Mathematica has a builtin for this? :)
    – Daffy
    Nov 27 '18 at 11:25






  • 3




    Converting integers to English words
    – user202729
    Nov 27 '18 at 11:27








1




1




Could you add something like 123,456,789,012,345.6789 to the examples? It should cover a lot of test cases.
– maxb
Nov 27 '18 at 10:42




Could you add something like 123,456,789,012,345.6789 to the examples? It should cover a lot of test cases.
– maxb
Nov 27 '18 at 10:42




2




2




Can we use minus instead of negative?
– Jo King
Nov 27 '18 at 10:55




Can we use minus instead of negative?
– Jo King
Nov 27 '18 at 10:55




3




3




For Mathematica: again there is a builtin, but / is over and negative number is minus, so it needs some manipulation.
– user202729
Nov 27 '18 at 11:21






For Mathematica: again there is a builtin, but / is over and negative number is minus, so it needs some manipulation.
– user202729
Nov 27 '18 at 11:21






2




2




@user202729 Amazing... why am I not surprised Mathematica has a builtin for this? :)
– Daffy
Nov 27 '18 at 11:25




@user202729 Amazing... why am I not surprised Mathematica has a builtin for this? :)
– Daffy
Nov 27 '18 at 11:25




3




3




Converting integers to English words
– user202729
Nov 27 '18 at 11:27




Converting integers to English words
– user202729
Nov 27 '18 at 11:27










7 Answers
7






active

oldest

votes


















15














JavaScript (ES6), 552 532 bytes



This filthy monster comes straight from the depths of code-golfing hell.



Expects an input string without any whitespace.





S=>S[R='replace'](/[d.,]+|./g,s=>1/s[0]?a(+s[S=0]&&14)+s[R](/(D?)(d+)/g,(_,s,n)=>s>','?' point'+n[R](/./g,a):j--*n?(u=a(n%10||14),n>99?a(n[0])+' hundred':'')+((n%=100)<13?a(n||14):n<20?(a(n)||u)+'teen':(a(n/10+18)||a(n/10))+'ty'+u)+a(j+27)+(j>1?'illion':''):'',j=s.split`,`.length):a(S='+-*/'.indexOf(s=='-'&&S||s)+34),a=n=>(s='zero0one0two0three0four0five0six0seven0eight0nine0ten0eleven0twelve0thir00fif000eigh00twen0thir0for0fif000eigh00thousand0m0b0tr0quadr0negative0plus0minus0times0divided by'.split`0`[n|0])&&' '+s).trim()


Try it online!






share|improve this answer



















  • 3




    You can cut 18 bytes by replacing your giant string literal with btoa`ÍêèÒ‰ÞÒÜ(ÒØkyí¢êô~+ÞÒȱÒǯz}ŠmÒx§{K^ŸG¥z÷§ÒÜ–÷´¶«ÓGâM4z(!ÓKpz}-†*ô~Šô~'ôÓG¢‚4¶.±©ÝÒmÒÚôªæ�¯IÞ�«b½í)–ë4š)î³Kb™ë4v+âuçu×Vò`.replace(111,' ').
    – kamoroso94
    Nov 27 '18 at 19:09










  • I love responses that creatively compress string literals like this.
    – Daffy
    Nov 27 '18 at 21:31



















6















Perl 6, 434 401 387 359 bytes





{~S:g/d+/{n($//100+64184)x($/>100),$/%100>19&&(n($//10%10+64175),n($!=$/%10)x?$!)||n($/%100+7679),[$,"thousand",|(<m b tr quadr>X~"illion")][+$/.postmatch.words[0].comb(',')]if +$/} /.trans("+,-/*"=><<plus''minus"divided by"times>>).words}o{S:g/.(d)+/ point {$0>>.&n}/}o{S:g/[s|^]0/ zero/}o{S:g/-(d)/negative $0/}
my&n=(*+1632+|0).uniname.lc.words[2..*]


Try it online!



Definitely room for improvement here. I say that, but I keep noticing edge cases I haven't handled :(. Assumes that the input has operators separated by whitespace and the negative of a number isn't separated.



Explanation:



my&n=(*+1632+|0).uniname.lc.words[2..*]  # Define a helper function
# This gets the unicode name, e.g ARABIC-INDIC DIGIT ZERO
# or AEGEAN NUMBER ONE HUNDRED
# And returns the 3rd word onwards in lowercase e.g. 'zero' or 'one hundred'
{S:g/-(d)/negative $0/} # Turn dashes before numbers to negative
{S:g/[s|^]0/ zero/} # Handle zeros
{S:g/.(d)+/ point {$0>>.&n}/} # Replace decimals
{~S:g/d+/ # Replace series of numbers with
n($//100+64184)x($/>100) # The hundreds if the num is bigger than 100
$/%100>19&& # If the number is bigger than 19
(
n($//10%10+64175), # The tens number
n($!=$/%10)x?$! # And the singles number (if it's not zero)
)
|| # Else
n($/%100+7679) # The name of the number below 20
, # Then
[$,"thousand",|(<m b tr quadr>X~"illion")][ # Index into the list of postfixes
+ .comb(',') # The number of commas
$/.postmatch.words[0] # in the rest of the number
if +$/ # All if the number is not 0
.trans("+,-/*"=><<plus''minus"divided by"times>>) # Translate operators
# And remove commas
.words} # And remove all the excess spaces between words





share|improve this answer































    5














    Ruby + Swift 4, 283 279 270 bytes





    $_=gsub(/(?<=d)-/,"minus ").gsub(/[*-/]/,?.=>"point ",?-=>"negative ",?+=>"plus ",?*=>"times ",?/=>"divided by ").gsub(/(?<=^|[^t] )d+|d/){`echo "import Foundation
    var f=NumberFormatter()
    f.numberStyle = .spellOut
    print(f.string(from:#$&)!)">.a
    swift .a`.tr'-
    ',' '}


    Try it online!



    I must be mad to propose such a Frankenstein solution, but on one hand, it is very tempting to use Swift's built-in functionality for this task, and on the other hand, processing strings with Regexes in Swift looks to be a golfing catastrophe.



    Therefore, I decided to do basic string processing in Ruby, but to spell out numbers, I store them in a Swift source file, run Swift in a shell command, and collect the output.



    I turns out that Swift's "spellOut" number formatter does almost exactly what we need, except inserting unnecessary hyphens for two-digit numbers, as in twenty-two. In fact, even the floating point output in the format of integer part point digit digit... is good, but here comes the caveat - there is no infinite precision, and with large enough numbers or a lot of decimal digits, the results go wrong. Therefore, I had to separate the integer and fractional parts and to feed the fraction digit by digit.






    share|improve this answer



















    • 1




      This is absolutely diabolical and I love it.
      – Daffy
      Nov 28 '18 at 22:02



















    4















    sfk, 853 bytes



    xed -i
    "_*_ [part1]_"
    +xed
    _+_plus_
    _*_times_
    "_/_divided by_"
    "_- _minus _"
    "_-_negative _"
    +xed
    "_,[keep][19 chars of 0-9,]_quadr@ _"
    "_,[keep][15 chars of 0-9,]_tr@ _"
    "_,[keep][11 chars of 0-9,]_b@ _"
    "_,[keep][digits],[digits],_b@ _"
    "_,[keep][digits],_m@ _"
    "_,_ thousand _"
    +xed
    "_ 000[chars]@__"
    "_ 000__"
    "_ 00[keep][digit]_ _"
    "_ 0[keep][2 digits]_ @_"
    "_ [digit][keep][2 digits]_[part2]hundred @_"
    "_ [ortext] 0[digit]0_ @[part2]_"
    "_ [keep][2 digits]_ @_"
    "_@_illion _"
    +xed
    _@11_eleven_
    _@12_twelve_
    _@1[digit]_@[part2]teen_
    _@1_ten_
    _@4_forty_
    _@[digit]_@[part2]ty_
    +xed
    _@2_twen_
    _@3_thir_
    _@4_four_
    _@5_fif_
    _@6_six_
    _@7_seven_
    _@8_eigh_
    _@9_nine_
    +xed
    "_0_ zero _"
    "_1_ one _"
    "_2_ two _"
    "_3_ three _"
    "_4_ four _"
    "_5_ five _"
    "_6_ six _"
    "_7_ seven _"
    "_8_ eight _"
    "_9_ nine _"
    "_._ point _"
    +xed
    "_[white]_ _"
    +xed
    "_[lstart] __"



    Try it online!



    Requires operators and numbers be separated by at least one space character.






    share|improve this answer





























      4















      Clean, 766 ... 687 bytes



      import StdEnv,Text
      m=""
      z="zero"
      @ =digitToInt
      r=reverse
      l k=(!!)k o@
      ^s=l[s:split" ""one two three four five six seven eight nine"]
      g s=l[m,m,"twen","thir",s,"fif","six","seven","eigh","nine"]
      ~['0':t]= ~t
      ~[a,b,c]= ^""a+" hundred "+ ~[b,c]
      ~[b,c]|b>'1'=g"for"b+"ty "+ ^""c|c>'2'=g"four"c+"teen"=["ten","eleven","twelve"]!!(@c)
      ~[c]= ^""c
      ~_=m
      $=m
      $[x:y]#(h,t)=span(e=e>'/'||e==',')if(x<'1')y[x:y]
      =trim(join" "((case x of'0'=[z];'-'=["negative",$h];'.'=["point":map(^z)h];_=(r[u+v\u<-r(map~(split[',']h))&v<-[m," thousand":[" "+k+"illion"\k<-["m","b","tr","quadr"]]]|u>m]))++[?t]))
      ?['-':t]="minus "+ $t
      ?['+':t]="plus "+ $t
      ?['/':t]="divided by "+ $t
      ?['*':t]="times "+ $t
      ?t= $t


      Try it online!



      Expects a string without whitespace.






      share|improve this answer































        1















        05AB1E, 315 295 282 276 bytes



        "+-*/"DˆS¡εDõQi'¢…ë'.¡VYнD_i'¡×ðë',¡DgUε0›i.•6b©•ð“†ìˆÈŒšï¿Ÿ¯¥Š“©'tKJ#'…§«…€µ‚•„í#®#«…—¿áÓÁÏ#«ìD9£©.•4º»Ÿć'Rþн•ŽH$S£“Œšï¿Ÿ¯¥Š“'tK#«„ty«sõšâðý«õšD®'°¡ðì«sâðý«yèð.•cG3₅¦„¥F•8ô'¾ß«…¡›‡È±°#«õªRXN-<èJëõ}}ðý}Yg<i®'¡×šYθSè'…®šðý}}J}s¯`Ã哉´Øè„ƺߓ#¤… by«¸s¨ì¯`ykè}.ιðý„  ð:„¢…Øè'¢…:


        Takes input without any spaces.



        Try it online or verify all test cases.



        Explanation:





        "+-*/"                    # Push string "+-*/"
        Dˆ # Duplicate it, pop the copy, and push it to the global array
        S¡ # Split the input by any "+", "-", "*", or "/"
        ε # Map each number to:
        DõQi # If the item is empty (happens for negative numbers)
        '¢… '# Push string "negative"
        ë # Else:
        '.¡ '# Split by "."
        VY # Store it in variable `Y`
        н # Take the first number (the integer part)
        D # Duplicate this integer part
        _i # If the integer part is exactly 0:
        # Discard the duplicated integer part
        '¡× '# Push string "zero"
        ð # Push a space " "
        ë # Else:
        ',¡ '# Split by ","
        DgU # Pop and store the amount of items in variable `X`
        ε # Map each part to:
        0›i # If it's larger than 0:
        .•6b©• # Push string "thir"
        ð # Push a space " "
        “†ìˆÈŒšï¿Ÿ¯¥Š“ # Push string "four five six seven eight nine"
        © # Store it in the register (without popping)
        'tK '# Remove all "t" (so "eight" becomes "eigh")
        J # Join it together with the "thir" and space
        # # Split by spaces
        '…§ '# Push string "teen"
        « # And append it to every string in the list
        # (We now have ["thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"])
        …€µ‚•„í # Push string "one two three"
        # # Split by spaces
        ® # Push the string from the register ("four" through "nine")
        #« # Split by spaces, and merge both lists together
        …—¿áÓÁÏ # Push string "ten eleven twelve"
        #« # Split by spaces, and also merge both lists together
        ì # Prepend "one" through "twelve" before "thirteen" through "nineteen"
        D9£ # Duplicate it, and take the first nine ("one" through "nine")
        © # Store it in the register (without popping)
        .•4º»Ÿć'Rþн• '# Push string "twenthirforfif"
        ŽH$ # Push integer 4433
        S # Split to digits: [4,4,3,3]
        £ # And split the to parts of that size: ["twen","thir","for","fif"]
        “Œšï¿Ÿ¯¥Š“ # Push string "six seven eight nine"
        'tK '# Remove all "t" (so "eight" becomes "eigh")
        #« # Split by spaces, and merge both lists together
        „ty # Push string "ty"
        « # And append it to every string in the list
        # (We now have ["twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"])
        s # Swap so the list "one" through "nine" is at the top again
        õš # Prepend an empty string to that list
        â # Create every possible pair of "one" through "nine" with "twenty" through "ninety"
        ðý # Join each pair with a space delimiter
        « # Merge the "twenty" through "ninety nine" list with "one" through "nineteen"
        õš # Prepend an empty string to that list
        D # Duplicate the entire list
        ® # Push the string from the register ("one" through "nine")
        '°¡ '# Push string "hundred"
        ðì # Prepend it with a space " "
        « # Append it to every string in the list
        # (We now have ["one hundred","two hundred",...,"nine hundred"])
        s # Swap the two lists
        â # Create every possible pair of "one hundred" through "nine hundred" with "" through "ninety nine"
        ðý # Join each pair with a space delimiter
        « # Merge the "one" through "ninety nine" with "one hundred " through "nine hundred ninety nine"
        # (We now have ["","one",...,"nine hundred ninety nine"])
        y # Get the current number of the map
        è # And index it into this list
        ð # Push a space " "
        .•cG3₅¦„¥F• # Push string "quadrilltrill"
        8ô # Split into pieces of size 8: ["quadrill","trill"]
        '¾ß '# Push string "ion"
        « # Append it to every string in the list
        …¡›‡È±° # Push string "billion million thousand"
        # # Split by spaces
        « # And merge both lists together
        õª # Append an empty string
        R # Reverse the list
        # (We now have ["","thousand","million","billion","trillion","quadrillion"])
        X # Push variable `X`
        N- # Subtract the map-index from it
        < # Subtract an additional 1
        è # And index it into the list
        J # Join the stack together
        ë # Else:
        õ # Push an empty string ""
        } # Close the if-else
        } # Close the map
        ðý # Join the mapped values with space delimiter
        } # Close the if-else
        Y # Push variable `Y`
        g<i # If its length is exactly 2:
        ® # Push the string from the register ("one" through "nine")
        '¡× '# Push "zero"
        š # Prepend it to the list
        Yθ # Push variable `Y` again, and leave the second number (the decimal part)
        S # Split it to digits
        è # And index each into the list
        '…® '# Push string "point"
        š # Prepend it in front of that list
        ðý # Join the list with space delimiter
        } # Close the if
        } # Close the if-else
        J # Join the stack together
        } # Close the map
        s # Swap to take the (implicit) input again
        ¯` # Push the global array, and dump it's content (string "+-*/")
        Ã # Only keep all "+", "-", "*", and "/", and remove everything else
        ε # Map each to:
        “‰´Øè„ƺߓ # Push string "plus minus times divided"
        # # Split by spaces
        ¤ # Take the last item (without popping the list)
        … by« # Append it with string " by"
        ¸ # Wrap it to a list: ["divided by"]
        s # Swap to take the list again
        ¨ # Remove the last item
        ì # Prepend it in front of the list: ["plus","minus","times","divided by"]
        ¯` # Push the global array, and dump it's content (string "+-*/")
        yk # Push the index in this string for the current map-value `y`
        è # And use that index to index into the string-list
        } # Close the map
        .ι # Interweave the list of numbers and list of operators
        ðý # Join everything with space delimiter
        „ ð: # Replace every two spaces for a single space
        „¢…Øè'¢…: '# And replace every "negative minus" with "negative"
        # (and output the result implicitly)


        See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand why:




        • (How to use the dictionary?) -- '¢… is "negative"; '¡× is "zero"; “†ìˆÈŒšï¿Ÿ¯¥Š“ is "four five six seven eight nine"; '…§ is "teen"; …€µ‚•„í is "one two three"; …—¿áÓÁÏ is "ten eleven twelve"; '°¡ is "hundred"; '¾ß is "ion"; …¡›‡È±° is "billion million thousand"; '…® is "point"; and “‰´Øè„ƺߓ is "plus minus times divided".

        • (How to compress strings not part of the dictionary?) -- .•6b©• is "thir"; .•4º»Ÿć'Rþн• is "twenthirforfif"; and .•cG3₅¦„¥F• is "quadrilltrill".

        • (How to compress large integers?) -- ŽH$ is 4433.






        share|improve this answer































          1















          Python 2, 790 774 bytes





          lambda T:B("([+/*-])",lambda m:dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))[m.group(0)],B("([+/*-]|^)-",r"1negative ",B("[^+/*-]+","{}",T))).format(*[J([g[int(S(".",j)[0])]+S("z",B("y","illion","z thousandz myz byz tryz quadry"))[len(S(",",m))+~i]+(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)for i,j in E(S(",",m))if 0<float(j)+(m<"1")])for m in S("[+/*-]+",T)[T[0]=='-':]])
          from re import*
          E,S,B,P=enumerate,split,sub," ";J=P.join
          s,e=S(P,"zero one two three four five six seven eight nine"),[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
          g=s+S(P,"ten eleven twelve")+e[1:8]+[a+(P+b)*(i>0)for a in e[8:]for i,b in E(s)]
          g=[(j+" hundred ")*(i>0)+k for i,j in E(s)for k in g]


          Try it online!



          So many bad practices. This almost hurt to write....



          Expects a non-unicode string with no whitespace as input.



          Explanation:



          # import all functions from re (python regex library)
          from re import*

          # rename some repeatedly-used functions/variables for reduced bytecount
          E,S,B,P=enumerate,split,sub," ";J=P.join

          # list the names of 0-9
          s=S(P,"zero one two three four five six seven eight nine")
          # generate "twenteen" through nineteen and twenty though ninety, changing "fourty" to forty
          # using enumerate (E) even though i is not required b/c it's shorter than range(len(x))
          # using re.split (S) instead of string.split since it's shorter
          e=[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
          # generate 0-999
          # 0-9
          g=s+
          # 10, 11, 12
          +S(P,"ten eleven twelve")+
          # remove "twenteen", 13-19
          +e[1:8]+
          # tens' place + ones' place, if ones' place is not zero
          +[a+(P+b)*(i>0) ]
          # for each tens' place in 20-90
          for a in e[8:]
          # for each index, value in ones' places 0-9
          for i,b in E(s)


          # hundreds' place if at least 100, plus tens' and ones' place (already calculated and stored in g from before)
          g=[(j+" hundred ")*(i>0)+k ]
          # (s) stores names for 0-9, need index to avoid "zero hundred"
          for i,j in E(s)
          # for each hundred, iterate over all values (0-99) already in g
          for k in g

          # actual function to call. uses previously declared global variable g.
          def f(T):
          # gets the numbers in the supplied string (T) by splitting (T) on any operator character
          # remove first item if blank (only happens when staring with a - for negative numbers)
          n=S("[+/*-]+",T)[T[0]=='-':]

          # triply-nested set of re.subs to convert (T) to a sting of where the operators are replaced by their names and numbers are replaced by "{}"
          # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}" -> "negative {} minus {} minus negative {}"
          # this sub happens last
          # re.sub (B) any operator, with the operators in a group "()" so that they return in match.group
          T=B("([+/*-])", )
          # an anonymous function to accept match objects (m) from re.sub's search.
          ,lambda m:
          # create a dictionary from the combination of operators and their names
          # like {"+":" plus ",...}
          # operator names are surrounded by spaces since number names are NOT
          dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))
          # from the constructed dictionary, select the operator matched by re.sub's search and return it for replacement
          [m.group(0)],
          # this substitution is second
          # re.sub (B) any operator followed by a minus (-), OR a minus at the beginning of the string
          # operators/start are grouped, trailing minus is not
          ,B("([+/*-]|^)-", )
          # replace match with the grouped items plus the word "negative"
          # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}"
          ,r"1negative ",
          # this substitution is done first
          # replace any sequence of NON-operators with "{}"
          # this removes numbers so the names can be inserted later
          # EX: "-1-1--1" -> "-{}-{}--{}"
          ,B("[^+/*-]+","{}",T))

          # technically the previous construction of (T) and (n) can be placed here to save 5 bytes but my poor eyes can't handle that.
          # insert constructed names back into original string.
          # EX: "-1-1--1" -> "negative {} minus {} minus negative {}" -> "negative one minus one minus negative one"
          print T.format( )
          # string.format needs items in array unpacked, or it will attempt to insert the string representation of the array itself
          *[ ]
          # for each number pulled from (T), generate names and join generated items back together with spaces
          # EX: "1,456" -> ["1", "456"] -> ["one thousand", "four hundred fifty six"] -> "one thousand four hundred fifty six"
          J( )for m in n
          # split j on periods (.) and take the first item
          # convert that item into an integer and find the item at that index in g (0-999)
          [g[int(S(".",j)[0])]+ ]
          # insert prefix for millions +, split string on "z" (spaces must be preserved for proper separation)
          +S("z",B("y","illion","z thousandz myz byz tryz quadry"))
          # left is largest, so take the item at index (total # of groups - current place - 1)
          [len(S(",",m))+~i]+
          # if group had a period, split string on period and take last item
          # replace every character in group with number 0-9 name
          # join them with spaces and add back to rest of group
          +(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)
          # split number into groups by comma
          # EX: "123,456" -> ["123","456"]
          # only return item if j != 0 (avoids returning empty string which will result in too many joined spaces)
          # OR if m == 0 (avoids not returning anything when should return "zero")
          for i,j in E(S(",",m))if 0


          I reduced by about 150 bytes while writing the explanation. Let it never be said that commenting/reviewing your code isn't helpful!






          share|improve this answer























            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "200"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f176619%2flazy-word-problems%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            7 Answers
            7






            active

            oldest

            votes








            7 Answers
            7






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            15














            JavaScript (ES6), 552 532 bytes



            This filthy monster comes straight from the depths of code-golfing hell.



            Expects an input string without any whitespace.





            S=>S[R='replace'](/[d.,]+|./g,s=>1/s[0]?a(+s[S=0]&&14)+s[R](/(D?)(d+)/g,(_,s,n)=>s>','?' point'+n[R](/./g,a):j--*n?(u=a(n%10||14),n>99?a(n[0])+' hundred':'')+((n%=100)<13?a(n||14):n<20?(a(n)||u)+'teen':(a(n/10+18)||a(n/10))+'ty'+u)+a(j+27)+(j>1?'illion':''):'',j=s.split`,`.length):a(S='+-*/'.indexOf(s=='-'&&S||s)+34),a=n=>(s='zero0one0two0three0four0five0six0seven0eight0nine0ten0eleven0twelve0thir00fif000eigh00twen0thir0for0fif000eigh00thousand0m0b0tr0quadr0negative0plus0minus0times0divided by'.split`0`[n|0])&&' '+s).trim()


            Try it online!






            share|improve this answer



















            • 3




              You can cut 18 bytes by replacing your giant string literal with btoa`ÍêèÒ‰ÞÒÜ(ÒØkyí¢êô~+ÞÒȱÒǯz}ŠmÒx§{K^ŸG¥z÷§ÒÜ–÷´¶«ÓGâM4z(!ÓKpz}-†*ô~Šô~'ôÓG¢‚4¶.±©ÝÒmÒÚôªæ�¯IÞ�«b½í)–ë4š)î³Kb™ë4v+âuçu×Vò`.replace(111,' ').
              – kamoroso94
              Nov 27 '18 at 19:09










            • I love responses that creatively compress string literals like this.
              – Daffy
              Nov 27 '18 at 21:31
















            15














            JavaScript (ES6), 552 532 bytes



            This filthy monster comes straight from the depths of code-golfing hell.



            Expects an input string without any whitespace.





            S=>S[R='replace'](/[d.,]+|./g,s=>1/s[0]?a(+s[S=0]&&14)+s[R](/(D?)(d+)/g,(_,s,n)=>s>','?' point'+n[R](/./g,a):j--*n?(u=a(n%10||14),n>99?a(n[0])+' hundred':'')+((n%=100)<13?a(n||14):n<20?(a(n)||u)+'teen':(a(n/10+18)||a(n/10))+'ty'+u)+a(j+27)+(j>1?'illion':''):'',j=s.split`,`.length):a(S='+-*/'.indexOf(s=='-'&&S||s)+34),a=n=>(s='zero0one0two0three0four0five0six0seven0eight0nine0ten0eleven0twelve0thir00fif000eigh00twen0thir0for0fif000eigh00thousand0m0b0tr0quadr0negative0plus0minus0times0divided by'.split`0`[n|0])&&' '+s).trim()


            Try it online!






            share|improve this answer



















            • 3




              You can cut 18 bytes by replacing your giant string literal with btoa`ÍêèÒ‰ÞÒÜ(ÒØkyí¢êô~+ÞÒȱÒǯz}ŠmÒx§{K^ŸG¥z÷§ÒÜ–÷´¶«ÓGâM4z(!ÓKpz}-†*ô~Šô~'ôÓG¢‚4¶.±©ÝÒmÒÚôªæ�¯IÞ�«b½í)–ë4š)î³Kb™ë4v+âuçu×Vò`.replace(111,' ').
              – kamoroso94
              Nov 27 '18 at 19:09










            • I love responses that creatively compress string literals like this.
              – Daffy
              Nov 27 '18 at 21:31














            15












            15








            15






            JavaScript (ES6), 552 532 bytes



            This filthy monster comes straight from the depths of code-golfing hell.



            Expects an input string without any whitespace.





            S=>S[R='replace'](/[d.,]+|./g,s=>1/s[0]?a(+s[S=0]&&14)+s[R](/(D?)(d+)/g,(_,s,n)=>s>','?' point'+n[R](/./g,a):j--*n?(u=a(n%10||14),n>99?a(n[0])+' hundred':'')+((n%=100)<13?a(n||14):n<20?(a(n)||u)+'teen':(a(n/10+18)||a(n/10))+'ty'+u)+a(j+27)+(j>1?'illion':''):'',j=s.split`,`.length):a(S='+-*/'.indexOf(s=='-'&&S||s)+34),a=n=>(s='zero0one0two0three0four0five0six0seven0eight0nine0ten0eleven0twelve0thir00fif000eigh00twen0thir0for0fif000eigh00thousand0m0b0tr0quadr0negative0plus0minus0times0divided by'.split`0`[n|0])&&' '+s).trim()


            Try it online!






            share|improve this answer














            JavaScript (ES6), 552 532 bytes



            This filthy monster comes straight from the depths of code-golfing hell.



            Expects an input string without any whitespace.





            S=>S[R='replace'](/[d.,]+|./g,s=>1/s[0]?a(+s[S=0]&&14)+s[R](/(D?)(d+)/g,(_,s,n)=>s>','?' point'+n[R](/./g,a):j--*n?(u=a(n%10||14),n>99?a(n[0])+' hundred':'')+((n%=100)<13?a(n||14):n<20?(a(n)||u)+'teen':(a(n/10+18)||a(n/10))+'ty'+u)+a(j+27)+(j>1?'illion':''):'',j=s.split`,`.length):a(S='+-*/'.indexOf(s=='-'&&S||s)+34),a=n=>(s='zero0one0two0three0four0five0six0seven0eight0nine0ten0eleven0twelve0thir00fif000eigh00twen0thir0for0fif000eigh00thousand0m0b0tr0quadr0negative0plus0minus0times0divided by'.split`0`[n|0])&&' '+s).trim()


            Try it online!







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 27 '18 at 16:46

























            answered Nov 27 '18 at 14:35









            Arnauld

            72.5k689305




            72.5k689305








            • 3




              You can cut 18 bytes by replacing your giant string literal with btoa`ÍêèÒ‰ÞÒÜ(ÒØkyí¢êô~+ÞÒȱÒǯz}ŠmÒx§{K^ŸG¥z÷§ÒÜ–÷´¶«ÓGâM4z(!ÓKpz}-†*ô~Šô~'ôÓG¢‚4¶.±©ÝÒmÒÚôªæ�¯IÞ�«b½í)–ë4š)î³Kb™ë4v+âuçu×Vò`.replace(111,' ').
              – kamoroso94
              Nov 27 '18 at 19:09










            • I love responses that creatively compress string literals like this.
              – Daffy
              Nov 27 '18 at 21:31














            • 3




              You can cut 18 bytes by replacing your giant string literal with btoa`ÍêèÒ‰ÞÒÜ(ÒØkyí¢êô~+ÞÒȱÒǯz}ŠmÒx§{K^ŸG¥z÷§ÒÜ–÷´¶«ÓGâM4z(!ÓKpz}-†*ô~Šô~'ôÓG¢‚4¶.±©ÝÒmÒÚôªæ�¯IÞ�«b½í)–ë4š)î³Kb™ë4v+âuçu×Vò`.replace(111,' ').
              – kamoroso94
              Nov 27 '18 at 19:09










            • I love responses that creatively compress string literals like this.
              – Daffy
              Nov 27 '18 at 21:31








            3




            3




            You can cut 18 bytes by replacing your giant string literal with btoa`ÍêèÒ‰ÞÒÜ(ÒØkyí¢êô~+ÞÒȱÒǯz}ŠmÒx§{K^ŸG¥z÷§ÒÜ–÷´¶«ÓGâM4z(!ÓKpz}-†*ô~Šô~'ôÓG¢‚4¶.±©ÝÒmÒÚôªæ�¯IÞ�«b½í)–ë4š)î³Kb™ë4v+âuçu×Vò`.replace(111,' ').
            – kamoroso94
            Nov 27 '18 at 19:09




            You can cut 18 bytes by replacing your giant string literal with btoa`ÍêèÒ‰ÞÒÜ(ÒØkyí¢êô~+ÞÒȱÒǯz}ŠmÒx§{K^ŸG¥z÷§ÒÜ–÷´¶«ÓGâM4z(!ÓKpz}-†*ô~Šô~'ôÓG¢‚4¶.±©ÝÒmÒÚôªæ�¯IÞ�«b½í)–ë4š)î³Kb™ë4v+âuçu×Vò`.replace(111,' ').
            – kamoroso94
            Nov 27 '18 at 19:09












            I love responses that creatively compress string literals like this.
            – Daffy
            Nov 27 '18 at 21:31




            I love responses that creatively compress string literals like this.
            – Daffy
            Nov 27 '18 at 21:31











            6















            Perl 6, 434 401 387 359 bytes





            {~S:g/d+/{n($//100+64184)x($/>100),$/%100>19&&(n($//10%10+64175),n($!=$/%10)x?$!)||n($/%100+7679),[$,"thousand",|(<m b tr quadr>X~"illion")][+$/.postmatch.words[0].comb(',')]if +$/} /.trans("+,-/*"=><<plus''minus"divided by"times>>).words}o{S:g/.(d)+/ point {$0>>.&n}/}o{S:g/[s|^]0/ zero/}o{S:g/-(d)/negative $0/}
            my&n=(*+1632+|0).uniname.lc.words[2..*]


            Try it online!



            Definitely room for improvement here. I say that, but I keep noticing edge cases I haven't handled :(. Assumes that the input has operators separated by whitespace and the negative of a number isn't separated.



            Explanation:



            my&n=(*+1632+|0).uniname.lc.words[2..*]  # Define a helper function
            # This gets the unicode name, e.g ARABIC-INDIC DIGIT ZERO
            # or AEGEAN NUMBER ONE HUNDRED
            # And returns the 3rd word onwards in lowercase e.g. 'zero' or 'one hundred'
            {S:g/-(d)/negative $0/} # Turn dashes before numbers to negative
            {S:g/[s|^]0/ zero/} # Handle zeros
            {S:g/.(d)+/ point {$0>>.&n}/} # Replace decimals
            {~S:g/d+/ # Replace series of numbers with
            n($//100+64184)x($/>100) # The hundreds if the num is bigger than 100
            $/%100>19&& # If the number is bigger than 19
            (
            n($//10%10+64175), # The tens number
            n($!=$/%10)x?$! # And the singles number (if it's not zero)
            )
            || # Else
            n($/%100+7679) # The name of the number below 20
            , # Then
            [$,"thousand",|(<m b tr quadr>X~"illion")][ # Index into the list of postfixes
            + .comb(',') # The number of commas
            $/.postmatch.words[0] # in the rest of the number
            if +$/ # All if the number is not 0
            .trans("+,-/*"=><<plus''minus"divided by"times>>) # Translate operators
            # And remove commas
            .words} # And remove all the excess spaces between words





            share|improve this answer




























              6















              Perl 6, 434 401 387 359 bytes





              {~S:g/d+/{n($//100+64184)x($/>100),$/%100>19&&(n($//10%10+64175),n($!=$/%10)x?$!)||n($/%100+7679),[$,"thousand",|(<m b tr quadr>X~"illion")][+$/.postmatch.words[0].comb(',')]if +$/} /.trans("+,-/*"=><<plus''minus"divided by"times>>).words}o{S:g/.(d)+/ point {$0>>.&n}/}o{S:g/[s|^]0/ zero/}o{S:g/-(d)/negative $0/}
              my&n=(*+1632+|0).uniname.lc.words[2..*]


              Try it online!



              Definitely room for improvement here. I say that, but I keep noticing edge cases I haven't handled :(. Assumes that the input has operators separated by whitespace and the negative of a number isn't separated.



              Explanation:



              my&n=(*+1632+|0).uniname.lc.words[2..*]  # Define a helper function
              # This gets the unicode name, e.g ARABIC-INDIC DIGIT ZERO
              # or AEGEAN NUMBER ONE HUNDRED
              # And returns the 3rd word onwards in lowercase e.g. 'zero' or 'one hundred'
              {S:g/-(d)/negative $0/} # Turn dashes before numbers to negative
              {S:g/[s|^]0/ zero/} # Handle zeros
              {S:g/.(d)+/ point {$0>>.&n}/} # Replace decimals
              {~S:g/d+/ # Replace series of numbers with
              n($//100+64184)x($/>100) # The hundreds if the num is bigger than 100
              $/%100>19&& # If the number is bigger than 19
              (
              n($//10%10+64175), # The tens number
              n($!=$/%10)x?$! # And the singles number (if it's not zero)
              )
              || # Else
              n($/%100+7679) # The name of the number below 20
              , # Then
              [$,"thousand",|(<m b tr quadr>X~"illion")][ # Index into the list of postfixes
              + .comb(',') # The number of commas
              $/.postmatch.words[0] # in the rest of the number
              if +$/ # All if the number is not 0
              .trans("+,-/*"=><<plus''minus"divided by"times>>) # Translate operators
              # And remove commas
              .words} # And remove all the excess spaces between words





              share|improve this answer


























                6












                6








                6







                Perl 6, 434 401 387 359 bytes





                {~S:g/d+/{n($//100+64184)x($/>100),$/%100>19&&(n($//10%10+64175),n($!=$/%10)x?$!)||n($/%100+7679),[$,"thousand",|(<m b tr quadr>X~"illion")][+$/.postmatch.words[0].comb(',')]if +$/} /.trans("+,-/*"=><<plus''minus"divided by"times>>).words}o{S:g/.(d)+/ point {$0>>.&n}/}o{S:g/[s|^]0/ zero/}o{S:g/-(d)/negative $0/}
                my&n=(*+1632+|0).uniname.lc.words[2..*]


                Try it online!



                Definitely room for improvement here. I say that, but I keep noticing edge cases I haven't handled :(. Assumes that the input has operators separated by whitespace and the negative of a number isn't separated.



                Explanation:



                my&n=(*+1632+|0).uniname.lc.words[2..*]  # Define a helper function
                # This gets the unicode name, e.g ARABIC-INDIC DIGIT ZERO
                # or AEGEAN NUMBER ONE HUNDRED
                # And returns the 3rd word onwards in lowercase e.g. 'zero' or 'one hundred'
                {S:g/-(d)/negative $0/} # Turn dashes before numbers to negative
                {S:g/[s|^]0/ zero/} # Handle zeros
                {S:g/.(d)+/ point {$0>>.&n}/} # Replace decimals
                {~S:g/d+/ # Replace series of numbers with
                n($//100+64184)x($/>100) # The hundreds if the num is bigger than 100
                $/%100>19&& # If the number is bigger than 19
                (
                n($//10%10+64175), # The tens number
                n($!=$/%10)x?$! # And the singles number (if it's not zero)
                )
                || # Else
                n($/%100+7679) # The name of the number below 20
                , # Then
                [$,"thousand",|(<m b tr quadr>X~"illion")][ # Index into the list of postfixes
                + .comb(',') # The number of commas
                $/.postmatch.words[0] # in the rest of the number
                if +$/ # All if the number is not 0
                .trans("+,-/*"=><<plus''minus"divided by"times>>) # Translate operators
                # And remove commas
                .words} # And remove all the excess spaces between words





                share|improve this answer















                Perl 6, 434 401 387 359 bytes





                {~S:g/d+/{n($//100+64184)x($/>100),$/%100>19&&(n($//10%10+64175),n($!=$/%10)x?$!)||n($/%100+7679),[$,"thousand",|(<m b tr quadr>X~"illion")][+$/.postmatch.words[0].comb(',')]if +$/} /.trans("+,-/*"=><<plus''minus"divided by"times>>).words}o{S:g/.(d)+/ point {$0>>.&n}/}o{S:g/[s|^]0/ zero/}o{S:g/-(d)/negative $0/}
                my&n=(*+1632+|0).uniname.lc.words[2..*]


                Try it online!



                Definitely room for improvement here. I say that, but I keep noticing edge cases I haven't handled :(. Assumes that the input has operators separated by whitespace and the negative of a number isn't separated.



                Explanation:



                my&n=(*+1632+|0).uniname.lc.words[2..*]  # Define a helper function
                # This gets the unicode name, e.g ARABIC-INDIC DIGIT ZERO
                # or AEGEAN NUMBER ONE HUNDRED
                # And returns the 3rd word onwards in lowercase e.g. 'zero' or 'one hundred'
                {S:g/-(d)/negative $0/} # Turn dashes before numbers to negative
                {S:g/[s|^]0/ zero/} # Handle zeros
                {S:g/.(d)+/ point {$0>>.&n}/} # Replace decimals
                {~S:g/d+/ # Replace series of numbers with
                n($//100+64184)x($/>100) # The hundreds if the num is bigger than 100
                $/%100>19&& # If the number is bigger than 19
                (
                n($//10%10+64175), # The tens number
                n($!=$/%10)x?$! # And the singles number (if it's not zero)
                )
                || # Else
                n($/%100+7679) # The name of the number below 20
                , # Then
                [$,"thousand",|(<m b tr quadr>X~"illion")][ # Index into the list of postfixes
                + .comb(',') # The number of commas
                $/.postmatch.words[0] # in the rest of the number
                if +$/ # All if the number is not 0
                .trans("+,-/*"=><<plus''minus"divided by"times>>) # Translate operators
                # And remove commas
                .words} # And remove all the excess spaces between words






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 29 '18 at 3:13

























                answered Nov 28 '18 at 7:00









                Jo King

                20.9k248110




                20.9k248110























                    5














                    Ruby + Swift 4, 283 279 270 bytes





                    $_=gsub(/(?<=d)-/,"minus ").gsub(/[*-/]/,?.=>"point ",?-=>"negative ",?+=>"plus ",?*=>"times ",?/=>"divided by ").gsub(/(?<=^|[^t] )d+|d/){`echo "import Foundation
                    var f=NumberFormatter()
                    f.numberStyle = .spellOut
                    print(f.string(from:#$&)!)">.a
                    swift .a`.tr'-
                    ',' '}


                    Try it online!



                    I must be mad to propose such a Frankenstein solution, but on one hand, it is very tempting to use Swift's built-in functionality for this task, and on the other hand, processing strings with Regexes in Swift looks to be a golfing catastrophe.



                    Therefore, I decided to do basic string processing in Ruby, but to spell out numbers, I store them in a Swift source file, run Swift in a shell command, and collect the output.



                    I turns out that Swift's "spellOut" number formatter does almost exactly what we need, except inserting unnecessary hyphens for two-digit numbers, as in twenty-two. In fact, even the floating point output in the format of integer part point digit digit... is good, but here comes the caveat - there is no infinite precision, and with large enough numbers or a lot of decimal digits, the results go wrong. Therefore, I had to separate the integer and fractional parts and to feed the fraction digit by digit.






                    share|improve this answer



















                    • 1




                      This is absolutely diabolical and I love it.
                      – Daffy
                      Nov 28 '18 at 22:02
















                    5














                    Ruby + Swift 4, 283 279 270 bytes





                    $_=gsub(/(?<=d)-/,"minus ").gsub(/[*-/]/,?.=>"point ",?-=>"negative ",?+=>"plus ",?*=>"times ",?/=>"divided by ").gsub(/(?<=^|[^t] )d+|d/){`echo "import Foundation
                    var f=NumberFormatter()
                    f.numberStyle = .spellOut
                    print(f.string(from:#$&)!)">.a
                    swift .a`.tr'-
                    ',' '}


                    Try it online!



                    I must be mad to propose such a Frankenstein solution, but on one hand, it is very tempting to use Swift's built-in functionality for this task, and on the other hand, processing strings with Regexes in Swift looks to be a golfing catastrophe.



                    Therefore, I decided to do basic string processing in Ruby, but to spell out numbers, I store them in a Swift source file, run Swift in a shell command, and collect the output.



                    I turns out that Swift's "spellOut" number formatter does almost exactly what we need, except inserting unnecessary hyphens for two-digit numbers, as in twenty-two. In fact, even the floating point output in the format of integer part point digit digit... is good, but here comes the caveat - there is no infinite precision, and with large enough numbers or a lot of decimal digits, the results go wrong. Therefore, I had to separate the integer and fractional parts and to feed the fraction digit by digit.






                    share|improve this answer



















                    • 1




                      This is absolutely diabolical and I love it.
                      – Daffy
                      Nov 28 '18 at 22:02














                    5












                    5








                    5






                    Ruby + Swift 4, 283 279 270 bytes





                    $_=gsub(/(?<=d)-/,"minus ").gsub(/[*-/]/,?.=>"point ",?-=>"negative ",?+=>"plus ",?*=>"times ",?/=>"divided by ").gsub(/(?<=^|[^t] )d+|d/){`echo "import Foundation
                    var f=NumberFormatter()
                    f.numberStyle = .spellOut
                    print(f.string(from:#$&)!)">.a
                    swift .a`.tr'-
                    ',' '}


                    Try it online!



                    I must be mad to propose such a Frankenstein solution, but on one hand, it is very tempting to use Swift's built-in functionality for this task, and on the other hand, processing strings with Regexes in Swift looks to be a golfing catastrophe.



                    Therefore, I decided to do basic string processing in Ruby, but to spell out numbers, I store them in a Swift source file, run Swift in a shell command, and collect the output.



                    I turns out that Swift's "spellOut" number formatter does almost exactly what we need, except inserting unnecessary hyphens for two-digit numbers, as in twenty-two. In fact, even the floating point output in the format of integer part point digit digit... is good, but here comes the caveat - there is no infinite precision, and with large enough numbers or a lot of decimal digits, the results go wrong. Therefore, I had to separate the integer and fractional parts and to feed the fraction digit by digit.






                    share|improve this answer














                    Ruby + Swift 4, 283 279 270 bytes





                    $_=gsub(/(?<=d)-/,"minus ").gsub(/[*-/]/,?.=>"point ",?-=>"negative ",?+=>"plus ",?*=>"times ",?/=>"divided by ").gsub(/(?<=^|[^t] )d+|d/){`echo "import Foundation
                    var f=NumberFormatter()
                    f.numberStyle = .spellOut
                    print(f.string(from:#$&)!)">.a
                    swift .a`.tr'-
                    ',' '}


                    Try it online!



                    I must be mad to propose such a Frankenstein solution, but on one hand, it is very tempting to use Swift's built-in functionality for this task, and on the other hand, processing strings with Regexes in Swift looks to be a golfing catastrophe.



                    Therefore, I decided to do basic string processing in Ruby, but to spell out numbers, I store them in a Swift source file, run Swift in a shell command, and collect the output.



                    I turns out that Swift's "spellOut" number formatter does almost exactly what we need, except inserting unnecessary hyphens for two-digit numbers, as in twenty-two. In fact, even the floating point output in the format of integer part point digit digit... is good, but here comes the caveat - there is no infinite precision, and with large enough numbers or a lot of decimal digits, the results go wrong. Therefore, I had to separate the integer and fractional parts and to feed the fraction digit by digit.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 29 '18 at 14:52

























                    answered Nov 28 '18 at 13:59









                    Kirill L.

                    3,6551319




                    3,6551319








                    • 1




                      This is absolutely diabolical and I love it.
                      – Daffy
                      Nov 28 '18 at 22:02














                    • 1




                      This is absolutely diabolical and I love it.
                      – Daffy
                      Nov 28 '18 at 22:02








                    1




                    1




                    This is absolutely diabolical and I love it.
                    – Daffy
                    Nov 28 '18 at 22:02




                    This is absolutely diabolical and I love it.
                    – Daffy
                    Nov 28 '18 at 22:02











                    4















                    sfk, 853 bytes



                    xed -i
                    "_*_ [part1]_"
                    +xed
                    _+_plus_
                    _*_times_
                    "_/_divided by_"
                    "_- _minus _"
                    "_-_negative _"
                    +xed
                    "_,[keep][19 chars of 0-9,]_quadr@ _"
                    "_,[keep][15 chars of 0-9,]_tr@ _"
                    "_,[keep][11 chars of 0-9,]_b@ _"
                    "_,[keep][digits],[digits],_b@ _"
                    "_,[keep][digits],_m@ _"
                    "_,_ thousand _"
                    +xed
                    "_ 000[chars]@__"
                    "_ 000__"
                    "_ 00[keep][digit]_ _"
                    "_ 0[keep][2 digits]_ @_"
                    "_ [digit][keep][2 digits]_[part2]hundred @_"
                    "_ [ortext] 0[digit]0_ @[part2]_"
                    "_ [keep][2 digits]_ @_"
                    "_@_illion _"
                    +xed
                    _@11_eleven_
                    _@12_twelve_
                    _@1[digit]_@[part2]teen_
                    _@1_ten_
                    _@4_forty_
                    _@[digit]_@[part2]ty_
                    +xed
                    _@2_twen_
                    _@3_thir_
                    _@4_four_
                    _@5_fif_
                    _@6_six_
                    _@7_seven_
                    _@8_eigh_
                    _@9_nine_
                    +xed
                    "_0_ zero _"
                    "_1_ one _"
                    "_2_ two _"
                    "_3_ three _"
                    "_4_ four _"
                    "_5_ five _"
                    "_6_ six _"
                    "_7_ seven _"
                    "_8_ eight _"
                    "_9_ nine _"
                    "_._ point _"
                    +xed
                    "_[white]_ _"
                    +xed
                    "_[lstart] __"



                    Try it online!



                    Requires operators and numbers be separated by at least one space character.






                    share|improve this answer


























                      4















                      sfk, 853 bytes



                      xed -i
                      "_*_ [part1]_"
                      +xed
                      _+_plus_
                      _*_times_
                      "_/_divided by_"
                      "_- _minus _"
                      "_-_negative _"
                      +xed
                      "_,[keep][19 chars of 0-9,]_quadr@ _"
                      "_,[keep][15 chars of 0-9,]_tr@ _"
                      "_,[keep][11 chars of 0-9,]_b@ _"
                      "_,[keep][digits],[digits],_b@ _"
                      "_,[keep][digits],_m@ _"
                      "_,_ thousand _"
                      +xed
                      "_ 000[chars]@__"
                      "_ 000__"
                      "_ 00[keep][digit]_ _"
                      "_ 0[keep][2 digits]_ @_"
                      "_ [digit][keep][2 digits]_[part2]hundred @_"
                      "_ [ortext] 0[digit]0_ @[part2]_"
                      "_ [keep][2 digits]_ @_"
                      "_@_illion _"
                      +xed
                      _@11_eleven_
                      _@12_twelve_
                      _@1[digit]_@[part2]teen_
                      _@1_ten_
                      _@4_forty_
                      _@[digit]_@[part2]ty_
                      +xed
                      _@2_twen_
                      _@3_thir_
                      _@4_four_
                      _@5_fif_
                      _@6_six_
                      _@7_seven_
                      _@8_eigh_
                      _@9_nine_
                      +xed
                      "_0_ zero _"
                      "_1_ one _"
                      "_2_ two _"
                      "_3_ three _"
                      "_4_ four _"
                      "_5_ five _"
                      "_6_ six _"
                      "_7_ seven _"
                      "_8_ eight _"
                      "_9_ nine _"
                      "_._ point _"
                      +xed
                      "_[white]_ _"
                      +xed
                      "_[lstart] __"



                      Try it online!



                      Requires operators and numbers be separated by at least one space character.






                      share|improve this answer
























                        4












                        4








                        4







                        sfk, 853 bytes



                        xed -i
                        "_*_ [part1]_"
                        +xed
                        _+_plus_
                        _*_times_
                        "_/_divided by_"
                        "_- _minus _"
                        "_-_negative _"
                        +xed
                        "_,[keep][19 chars of 0-9,]_quadr@ _"
                        "_,[keep][15 chars of 0-9,]_tr@ _"
                        "_,[keep][11 chars of 0-9,]_b@ _"
                        "_,[keep][digits],[digits],_b@ _"
                        "_,[keep][digits],_m@ _"
                        "_,_ thousand _"
                        +xed
                        "_ 000[chars]@__"
                        "_ 000__"
                        "_ 00[keep][digit]_ _"
                        "_ 0[keep][2 digits]_ @_"
                        "_ [digit][keep][2 digits]_[part2]hundred @_"
                        "_ [ortext] 0[digit]0_ @[part2]_"
                        "_ [keep][2 digits]_ @_"
                        "_@_illion _"
                        +xed
                        _@11_eleven_
                        _@12_twelve_
                        _@1[digit]_@[part2]teen_
                        _@1_ten_
                        _@4_forty_
                        _@[digit]_@[part2]ty_
                        +xed
                        _@2_twen_
                        _@3_thir_
                        _@4_four_
                        _@5_fif_
                        _@6_six_
                        _@7_seven_
                        _@8_eigh_
                        _@9_nine_
                        +xed
                        "_0_ zero _"
                        "_1_ one _"
                        "_2_ two _"
                        "_3_ three _"
                        "_4_ four _"
                        "_5_ five _"
                        "_6_ six _"
                        "_7_ seven _"
                        "_8_ eight _"
                        "_9_ nine _"
                        "_._ point _"
                        +xed
                        "_[white]_ _"
                        +xed
                        "_[lstart] __"



                        Try it online!



                        Requires operators and numbers be separated by at least one space character.






                        share|improve this answer













                        sfk, 853 bytes



                        xed -i
                        "_*_ [part1]_"
                        +xed
                        _+_plus_
                        _*_times_
                        "_/_divided by_"
                        "_- _minus _"
                        "_-_negative _"
                        +xed
                        "_,[keep][19 chars of 0-9,]_quadr@ _"
                        "_,[keep][15 chars of 0-9,]_tr@ _"
                        "_,[keep][11 chars of 0-9,]_b@ _"
                        "_,[keep][digits],[digits],_b@ _"
                        "_,[keep][digits],_m@ _"
                        "_,_ thousand _"
                        +xed
                        "_ 000[chars]@__"
                        "_ 000__"
                        "_ 00[keep][digit]_ _"
                        "_ 0[keep][2 digits]_ @_"
                        "_ [digit][keep][2 digits]_[part2]hundred @_"
                        "_ [ortext] 0[digit]0_ @[part2]_"
                        "_ [keep][2 digits]_ @_"
                        "_@_illion _"
                        +xed
                        _@11_eleven_
                        _@12_twelve_
                        _@1[digit]_@[part2]teen_
                        _@1_ten_
                        _@4_forty_
                        _@[digit]_@[part2]ty_
                        +xed
                        _@2_twen_
                        _@3_thir_
                        _@4_four_
                        _@5_fif_
                        _@6_six_
                        _@7_seven_
                        _@8_eigh_
                        _@9_nine_
                        +xed
                        "_0_ zero _"
                        "_1_ one _"
                        "_2_ two _"
                        "_3_ three _"
                        "_4_ four _"
                        "_5_ five _"
                        "_6_ six _"
                        "_7_ seven _"
                        "_8_ eight _"
                        "_9_ nine _"
                        "_._ point _"
                        +xed
                        "_[white]_ _"
                        +xed
                        "_[lstart] __"



                        Try it online!



                        Requires operators and numbers be separated by at least one space character.







                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Nov 28 '18 at 2:17









                        Οurous

                        6,48211033




                        6,48211033























                            4















                            Clean, 766 ... 687 bytes



                            import StdEnv,Text
                            m=""
                            z="zero"
                            @ =digitToInt
                            r=reverse
                            l k=(!!)k o@
                            ^s=l[s:split" ""one two three four five six seven eight nine"]
                            g s=l[m,m,"twen","thir",s,"fif","six","seven","eigh","nine"]
                            ~['0':t]= ~t
                            ~[a,b,c]= ^""a+" hundred "+ ~[b,c]
                            ~[b,c]|b>'1'=g"for"b+"ty "+ ^""c|c>'2'=g"four"c+"teen"=["ten","eleven","twelve"]!!(@c)
                            ~[c]= ^""c
                            ~_=m
                            $=m
                            $[x:y]#(h,t)=span(e=e>'/'||e==',')if(x<'1')y[x:y]
                            =trim(join" "((case x of'0'=[z];'-'=["negative",$h];'.'=["point":map(^z)h];_=(r[u+v\u<-r(map~(split[',']h))&v<-[m," thousand":[" "+k+"illion"\k<-["m","b","tr","quadr"]]]|u>m]))++[?t]))
                            ?['-':t]="minus "+ $t
                            ?['+':t]="plus "+ $t
                            ?['/':t]="divided by "+ $t
                            ?['*':t]="times "+ $t
                            ?t= $t


                            Try it online!



                            Expects a string without whitespace.






                            share|improve this answer




























                              4















                              Clean, 766 ... 687 bytes



                              import StdEnv,Text
                              m=""
                              z="zero"
                              @ =digitToInt
                              r=reverse
                              l k=(!!)k o@
                              ^s=l[s:split" ""one two three four five six seven eight nine"]
                              g s=l[m,m,"twen","thir",s,"fif","six","seven","eigh","nine"]
                              ~['0':t]= ~t
                              ~[a,b,c]= ^""a+" hundred "+ ~[b,c]
                              ~[b,c]|b>'1'=g"for"b+"ty "+ ^""c|c>'2'=g"four"c+"teen"=["ten","eleven","twelve"]!!(@c)
                              ~[c]= ^""c
                              ~_=m
                              $=m
                              $[x:y]#(h,t)=span(e=e>'/'||e==',')if(x<'1')y[x:y]
                              =trim(join" "((case x of'0'=[z];'-'=["negative",$h];'.'=["point":map(^z)h];_=(r[u+v\u<-r(map~(split[',']h))&v<-[m," thousand":[" "+k+"illion"\k<-["m","b","tr","quadr"]]]|u>m]))++[?t]))
                              ?['-':t]="minus "+ $t
                              ?['+':t]="plus "+ $t
                              ?['/':t]="divided by "+ $t
                              ?['*':t]="times "+ $t
                              ?t= $t


                              Try it online!



                              Expects a string without whitespace.






                              share|improve this answer


























                                4












                                4








                                4







                                Clean, 766 ... 687 bytes



                                import StdEnv,Text
                                m=""
                                z="zero"
                                @ =digitToInt
                                r=reverse
                                l k=(!!)k o@
                                ^s=l[s:split" ""one two three four five six seven eight nine"]
                                g s=l[m,m,"twen","thir",s,"fif","six","seven","eigh","nine"]
                                ~['0':t]= ~t
                                ~[a,b,c]= ^""a+" hundred "+ ~[b,c]
                                ~[b,c]|b>'1'=g"for"b+"ty "+ ^""c|c>'2'=g"four"c+"teen"=["ten","eleven","twelve"]!!(@c)
                                ~[c]= ^""c
                                ~_=m
                                $=m
                                $[x:y]#(h,t)=span(e=e>'/'||e==',')if(x<'1')y[x:y]
                                =trim(join" "((case x of'0'=[z];'-'=["negative",$h];'.'=["point":map(^z)h];_=(r[u+v\u<-r(map~(split[',']h))&v<-[m," thousand":[" "+k+"illion"\k<-["m","b","tr","quadr"]]]|u>m]))++[?t]))
                                ?['-':t]="minus "+ $t
                                ?['+':t]="plus "+ $t
                                ?['/':t]="divided by "+ $t
                                ?['*':t]="times "+ $t
                                ?t= $t


                                Try it online!



                                Expects a string without whitespace.






                                share|improve this answer















                                Clean, 766 ... 687 bytes



                                import StdEnv,Text
                                m=""
                                z="zero"
                                @ =digitToInt
                                r=reverse
                                l k=(!!)k o@
                                ^s=l[s:split" ""one two three four five six seven eight nine"]
                                g s=l[m,m,"twen","thir",s,"fif","six","seven","eigh","nine"]
                                ~['0':t]= ~t
                                ~[a,b,c]= ^""a+" hundred "+ ~[b,c]
                                ~[b,c]|b>'1'=g"for"b+"ty "+ ^""c|c>'2'=g"four"c+"teen"=["ten","eleven","twelve"]!!(@c)
                                ~[c]= ^""c
                                ~_=m
                                $=m
                                $[x:y]#(h,t)=span(e=e>'/'||e==',')if(x<'1')y[x:y]
                                =trim(join" "((case x of'0'=[z];'-'=["negative",$h];'.'=["point":map(^z)h];_=(r[u+v\u<-r(map~(split[',']h))&v<-[m," thousand":[" "+k+"illion"\k<-["m","b","tr","quadr"]]]|u>m]))++[?t]))
                                ?['-':t]="minus "+ $t
                                ?['+':t]="plus "+ $t
                                ?['/':t]="divided by "+ $t
                                ?['*':t]="times "+ $t
                                ?t= $t


                                Try it online!



                                Expects a string without whitespace.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Nov 29 '18 at 2:25

























                                answered Nov 27 '18 at 22:29









                                Οurous

                                6,48211033




                                6,48211033























                                    1















                                    05AB1E, 315 295 282 276 bytes



                                    "+-*/"DˆS¡εDõQi'¢…ë'.¡VYнD_i'¡×ðë',¡DgUε0›i.•6b©•ð“†ìˆÈŒšï¿Ÿ¯¥Š“©'tKJ#'…§«…€µ‚•„í#®#«…—¿áÓÁÏ#«ìD9£©.•4º»Ÿć'Rþн•ŽH$S£“Œšï¿Ÿ¯¥Š“'tK#«„ty«sõšâðý«õšD®'°¡ðì«sâðý«yèð.•cG3₅¦„¥F•8ô'¾ß«…¡›‡È±°#«õªRXN-<èJëõ}}ðý}Yg<i®'¡×šYθSè'…®šðý}}J}s¯`Ã哉´Øè„ƺߓ#¤… by«¸s¨ì¯`ykè}.ιðý„  ð:„¢…Øè'¢…:


                                    Takes input without any spaces.



                                    Try it online or verify all test cases.



                                    Explanation:





                                    "+-*/"                    # Push string "+-*/"
                                    Dˆ # Duplicate it, pop the copy, and push it to the global array
                                    S¡ # Split the input by any "+", "-", "*", or "/"
                                    ε # Map each number to:
                                    DõQi # If the item is empty (happens for negative numbers)
                                    '¢… '# Push string "negative"
                                    ë # Else:
                                    '.¡ '# Split by "."
                                    VY # Store it in variable `Y`
                                    н # Take the first number (the integer part)
                                    D # Duplicate this integer part
                                    _i # If the integer part is exactly 0:
                                    # Discard the duplicated integer part
                                    '¡× '# Push string "zero"
                                    ð # Push a space " "
                                    ë # Else:
                                    ',¡ '# Split by ","
                                    DgU # Pop and store the amount of items in variable `X`
                                    ε # Map each part to:
                                    0›i # If it's larger than 0:
                                    .•6b©• # Push string "thir"
                                    ð # Push a space " "
                                    “†ìˆÈŒšï¿Ÿ¯¥Š“ # Push string "four five six seven eight nine"
                                    © # Store it in the register (without popping)
                                    'tK '# Remove all "t" (so "eight" becomes "eigh")
                                    J # Join it together with the "thir" and space
                                    # # Split by spaces
                                    '…§ '# Push string "teen"
                                    « # And append it to every string in the list
                                    # (We now have ["thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"])
                                    …€µ‚•„í # Push string "one two three"
                                    # # Split by spaces
                                    ® # Push the string from the register ("four" through "nine")
                                    #« # Split by spaces, and merge both lists together
                                    …—¿áÓÁÏ # Push string "ten eleven twelve"
                                    #« # Split by spaces, and also merge both lists together
                                    ì # Prepend "one" through "twelve" before "thirteen" through "nineteen"
                                    D9£ # Duplicate it, and take the first nine ("one" through "nine")
                                    © # Store it in the register (without popping)
                                    .•4º»Ÿć'Rþн• '# Push string "twenthirforfif"
                                    ŽH$ # Push integer 4433
                                    S # Split to digits: [4,4,3,3]
                                    £ # And split the to parts of that size: ["twen","thir","for","fif"]
                                    “Œšï¿Ÿ¯¥Š“ # Push string "six seven eight nine"
                                    'tK '# Remove all "t" (so "eight" becomes "eigh")
                                    #« # Split by spaces, and merge both lists together
                                    „ty # Push string "ty"
                                    « # And append it to every string in the list
                                    # (We now have ["twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"])
                                    s # Swap so the list "one" through "nine" is at the top again
                                    õš # Prepend an empty string to that list
                                    â # Create every possible pair of "one" through "nine" with "twenty" through "ninety"
                                    ðý # Join each pair with a space delimiter
                                    « # Merge the "twenty" through "ninety nine" list with "one" through "nineteen"
                                    õš # Prepend an empty string to that list
                                    D # Duplicate the entire list
                                    ® # Push the string from the register ("one" through "nine")
                                    '°¡ '# Push string "hundred"
                                    ðì # Prepend it with a space " "
                                    « # Append it to every string in the list
                                    # (We now have ["one hundred","two hundred",...,"nine hundred"])
                                    s # Swap the two lists
                                    â # Create every possible pair of "one hundred" through "nine hundred" with "" through "ninety nine"
                                    ðý # Join each pair with a space delimiter
                                    « # Merge the "one" through "ninety nine" with "one hundred " through "nine hundred ninety nine"
                                    # (We now have ["","one",...,"nine hundred ninety nine"])
                                    y # Get the current number of the map
                                    è # And index it into this list
                                    ð # Push a space " "
                                    .•cG3₅¦„¥F• # Push string "quadrilltrill"
                                    8ô # Split into pieces of size 8: ["quadrill","trill"]
                                    '¾ß '# Push string "ion"
                                    « # Append it to every string in the list
                                    …¡›‡È±° # Push string "billion million thousand"
                                    # # Split by spaces
                                    « # And merge both lists together
                                    õª # Append an empty string
                                    R # Reverse the list
                                    # (We now have ["","thousand","million","billion","trillion","quadrillion"])
                                    X # Push variable `X`
                                    N- # Subtract the map-index from it
                                    < # Subtract an additional 1
                                    è # And index it into the list
                                    J # Join the stack together
                                    ë # Else:
                                    õ # Push an empty string ""
                                    } # Close the if-else
                                    } # Close the map
                                    ðý # Join the mapped values with space delimiter
                                    } # Close the if-else
                                    Y # Push variable `Y`
                                    g<i # If its length is exactly 2:
                                    ® # Push the string from the register ("one" through "nine")
                                    '¡× '# Push "zero"
                                    š # Prepend it to the list
                                    Yθ # Push variable `Y` again, and leave the second number (the decimal part)
                                    S # Split it to digits
                                    è # And index each into the list
                                    '…® '# Push string "point"
                                    š # Prepend it in front of that list
                                    ðý # Join the list with space delimiter
                                    } # Close the if
                                    } # Close the if-else
                                    J # Join the stack together
                                    } # Close the map
                                    s # Swap to take the (implicit) input again
                                    ¯` # Push the global array, and dump it's content (string "+-*/")
                                    Ã # Only keep all "+", "-", "*", and "/", and remove everything else
                                    ε # Map each to:
                                    “‰´Øè„ƺߓ # Push string "plus minus times divided"
                                    # # Split by spaces
                                    ¤ # Take the last item (without popping the list)
                                    … by« # Append it with string " by"
                                    ¸ # Wrap it to a list: ["divided by"]
                                    s # Swap to take the list again
                                    ¨ # Remove the last item
                                    ì # Prepend it in front of the list: ["plus","minus","times","divided by"]
                                    ¯` # Push the global array, and dump it's content (string "+-*/")
                                    yk # Push the index in this string for the current map-value `y`
                                    è # And use that index to index into the string-list
                                    } # Close the map
                                    .ι # Interweave the list of numbers and list of operators
                                    ðý # Join everything with space delimiter
                                    „ ð: # Replace every two spaces for a single space
                                    „¢…Øè'¢…: '# And replace every "negative minus" with "negative"
                                    # (and output the result implicitly)


                                    See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand why:




                                    • (How to use the dictionary?) -- '¢… is "negative"; '¡× is "zero"; “†ìˆÈŒšï¿Ÿ¯¥Š“ is "four five six seven eight nine"; '…§ is "teen"; …€µ‚•„í is "one two three"; …—¿áÓÁÏ is "ten eleven twelve"; '°¡ is "hundred"; '¾ß is "ion"; …¡›‡È±° is "billion million thousand"; '…® is "point"; and “‰´Øè„ƺߓ is "plus minus times divided".

                                    • (How to compress strings not part of the dictionary?) -- .•6b©• is "thir"; .•4º»Ÿć'Rþн• is "twenthirforfif"; and .•cG3₅¦„¥F• is "quadrilltrill".

                                    • (How to compress large integers?) -- ŽH$ is 4433.






                                    share|improve this answer




























                                      1















                                      05AB1E, 315 295 282 276 bytes



                                      "+-*/"DˆS¡εDõQi'¢…ë'.¡VYнD_i'¡×ðë',¡DgUε0›i.•6b©•ð“†ìˆÈŒšï¿Ÿ¯¥Š“©'tKJ#'…§«…€µ‚•„í#®#«…—¿áÓÁÏ#«ìD9£©.•4º»Ÿć'Rþн•ŽH$S£“Œšï¿Ÿ¯¥Š“'tK#«„ty«sõšâðý«õšD®'°¡ðì«sâðý«yèð.•cG3₅¦„¥F•8ô'¾ß«…¡›‡È±°#«õªRXN-<èJëõ}}ðý}Yg<i®'¡×šYθSè'…®šðý}}J}s¯`Ã哉´Øè„ƺߓ#¤… by«¸s¨ì¯`ykè}.ιðý„  ð:„¢…Øè'¢…:


                                      Takes input without any spaces.



                                      Try it online or verify all test cases.



                                      Explanation:





                                      "+-*/"                    # Push string "+-*/"
                                      Dˆ # Duplicate it, pop the copy, and push it to the global array
                                      S¡ # Split the input by any "+", "-", "*", or "/"
                                      ε # Map each number to:
                                      DõQi # If the item is empty (happens for negative numbers)
                                      '¢… '# Push string "negative"
                                      ë # Else:
                                      '.¡ '# Split by "."
                                      VY # Store it in variable `Y`
                                      н # Take the first number (the integer part)
                                      D # Duplicate this integer part
                                      _i # If the integer part is exactly 0:
                                      # Discard the duplicated integer part
                                      '¡× '# Push string "zero"
                                      ð # Push a space " "
                                      ë # Else:
                                      ',¡ '# Split by ","
                                      DgU # Pop and store the amount of items in variable `X`
                                      ε # Map each part to:
                                      0›i # If it's larger than 0:
                                      .•6b©• # Push string "thir"
                                      ð # Push a space " "
                                      “†ìˆÈŒšï¿Ÿ¯¥Š“ # Push string "four five six seven eight nine"
                                      © # Store it in the register (without popping)
                                      'tK '# Remove all "t" (so "eight" becomes "eigh")
                                      J # Join it together with the "thir" and space
                                      # # Split by spaces
                                      '…§ '# Push string "teen"
                                      « # And append it to every string in the list
                                      # (We now have ["thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"])
                                      …€µ‚•„í # Push string "one two three"
                                      # # Split by spaces
                                      ® # Push the string from the register ("four" through "nine")
                                      #« # Split by spaces, and merge both lists together
                                      …—¿áÓÁÏ # Push string "ten eleven twelve"
                                      #« # Split by spaces, and also merge both lists together
                                      ì # Prepend "one" through "twelve" before "thirteen" through "nineteen"
                                      D9£ # Duplicate it, and take the first nine ("one" through "nine")
                                      © # Store it in the register (without popping)
                                      .•4º»Ÿć'Rþн• '# Push string "twenthirforfif"
                                      ŽH$ # Push integer 4433
                                      S # Split to digits: [4,4,3,3]
                                      £ # And split the to parts of that size: ["twen","thir","for","fif"]
                                      “Œšï¿Ÿ¯¥Š“ # Push string "six seven eight nine"
                                      'tK '# Remove all "t" (so "eight" becomes "eigh")
                                      #« # Split by spaces, and merge both lists together
                                      „ty # Push string "ty"
                                      « # And append it to every string in the list
                                      # (We now have ["twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"])
                                      s # Swap so the list "one" through "nine" is at the top again
                                      õš # Prepend an empty string to that list
                                      â # Create every possible pair of "one" through "nine" with "twenty" through "ninety"
                                      ðý # Join each pair with a space delimiter
                                      « # Merge the "twenty" through "ninety nine" list with "one" through "nineteen"
                                      õš # Prepend an empty string to that list
                                      D # Duplicate the entire list
                                      ® # Push the string from the register ("one" through "nine")
                                      '°¡ '# Push string "hundred"
                                      ðì # Prepend it with a space " "
                                      « # Append it to every string in the list
                                      # (We now have ["one hundred","two hundred",...,"nine hundred"])
                                      s # Swap the two lists
                                      â # Create every possible pair of "one hundred" through "nine hundred" with "" through "ninety nine"
                                      ðý # Join each pair with a space delimiter
                                      « # Merge the "one" through "ninety nine" with "one hundred " through "nine hundred ninety nine"
                                      # (We now have ["","one",...,"nine hundred ninety nine"])
                                      y # Get the current number of the map
                                      è # And index it into this list
                                      ð # Push a space " "
                                      .•cG3₅¦„¥F• # Push string "quadrilltrill"
                                      8ô # Split into pieces of size 8: ["quadrill","trill"]
                                      '¾ß '# Push string "ion"
                                      « # Append it to every string in the list
                                      …¡›‡È±° # Push string "billion million thousand"
                                      # # Split by spaces
                                      « # And merge both lists together
                                      õª # Append an empty string
                                      R # Reverse the list
                                      # (We now have ["","thousand","million","billion","trillion","quadrillion"])
                                      X # Push variable `X`
                                      N- # Subtract the map-index from it
                                      < # Subtract an additional 1
                                      è # And index it into the list
                                      J # Join the stack together
                                      ë # Else:
                                      õ # Push an empty string ""
                                      } # Close the if-else
                                      } # Close the map
                                      ðý # Join the mapped values with space delimiter
                                      } # Close the if-else
                                      Y # Push variable `Y`
                                      g<i # If its length is exactly 2:
                                      ® # Push the string from the register ("one" through "nine")
                                      '¡× '# Push "zero"
                                      š # Prepend it to the list
                                      Yθ # Push variable `Y` again, and leave the second number (the decimal part)
                                      S # Split it to digits
                                      è # And index each into the list
                                      '…® '# Push string "point"
                                      š # Prepend it in front of that list
                                      ðý # Join the list with space delimiter
                                      } # Close the if
                                      } # Close the if-else
                                      J # Join the stack together
                                      } # Close the map
                                      s # Swap to take the (implicit) input again
                                      ¯` # Push the global array, and dump it's content (string "+-*/")
                                      Ã # Only keep all "+", "-", "*", and "/", and remove everything else
                                      ε # Map each to:
                                      “‰´Øè„ƺߓ # Push string "plus minus times divided"
                                      # # Split by spaces
                                      ¤ # Take the last item (without popping the list)
                                      … by« # Append it with string " by"
                                      ¸ # Wrap it to a list: ["divided by"]
                                      s # Swap to take the list again
                                      ¨ # Remove the last item
                                      ì # Prepend it in front of the list: ["plus","minus","times","divided by"]
                                      ¯` # Push the global array, and dump it's content (string "+-*/")
                                      yk # Push the index in this string for the current map-value `y`
                                      è # And use that index to index into the string-list
                                      } # Close the map
                                      .ι # Interweave the list of numbers and list of operators
                                      ðý # Join everything with space delimiter
                                      „ ð: # Replace every two spaces for a single space
                                      „¢…Øè'¢…: '# And replace every "negative minus" with "negative"
                                      # (and output the result implicitly)


                                      See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand why:




                                      • (How to use the dictionary?) -- '¢… is "negative"; '¡× is "zero"; “†ìˆÈŒšï¿Ÿ¯¥Š“ is "four five six seven eight nine"; '…§ is "teen"; …€µ‚•„í is "one two three"; …—¿áÓÁÏ is "ten eleven twelve"; '°¡ is "hundred"; '¾ß is "ion"; …¡›‡È±° is "billion million thousand"; '…® is "point"; and “‰´Øè„ƺߓ is "plus minus times divided".

                                      • (How to compress strings not part of the dictionary?) -- .•6b©• is "thir"; .•4º»Ÿć'Rþн• is "twenthirforfif"; and .•cG3₅¦„¥F• is "quadrilltrill".

                                      • (How to compress large integers?) -- ŽH$ is 4433.






                                      share|improve this answer


























                                        1












                                        1








                                        1







                                        05AB1E, 315 295 282 276 bytes



                                        "+-*/"DˆS¡εDõQi'¢…ë'.¡VYнD_i'¡×ðë',¡DgUε0›i.•6b©•ð“†ìˆÈŒšï¿Ÿ¯¥Š“©'tKJ#'…§«…€µ‚•„í#®#«…—¿áÓÁÏ#«ìD9£©.•4º»Ÿć'Rþн•ŽH$S£“Œšï¿Ÿ¯¥Š“'tK#«„ty«sõšâðý«õšD®'°¡ðì«sâðý«yèð.•cG3₅¦„¥F•8ô'¾ß«…¡›‡È±°#«õªRXN-<èJëõ}}ðý}Yg<i®'¡×šYθSè'…®šðý}}J}s¯`Ã哉´Øè„ƺߓ#¤… by«¸s¨ì¯`ykè}.ιðý„  ð:„¢…Øè'¢…:


                                        Takes input without any spaces.



                                        Try it online or verify all test cases.



                                        Explanation:





                                        "+-*/"                    # Push string "+-*/"
                                        Dˆ # Duplicate it, pop the copy, and push it to the global array
                                        S¡ # Split the input by any "+", "-", "*", or "/"
                                        ε # Map each number to:
                                        DõQi # If the item is empty (happens for negative numbers)
                                        '¢… '# Push string "negative"
                                        ë # Else:
                                        '.¡ '# Split by "."
                                        VY # Store it in variable `Y`
                                        н # Take the first number (the integer part)
                                        D # Duplicate this integer part
                                        _i # If the integer part is exactly 0:
                                        # Discard the duplicated integer part
                                        '¡× '# Push string "zero"
                                        ð # Push a space " "
                                        ë # Else:
                                        ',¡ '# Split by ","
                                        DgU # Pop and store the amount of items in variable `X`
                                        ε # Map each part to:
                                        0›i # If it's larger than 0:
                                        .•6b©• # Push string "thir"
                                        ð # Push a space " "
                                        “†ìˆÈŒšï¿Ÿ¯¥Š“ # Push string "four five six seven eight nine"
                                        © # Store it in the register (without popping)
                                        'tK '# Remove all "t" (so "eight" becomes "eigh")
                                        J # Join it together with the "thir" and space
                                        # # Split by spaces
                                        '…§ '# Push string "teen"
                                        « # And append it to every string in the list
                                        # (We now have ["thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"])
                                        …€µ‚•„í # Push string "one two three"
                                        # # Split by spaces
                                        ® # Push the string from the register ("four" through "nine")
                                        #« # Split by spaces, and merge both lists together
                                        …—¿áÓÁÏ # Push string "ten eleven twelve"
                                        #« # Split by spaces, and also merge both lists together
                                        ì # Prepend "one" through "twelve" before "thirteen" through "nineteen"
                                        D9£ # Duplicate it, and take the first nine ("one" through "nine")
                                        © # Store it in the register (without popping)
                                        .•4º»Ÿć'Rþн• '# Push string "twenthirforfif"
                                        ŽH$ # Push integer 4433
                                        S # Split to digits: [4,4,3,3]
                                        £ # And split the to parts of that size: ["twen","thir","for","fif"]
                                        “Œšï¿Ÿ¯¥Š“ # Push string "six seven eight nine"
                                        'tK '# Remove all "t" (so "eight" becomes "eigh")
                                        #« # Split by spaces, and merge both lists together
                                        „ty # Push string "ty"
                                        « # And append it to every string in the list
                                        # (We now have ["twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"])
                                        s # Swap so the list "one" through "nine" is at the top again
                                        õš # Prepend an empty string to that list
                                        â # Create every possible pair of "one" through "nine" with "twenty" through "ninety"
                                        ðý # Join each pair with a space delimiter
                                        « # Merge the "twenty" through "ninety nine" list with "one" through "nineteen"
                                        õš # Prepend an empty string to that list
                                        D # Duplicate the entire list
                                        ® # Push the string from the register ("one" through "nine")
                                        '°¡ '# Push string "hundred"
                                        ðì # Prepend it with a space " "
                                        « # Append it to every string in the list
                                        # (We now have ["one hundred","two hundred",...,"nine hundred"])
                                        s # Swap the two lists
                                        â # Create every possible pair of "one hundred" through "nine hundred" with "" through "ninety nine"
                                        ðý # Join each pair with a space delimiter
                                        « # Merge the "one" through "ninety nine" with "one hundred " through "nine hundred ninety nine"
                                        # (We now have ["","one",...,"nine hundred ninety nine"])
                                        y # Get the current number of the map
                                        è # And index it into this list
                                        ð # Push a space " "
                                        .•cG3₅¦„¥F• # Push string "quadrilltrill"
                                        8ô # Split into pieces of size 8: ["quadrill","trill"]
                                        '¾ß '# Push string "ion"
                                        « # Append it to every string in the list
                                        …¡›‡È±° # Push string "billion million thousand"
                                        # # Split by spaces
                                        « # And merge both lists together
                                        õª # Append an empty string
                                        R # Reverse the list
                                        # (We now have ["","thousand","million","billion","trillion","quadrillion"])
                                        X # Push variable `X`
                                        N- # Subtract the map-index from it
                                        < # Subtract an additional 1
                                        è # And index it into the list
                                        J # Join the stack together
                                        ë # Else:
                                        õ # Push an empty string ""
                                        } # Close the if-else
                                        } # Close the map
                                        ðý # Join the mapped values with space delimiter
                                        } # Close the if-else
                                        Y # Push variable `Y`
                                        g<i # If its length is exactly 2:
                                        ® # Push the string from the register ("one" through "nine")
                                        '¡× '# Push "zero"
                                        š # Prepend it to the list
                                        Yθ # Push variable `Y` again, and leave the second number (the decimal part)
                                        S # Split it to digits
                                        è # And index each into the list
                                        '…® '# Push string "point"
                                        š # Prepend it in front of that list
                                        ðý # Join the list with space delimiter
                                        } # Close the if
                                        } # Close the if-else
                                        J # Join the stack together
                                        } # Close the map
                                        s # Swap to take the (implicit) input again
                                        ¯` # Push the global array, and dump it's content (string "+-*/")
                                        Ã # Only keep all "+", "-", "*", and "/", and remove everything else
                                        ε # Map each to:
                                        “‰´Øè„ƺߓ # Push string "plus minus times divided"
                                        # # Split by spaces
                                        ¤ # Take the last item (without popping the list)
                                        … by« # Append it with string " by"
                                        ¸ # Wrap it to a list: ["divided by"]
                                        s # Swap to take the list again
                                        ¨ # Remove the last item
                                        ì # Prepend it in front of the list: ["plus","minus","times","divided by"]
                                        ¯` # Push the global array, and dump it's content (string "+-*/")
                                        yk # Push the index in this string for the current map-value `y`
                                        è # And use that index to index into the string-list
                                        } # Close the map
                                        .ι # Interweave the list of numbers and list of operators
                                        ðý # Join everything with space delimiter
                                        „ ð: # Replace every two spaces for a single space
                                        „¢…Øè'¢…: '# And replace every "negative minus" with "negative"
                                        # (and output the result implicitly)


                                        See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand why:




                                        • (How to use the dictionary?) -- '¢… is "negative"; '¡× is "zero"; “†ìˆÈŒšï¿Ÿ¯¥Š“ is "four five six seven eight nine"; '…§ is "teen"; …€µ‚•„í is "one two three"; …—¿áÓÁÏ is "ten eleven twelve"; '°¡ is "hundred"; '¾ß is "ion"; …¡›‡È±° is "billion million thousand"; '…® is "point"; and “‰´Øè„ƺߓ is "plus minus times divided".

                                        • (How to compress strings not part of the dictionary?) -- .•6b©• is "thir"; .•4º»Ÿć'Rþн• is "twenthirforfif"; and .•cG3₅¦„¥F• is "quadrilltrill".

                                        • (How to compress large integers?) -- ŽH$ is 4433.






                                        share|improve this answer















                                        05AB1E, 315 295 282 276 bytes



                                        "+-*/"DˆS¡εDõQi'¢…ë'.¡VYнD_i'¡×ðë',¡DgUε0›i.•6b©•ð“†ìˆÈŒšï¿Ÿ¯¥Š“©'tKJ#'…§«…€µ‚•„í#®#«…—¿áÓÁÏ#«ìD9£©.•4º»Ÿć'Rþн•ŽH$S£“Œšï¿Ÿ¯¥Š“'tK#«„ty«sõšâðý«õšD®'°¡ðì«sâðý«yèð.•cG3₅¦„¥F•8ô'¾ß«…¡›‡È±°#«õªRXN-<èJëõ}}ðý}Yg<i®'¡×šYθSè'…®šðý}}J}s¯`Ã哉´Øè„ƺߓ#¤… by«¸s¨ì¯`ykè}.ιðý„  ð:„¢…Øè'¢…:


                                        Takes input without any spaces.



                                        Try it online or verify all test cases.



                                        Explanation:





                                        "+-*/"                    # Push string "+-*/"
                                        Dˆ # Duplicate it, pop the copy, and push it to the global array
                                        S¡ # Split the input by any "+", "-", "*", or "/"
                                        ε # Map each number to:
                                        DõQi # If the item is empty (happens for negative numbers)
                                        '¢… '# Push string "negative"
                                        ë # Else:
                                        '.¡ '# Split by "."
                                        VY # Store it in variable `Y`
                                        н # Take the first number (the integer part)
                                        D # Duplicate this integer part
                                        _i # If the integer part is exactly 0:
                                        # Discard the duplicated integer part
                                        '¡× '# Push string "zero"
                                        ð # Push a space " "
                                        ë # Else:
                                        ',¡ '# Split by ","
                                        DgU # Pop and store the amount of items in variable `X`
                                        ε # Map each part to:
                                        0›i # If it's larger than 0:
                                        .•6b©• # Push string "thir"
                                        ð # Push a space " "
                                        “†ìˆÈŒšï¿Ÿ¯¥Š“ # Push string "four five six seven eight nine"
                                        © # Store it in the register (without popping)
                                        'tK '# Remove all "t" (so "eight" becomes "eigh")
                                        J # Join it together with the "thir" and space
                                        # # Split by spaces
                                        '…§ '# Push string "teen"
                                        « # And append it to every string in the list
                                        # (We now have ["thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"])
                                        …€µ‚•„í # Push string "one two three"
                                        # # Split by spaces
                                        ® # Push the string from the register ("four" through "nine")
                                        #« # Split by spaces, and merge both lists together
                                        …—¿áÓÁÏ # Push string "ten eleven twelve"
                                        #« # Split by spaces, and also merge both lists together
                                        ì # Prepend "one" through "twelve" before "thirteen" through "nineteen"
                                        D9£ # Duplicate it, and take the first nine ("one" through "nine")
                                        © # Store it in the register (without popping)
                                        .•4º»Ÿć'Rþн• '# Push string "twenthirforfif"
                                        ŽH$ # Push integer 4433
                                        S # Split to digits: [4,4,3,3]
                                        £ # And split the to parts of that size: ["twen","thir","for","fif"]
                                        “Œšï¿Ÿ¯¥Š“ # Push string "six seven eight nine"
                                        'tK '# Remove all "t" (so "eight" becomes "eigh")
                                        #« # Split by spaces, and merge both lists together
                                        „ty # Push string "ty"
                                        « # And append it to every string in the list
                                        # (We now have ["twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"])
                                        s # Swap so the list "one" through "nine" is at the top again
                                        õš # Prepend an empty string to that list
                                        â # Create every possible pair of "one" through "nine" with "twenty" through "ninety"
                                        ðý # Join each pair with a space delimiter
                                        « # Merge the "twenty" through "ninety nine" list with "one" through "nineteen"
                                        õš # Prepend an empty string to that list
                                        D # Duplicate the entire list
                                        ® # Push the string from the register ("one" through "nine")
                                        '°¡ '# Push string "hundred"
                                        ðì # Prepend it with a space " "
                                        « # Append it to every string in the list
                                        # (We now have ["one hundred","two hundred",...,"nine hundred"])
                                        s # Swap the two lists
                                        â # Create every possible pair of "one hundred" through "nine hundred" with "" through "ninety nine"
                                        ðý # Join each pair with a space delimiter
                                        « # Merge the "one" through "ninety nine" with "one hundred " through "nine hundred ninety nine"
                                        # (We now have ["","one",...,"nine hundred ninety nine"])
                                        y # Get the current number of the map
                                        è # And index it into this list
                                        ð # Push a space " "
                                        .•cG3₅¦„¥F• # Push string "quadrilltrill"
                                        8ô # Split into pieces of size 8: ["quadrill","trill"]
                                        '¾ß '# Push string "ion"
                                        « # Append it to every string in the list
                                        …¡›‡È±° # Push string "billion million thousand"
                                        # # Split by spaces
                                        « # And merge both lists together
                                        õª # Append an empty string
                                        R # Reverse the list
                                        # (We now have ["","thousand","million","billion","trillion","quadrillion"])
                                        X # Push variable `X`
                                        N- # Subtract the map-index from it
                                        < # Subtract an additional 1
                                        è # And index it into the list
                                        J # Join the stack together
                                        ë # Else:
                                        õ # Push an empty string ""
                                        } # Close the if-else
                                        } # Close the map
                                        ðý # Join the mapped values with space delimiter
                                        } # Close the if-else
                                        Y # Push variable `Y`
                                        g<i # If its length is exactly 2:
                                        ® # Push the string from the register ("one" through "nine")
                                        '¡× '# Push "zero"
                                        š # Prepend it to the list
                                        Yθ # Push variable `Y` again, and leave the second number (the decimal part)
                                        S # Split it to digits
                                        è # And index each into the list
                                        '…® '# Push string "point"
                                        š # Prepend it in front of that list
                                        ðý # Join the list with space delimiter
                                        } # Close the if
                                        } # Close the if-else
                                        J # Join the stack together
                                        } # Close the map
                                        s # Swap to take the (implicit) input again
                                        ¯` # Push the global array, and dump it's content (string "+-*/")
                                        Ã # Only keep all "+", "-", "*", and "/", and remove everything else
                                        ε # Map each to:
                                        “‰´Øè„ƺߓ # Push string "plus minus times divided"
                                        # # Split by spaces
                                        ¤ # Take the last item (without popping the list)
                                        … by« # Append it with string " by"
                                        ¸ # Wrap it to a list: ["divided by"]
                                        s # Swap to take the list again
                                        ¨ # Remove the last item
                                        ì # Prepend it in front of the list: ["plus","minus","times","divided by"]
                                        ¯` # Push the global array, and dump it's content (string "+-*/")
                                        yk # Push the index in this string for the current map-value `y`
                                        è # And use that index to index into the string-list
                                        } # Close the map
                                        .ι # Interweave the list of numbers and list of operators
                                        ðý # Join everything with space delimiter
                                        „ ð: # Replace every two spaces for a single space
                                        „¢…Øè'¢…: '# And replace every "negative minus" with "negative"
                                        # (and output the result implicitly)


                                        See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand why:




                                        • (How to use the dictionary?) -- '¢… is "negative"; '¡× is "zero"; “†ìˆÈŒšï¿Ÿ¯¥Š“ is "four five six seven eight nine"; '…§ is "teen"; …€µ‚•„í is "one two three"; …—¿áÓÁÏ is "ten eleven twelve"; '°¡ is "hundred"; '¾ß is "ion"; …¡›‡È±° is "billion million thousand"; '…® is "point"; and “‰´Øè„ƺߓ is "plus minus times divided".

                                        • (How to compress strings not part of the dictionary?) -- .•6b©• is "thir"; .•4º»Ÿć'Rþн• is "twenthirforfif"; and .•cG3₅¦„¥F• is "quadrilltrill".

                                        • (How to compress large integers?) -- ŽH$ is 4433.







                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Nov 28 '18 at 22:43

























                                        answered Nov 28 '18 at 13:24









                                        Kevin Cruijssen

                                        35.7k554187




                                        35.7k554187























                                            1















                                            Python 2, 790 774 bytes





                                            lambda T:B("([+/*-])",lambda m:dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))[m.group(0)],B("([+/*-]|^)-",r"1negative ",B("[^+/*-]+","{}",T))).format(*[J([g[int(S(".",j)[0])]+S("z",B("y","illion","z thousandz myz byz tryz quadry"))[len(S(",",m))+~i]+(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)for i,j in E(S(",",m))if 0<float(j)+(m<"1")])for m in S("[+/*-]+",T)[T[0]=='-':]])
                                            from re import*
                                            E,S,B,P=enumerate,split,sub," ";J=P.join
                                            s,e=S(P,"zero one two three four five six seven eight nine"),[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
                                            g=s+S(P,"ten eleven twelve")+e[1:8]+[a+(P+b)*(i>0)for a in e[8:]for i,b in E(s)]
                                            g=[(j+" hundred ")*(i>0)+k for i,j in E(s)for k in g]


                                            Try it online!



                                            So many bad practices. This almost hurt to write....



                                            Expects a non-unicode string with no whitespace as input.



                                            Explanation:



                                            # import all functions from re (python regex library)
                                            from re import*

                                            # rename some repeatedly-used functions/variables for reduced bytecount
                                            E,S,B,P=enumerate,split,sub," ";J=P.join

                                            # list the names of 0-9
                                            s=S(P,"zero one two three four five six seven eight nine")
                                            # generate "twenteen" through nineteen and twenty though ninety, changing "fourty" to forty
                                            # using enumerate (E) even though i is not required b/c it's shorter than range(len(x))
                                            # using re.split (S) instead of string.split since it's shorter
                                            e=[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
                                            # generate 0-999
                                            # 0-9
                                            g=s+
                                            # 10, 11, 12
                                            +S(P,"ten eleven twelve")+
                                            # remove "twenteen", 13-19
                                            +e[1:8]+
                                            # tens' place + ones' place, if ones' place is not zero
                                            +[a+(P+b)*(i>0) ]
                                            # for each tens' place in 20-90
                                            for a in e[8:]
                                            # for each index, value in ones' places 0-9
                                            for i,b in E(s)


                                            # hundreds' place if at least 100, plus tens' and ones' place (already calculated and stored in g from before)
                                            g=[(j+" hundred ")*(i>0)+k ]
                                            # (s) stores names for 0-9, need index to avoid "zero hundred"
                                            for i,j in E(s)
                                            # for each hundred, iterate over all values (0-99) already in g
                                            for k in g

                                            # actual function to call. uses previously declared global variable g.
                                            def f(T):
                                            # gets the numbers in the supplied string (T) by splitting (T) on any operator character
                                            # remove first item if blank (only happens when staring with a - for negative numbers)
                                            n=S("[+/*-]+",T)[T[0]=='-':]

                                            # triply-nested set of re.subs to convert (T) to a sting of where the operators are replaced by their names and numbers are replaced by "{}"
                                            # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}" -> "negative {} minus {} minus negative {}"
                                            # this sub happens last
                                            # re.sub (B) any operator, with the operators in a group "()" so that they return in match.group
                                            T=B("([+/*-])", )
                                            # an anonymous function to accept match objects (m) from re.sub's search.
                                            ,lambda m:
                                            # create a dictionary from the combination of operators and their names
                                            # like {"+":" plus ",...}
                                            # operator names are surrounded by spaces since number names are NOT
                                            dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))
                                            # from the constructed dictionary, select the operator matched by re.sub's search and return it for replacement
                                            [m.group(0)],
                                            # this substitution is second
                                            # re.sub (B) any operator followed by a minus (-), OR a minus at the beginning of the string
                                            # operators/start are grouped, trailing minus is not
                                            ,B("([+/*-]|^)-", )
                                            # replace match with the grouped items plus the word "negative"
                                            # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}"
                                            ,r"1negative ",
                                            # this substitution is done first
                                            # replace any sequence of NON-operators with "{}"
                                            # this removes numbers so the names can be inserted later
                                            # EX: "-1-1--1" -> "-{}-{}--{}"
                                            ,B("[^+/*-]+","{}",T))

                                            # technically the previous construction of (T) and (n) can be placed here to save 5 bytes but my poor eyes can't handle that.
                                            # insert constructed names back into original string.
                                            # EX: "-1-1--1" -> "negative {} minus {} minus negative {}" -> "negative one minus one minus negative one"
                                            print T.format( )
                                            # string.format needs items in array unpacked, or it will attempt to insert the string representation of the array itself
                                            *[ ]
                                            # for each number pulled from (T), generate names and join generated items back together with spaces
                                            # EX: "1,456" -> ["1", "456"] -> ["one thousand", "four hundred fifty six"] -> "one thousand four hundred fifty six"
                                            J( )for m in n
                                            # split j on periods (.) and take the first item
                                            # convert that item into an integer and find the item at that index in g (0-999)
                                            [g[int(S(".",j)[0])]+ ]
                                            # insert prefix for millions +, split string on "z" (spaces must be preserved for proper separation)
                                            +S("z",B("y","illion","z thousandz myz byz tryz quadry"))
                                            # left is largest, so take the item at index (total # of groups - current place - 1)
                                            [len(S(",",m))+~i]+
                                            # if group had a period, split string on period and take last item
                                            # replace every character in group with number 0-9 name
                                            # join them with spaces and add back to rest of group
                                            +(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)
                                            # split number into groups by comma
                                            # EX: "123,456" -> ["123","456"]
                                            # only return item if j != 0 (avoids returning empty string which will result in too many joined spaces)
                                            # OR if m == 0 (avoids not returning anything when should return "zero")
                                            for i,j in E(S(",",m))if 0


                                            I reduced by about 150 bytes while writing the explanation. Let it never be said that commenting/reviewing your code isn't helpful!






                                            share|improve this answer




























                                              1















                                              Python 2, 790 774 bytes





                                              lambda T:B("([+/*-])",lambda m:dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))[m.group(0)],B("([+/*-]|^)-",r"1negative ",B("[^+/*-]+","{}",T))).format(*[J([g[int(S(".",j)[0])]+S("z",B("y","illion","z thousandz myz byz tryz quadry"))[len(S(",",m))+~i]+(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)for i,j in E(S(",",m))if 0<float(j)+(m<"1")])for m in S("[+/*-]+",T)[T[0]=='-':]])
                                              from re import*
                                              E,S,B,P=enumerate,split,sub," ";J=P.join
                                              s,e=S(P,"zero one two three four five six seven eight nine"),[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
                                              g=s+S(P,"ten eleven twelve")+e[1:8]+[a+(P+b)*(i>0)for a in e[8:]for i,b in E(s)]
                                              g=[(j+" hundred ")*(i>0)+k for i,j in E(s)for k in g]


                                              Try it online!



                                              So many bad practices. This almost hurt to write....



                                              Expects a non-unicode string with no whitespace as input.



                                              Explanation:



                                              # import all functions from re (python regex library)
                                              from re import*

                                              # rename some repeatedly-used functions/variables for reduced bytecount
                                              E,S,B,P=enumerate,split,sub," ";J=P.join

                                              # list the names of 0-9
                                              s=S(P,"zero one two three four five six seven eight nine")
                                              # generate "twenteen" through nineteen and twenty though ninety, changing "fourty" to forty
                                              # using enumerate (E) even though i is not required b/c it's shorter than range(len(x))
                                              # using re.split (S) instead of string.split since it's shorter
                                              e=[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
                                              # generate 0-999
                                              # 0-9
                                              g=s+
                                              # 10, 11, 12
                                              +S(P,"ten eleven twelve")+
                                              # remove "twenteen", 13-19
                                              +e[1:8]+
                                              # tens' place + ones' place, if ones' place is not zero
                                              +[a+(P+b)*(i>0) ]
                                              # for each tens' place in 20-90
                                              for a in e[8:]
                                              # for each index, value in ones' places 0-9
                                              for i,b in E(s)


                                              # hundreds' place if at least 100, plus tens' and ones' place (already calculated and stored in g from before)
                                              g=[(j+" hundred ")*(i>0)+k ]
                                              # (s) stores names for 0-9, need index to avoid "zero hundred"
                                              for i,j in E(s)
                                              # for each hundred, iterate over all values (0-99) already in g
                                              for k in g

                                              # actual function to call. uses previously declared global variable g.
                                              def f(T):
                                              # gets the numbers in the supplied string (T) by splitting (T) on any operator character
                                              # remove first item if blank (only happens when staring with a - for negative numbers)
                                              n=S("[+/*-]+",T)[T[0]=='-':]

                                              # triply-nested set of re.subs to convert (T) to a sting of where the operators are replaced by their names and numbers are replaced by "{}"
                                              # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}" -> "negative {} minus {} minus negative {}"
                                              # this sub happens last
                                              # re.sub (B) any operator, with the operators in a group "()" so that they return in match.group
                                              T=B("([+/*-])", )
                                              # an anonymous function to accept match objects (m) from re.sub's search.
                                              ,lambda m:
                                              # create a dictionary from the combination of operators and their names
                                              # like {"+":" plus ",...}
                                              # operator names are surrounded by spaces since number names are NOT
                                              dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))
                                              # from the constructed dictionary, select the operator matched by re.sub's search and return it for replacement
                                              [m.group(0)],
                                              # this substitution is second
                                              # re.sub (B) any operator followed by a minus (-), OR a minus at the beginning of the string
                                              # operators/start are grouped, trailing minus is not
                                              ,B("([+/*-]|^)-", )
                                              # replace match with the grouped items plus the word "negative"
                                              # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}"
                                              ,r"1negative ",
                                              # this substitution is done first
                                              # replace any sequence of NON-operators with "{}"
                                              # this removes numbers so the names can be inserted later
                                              # EX: "-1-1--1" -> "-{}-{}--{}"
                                              ,B("[^+/*-]+","{}",T))

                                              # technically the previous construction of (T) and (n) can be placed here to save 5 bytes but my poor eyes can't handle that.
                                              # insert constructed names back into original string.
                                              # EX: "-1-1--1" -> "negative {} minus {} minus negative {}" -> "negative one minus one minus negative one"
                                              print T.format( )
                                              # string.format needs items in array unpacked, or it will attempt to insert the string representation of the array itself
                                              *[ ]
                                              # for each number pulled from (T), generate names and join generated items back together with spaces
                                              # EX: "1,456" -> ["1", "456"] -> ["one thousand", "four hundred fifty six"] -> "one thousand four hundred fifty six"
                                              J( )for m in n
                                              # split j on periods (.) and take the first item
                                              # convert that item into an integer and find the item at that index in g (0-999)
                                              [g[int(S(".",j)[0])]+ ]
                                              # insert prefix for millions +, split string on "z" (spaces must be preserved for proper separation)
                                              +S("z",B("y","illion","z thousandz myz byz tryz quadry"))
                                              # left is largest, so take the item at index (total # of groups - current place - 1)
                                              [len(S(",",m))+~i]+
                                              # if group had a period, split string on period and take last item
                                              # replace every character in group with number 0-9 name
                                              # join them with spaces and add back to rest of group
                                              +(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)
                                              # split number into groups by comma
                                              # EX: "123,456" -> ["123","456"]
                                              # only return item if j != 0 (avoids returning empty string which will result in too many joined spaces)
                                              # OR if m == 0 (avoids not returning anything when should return "zero")
                                              for i,j in E(S(",",m))if 0


                                              I reduced by about 150 bytes while writing the explanation. Let it never be said that commenting/reviewing your code isn't helpful!






                                              share|improve this answer


























                                                1












                                                1








                                                1







                                                Python 2, 790 774 bytes





                                                lambda T:B("([+/*-])",lambda m:dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))[m.group(0)],B("([+/*-]|^)-",r"1negative ",B("[^+/*-]+","{}",T))).format(*[J([g[int(S(".",j)[0])]+S("z",B("y","illion","z thousandz myz byz tryz quadry"))[len(S(",",m))+~i]+(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)for i,j in E(S(",",m))if 0<float(j)+(m<"1")])for m in S("[+/*-]+",T)[T[0]=='-':]])
                                                from re import*
                                                E,S,B,P=enumerate,split,sub," ";J=P.join
                                                s,e=S(P,"zero one two three four five six seven eight nine"),[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
                                                g=s+S(P,"ten eleven twelve")+e[1:8]+[a+(P+b)*(i>0)for a in e[8:]for i,b in E(s)]
                                                g=[(j+" hundred ")*(i>0)+k for i,j in E(s)for k in g]


                                                Try it online!



                                                So many bad practices. This almost hurt to write....



                                                Expects a non-unicode string with no whitespace as input.



                                                Explanation:



                                                # import all functions from re (python regex library)
                                                from re import*

                                                # rename some repeatedly-used functions/variables for reduced bytecount
                                                E,S,B,P=enumerate,split,sub," ";J=P.join

                                                # list the names of 0-9
                                                s=S(P,"zero one two three four five six seven eight nine")
                                                # generate "twenteen" through nineteen and twenty though ninety, changing "fourty" to forty
                                                # using enumerate (E) even though i is not required b/c it's shorter than range(len(x))
                                                # using re.split (S) instead of string.split since it's shorter
                                                e=[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
                                                # generate 0-999
                                                # 0-9
                                                g=s+
                                                # 10, 11, 12
                                                +S(P,"ten eleven twelve")+
                                                # remove "twenteen", 13-19
                                                +e[1:8]+
                                                # tens' place + ones' place, if ones' place is not zero
                                                +[a+(P+b)*(i>0) ]
                                                # for each tens' place in 20-90
                                                for a in e[8:]
                                                # for each index, value in ones' places 0-9
                                                for i,b in E(s)


                                                # hundreds' place if at least 100, plus tens' and ones' place (already calculated and stored in g from before)
                                                g=[(j+" hundred ")*(i>0)+k ]
                                                # (s) stores names for 0-9, need index to avoid "zero hundred"
                                                for i,j in E(s)
                                                # for each hundred, iterate over all values (0-99) already in g
                                                for k in g

                                                # actual function to call. uses previously declared global variable g.
                                                def f(T):
                                                # gets the numbers in the supplied string (T) by splitting (T) on any operator character
                                                # remove first item if blank (only happens when staring with a - for negative numbers)
                                                n=S("[+/*-]+",T)[T[0]=='-':]

                                                # triply-nested set of re.subs to convert (T) to a sting of where the operators are replaced by their names and numbers are replaced by "{}"
                                                # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}" -> "negative {} minus {} minus negative {}"
                                                # this sub happens last
                                                # re.sub (B) any operator, with the operators in a group "()" so that they return in match.group
                                                T=B("([+/*-])", )
                                                # an anonymous function to accept match objects (m) from re.sub's search.
                                                ,lambda m:
                                                # create a dictionary from the combination of operators and their names
                                                # like {"+":" plus ",...}
                                                # operator names are surrounded by spaces since number names are NOT
                                                dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))
                                                # from the constructed dictionary, select the operator matched by re.sub's search and return it for replacement
                                                [m.group(0)],
                                                # this substitution is second
                                                # re.sub (B) any operator followed by a minus (-), OR a minus at the beginning of the string
                                                # operators/start are grouped, trailing minus is not
                                                ,B("([+/*-]|^)-", )
                                                # replace match with the grouped items plus the word "negative"
                                                # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}"
                                                ,r"1negative ",
                                                # this substitution is done first
                                                # replace any sequence of NON-operators with "{}"
                                                # this removes numbers so the names can be inserted later
                                                # EX: "-1-1--1" -> "-{}-{}--{}"
                                                ,B("[^+/*-]+","{}",T))

                                                # technically the previous construction of (T) and (n) can be placed here to save 5 bytes but my poor eyes can't handle that.
                                                # insert constructed names back into original string.
                                                # EX: "-1-1--1" -> "negative {} minus {} minus negative {}" -> "negative one minus one minus negative one"
                                                print T.format( )
                                                # string.format needs items in array unpacked, or it will attempt to insert the string representation of the array itself
                                                *[ ]
                                                # for each number pulled from (T), generate names and join generated items back together with spaces
                                                # EX: "1,456" -> ["1", "456"] -> ["one thousand", "four hundred fifty six"] -> "one thousand four hundred fifty six"
                                                J( )for m in n
                                                # split j on periods (.) and take the first item
                                                # convert that item into an integer and find the item at that index in g (0-999)
                                                [g[int(S(".",j)[0])]+ ]
                                                # insert prefix for millions +, split string on "z" (spaces must be preserved for proper separation)
                                                +S("z",B("y","illion","z thousandz myz byz tryz quadry"))
                                                # left is largest, so take the item at index (total # of groups - current place - 1)
                                                [len(S(",",m))+~i]+
                                                # if group had a period, split string on period and take last item
                                                # replace every character in group with number 0-9 name
                                                # join them with spaces and add back to rest of group
                                                +(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)
                                                # split number into groups by comma
                                                # EX: "123,456" -> ["123","456"]
                                                # only return item if j != 0 (avoids returning empty string which will result in too many joined spaces)
                                                # OR if m == 0 (avoids not returning anything when should return "zero")
                                                for i,j in E(S(",",m))if 0


                                                I reduced by about 150 bytes while writing the explanation. Let it never be said that commenting/reviewing your code isn't helpful!






                                                share|improve this answer















                                                Python 2, 790 774 bytes





                                                lambda T:B("([+/*-])",lambda m:dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))[m.group(0)],B("([+/*-]|^)-",r"1negative ",B("[^+/*-]+","{}",T))).format(*[J([g[int(S(".",j)[0])]+S("z",B("y","illion","z thousandz myz byz tryz quadry"))[len(S(",",m))+~i]+(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)for i,j in E(S(",",m))if 0<float(j)+(m<"1")])for m in S("[+/*-]+",T)[T[0]=='-':]])
                                                from re import*
                                                E,S,B,P=enumerate,split,sub," ";J=P.join
                                                s,e=S(P,"zero one two three four five six seven eight nine"),[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
                                                g=s+S(P,"ten eleven twelve")+e[1:8]+[a+(P+b)*(i>0)for a in e[8:]for i,b in E(s)]
                                                g=[(j+" hundred ")*(i>0)+k for i,j in E(s)for k in g]


                                                Try it online!



                                                So many bad practices. This almost hurt to write....



                                                Expects a non-unicode string with no whitespace as input.



                                                Explanation:



                                                # import all functions from re (python regex library)
                                                from re import*

                                                # rename some repeatedly-used functions/variables for reduced bytecount
                                                E,S,B,P=enumerate,split,sub," ";J=P.join

                                                # list the names of 0-9
                                                s=S(P,"zero one two three four five six seven eight nine")
                                                # generate "twenteen" through nineteen and twenty though ninety, changing "fourty" to forty
                                                # using enumerate (E) even though i is not required b/c it's shorter than range(len(x))
                                                # using re.split (S) instead of string.split since it's shorter
                                                e=[B("urty","rty",j)for i,j in E(c+d for d in S(P,"teen ty")for c in S(P,"twen thir four fif six seven eigh nine"))]
                                                # generate 0-999
                                                # 0-9
                                                g=s+
                                                # 10, 11, 12
                                                +S(P,"ten eleven twelve")+
                                                # remove "twenteen", 13-19
                                                +e[1:8]+
                                                # tens' place + ones' place, if ones' place is not zero
                                                +[a+(P+b)*(i>0) ]
                                                # for each tens' place in 20-90
                                                for a in e[8:]
                                                # for each index, value in ones' places 0-9
                                                for i,b in E(s)


                                                # hundreds' place if at least 100, plus tens' and ones' place (already calculated and stored in g from before)
                                                g=[(j+" hundred ")*(i>0)+k ]
                                                # (s) stores names for 0-9, need index to avoid "zero hundred"
                                                for i,j in E(s)
                                                # for each hundred, iterate over all values (0-99) already in g
                                                for k in g

                                                # actual function to call. uses previously declared global variable g.
                                                def f(T):
                                                # gets the numbers in the supplied string (T) by splitting (T) on any operator character
                                                # remove first item if blank (only happens when staring with a - for negative numbers)
                                                n=S("[+/*-]+",T)[T[0]=='-':]

                                                # triply-nested set of re.subs to convert (T) to a sting of where the operators are replaced by their names and numbers are replaced by "{}"
                                                # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}" -> "negative {} minus {} minus negative {}"
                                                # this sub happens last
                                                # re.sub (B) any operator, with the operators in a group "()" so that they return in match.group
                                                T=B("([+/*-])", )
                                                # an anonymous function to accept match objects (m) from re.sub's search.
                                                ,lambda m:
                                                # create a dictionary from the combination of operators and their names
                                                # like {"+":" plus ",...}
                                                # operator names are surrounded by spaces since number names are NOT
                                                dict(zip("+/*-",S("z"," plus z divided by z times z minus ")))
                                                # from the constructed dictionary, select the operator matched by re.sub's search and return it for replacement
                                                [m.group(0)],
                                                # this substitution is second
                                                # re.sub (B) any operator followed by a minus (-), OR a minus at the beginning of the string
                                                # operators/start are grouped, trailing minus is not
                                                ,B("([+/*-]|^)-", )
                                                # replace match with the grouped items plus the word "negative"
                                                # EX: "-1-1--1" -> "-{}-{}--{}" -> "negative {}-{}-negative {}"
                                                ,r"1negative ",
                                                # this substitution is done first
                                                # replace any sequence of NON-operators with "{}"
                                                # this removes numbers so the names can be inserted later
                                                # EX: "-1-1--1" -> "-{}-{}--{}"
                                                ,B("[^+/*-]+","{}",T))

                                                # technically the previous construction of (T) and (n) can be placed here to save 5 bytes but my poor eyes can't handle that.
                                                # insert constructed names back into original string.
                                                # EX: "-1-1--1" -> "negative {} minus {} minus negative {}" -> "negative one minus one minus negative one"
                                                print T.format( )
                                                # string.format needs items in array unpacked, or it will attempt to insert the string representation of the array itself
                                                *[ ]
                                                # for each number pulled from (T), generate names and join generated items back together with spaces
                                                # EX: "1,456" -> ["1", "456"] -> ["one thousand", "four hundred fifty six"] -> "one thousand four hundred fifty six"
                                                J( )for m in n
                                                # split j on periods (.) and take the first item
                                                # convert that item into an integer and find the item at that index in g (0-999)
                                                [g[int(S(".",j)[0])]+ ]
                                                # insert prefix for millions +, split string on "z" (spaces must be preserved for proper separation)
                                                +S("z",B("y","illion","z thousandz myz byz tryz quadry"))
                                                # left is largest, so take the item at index (total # of groups - current place - 1)
                                                [len(S(",",m))+~i]+
                                                # if group had a period, split string on period and take last item
                                                # replace every character in group with number 0-9 name
                                                # join them with spaces and add back to rest of group
                                                +(" point "+J(s[int(c)]for c in S(".",j)[-1]))*("."in j)
                                                # split number into groups by comma
                                                # EX: "123,456" -> ["123","456"]
                                                # only return item if j != 0 (avoids returning empty string which will result in too many joined spaces)
                                                # OR if m == 0 (avoids not returning anything when should return "zero")
                                                for i,j in E(S(",",m))if 0


                                                I reduced by about 150 bytes while writing the explanation. Let it never be said that commenting/reviewing your code isn't helpful!







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Nov 30 '18 at 16:04

























                                                answered Nov 29 '18 at 23:50









                                                Triggernometry

                                                57517




                                                57517






























                                                    draft saved

                                                    draft discarded




















































                                                    If this is an answer to a challenge…




                                                    • …Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.


                                                    • …Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
                                                      Explanations of your answer make it more interesting to read and are very much encouraged.


                                                    • …Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.



                                                    More generally…




                                                    • …Please make sure to answer the question and provide sufficient detail.


                                                    • …Avoid asking for help, clarification or responding to other answers (use comments instead).






                                                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                                    Please pay close attention to the following guidance:


                                                    • Please be sure to answer the question. Provide details and share your research!

                                                    But avoid



                                                    • Asking for help, clarification, or responding to other answers.

                                                    • Making statements based on opinion; back them up with references or personal experience.


                                                    To learn more, see our tips on writing great answers.




                                                    draft saved


                                                    draft discarded














                                                    StackExchange.ready(
                                                    function () {
                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f176619%2flazy-word-problems%23new-answer', 'question_page');
                                                    }
                                                    );

                                                    Post as a guest















                                                    Required, but never shown





















































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown

































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown







                                                    Popular posts from this blog

                                                    Quarter-circle Tiles

                                                    build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

                                                    Mont Emei