From f6322e0c9f50c5e1cef3fd71792b433949cf0d93 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Fri, 23 Oct 2020 15:57:38 +1300 Subject: [PATCH 001/120] Updated README.md to use SpelledOut.jl --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c8d654a7..09898b9b 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ This is a minimal package for a pure Julia implementation of converting numbers ## Examples ```julia +julia> using SpelledOut + julia> spelled_out(12) "twelve" @@ -27,4 +29,4 @@ julia> spelled_out(112, dict = :european) Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. [code-style-img]: https://img.shields.io/badge/code%20style-blue-4495d1.svg -[code-style-url]: https://github.com/invenia/BlueStyle \ No newline at end of file +[code-style-url]: https://github.com/invenia/BlueStyle From fae56f2cad0fabe958f79850435396cd71c4a5f5 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 12:24:17 +1300 Subject: [PATCH 002/120] Updated .travis.yml --- .travis.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..0800c95c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +## Documentation: http://docs.travis-ci.com/user/languages/julia/ +language: julia +os: + - linux + - osx +julia: + - 1.0 + - 1.5 + - nightly +notifications: + email: false +git: + depth: 99999999 + From 5ed572a11f9afc11e5d28a44c9e76669b939e5f9 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 14:17:58 +1300 Subject: [PATCH 003/120] Updated .travis.yml --- .travis.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0800c95c..a820ce9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,39 @@ ## Documentation: http://docs.travis-ci.com/user/languages/julia/ language: julia + os: - linux - osx + julia: - 1.0 - 1.5 - nightly + notifications: email: false + +sudo: false + git: depth: 99999999 +jobs: + include: + - stage: test + script: + - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' + - julia --color=yes --project=. test/runtests.jl + julia: 1.0 + + - stage: test + script: + - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' + - julia --color=yes --project=. test/runtests.jl + julia: 1.5 + + - stage: test + script: + - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' + - julia --color=yes --project=. test/runtests.jl + julia: nightly \ No newline at end of file From 84a4fc077204d60812f16337fdb9cad175f23d46 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 15:18:12 +1300 Subject: [PATCH 004/120] Updated .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a820ce9d..652d94a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ language: julia os: - linux - osx + - windows julia: - 1.0 From 090466b51ab45190788b848c0664739718feacdc Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 16:18:31 +1300 Subject: [PATCH 005/120] Bug fixes --- Project.toml | 2 +- src/standard_dictionary_numbers_extended.jl | 44 +++++++++++---------- test/runtests.jl | 14 +++++-- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/Project.toml b/Project.toml index 9626967f..5ec4b97c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "0.1.0" +version = "0.1.1" [compat] julia = "1" diff --git a/src/standard_dictionary_numbers_extended.jl b/src/standard_dictionary_numbers_extended.jl index f2db2b4c..41666fc1 100644 --- a/src/standard_dictionary_numbers_extended.jl +++ b/src/standard_dictionary_numbers_extended.jl @@ -10,33 +10,35 @@ const _scale_modern = String[ "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", "decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion", - "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion", - "unvigintillion", "duovigintillion", "tresvigintillion", "quattuorvigintillion", "quinvigintillion", - "sesvigintillion", "septemvigintillion", "octovigintillion", "novemvigintillion", "trigintillion", - "untrigintillion", "duotrigintillion", "trestrigintillion", "quattuortrigintillion", "quintrigintillion", - "sestrigintillion", "septentrigintillion", "octotrigintillion", "noventrigintillion", "quadragintillion" + "quindecillion", "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", + "vigintillion", "unvigintillion", "duovigintillion", "tresvigintillion", "quattuorvigintillion", + "quinvigintillion", "sesvigintillion", "septemvigintillion", "octovigintillion", "novemvigintillion", + "trigintillion", "untrigintillion", "duotrigintillion", "trestrigintillion", "quattuortrigintillion", + "quintrigintillion", "sestrigintillion", "septentrigintillion", "octotrigintillion", "noventrigintillion", + "quadragintillion" ] const _scale_traditional_british = String[ - "million", "thousand million", "billion", "thousand billion", "trillion", - "thousand trillion", "quadrillion", "thousand quadrillion", "quintillion", "thousand quintillion", - "sextillion", "thousand sextillion", "septillion", "thousand septillion", "octillion", - "thousand octillion", "nonillion", "thousand nonillion", "decillion", "thousand decillion", - "undecillion", "thousand undecillion", "duodecillion", "thousand duodecillion", "tredecillion", - "thousand tredecillion", "quattuordecillion", "thousand quattuordecillion","quindecillion", "thousand quindecillion", - "sedecillion", "thousand sedecillion", "septendecillion", "thousand septendecillion","octodecillion", - "thousand octodecillion","novendecillion", "thousand novendecillion", "vigintillion", "thousand vigintillion" + "thousand", "million", "thousand million", "billion", "thousand billion", + "trillion", "thousand trillion", "quadrillion", "thousand quadrillion", "quintillion", + "thousand quintillion", "sextillion", "thousand sextillion", "septillion", "thousand septillion", "octillion", "thousand octillion", "nonillion", "thousand nonillion", "decillion", + "thousand decillion", "undecillion", "thousand undecillion", "duodecillion", "thousand duodecillion", + "tredecillion", "thousand tredecillion", "quattuordecillion", "thousand quattuordecillion","quindecillion", + "thousand quindecillion","sedecillion", "thousand sedecillion", "septendecillion", "thousand septendecillion", + "octodecillion", "thousand octodecillion","novendecillion", "thousand novendecillion", "vigintillion", + "thousand vigintillion" ] const _scale_traditional_european = String[ - "million", "milliard", "billion", "billiard", "trillion", - "trilliard", "quadrillion", "quadrilliard", "quintillion", "quintilliard", - "sextillion", "sextilliard", "septillion", "septilliard", "octillion", - "octilliard", "nonillion", "nonilliard", "decillion", "decilliard", - "undecillion", "undecilliard", "duodecillion", "duodecilliard", "tredecillion", - "tredecilliard", "quattuordecillion", "quattuordecilliard","quindecillion", "quindecilliard", - "sedecillion", "sedecilliard", "septendecillion", "septendecilliard", "octodecillion", - "octodecilliard", "novendecillion", "novendecilliard", "vigintillion", "vigintilliard" + "thousand", "million", "milliard", "billion", "billiard", + "trillion", "trilliard", "quadrillion", "quadrilliard", "quintillion", + "quintilliard", "sextillion", "sextilliard", "septillion", "septilliard", + "octillion", "octilliard", "nonillion", "nonilliard", "decillion", + "decilliard", "undecillion", "undecilliard", "duodecillion", "duodecilliard", + "tredecillion", "tredecilliard", "quattuordecillion", "quattuordecilliard", "quindecillion", + "quindecilliard", "sedecillion", "sedecilliard", "septendecillion", "septendecilliard", + "octodecillion", "octodecilliard", "novendecillion", "novendecilliard", "vigintillion", + "vigintilliard" ] const limit = BigInt(big(10)^120) diff --git a/test/runtests.jl b/test/runtests.jl index facad676..594ace2b 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,9 @@ +#!/usr/bin/env bash + #= + exec julia --project="$(realpath $(dirname $(realpath $(dirname $0))))/examples/" "${BASH_SOURCE[0]}" "$@" -e "include(popfirst!(ARGS))" \ + "${BASH_SOURCE[0]}" "$@" + =# + include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")) using .SpelledOut @@ -15,9 +21,9 @@ using Test @test spelled_out(0, british=true) == "zero" @test spelled_out(100) == "one hundred" @test spelled_out(100, british=true) == "one hundred" - @test spelled_out(123456789, british=true, dict=:european)== "one hundred and thirty-three milliard, four hundred and fifty-six million, seven hundred and eighty-nine" - @test spelled_out(123456789, dict=:european) == "one hundred thirty-three milliard, four hundred fifty-six million, seven hundred eighty-nine" - @test spelled_out(123456789, british=true, dict=:british) == "one hundred and thirty-three thousand million, four hundred and fifty-six million, seven hundred and eighty-nine" - @test spelled_out(1234567890123, british=true, dict=:british) == "one thousand billion, two hundred and thirty-four billion, five hundred and sixty-seven thousand million, eight hundred and ninety million, one hundred and thirty-three" + @test spelled_out(123456789, british=true, dict=:european) == "one hundred and thirty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(123456789, dict=:european) == "one hundred thirty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, british=true, dict=:british) == "one hundred and thirty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(1234567890123, british=true, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and thirty-three" @test spelled_out(1234567890123, british=true, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and thirty-three" end From 30cfb8170205e4bd2c6dd4b49fd905f3f2312618 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 17:49:25 +1300 Subject: [PATCH 006/120] Updated .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 652d94a6..66287b6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ git: jobs: include: - - stage: test + - stage: test script: - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' - julia --color=yes --project=. test/runtests.jl From 70e0f42eb797e72ed52367a15dc3c99e1cfadff8 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 20:47:02 +1300 Subject: [PATCH 007/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 5ec4b97c..c2338c9f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "0.1.1" +version = "1.0.1" [compat] julia = "1" From cde7d4bd6873c5929e70fcc43ff18164bd898014 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 21:07:29 +1300 Subject: [PATCH 008/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index c2338c9f..4f625168 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.0.1" +version = "1.0.0" [compat] julia = "1" From 03d92d7de6ced533cc8d4d1b202b050bcbe8719b Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 21:09:51 +1300 Subject: [PATCH 009/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 4f625168..c2338c9f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.0.0" +version = "1.0.1" [compat] julia = "1" From c8e6707f655710edcf3eea31a8be009e501bcd9b Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 21:12:01 +1300 Subject: [PATCH 010/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index c2338c9f..4f625168 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.0.1" +version = "1.0.0" [compat] julia = "1" From d1ac283eaa7524333b999532b15c7d77bfca325d Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 28 Oct 2020 21:54:59 +1300 Subject: [PATCH 011/120] Added OS BSD to .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 66287b6f..610c82e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ os: - linux - osx - windows + - bsd julia: - 1.0 From 60fe0c71dbf452418f1253e88bafb4d472549fbd Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Thu, 29 Oct 2020 03:18:27 +1300 Subject: [PATCH 012/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 4f625168..5ec4b97c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.0.0" +version = "0.1.1" [compat] julia = "1" From 7d3f70e3c568172d4ce6b1cbba5ad47a99e98144 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Thu, 29 Oct 2020 03:58:48 +1300 Subject: [PATCH 013/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 5ec4b97c..4f625168 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "0.1.1" +version = "1.0.0" [compat] julia = "1" From 820e794e2de5d619308a01cb8494a29ee138125e Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Sun, 1 Nov 2020 13:00:20 +1300 Subject: [PATCH 014/120] Bug fix (closes #12) --- Project.toml | 2 +- src/SpelledOut.jl | 2 +- test/runtests.jl | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Project.toml b/Project.toml index 4f625168..c2338c9f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.0.0" +version = "1.0.1" [compat] julia = "1" diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 9c0d3870..364385d5 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -14,7 +14,7 @@ function small_convert(number::Integer; british::Bool=false, dict::Symbol=:moder return word end - v = 1 + v = 0 while v < length(_tens) d_cap = _tens[v + 1] d_number = BigInt(20 + 10 * v) diff --git a/test/runtests.jl b/test/runtests.jl index 594ace2b..3aad07ab 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,15 +15,15 @@ using Test @test Spelled_out(1234) == "One thousand, two hundred thirty-four" @test Spelled_Out(1234) == "One Thousand, Two Hundred Thirty-Four" @test SPELLED_OUT(1234) == "ONE THOUSAND, TWO HUNDRED THIRTY-FOUR" - @test spelled_out(123456789) == "one hundred thirty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, british=true) == "one hundred and thirty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(123456789) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, british=true) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" @test spelled_out(0) == "zero" @test spelled_out(0, british=true) == "zero" @test spelled_out(100) == "one hundred" @test spelled_out(100, british=true) == "one hundred" - @test spelled_out(123456789, british=true, dict=:european) == "one hundred and thirty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(123456789, dict=:european) == "one hundred thirty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, british=true, dict=:british) == "one hundred and thirty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(1234567890123, british=true, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and thirty-three" - @test spelled_out(1234567890123, british=true, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and thirty-three" + @test spelled_out(123456789, british=true, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(123456789, dict=:european) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, british=true, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(1234567890123, british=true, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" + @test spelled_out(1234567890123, british=true, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" end From a225a6cde2cce78fedeca325a6e73d71f072705d Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Sun, 1 Nov 2020 19:37:06 +1300 Subject: [PATCH 015/120] Implemented floating point spelled out (closes #14) --- Project.toml | 3 ++ src/SpelledOut.jl | 38 +++++++++++++-------- src/standard_dictionary_numbers_extended.jl | 4 +++ test/runtests.jl | 3 ++ 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Project.toml b/Project.toml index c2338c9f..80f79c9c 100644 --- a/Project.toml +++ b/Project.toml @@ -3,6 +3,9 @@ uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] version = "1.0.1" +[deps] +DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" + [compat] julia = "1" diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 364385d5..dbc41648 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -1,12 +1,14 @@ module SpelledOut +using DecFP: Dec64 + export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include(joinpath(dirname(@__FILE__), "standard_dictionary_numbers_extended.jl")) include(joinpath(dirname(@__FILE__), "large_standard_dictionary_numbers_extended.jl")) # convert a value < 100 to English. -function small_convert(number::Integer; british::Bool=false, dict::Symbol=:modern)::String +function small_convert(number::Integer; british::Bool=false, dict::Symbol=:modern) scale_numbers = _scale_modern # define scale type if number < 20 word = _small_numbers[number + 1] @@ -35,7 +37,7 @@ end # convert a value < 1000 to english, special cased because it is the level that excludes # the < 100 special case. The rest are more general. This also allows you to get # strings in the form of "forty-five hundred" if called directly. -function large_convert(number::Integer; british::Bool=false, dict::Symbol=:modern)::String +function large_convert(number::Integer; british::Bool=false, dict::Symbol=:modern) scale_numbers = _scale_modern # define scale type word = string() # initiate empty string divisor = div(number, 100) @@ -61,7 +63,18 @@ function large_convert(number::Integer; british::Bool=false, dict::Symbol=:moder return word end -function spelled_out(number::Integer; british::Bool=false, dict::Symbol=:modern)::String +function decimal_convert(number::AbstractFloat; british::Bool=false, dict::Symbol=:modern) + whole, decimal = split(string(number), ".") + word = spelled_out(parse(BigInt, whole), british=british, dict=dict) * string(" point") + + for i in decimal + word = word * " " * _small_number_dictionary[i] + end + + return word +end + +function spelled_out(number::Integer; british::Bool=false, dict::Symbol=:modern) scale_numbers = _scale_modern # default to :modern if isequal(dict, :british) scale_numbers = _scale_traditional_british @@ -125,21 +138,18 @@ function spelled_out(number::Integer; british::Bool=false, dict::Symbol=:modern) end end -function spelled_out(number::AbstractFloat; british::Bool=false, dict::Symbol=:modern)::String - type = typeof(number) - number = big(number) - +function spelled_out(number::AbstractFloat; british::Bool=false, dict::Symbol=:modern) try - number = BigInt(number) + return spelled_out(BigInt(number), british=british, dict=dict) catch - throw(error("Cannot parse an object of type `$(type)` into the required integer type.")) + number = Dec64(number) + + return decimal_convert(number, british=british, dict=dict) end - - return spelled_out(number, british=british, dict=dict) end -Spelled_out(number::Real; british::Bool=false, dict::Symbol=:modern)::String = uppercasefirst(spelled_out(number, british=british, dict=dict)) -Spelled_Out(number::Real; british::Bool=false, dict::Symbol=:modern)::String = titlecase(spelled_out(number, british=british, dict=dict)) -SPELLED_OUT(number::Real; british::Bool=false, dict::Symbol=:modern)::String = uppercase(spelled_out(number, british=british, dict=dict)) +Spelled_out(number::Number; british::Bool=false, dict::Symbol=:modern) = uppercasefirst(spelled_out(number, british=british, dict=dict)) +Spelled_Out(number::Number; british::Bool=false, dict::Symbol=:modern) = titlecase(spelled_out(number, british=british, dict=dict)) +SPELLED_OUT(number::Number; british::Bool=false, dict::Symbol=:modern) = uppercase(spelled_out(number, british=british, dict=dict)) end # end module diff --git a/src/standard_dictionary_numbers_extended.jl b/src/standard_dictionary_numbers_extended.jl index 41666fc1..fc2df968 100644 --- a/src/standard_dictionary_numbers_extended.jl +++ b/src/standard_dictionary_numbers_extended.jl @@ -2,6 +2,10 @@ const _small_numbers = String[ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"] +const _small_number_dictionary = Dict{Char, String}( + '0' => "zero", '1' => "one", '2' => "two", '3' => "three", '4' => "four", '5' => "five", '6' => "six", + '7' => "seven", '8' => "eight", '9' => "nine") + const _tens = String[ "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"] diff --git a/test/runtests.jl b/test/runtests.jl index 3aad07ab..24de8fe4 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -26,4 +26,7 @@ using Test @test spelled_out(123456789, british=true, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" @test spelled_out(1234567890123, british=true, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" @test spelled_out(1234567890123, british=true, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" + @test spelled_out(3.0) == "three" + @test spelled_out(3) == "three" + @test spelled_out(3.141592653) == "three point one four one five nine two six five three" end From ef655285bf5ca3e0577df43e0a2a3dd066896524 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Sun, 1 Nov 2020 19:47:43 +1300 Subject: [PATCH 016/120] Began work on complex numbers (addresses #15) --- src/SpelledOut.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index dbc41648..0d8dd413 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -148,6 +148,10 @@ function spelled_out(number::AbstractFloat; british::Bool=false, dict::Symbol=:m end end +function spelled_out(number::Complex; british::Bool=false, dict::Symbol=:modern) + return spelled_out(real(number), british=british, dict=dict) * " and " * spelled_out(imag(number), british=british, dict=dict) * " imaginaries" +end + Spelled_out(number::Number; british::Bool=false, dict::Symbol=:modern) = uppercasefirst(spelled_out(number, british=british, dict=dict)) Spelled_Out(number::Number; british::Bool=false, dict::Symbol=:modern) = titlecase(spelled_out(number, british=british, dict=dict)) SPELLED_OUT(number::Number; british::Bool=false, dict::Symbol=:modern) = uppercase(spelled_out(number, british=british, dict=dict)) From 5b7bb0d3bfdcd95e3e610494a856e71adbdae78f Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Sun, 1 Nov 2020 20:05:00 +1300 Subject: [PATCH 017/120] Removed 1.0 from travis testing, as DecFP requires 1.3 or greater --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 610c82e4..72926895 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ os: - bsd julia: - - 1.0 - 1.5 - nightly From 33c15f67c5632f5c0ffc3cdf94f96014d8899f1b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 28 Nov 2020 00:39:26 +0000 Subject: [PATCH 018/120] CompatHelper: add new compat entry for "DecFP" at version "1.1" --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index 80f79c9c..f74daa88 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ version = "1.0.1" DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" [compat] +DecFP = "1.1" julia = "1" [extras] From 1a8a90ba5b0d5348baa464265a92658eaad4150a Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Wed, 30 Dec 2020 13:55:20 +1300 Subject: [PATCH 019/120] Removed testing 1.0 for LTR 1.6 out soon --- .travis.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 72926895..6d68357d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,12 +21,6 @@ git: jobs: include: - - stage: test - script: - - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' - - julia --color=yes --project=. test/runtests.jl - julia: 1.0 - - stage: test script: - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' @@ -37,4 +31,4 @@ jobs: script: - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' - julia --color=yes --project=. test/runtests.jl - julia: nightly \ No newline at end of file + julia: nightly From 71894d4ba5fbc236012f0b58dd8e088a9b706e6b Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 21:38:11 +1300 Subject: [PATCH 020/120] Refactored for setup for multiple language support --- src/SpelledOut.jl | 157 ++---------------- src/en.jl | 147 ++++++++++++++++ ...ge_standard_dictionary_numbers_extended.jl | 0 .../standard_dictionary_numbers_extended.jl | 0 test/runtests.jl | 40 ++--- 5 files changed, 180 insertions(+), 164 deletions(-) create mode 100644 src/en.jl rename src/{ => en}/large_standard_dictionary_numbers_extended.jl (100%) rename src/{ => en}/standard_dictionary_numbers_extended.jl (100%) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 0d8dd413..05e9c1a5 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -4,156 +4,23 @@ using DecFP: Dec64 export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT -include(joinpath(dirname(@__FILE__), "standard_dictionary_numbers_extended.jl")) -include(joinpath(dirname(@__FILE__), "large_standard_dictionary_numbers_extended.jl")) - -# convert a value < 100 to English. -function small_convert(number::Integer; british::Bool=false, dict::Symbol=:modern) - scale_numbers = _scale_modern # define scale type - if number < 20 - word = _small_numbers[number + 1] - - return word - end - - v = 0 - while v < length(_tens) - d_cap = _tens[v + 1] - d_number = BigInt(20 + 10 * v) - - if d_number + 10 > number - if mod(number, 10) ≠ 0 - word = d_cap * "-" * _small_numbers[mod(number, 10) + 1] - - return word - end +include("en.jl") - return d_cap - end - v += 1 +function spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) + if lang == :en + return spelled_out_en(number, british = british, dict = dict) end -end - -# convert a value < 1000 to english, special cased because it is the level that excludes -# the < 100 special case. The rest are more general. This also allows you to get -# strings in the form of "forty-five hundred" if called directly. -function large_convert(number::Integer; british::Bool=false, dict::Symbol=:modern) - scale_numbers = _scale_modern # define scale type - word = string() # initiate empty string - divisor = div(number, 100) - modulus = mod(number, 100) - if divisor > 0 - word = _small_numbers[divisor + 1] * " hundred" - if modulus > 0 - word = word * " " - end - end - - if british - if ! iszero(divisor) && ! iszero(modulus) - word = word * "and " - end - end + throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) - if modulus > 0 - word = word * small_convert(modulus, british=british, dict=dict) - end - - return word -end - -function decimal_convert(number::AbstractFloat; british::Bool=false, dict::Symbol=:modern) - whole, decimal = split(string(number), ".") - word = spelled_out(parse(BigInt, whole), british=british, dict=dict) * string(" point") - - for i in decimal - word = word * " " * _small_number_dictionary[i] - end - - return word -end - -function spelled_out(number::Integer; british::Bool=false, dict::Symbol=:modern) - scale_numbers = _scale_modern # default to :modern - if isequal(dict, :british) - scale_numbers = _scale_traditional_british - elseif isequal(dict, :european) - scale_numbers = _scale_traditional_european - end - - number = big(number) - isnegative = false - if number < 0 - isnegative = true - end - - number = abs(number) - if number > limit - 1 - throw(error("SpelledOut.jl does not support numbers larger than $(spelled_out(limit - 1, british=true)). Sorry about that!")) - end - - if number < 100 - word = small_convert(number, british=british, dict=dict) - - if isnegative - word = "negative " * word - end - - return word - end - - if number < 1000 - word = large_convert(number, british=british, dict=dict) - - if isnegative - word = "negative " * word - end - - return word - end - - v = 0 - while v ≤ length(scale_numbers) - d_idx = v - d_number = BigInt(round(big(1000)^v)) - - if d_number > number - modulus = BigInt(big(1000)^(d_idx - 1)) - l, r = divrem(number, modulus) - word = large_convert(l, british=british, dict=dict) * " " * scale_numbers[d_idx - 1] - - if r > 0 - word = word * ", " * spelled_out(r, british=british, dict=dict) - end - - if isnegative - word = "negative " * word - end - - return word - end - - v += 1 - end -end - -function spelled_out(number::AbstractFloat; british::Bool=false, dict::Symbol=:modern) - try - return spelled_out(BigInt(number), british=british, dict=dict) - catch - number = Dec64(number) - - return decimal_convert(number, british=british, dict=dict) - end -end - -function spelled_out(number::Complex; british::Bool=false, dict::Symbol=:modern) - return spelled_out(real(number), british=british, dict=dict) * " and " * spelled_out(imag(number), british=british, dict=dict) * " imaginaries" + return nothing end -Spelled_out(number::Number; british::Bool=false, dict::Symbol=:modern) = uppercasefirst(spelled_out(number, british=british, dict=dict)) -Spelled_Out(number::Number; british::Bool=false, dict::Symbol=:modern) = titlecase(spelled_out(number, british=british, dict=dict)) -SPELLED_OUT(number::Number; british::Bool=false, dict::Symbol=:modern) = uppercase(spelled_out(number, british=british, dict=dict)) +Spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = + uppercasefirst(spelled_out(number, british=british, dict=dict)) +Spelled_Out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = + titlecase(spelled_out(number, british=british, dict=dict)) +SPELLED_OUT(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = + uppercase(spelled_out(number, british=british, dict=dict)) end # end module diff --git a/src/en.jl b/src/en.jl new file mode 100644 index 00000000..1ca51c41 --- /dev/null +++ b/src/en.jl @@ -0,0 +1,147 @@ +include(joinpath(@__DIR__, "en", "standard_dictionary_numbers_extended.jl")) +include(joinpath(@__DIR__, "en", "large_standard_dictionary_numbers_extended.jl")) + +# convert a value < 100 to English. +function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + scale_numbers = _scale_modern # define scale type + if number < 20 + word = _small_numbers[number + 1] + + return word + end + + v = 0 + while v < length(_tens) + d_cap = _tens[v + 1] + d_number = BigInt(20 + 10 * v) + + if d_number + 10 > number + if mod(number, 10) ≠ 0 + word = d_cap * "-" * _small_numbers[mod(number, 10) + 1] + + return word + end + + return d_cap + end + v += 1 + end +end + +# convert a value < 1000 to english, special cased because it is the level that excludes +# the < 100 special case. The rest are more general. This also allows you to get +# strings in the form of "forty-five hundred" if called directly. +function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + scale_numbers = _scale_modern # define scale type + word = string() # initiate empty string + divisor = div(number, 100) + modulus = mod(number, 100) + + if divisor > 0 + word = _small_numbers[divisor + 1] * " hundred" + if modulus > 0 + word = word * " " + end + end + + if british + if ! iszero(divisor) && ! iszero(modulus) + word = word * "and " + end + end + + if modulus > 0 + word = word * small_convert_en(modulus, british=british, dict=dict) + end + + return word +end + +function decimal_convert_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) + whole, decimal = split(string(number), ".") + word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") + + for i in decimal + word = word * " " * _small_number_dictionary[i] + end + + return word +end + +function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + scale_numbers = _scale_modern # default to :modern + if isequal(dict, :british) + scale_numbers = _scale_traditional_british + elseif isequal(dict, :european) + scale_numbers = _scale_traditional_european + end + + number = big(number) + isnegative = false + if number < 0 + isnegative = true + end + + number = abs(number) + if number > limit - 1 + throw(error("SpelledOut.jl does not support numbers larger than $(spelled_out_en(limit - 1, british=true)). Sorry about that!")) + end + + if number < 100 + word = small_convert_en(number, british=british, dict=dict) + + if isnegative + word = "negative " * word + end + + return word + end + + if number < 1000 + word = large_convert_en(number, british=british, dict=dict) + + if isnegative + word = "negative " * word + end + + return word + end + + v = 0 + while v ≤ length(scale_numbers) + d_idx = v + d_number = BigInt(round(big(1000)^v)) + + if d_number > number + modulus = BigInt(big(1000)^(d_idx - 1)) + l, r = divrem(number, modulus) + word = large_convert_en(l, british=british, dict=dict) * " " * scale_numbers[d_idx - 1] + + if r > 0 + word = word * ", " * spelled_out_en(r, british=british, dict=dict) + end + + if isnegative + word = "negative " * word + end + + return word + end + + v += 1 + end +end + +function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) + try + return spelled_out_en(BigInt(number), british = british, dict = dict) + catch + return decimal_convert_en(Dec64(number), british = british, dict = dict) + end + + return nothing +end + +function spelled_out_en(number::Complex; british::Bool = false, dict::Symbol = :modern) + return spelled_out_en(real(number), british = british, dict = dict) * " and " * spelled_out_en(imag(number), british = british, dict=dict) * " imaginaries" +end diff --git a/src/large_standard_dictionary_numbers_extended.jl b/src/en/large_standard_dictionary_numbers_extended.jl similarity index 100% rename from src/large_standard_dictionary_numbers_extended.jl rename to src/en/large_standard_dictionary_numbers_extended.jl diff --git a/src/standard_dictionary_numbers_extended.jl b/src/en/standard_dictionary_numbers_extended.jl similarity index 100% rename from src/standard_dictionary_numbers_extended.jl rename to src/en/standard_dictionary_numbers_extended.jl diff --git a/test/runtests.jl b/test/runtests.jl index 24de8fe4..865aa7b2 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -10,23 +10,25 @@ using .SpelledOut using Test @testset "SpelledOut.jl" begin - @test spelled_out(1234) == "one thousand, two hundred thirty-four" - @test spelled_out(1234, british=true) == "one thousand, two hundred and thirty-four" - @test Spelled_out(1234) == "One thousand, two hundred thirty-four" - @test Spelled_Out(1234) == "One Thousand, Two Hundred Thirty-Four" - @test SPELLED_OUT(1234) == "ONE THOUSAND, TWO HUNDRED THIRTY-FOUR" - @test spelled_out(123456789) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, british=true) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(0) == "zero" - @test spelled_out(0, british=true) == "zero" - @test spelled_out(100) == "one hundred" - @test spelled_out(100, british=true) == "one hundred" - @test spelled_out(123456789, british=true, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(123456789, dict=:european) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, british=true, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(1234567890123, british=true, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" - @test spelled_out(1234567890123, british=true, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" - @test spelled_out(3.0) == "three" - @test spelled_out(3) == "three" - @test spelled_out(3.141592653) == "three point one four one five nine two six five three" +### ENGLISH TESTS + @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" + @test spelled_out(1234) == "one thousand, two hundred thirty-four" # default to english + @test spelled_out(1234, lang = :en, british=true) == "one thousand, two hundred and thirty-four" + @test Spelled_out(1234, lang = :en) == "One thousand, two hundred thirty-four" + @test Spelled_Out(1234, lang = :en) == "One Thousand, Two Hundred Thirty-Four" + @test SPELLED_OUT(1234, lang = :en) == "ONE THOUSAND, TWO HUNDRED THIRTY-FOUR" + @test spelled_out(123456789, lang = :en) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, lang = :en, british=true) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(0, lang = :en) == "zero" + @test spelled_out(0, lang = :en, british=true) == "zero" + @test spelled_out(100, lang = :en) == "one hundred" + @test spelled_out(100, lang = :en, british=true) == "one hundred" + @test spelled_out(123456789, lang = :en, british=true, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(123456789, lang = :en, dict=:european) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, lang = :en, british=true, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(1234567890123, lang = :en, british=true, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" + @test spelled_out(1234567890123, lang = :en, british=true, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" + @test spelled_out(3.0, lang = :en) == "three" + @test spelled_out(3, lang = :en) == "three" + @test spelled_out(3.141592653, lang = :en) == "three point one four one five nine two six five three" end From 3aa9d5a787fa320e729202b5420c5cf396c6e93c Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 21:42:24 +1300 Subject: [PATCH 021/120] Migrated to GitHub Actions --- .github/workflows/CI.yml | 74 ++++++++++++++++++++++++++++++++++ .travis.yml => .old_travis.yml | 0 2 files changed, 74 insertions(+) create mode 100644 .github/workflows/CI.yml rename .travis.yml => .old_travis.yml (100%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 00000000..70d800c1 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,74 @@ +name: CI +# Run on master, tags, or any pull request +on: + schedule: + - cron: '0 2 * * *' # Daily at 2 AM UTC (8 PM CST) + push: + branches: [master] + tags: ["*"] + pull_request: +jobs: + test: + name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + version: + - "1.5" # current + - "nightly" # Latest Release + os: + - ubuntu-latest + - macOS-latest + - windows-latest + arch: + - x64 + - x86 + exclude: + # Test 32-bit only on Linux + - os: macOS-latest + arch: x86 + - os: windows-latest + arch: x86 + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: actions/cache@v1 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- + - uses: julia-actions/julia-buildpkg@latest + - run: | + git config --global user.name Tester + git config --global user.email te@st.er + - uses: julia-actions/julia-runtest@latest + + docs: + name: Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/setup-julia@v1 + with: + version: '1' + - run: | + git config --global user.name name + git config --global user.email email + git config --global github.user username + - run: | + julia --project=docs -e ' + using Pkg; + Pkg.develop(PackageSpec(path=pwd())); + Pkg.instantiate();' + - run: julia --project=docs docs/make.jl + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.travis.yml b/.old_travis.yml similarity index 100% rename from .travis.yml rename to .old_travis.yml From f389b1d121e3c494171642d24958e75f5957e4a9 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 21:46:55 +1300 Subject: [PATCH 022/120] Added docstrings --- src/SpelledOut.jl | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 05e9c1a5..7deaa551 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -6,6 +6,14 @@ export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") +@doc raw""" +```julia +spelled_out(number; lang = :en, british = false, dict = :modern) +``` + +Spells out a number in words, in lowercase, given a specified language. Current languages to choose from are: + - `:en` +""" function spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) if lang == :en return spelled_out_en(number, british = british, dict = dict) @@ -16,10 +24,36 @@ function spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, return nothing end +@doc raw"""" +```julia +Spelled_out(number; lang = :en, british = false, dict = :modern) +``` + +Spells out a number in words, starting with a capital letter, given a specified language. Current languages to choose from are: + - `:en` +""" Spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = uppercasefirst(spelled_out(number, british=british, dict=dict)) + +@doc raw"""" +```julia +Spelled_Out(number; lang = :en, british = false, dict = :modern) +``` + +Spells out a number in words, in title-case, given a specified language. Current languages to choose from are: + - `:en` +""" Spelled_Out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = titlecase(spelled_out(number, british=british, dict=dict)) + +@doc raw"""" +```julia +SPELLED_OUT(number; lang = :en, british = false, dict = :modern) +``` + +Spells out a number in words, in uppercase, given a specified language. Current languages to choose from are: + - `:en` +""" SPELLED_OUT(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = uppercase(spelled_out(number, british=british, dict=dict)) From eb7280d79cd952af2495ceeb307b2d88a890afdb Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 21:56:07 +1300 Subject: [PATCH 023/120] Docs setup --- README.md | 20 -------------------- docs/Project.toml | 3 +++ docs/make.jl | 19 +++++++++++++++++++ docs/src/index.md | 27 +++++++++++++++++++++++++++ src/SpelledOut.jl | 40 ++++++++++++++++++++++++++++++++-------- 5 files changed, 81 insertions(+), 28 deletions(-) create mode 100644 docs/Project.toml create mode 100644 docs/make.jl create mode 100644 docs/src/index.md diff --git a/README.md b/README.md index 09898b9b..27aeb467 100644 --- a/README.md +++ b/README.md @@ -8,25 +8,5 @@ ## Description This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, to write out in **long hand**, and — as a great mind once suggested — to **transnumerate**. -## Examples - -```julia -julia> using SpelledOut - -julia> spelled_out(12) -"twelve" - -julia> spelled_out(112) -"one hundred twelve" - -julia> spelled_out(112, british = true) -"one hundred and twelve" - -julia> spelled_out(112, dict = :european) -"one hundred twelve" -``` - -Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. - [code-style-img]: https://img.shields.io/badge/code%20style-blue-4495d1.svg [code-style-url]: https://github.com/invenia/BlueStyle diff --git a/docs/Project.toml b/docs/Project.toml new file mode 100644 index 00000000..01cc3ec4 --- /dev/null +++ b/docs/Project.toml @@ -0,0 +1,3 @@ +[deps] +DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" diff --git a/docs/make.jl b/docs/make.jl new file mode 100644 index 00000000..f4c5f09c --- /dev/null +++ b/docs/make.jl @@ -0,0 +1,19 @@ +include(joinpath(dirname(@__DIR__), "src", "SpelledOut.jl")) +using Documenter, .SpelledOut + +Documenter.makedocs( + clean = true, + doctest = true, + modules = Module[SpelledOut], + repo = "", + highlightsig = true, + sitename = "SpelledOut Documentation", + expandfirst = [], + pages = [ + "Index" => "index.md", + ] +) + +deploydocs(; + repo = "github.com/jakewilliami/SpelledOut.jl.git", +) diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 00000000..fa23a3ba --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,27 @@ +# SpelledOut.jl Documentation + +```@contents +``` + +```@meta +CurrentModule = SpelledOut +DocTestSetup = quote + using SpelledOut +end +``` + +## Adding SpelledOut.jl +```@repl +using Pkg +Pkg.add("SpelledOut") +``` + +## Documentation +```@autodocs +Modules = [SpelledOut] +``` + +## Index + +```@index +``` diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 7deaa551..c73926e9 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -6,13 +6,37 @@ export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") -@doc raw""" +_supported_languages = """ + - `:en` + - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. + - If the `british` boolean is true (which it is not by default), the programme will add "and" where needed. +""" + +""" ```julia spelled_out(number; lang = :en, british = false, dict = :modern) ``` Spells out a number in words, in lowercase, given a specified language. Current languages to choose from are: - - `:en` +$_supported_languages + +--- + +### Examples + +```julia +julia> spelled_out(12, lang = :en) +"twelve" + +julia> spelled_out(112, lang = :en) +"one hundred twelve" + +julia> spelled_out(112, lang = :en, british = true) +"one hundred and twelve" + +julia> spelled_out(112, lang = :en, dict = :european) +"one hundred twelve" +``` """ function spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) if lang == :en @@ -24,35 +48,35 @@ function spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, return nothing end -@doc raw"""" +"""" ```julia Spelled_out(number; lang = :en, british = false, dict = :modern) ``` Spells out a number in words, starting with a capital letter, given a specified language. Current languages to choose from are: - - `:en` +$_supported_languages """ Spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = uppercasefirst(spelled_out(number, british=british, dict=dict)) -@doc raw"""" +"""" ```julia Spelled_Out(number; lang = :en, british = false, dict = :modern) ``` Spells out a number in words, in title-case, given a specified language. Current languages to choose from are: - - `:en` +$_supported_languages """ Spelled_Out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = titlecase(spelled_out(number, british=british, dict=dict)) -@doc raw"""" +"""" ```julia SPELLED_OUT(number; lang = :en, british = false, dict = :modern) ``` Spells out a number in words, in uppercase, given a specified language. Current languages to choose from are: - - `:en` +$_supported_languages """ SPELLED_OUT(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = uppercase(spelled_out(number, british=british, dict=dict)) From acfd41185613535efcf71ecac12d2dc26db4a0c6 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 21:58:48 +1300 Subject: [PATCH 024/120] Added docs tag --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 27aeb467..31532556 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,12 @@ SpelledOut.jl -[![Code Style: Blue][code-style-img]][code-style-url] [![Build Status](https://travis-ci.com/jakewilliami/SpelledOut.jl.svg?branch=master)](https://travis-ci.com/jakewilliami/SpelledOut.jl) ![Project Status](https://img.shields.io/badge/status-maturing-green) + +[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://jakewilliami.github.io/SpelledOut.jl/dev) +[![CI](https://github.com/invenia/PkgTemplates.jl/workflows/CI/badge.svg)](https://github.com/jakewilliami/SpelledOut.jl/actions?query=workflow%3ACI) +[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/invenia/BlueStyle) +![Project Status](https://img.shields.io/badge/status-maturing-green) ## Description This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, to write out in **long hand**, and — as a great mind once suggested — to **transnumerate**. - -[code-style-img]: https://img.shields.io/badge/code%20style-blue-4495d1.svg -[code-style-url]: https://github.com/invenia/BlueStyle From 97686854852f96f1e4ee83ca58a8a9075c50d5b4 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 22:01:34 +1300 Subject: [PATCH 025/120] Fixed typo in docs --- src/SpelledOut.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index c73926e9..eaaac950 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -48,7 +48,7 @@ function spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, return nothing end -"""" +""" ```julia Spelled_out(number; lang = :en, british = false, dict = :modern) ``` @@ -59,7 +59,7 @@ $_supported_languages Spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = uppercasefirst(spelled_out(number, british=british, dict=dict)) -"""" +""" ```julia Spelled_Out(number; lang = :en, british = false, dict = :modern) ``` @@ -70,7 +70,7 @@ $_supported_languages Spelled_Out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = titlecase(spelled_out(number, british=british, dict=dict)) -"""" +""" ```julia SPELLED_OUT(number; lang = :en, british = false, dict = :modern) ``` From 135ce3f9aaf412ec81a3da29bbc296d58a362bc4 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 22:06:04 +1300 Subject: [PATCH 026/120] Rectified bug with language kwarg --- src/SpelledOut.jl | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index eaaac950..42408be8 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -4,21 +4,21 @@ using DecFP: Dec64 export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT -include("en.jl") - _supported_languages = """ +Current languages to choose from are: - `:en` - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. - If the `british` boolean is true (which it is not by default), the programme will add "and" where needed. """ +include("en.jl") + """ ```julia spelled_out(number; lang = :en, british = false, dict = :modern) ``` -Spells out a number in words, in lowercase, given a specified language. Current languages to choose from are: -$_supported_languages +Spells out a number in words, in lowercase, given a specified language. $_supported_languages --- @@ -53,32 +53,29 @@ end Spelled_out(number; lang = :en, british = false, dict = :modern) ``` -Spells out a number in words, starting with a capital letter, given a specified language. Current languages to choose from are: -$_supported_languages +Spells out a number in words, starting with a capital letter, given a specified language. $_supported_languages """ Spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = - uppercasefirst(spelled_out(number, british=british, dict=dict)) + uppercasefirst(spelled_out(number, lang = lang, british = british, dict = dict)) """ ```julia Spelled_Out(number; lang = :en, british = false, dict = :modern) ``` -Spells out a number in words, in title-case, given a specified language. Current languages to choose from are: -$_supported_languages +Spells out a number in words, in title-case, given a specified language. $_supported_languages """ Spelled_Out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = - titlecase(spelled_out(number, british=british, dict=dict)) + titlecase(spelled_out(number, lang = lang, british = british, dict = dict)) """ ```julia SPELLED_OUT(number; lang = :en, british = false, dict = :modern) ``` -Spells out a number in words, in uppercase, given a specified language. Current languages to choose from are: -$_supported_languages +Spells out a number in words, in uppercase, given a specified language. $_supported_languages """ SPELLED_OUT(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = - uppercase(spelled_out(number, british=british, dict=dict)) + uppercase(spelled_out(number, lang = lang, british = british, dict = dict)) end # end module From d204234bb6974a43beaaa16bc4804ff82ff1c45d Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 22:19:01 +1300 Subject: [PATCH 027/120] Refactored docs --- docs/Project.toml | 1 + docs/make.jl | 4 +++- docs/src/index.md | 11 +++-------- docs/src/supported_languages.md | 6 ++++++ docs/src/usage.md | 5 +++++ src/SpelledOut.jl | 15 ++++----------- 6 files changed, 22 insertions(+), 20 deletions(-) create mode 100644 docs/src/supported_languages.md create mode 100644 docs/src/usage.md diff --git a/docs/Project.toml b/docs/Project.toml index 01cc3ec4..044b05d2 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,3 +1,4 @@ [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +SpelledOut = "4728c690-e668-4265-bc0d-51a8c0f93067" diff --git a/docs/make.jl b/docs/make.jl index f4c5f09c..4989e340 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -10,7 +10,9 @@ Documenter.makedocs( sitename = "SpelledOut Documentation", expandfirst = [], pages = [ - "Index" => "index.md", + "Home" => "index.md", + "Supported Languages" => "supported_languages.md", + "Usage" => "usage.md" ] ) diff --git a/docs/src/index.md b/docs/src/index.md index fa23a3ba..61f10fa8 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,5 +1,6 @@ -# SpelledOut.jl Documentation +# Home +## Contents ```@contents ``` @@ -10,18 +11,12 @@ DocTestSetup = quote end ``` -## Adding SpelledOut.jl +## Installing SpelledOut.jl ```@repl using Pkg Pkg.add("SpelledOut") ``` -## Documentation -```@autodocs -Modules = [SpelledOut] -``` - ## Index - ```@index ``` diff --git a/docs/src/supported_languages.md b/docs/src/supported_languages.md new file mode 100644 index 00000000..a16c51f1 --- /dev/null +++ b/docs/src/supported_languages.md @@ -0,0 +1,6 @@ +## Supported Languages + +Current languages to choose from are: + - `:en` + - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. + - If the `british` boolean is true (which it is not by default), the programme will add "and" where needed. diff --git a/docs/src/usage.md b/docs/src/usage.md new file mode 100644 index 00000000..5b2296aa --- /dev/null +++ b/docs/src/usage.md @@ -0,0 +1,5 @@ +## Usage + +```@autodocs +Modules = [SpelledOut] +``` diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 42408be8..c28a32e0 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -4,13 +4,6 @@ using DecFP: Dec64 export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT -_supported_languages = """ -Current languages to choose from are: - - `:en` - - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. - - If the `british` boolean is true (which it is not by default), the programme will add "and" where needed. -""" - include("en.jl") """ @@ -18,7 +11,7 @@ include("en.jl") spelled_out(number; lang = :en, british = false, dict = :modern) ``` -Spells out a number in words, in lowercase, given a specified language. $_supported_languages +Spells out a number in words, in lowercase, given a specified language. --- @@ -53,7 +46,7 @@ end Spelled_out(number; lang = :en, british = false, dict = :modern) ``` -Spells out a number in words, starting with a capital letter, given a specified language. $_supported_languages +A wrapper for `spelled_out`. Spells out a number in words, starting with a capital letter, given a specified language. """ Spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = uppercasefirst(spelled_out(number, lang = lang, british = british, dict = dict)) @@ -63,7 +56,7 @@ Spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Sym Spelled_Out(number; lang = :en, british = false, dict = :modern) ``` -Spells out a number in words, in title-case, given a specified language. $_supported_languages +A wrapper for `spelled_out`. Spells out a number in words, in title-case, given a specified language. """ Spelled_Out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = titlecase(spelled_out(number, lang = lang, british = british, dict = dict)) @@ -73,7 +66,7 @@ Spelled_Out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Sym SPELLED_OUT(number; lang = :en, british = false, dict = :modern) ``` -Spells out a number in words, in uppercase, given a specified language. $_supported_languages +A wrapper for `spelled_out`. Spells out a number in words, in uppercase, given a specified language. """ SPELLED_OUT(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = uppercase(spelled_out(number, lang = lang, british = british, dict = dict)) From 3ae0c254a4dace75c4b8f0707b36b8c58d1c50fd Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 22:22:07 +1300 Subject: [PATCH 028/120] Added description in docs home page --- docs/src/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/index.md b/docs/src/index.md index 61f10fa8..33aaa92f 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,5 +1,7 @@ # Home +This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their language form. The process of **spelling out** a number has also been referred to as **set full out**, to write out in **long hand**, and — as a great mind once suggested — to **transnumerate**. + ## Contents ```@contents ``` From 68428f6364a02878bd617a54ca8abcee57a0838a Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 22:24:25 +1300 Subject: [PATCH 029/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index f74daa88..8ce87cbe 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.0.1" +version = "1.0.2" [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" From 4ac38e2f4a9bd616b142d446f9e531830a5d03db Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Tue, 12 Jan 2021 23:01:00 +1300 Subject: [PATCH 030/120] Some ground work for russian spelled-out --- src/ru.jl | 3 ++ src/ru/standard_dictionary_numbers.jl | 72 +++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/ru.jl create mode 100644 src/ru/standard_dictionary_numbers.jl diff --git a/src/ru.jl b/src/ru.jl new file mode 100644 index 00000000..707f1d1d --- /dev/null +++ b/src/ru.jl @@ -0,0 +1,3 @@ +function spelled_out_ru(number::Number) + +end diff --git a/src/ru/standard_dictionary_numbers.jl b/src/ru/standard_dictionary_numbers.jl new file mode 100644 index 00000000..bc638d70 --- /dev/null +++ b/src/ru/standard_dictionary_numbers.jl @@ -0,0 +1,72 @@ +_ones_feminine = Dict{Int, NTuple{1, String}}( + 1 => ("одна",), + 2 => ("две",), + 3 => ("три",), + 4 => ("четыре",), + 5 => ("пять",), + 6 => ("шесть",), + 7 => ("семь",), + 8 => ("восемь",), + 9 => ("девять",), +) + +_ones = Dict{Int, NTuple{1, String}}( + 1 => ("один",), + 2 => ("два",), + 3 => ("три",), + 4 => ("четыре",), + 5 => ("пять",), + 6 => ("шесть",), + 7 => ("семь",), + 8 => ("восемь",), + 9 => ("девять",), +) + +_tens = Dict{Int, NTuple{1, String}}( + 0 => ("десять",), + 1 => ("одиннадцать",), + 2 => ("двенадцать",), + 3 => ("тринадцать",), + 4 => ("четырнадцать",), + 5 => ("пятнадцать",), + 6 => ("шестнадцать",), + 7 => ("семнадцать",), + 8 => ("восемнадцать",), + 9 => ("девятнадцать",), +) + +_twenties = Dict{Int, NTuple{1, String}}( + 2 => ("двадцать",), + 3 => ("тридцать",), + 4 => ("сорок",), + 5 => ("пятьдесят",), + 6 => ("шестьдесят",), + 7 => ("семьдесят",), + 8 => ("восемьдесят",), + 9 => ("девяносто",), +) + +_hundreds = Dict{Int, NTuple{1, String}}( + 1 => ("сто",), + 2 => ("двести",), + 3 => ("триста",), + 4 => ("четыреста",), + 5 => ("пятьсот",), + 6 => ("шестьсот",), + 7 => ("семьсот",), + 8 => ("восемьсот",), + 9 => ("девятьсот",), +) + +_thousands = Dict{Int, NTuple{3, String}}( + 1 => ("тысяча", "тысячи", "тысяч"), # 10^3 + 2 => ("миллион", "миллиона", "миллионов"), # 10^6 + 3 => ("миллиард", "миллиарда", "миллиардов"), # 10^9 + 4 => ("триллион", "триллиона", "триллионов"), # 10^12 + 5 => ("квадриллион", "квадриллиона", "квадриллионов"), # 10^15 + 6 => ("квинтиллион", "квинтиллиона", "квинтиллионов"), # 10^18 + 7 => ("секстиллион", "секстиллиона", "секстиллионов"), # 10^21 + 8 => ("септиллион", "септиллиона", "септиллионов"), # 10^24 + 9 => ("октиллион", "октиллиона", "октиллионов"), # 10^27 + 10 => ("нониллион", "нониллиона", "нониллионов"), # 10^30 +) From dd947c3c657939124062d147a49cbb995c9364e2 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 13 Jan 2021 18:59:16 +1300 Subject: [PATCH 031/120] Fixed error message (addresses #25) --- src/en.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/en.jl b/src/en.jl index 1ca51c41..cc01cd95 100644 --- a/src/en.jl +++ b/src/en.jl @@ -84,7 +84,7 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : number = abs(number) if number > limit - 1 - throw(error("SpelledOut.jl does not support numbers larger than $(spelled_out_en(limit - 1, british=true)). Sorry about that!")) + throw(error("SpelledOut.jl does not support numbers larger than $(limit). Sorry about that!")) end if number < 100 From 6b6ae59b453b65adc73c3ce5d6390f6cf870de6f Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 13 Jan 2021 18:59:56 +1300 Subject: [PATCH 032/120] Fixed error message (addresses #25) --- src/en.jl | 2 +- src/en/standard_dictionary_numbers_extended.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/en.jl b/src/en.jl index cc01cd95..c6fc50e2 100644 --- a/src/en.jl +++ b/src/en.jl @@ -84,7 +84,7 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : number = abs(number) if number > limit - 1 - throw(error("SpelledOut.jl does not support numbers larger than $(limit). Sorry about that!")) + throw(error("SpelledOut.jl does not support numbers larger than $(limit_str). Sorry about that!")) end if number < 100 diff --git a/src/en/standard_dictionary_numbers_extended.jl b/src/en/standard_dictionary_numbers_extended.jl index fc2df968..264ec93a 100644 --- a/src/en/standard_dictionary_numbers_extended.jl +++ b/src/en/standard_dictionary_numbers_extended.jl @@ -46,3 +46,4 @@ const _scale_traditional_european = String[ ] const limit = BigInt(big(10)^120) +const limit_str = "10^120" From 0f564918845b290675223f8cb4ac4630cffc12ab Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 13 Jan 2021 19:06:19 +1300 Subject: [PATCH 033/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 8ce87cbe..6228edc2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.0.2" +version = "1.0.3" [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" From 0dc97812c6a21ff0f104549ecaffff99bb427958 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 13 Jan 2021 19:59:37 +1300 Subject: [PATCH 034/120] Made error message slightly more correct --- src/en.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/en.jl b/src/en.jl index c6fc50e2..6f6b9549 100644 --- a/src/en.jl +++ b/src/en.jl @@ -84,7 +84,7 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : number = abs(number) if number > limit - 1 - throw(error("SpelledOut.jl does not support numbers larger than $(limit_str). Sorry about that!")) + throw(error("""SpelledOut.jl does not support numbers larger than $(limit_str * " - 1"). Sorry about that!""")) end if number < 100 From 54f0ab16b7cce135452e770fb4f729719e7dc00e Mon Sep 17 00:00:00 2001 From: Ricardo Rosa Date: Wed, 13 Jan 2021 18:45:09 -0300 Subject: [PATCH 035/120] add .vscode to .gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 46b522ae..88cdeb53 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,7 @@ docs/site/ Manifest.toml # Silly macOS stuff -.DS_Store \ No newline at end of file +.DS_Store + +# VS Code folder +.vscode \ No newline at end of file From a1e7d43fe3eba05024ec25e69ea64ef90ccc6da8 Mon Sep 17 00:00:00 2001 From: Ricardo Rosa Date: Wed, 13 Jan 2021 19:08:48 -0300 Subject: [PATCH 036/120] add test project --- test/Project.toml | 3 +++ test/runtests.jl | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 test/Project.toml diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 00000000..28bcb829 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,3 @@ +[deps] +DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/runtests.jl b/test/runtests.jl index 865aa7b2..0cf9167d 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,12 +4,12 @@ "${BASH_SOURCE[0]}" "$@" =# -include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")) +#include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")) -using .SpelledOut using Test +using SpelledOut -@testset "SpelledOut.jl" begin +@testset "English" begin ### ENGLISH TESTS @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" @test spelled_out(1234) == "one thousand, two hundred thirty-four" # default to english @@ -32,3 +32,5 @@ using Test @test spelled_out(3, lang = :en) == "three" @test spelled_out(3.141592653, lang = :en) == "three point one four one five nine two six five three" end + +nothing \ No newline at end of file From 74b60ed146d0babfe202258beb09dc22fc0b5758 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Thu, 14 Jan 2021 13:13:41 +1300 Subject: [PATCH 037/120] Removed kwarg from exported function and replaced with language variant; updated docs accordingly --- docs/Project.toml | 1 - docs/src/supported_languages.md | 6 ++++-- src/SpelledOut.jl | 36 +++++++++++++++++---------------- test/runtests.jl | 29 ++++++++++---------------- 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 044b05d2..01cc3ec4 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,4 +1,3 @@ [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -SpelledOut = "4728c690-e668-4265-bc0d-51a8c0f93067" diff --git a/docs/src/supported_languages.md b/docs/src/supported_languages.md index a16c51f1..95bf6035 100644 --- a/docs/src/supported_languages.md +++ b/docs/src/supported_languages.md @@ -1,6 +1,8 @@ ## Supported Languages Current languages to choose from are: - - `:en` + - English + - Variants + - `:en_US` (using `:en` is an alias for `:en_US`) + - `:en_UK` - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. - - If the `british` boolean is true (which it is not by default), the programme will add "and" where needed. diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index c28a32e0..8e420357 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -8,10 +8,10 @@ include("en.jl") """ ```julia -spelled_out(number; lang = :en, british = false, dict = :modern) +spelled_out(number; lang = :en, dict = :modern) ``` -Spells out a number in words, in lowercase, given a specified language. +Spells out a number in words, in lowercase, given a specified language. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. --- @@ -31,9 +31,11 @@ julia> spelled_out(112, lang = :en, dict = :european) "one hundred twelve" ``` """ -function spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) - if lang == :en - return spelled_out_en(number, british = british, dict = dict) +function spelled_out(number::Number; lang::Symbol = :en, dict::Symbol = :modern) + if lang == :en || lang == :en_US + return spelled_out_en(number, british = false, dict = dict) + elseif lang == :en_UK + return spelled_out_en(number, british = true, dict = dict) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) @@ -43,32 +45,32 @@ end """ ```julia -Spelled_out(number; lang = :en, british = false, dict = :modern) +Spelled_out(number; lang = :en, dict = :modern) ``` -A wrapper for `spelled_out`. Spells out a number in words, starting with a capital letter, given a specified language. +A wrapper for `spelled_out`. Spells out a number in words, starting with a capital letter, given a specified language. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. """ -Spelled_out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = - uppercasefirst(spelled_out(number, lang = lang, british = british, dict = dict)) +Spelled_out(number::Number; lang::Symbol = :en, dict::Symbol = :modern) = + uppercasefirst(spelled_out(number, lang = lang, dict = dict)) """ ```julia -Spelled_Out(number; lang = :en, british = false, dict = :modern) +Spelled_Out(number; lang = :en, dict = :modern) ``` -A wrapper for `spelled_out`. Spells out a number in words, in title-case, given a specified language. +A wrapper for `spelled_out`. Spells out a number in words, in title-case, given a specified language. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. """ -Spelled_Out(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = - titlecase(spelled_out(number, lang = lang, british = british, dict = dict)) +Spelled_Out(number::Number; lang::Symbol = :en, dict::Symbol = :modern) = + titlecase(spelled_out(number, lang = lang, dict = dict)) """ ```julia -SPELLED_OUT(number; lang = :en, british = false, dict = :modern) +SPELLED_OUT(number; lang = :en, dict = :modern) ``` -A wrapper for `spelled_out`. Spells out a number in words, in uppercase, given a specified language. +A wrapper for `spelled_out`. Spells out a number in words, in uppercase, given a specified language. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. """ -SPELLED_OUT(number::Number; lang::Symbol = :en, british::Bool = false, dict::Symbol = :modern) = - uppercase(spelled_out(number, lang = lang, british = british, dict = dict)) +SPELLED_OUT(number::Number; lang::Symbol = :en, dict::Symbol = :modern) = + uppercase(spelled_out(number, lang = lang, dict = dict)) end # end module diff --git a/test/runtests.jl b/test/runtests.jl index 0cf9167d..af4d7065 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,36 +1,29 @@ -#!/usr/bin/env bash - #= - exec julia --project="$(realpath $(dirname $(realpath $(dirname $0))))/examples/" "${BASH_SOURCE[0]}" "$@" -e "include(popfirst!(ARGS))" \ - "${BASH_SOURCE[0]}" "$@" - =# - -#include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")) - +# include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")); using .SpelledOut using Test using SpelledOut @testset "English" begin -### ENGLISH TESTS @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" + @test spelled_out(1234, lang = :en_US) == "one thousand, two hundred thirty-four" @test spelled_out(1234) == "one thousand, two hundred thirty-four" # default to english - @test spelled_out(1234, lang = :en, british=true) == "one thousand, two hundred and thirty-four" + @test spelled_out(1234, lang = :en_UK) == "one thousand, two hundred and thirty-four" @test Spelled_out(1234, lang = :en) == "One thousand, two hundred thirty-four" @test Spelled_Out(1234, lang = :en) == "One Thousand, Two Hundred Thirty-Four" @test SPELLED_OUT(1234, lang = :en) == "ONE THOUSAND, TWO HUNDRED THIRTY-FOUR" @test spelled_out(123456789, lang = :en) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, lang = :en, british=true) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(123456789, lang = :en_UK) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" @test spelled_out(0, lang = :en) == "zero" - @test spelled_out(0, lang = :en, british=true) == "zero" + @test spelled_out(0, lang = :en_UK) == "zero" @test spelled_out(100, lang = :en) == "one hundred" - @test spelled_out(100, lang = :en, british=true) == "one hundred" - @test spelled_out(123456789, lang = :en, british=true, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(100, lang = :en_UK) == "one hundred" + @test spelled_out(123456789, lang = :en_UK, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" @test spelled_out(123456789, lang = :en, dict=:european) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, lang = :en, british=true, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(1234567890123, lang = :en, british=true, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" - @test spelled_out(1234567890123, lang = :en, british=true, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" + @test spelled_out(123456789, lang = :en_UK, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(1234567890123, lang = :en_UK, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" + @test spelled_out(1234567890123, lang = :en_UK, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" @test spelled_out(3.0, lang = :en) == "three" @test spelled_out(3, lang = :en) == "three" @test spelled_out(3.141592653, lang = :en) == "three point one four one five nine two six five three" end -nothing \ No newline at end of file +nothing From 57c36fe35cbdedb7d96d616876ea251ee040d6d2 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Thu, 14 Jan 2021 13:15:03 +1300 Subject: [PATCH 038/120] Removed un-needed variants (good suggestion by @rmsrosa) --- src/SpelledOut.jl | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 8e420357..7079ac8e 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -43,34 +43,4 @@ function spelled_out(number::Number; lang::Symbol = :en, dict::Symbol = :modern) return nothing end -""" -```julia -Spelled_out(number; lang = :en, dict = :modern) -``` - -A wrapper for `spelled_out`. Spells out a number in words, starting with a capital letter, given a specified language. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. -""" -Spelled_out(number::Number; lang::Symbol = :en, dict::Symbol = :modern) = - uppercasefirst(spelled_out(number, lang = lang, dict = dict)) - -""" -```julia -Spelled_Out(number; lang = :en, dict = :modern) -``` - -A wrapper for `spelled_out`. Spells out a number in words, in title-case, given a specified language. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. -""" -Spelled_Out(number::Number; lang::Symbol = :en, dict::Symbol = :modern) = - titlecase(spelled_out(number, lang = lang, dict = dict)) - -""" -```julia -SPELLED_OUT(number; lang = :en, dict = :modern) -``` - -A wrapper for `spelled_out`. Spells out a number in words, in uppercase, given a specified language. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. -""" -SPELLED_OUT(number::Number; lang::Symbol = :en, dict::Symbol = :modern) = - uppercase(spelled_out(number, lang = lang, dict = dict)) - end # end module From 61c105a4389f1e74e31de5c0a728603eceb09339 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Thu, 14 Jan 2021 21:19:16 +1300 Subject: [PATCH 039/120] Default language to system locale (suggestion by @rmsrosa) --- docs/src/supported_languages.md | 4 ++-- src/SpelledOut.jl | 19 ++++++++++++++----- test/runtests.jl | 8 ++------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/docs/src/supported_languages.md b/docs/src/supported_languages.md index 95bf6035..e3b6e926 100644 --- a/docs/src/supported_languages.md +++ b/docs/src/supported_languages.md @@ -3,6 +3,6 @@ Current languages to choose from are: - English - Variants - - `:en_US` (using `:en` is an alias for `:en_US`) - - `:en_UK` + - `:en_US` (aliases: `:en`) + - `:en_UK` (aliases: `:en_GB`; equivalencies: `:en_NZ`, `:en_AU`) - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 7079ac8e..11e28cd7 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -8,10 +8,14 @@ include("en.jl") """ ```julia -spelled_out(number; lang = :en, dict = :modern) +function spelled_out( + number::Number; + lang::Symbol = , + dict::Symbol = :modern +) ``` -Spells out a number in words, in lowercase, given a specified language. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. +Spells out a number in words, in lowercase, given a specified language. The default language is the one used on your system. The `dict` keyword argument only applies to some languages; see "Supported Languages" in the docs for more information. --- @@ -31,10 +35,15 @@ julia> spelled_out(112, lang = :en, dict = :european) "one hundred twelve" ``` """ -function spelled_out(number::Number; lang::Symbol = :en, dict::Symbol = :modern) - if lang == :en || lang == :en_US +function spelled_out( + number::Number; + lang::Symbol = Symbol(first(split(ENV["LANG"], '.'))), + dict::Symbol = :modern +) + + if lang ∈ (:en, :en_US) return spelled_out_en(number, british = false, dict = dict) - elseif lang == :en_UK + elseif lang ∈ (:en_UK, :en_GB, :en_NZ, :en_AU) return spelled_out_en(number, british = true, dict = dict) end diff --git a/test/runtests.jl b/test/runtests.jl index af4d7065..c8329c99 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,15 +1,11 @@ -# include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")); using .SpelledOut +include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")); using .SpelledOut using Test -using SpelledOut +# using SpelledOut @testset "English" begin @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" @test spelled_out(1234, lang = :en_US) == "one thousand, two hundred thirty-four" - @test spelled_out(1234) == "one thousand, two hundred thirty-four" # default to english @test spelled_out(1234, lang = :en_UK) == "one thousand, two hundred and thirty-four" - @test Spelled_out(1234, lang = :en) == "One thousand, two hundred thirty-four" - @test Spelled_Out(1234, lang = :en) == "One Thousand, Two Hundred Thirty-Four" - @test SPELLED_OUT(1234, lang = :en) == "ONE THOUSAND, TWO HUNDRED THIRTY-FOUR" @test spelled_out(123456789, lang = :en) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" @test spelled_out(123456789, lang = :en_UK) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" @test spelled_out(0, lang = :en) == "zero" From 78e3f057c94afd19bab714e6737733e750852ecc Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Mon, 18 Jan 2021 19:33:57 +1300 Subject: [PATCH 040/120] Allowed english SpelledOut to parse big numbers in scientific notation --- Project.toml | 1 + src/SpelledOut.jl | 3 ++- src/en.jl | 46 ++++++++++++++++++++++++++++++++-------------- test/runtests.jl | 5 +++-- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Project.toml b/Project.toml index 6228edc2..a5854a63 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "1.0.3" [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" +Formatting = "59287772-0a20-5a39-b81b-1366585eb4c0" [compat] DecFP = "1.1" diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 11e28cd7..ec8e6f75 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -1,6 +1,7 @@ module SpelledOut -using DecFP: Dec64 +using DecFP: Dec128 +using Formatting: format export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT diff --git a/src/en.jl b/src/en.jl index 6f6b9549..f96db30a 100644 --- a/src/en.jl +++ b/src/en.jl @@ -57,17 +57,6 @@ function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = return word end -function decimal_convert_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) - whole, decimal = split(string(number), ".") - word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") - - for i in decimal - word = word * " " * _small_number_dictionary[i] - end - - return word -end - function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # default to :modern if isequal(dict, :british) @@ -132,13 +121,42 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : end end +function decimal_convert_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) + # decimal, whole = modf(number) + # whole = round(BigInt, whole) + whole, decimal = split(string(number), ".") + word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") + # word = spelled_out_en(whole, british=british, dict=dict) * string(" point") + + for i in decimal + word = word * " " * _small_number_dictionary[i] + end + + return word +end + function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) - try + str_number = format(number) + if occursin('.', str_number) + _length_of_presicion = length(string(first(modf(number)))) - 2 + number = parse(BigFloat, format(number, precision = _length_of_presicion)) # convert 1.01e10 to 10100000000 + else + # It is an integer is scientific notation, treat normally without decimal precision considerations + number = parse(BigFloat, str_number) + end + + if isinteger(number) return spelled_out_en(BigInt(number), british = british, dict = dict) - catch - return decimal_convert_en(Dec64(number), british = british, dict = dict) + else + return decimal_convert_en(Dec128(number), british = british, dict = dict) end + # try + # return spelled_out_en(parse(BigInt, number), british = british, dict = dict) + # catch + # return decimal_convert_en(parse(Dec128, number), british = british, dict = dict) + # end + return nothing end diff --git a/test/runtests.jl b/test/runtests.jl index c8329c99..7124e9cf 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,6 @@ -include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")); using .SpelledOut +# include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")); using .SpelledOut using Test -# using SpelledOut +using SpelledOut @testset "English" begin @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" @@ -20,6 +20,7 @@ using Test @test spelled_out(3.0, lang = :en) == "three" @test spelled_out(3, lang = :en) == "three" @test spelled_out(3.141592653, lang = :en) == "three point one four one five nine two six five three" + @test spelled_out(2^log2(3390000), lang = :en) == "three million, three hundred ninety thousand" # should convert 3.3899999999999986e6 to an integer end nothing From 24209e0eff5d59e3d62b118688206681dbb72253 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Mon, 18 Jan 2021 19:43:06 +1300 Subject: [PATCH 041/120] Added formatting dependency to docs-specific dependencies --- docs/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Project.toml b/docs/Project.toml index 01cc3ec4..c247d2ab 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,3 +1,4 @@ [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Formatting = "59287772-0a20-5a39-b81b-1366585eb4c0" From d13b6cd5b3a091822ef8c60a24de5a76bdcf8b0e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 19 Jan 2021 01:24:31 +0000 Subject: [PATCH 042/120] CompatHelper: add new compat entry for "Formatting" at version "0.4" --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index a5854a63..fa3307a3 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,7 @@ Formatting = "59287772-0a20-5a39-b81b-1366585eb4c0" [compat] DecFP = "1.1" +Formatting = "0.4" julia = "1" [extras] From 6ad4f40d274dfb1bac7333662e4a3bd82a4893a9 Mon Sep 17 00:00:00 2001 From: longemen3000 Date: Thu, 21 Jan 2021 20:58:46 -0300 Subject: [PATCH 043/120] add spanish --- _git2_a23528 | 1 + src/SpelledOut.jl | 6 ++ src/en.jl | 3 + src/es.jl | 147 ++++++++++++++++++++++++++++++++++++++++++ src/es/standard_es.jl | 95 +++++++++++++++++++++++++++ test/runtests.jl | 5 ++ 6 files changed, 257 insertions(+) create mode 120000 _git2_a23528 create mode 100644 src/es.jl create mode 100644 src/es/standard_es.jl diff --git a/_git2_a23528 b/_git2_a23528 new file mode 120000 index 00000000..9a2c7732 --- /dev/null +++ b/_git2_a23528 @@ -0,0 +1 @@ +testing \ No newline at end of file diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index ec8e6f75..1d3e168b 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -6,6 +6,7 @@ using Formatting: format export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") +include("es.jl") """ ```julia @@ -34,6 +35,9 @@ julia> spelled_out(112, lang = :en, british = true) julia> spelled_out(112, lang = :en, dict = :european) "one hundred twelve" + +julia> spelled_out(112, lang = :es) +"ciento doce" ``` """ function spelled_out( @@ -46,6 +50,8 @@ function spelled_out( return spelled_out_en(number, british = false, dict = dict) elseif lang ∈ (:en_UK, :en_GB, :en_NZ, :en_AU) return spelled_out_en(number, british = true, dict = dict) + elseif lang ∈ (:es,) + return spelled_out_es(number,dict) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) diff --git a/src/en.jl b/src/en.jl index f96db30a..a120d1c5 100644 --- a/src/en.jl +++ b/src/en.jl @@ -63,6 +63,9 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : scale_numbers = _scale_traditional_british elseif isequal(dict, :european) scale_numbers = _scale_traditional_european + elseif isequal(dict, :modern) + else + throw(error("unrecognized dict value: $dict")) end number = big(number) diff --git a/src/es.jl b/src/es.jl new file mode 100644 index 00000000..bad01488 --- /dev/null +++ b/src/es.jl @@ -0,0 +1,147 @@ +include(joinpath(@__DIR__, "es", "standard_es.jl")) + +#retuns a vector of ints, each of that +function split_numbers_10³(num::Integer) + digits(num,base=10^3) +end + +function split_numbers_10⁶(num::Integer) + digits(num,base=10^6) +end + +#function +function es_spell_1e3(number,short_one=false) + if number <= 99 #0 - 99 + if number<30 #1 - 30 + iszero(number) && return "" + if isone(number) && short_one + return "uno" + elseif number == 21 && short_one + return "veintiuno" + else + return es_1_a_29[number] + end + else #30-99 + unit,dec = digits(number) + if isone(unit) && short_one + unit_text = " y uno" + elseif iszero(unit) + unit_text = "" + else + unit_text = " y " * es_1_a_29[unit] + end + return es_decenas[dec] * unit_text + end + elseif 100 <= number <= 999 + number == 100 && return "cien" + unit,cent = digits(number,base=100) + unit_text = es_spell_1e3(unit,short_one) + return es_centenas[cent] * " " * unit_text + end +end + +function es_spell_1e6(number,short_one=false) + number = Int(number) + number == 0 && return "" + number == 1000 && return "mil" + number <= 999 && return es_spell_1e3(number,short_one) + low,high = digits(number,base=1000) + low_txt = es_spell_1e3(low,short_one) + if high == 1 + high_text = "mil " + else + high_text = es_spell_1e3(high,false) * " mil " + end + return high_text * low_txt +end + +#spells only decimals, including 0 +function es_spell_decimal(number,partitive=true) + whole, decimal = split(string(number), ".") + decnum,wholenum = abs.(modf(number)) + decimal_length = length(decimal) + decint = decnum*10^decimal_length + if partitive + if decimal_length>6 + throw(error("""partitive pronunciation of spanish decimals is only supported to up to six decimals, the decimal part is $decimal . + If you want english-like decimals (cero punto dos), try using partitive = false. + If the decimal part seems to differ from the perceived input number, try using big numbers: `big"123.23"`. + """)) + end + + dectext = es_spell_1e6(Dec128(decint),false) + res = strip(dectext) * " " * es_decimales[decimal_length] + if decint != 1 + res = res * "s" + end + return res + else + res = digits(decint) .|> z->es_spell_1e3(z,true) .|> strip |> reverse |> z->join(z," ") + res = "punto " * res + end +end + + +function es_spell_large_map(number,i) + if isone(i) + return es_spell_1e6(number,true) + elseif isone(number) + return "un " * es_multiplos_1e6_singular[i-1] + else + + return es_spell_1e6(number,false) * " " * es_multiplos_1e6_plural[i-1] + end +end + +function es_spell_large(_number) + number = Int(abs(_number)) #could cause problems, as we cannot convert (yet) to big int + list =digits(number,base=1_000_000) + res = es_spell_large_map.(list,1:length(list)) .|> strip |> reverse |> z->join(z," ") + (_number < 0) && (res = "menos " * res) + return res +end + + +function spelled_out_es(number,dict=:standard) + if iszero(number) + return "cero" + end + if isinteger(number) + if dict in (:standard,:large,:modern) + res = es_spell_large(number) + elseif dict in (:short,) + res = es_spell_short(number) + else + throw(error("unrecognized dict value: $dict")) + end + return res + else #with decimals + + #delete this when proper separate keywords are implemented + partitive = true + _dec,_int = modf(number) + _int = Dec128(_int) + if (_int == 0) & !partitive + intres = "cero" + + elseif (_int == 0) & partitive + intres = "" + elseif dict in (:standard,:large,:modern) + intres = es_spell_large(_int) * " con " + elseif dict in (:short,) + intres = es_spell_short(_int) * " con " + else + throw(error("unrecognized dict value: $dict")) + end + + decres = es_spell_decimal(abs(_dec)) + return intres * decres + end +end + + + + + + + diff --git a/src/es/standard_es.jl b/src/es/standard_es.jl new file mode 100644 index 00000000..db66bcad --- /dev/null +++ b/src/es/standard_es.jl @@ -0,0 +1,95 @@ +const es_1_a_29 =[ +"un" +"dos" +"tres" +"cuatro" +"cinco" +"seis" +"siete" +"ocho" +"nueve" +"diez" +"once" +"doce" +"trece" +"catorce" +"quince" +"dieciséis" +"diecisiete" +"dieciocho" +"diecinueve" +"veinte" +"veintiun" +"veintidós" +"veintitrés" +"veinticuatro" +"veinticinco" +"veintiséis" +"veintisiete" +"veintiocho" +"veintinueve" +] + +const es_decenas = [ + "" + "" + "treinta" + "cuarenta" + "cincuenta" + "sesenta" + "setenta" + "ochenta" + "noventa" +] + + +const es_centenas = [ +"ciento" +"doscientos" +"trescientos" +"cuatrocientos" +"quinientos" +"seiscientos" +"setecientos" +"ochocientos" +"novecientos" +] + +const es_multiplos_1e6_singular = [ + "millón" + "billón" + "trillón" + "cuatrillón" + "quintillón" + "sextillón" + "septillón" + "octillón" + "nonillón" + "decillón" + "undecillón" + "duodecillón" +] + +const es_multiplos_1e6_plural = [ + "millones" + "billones" + "trillones" + "cuatrillones" + "quintillones" + "sextillones" + "septillones" + "octillones" + "nonillones" + "decillones" + "undecillones" + "duodecillones" +] + +const es_decimales = [ + "décimo" + "centécimo" + "milésimo" + "diezmilésimo" + "cienmilésimo" + "millonésimo" +] \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 7124e9cf..db01aff3 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -23,4 +23,9 @@ using SpelledOut @test spelled_out(2^log2(3390000), lang = :en) == "three million, three hundred ninety thousand" # should convert 3.3899999999999986e6 to an integer end +@testset "Spanish" begin + @test spelled_out(585000, lang = :es) == "quinientos ochenta y cinco mil" + +end + nothing From 46c6c2699d20ed52be189427885f52efd21d5bb2 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 25 Jan 2021 12:38:55 +1300 Subject: [PATCH 044/120] Delete _git2_a23528 --- _git2_a23528 | 1 - 1 file changed, 1 deletion(-) delete mode 120000 _git2_a23528 diff --git a/_git2_a23528 b/_git2_a23528 deleted file mode 120000 index 9a2c7732..00000000 --- a/_git2_a23528 +++ /dev/null @@ -1 +0,0 @@ -testing \ No newline at end of file From 774bb760347e115e04bef817c05402423c9e3fa7 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 25 Jan 2021 12:40:51 +1300 Subject: [PATCH 045/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index fa3307a3..c9f48b12 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.0.3" +version = "1.1.3" [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" From e2205ccd8ed2f583c3a44fd4058f7488ef9ba096 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 25 Jan 2021 12:42:41 +1300 Subject: [PATCH 046/120] Update supported_languages.md --- docs/src/supported_languages.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/supported_languages.md b/docs/src/supported_languages.md index e3b6e926..d7a7bf4a 100644 --- a/docs/src/supported_languages.md +++ b/docs/src/supported_languages.md @@ -6,3 +6,4 @@ Current languages to choose from are: - `:en_US` (aliases: `:en`) - `:en_UK` (aliases: `:en_GB`; equivalencies: `:en_NZ`, `:en_AU`) - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. + - Spanish (`:es`) From 8b59553d824de5fafcc8b537b7734a65cb0d691d Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 25 Jan 2021 13:05:55 +1300 Subject: [PATCH 047/120] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index c9f48b12..bb3dc47f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.1.3" +version = "1.1.0" [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" From 1b99bfff3d2ee8623a59c5d55fcfa18d5c7b638f Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 27 Jan 2021 23:08:03 +1300 Subject: [PATCH 048/120] Fixed large floats being parsed scientifically Fix was to parse floats as strings ASAP. Similar to fix for #32. Addresses #37. --- src/SpelledOut.jl | 2 +- src/en.jl | 46 ++++++++++++++++++++++++++++++++++++++++------ test/runtests.jl | 3 ++- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index ec8e6f75..f0a315d5 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -1,6 +1,6 @@ module SpelledOut -using DecFP: Dec128 +using DecFP: Dec64 using Formatting: format export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT diff --git a/src/en.jl b/src/en.jl index f96db30a..9e48a0cb 100644 --- a/src/en.jl +++ b/src/en.jl @@ -121,10 +121,11 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : end end -function decimal_convert_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) +# This method is an internal method used for spelling out floats +function decimal_convert_en(number::AbstractString; british::Bool = false, dict::Symbol = :modern) # decimal, whole = modf(number) # whole = round(BigInt, whole) - whole, decimal = split(string(number), ".") + whole, decimal = split(number, ".") word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") # word = spelled_out_en(whole, british=british, dict=dict) * string(" point") @@ -135,20 +136,53 @@ function decimal_convert_en(number::AbstractFloat; british::Bool = false, dict:: return word end +function decimal_convert_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) + #=# decimal, whole = modf(number) + # whole = round(BigInt, whole) + whole, decimal = split(string(number), ".") + word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") + # word = spelled_out_en(whole, british=british, dict=dict) * string(" point") + + for i in decimal + word = word * " " * _small_number_dictionary[i] + end + + return word=# + return decimal_convert_en(format(number), british = british, dict = dict) +end + function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) str_number = format(number) if occursin('.', str_number) - _length_of_presicion = length(string(first(modf(number)))) - 2 - number = parse(BigFloat, format(number, precision = _length_of_presicion)) # convert 1.01e10 to 10100000000 + # if ! isinteger(number) + _decimal, _ = modf(Dec64(number)) + # println(_decimal) + _length_of_presicion = length(string(_decimal)) - 2 # (ndigits(_whole) + 1) + # println(split(str_number, '.')) + # _length_of_presicion = length(last(split(str_number, '.'))) + # println(format(number, precision = _length_of_presicion)) + # number = parse(Dec128, format(number, precision = _length_of_presicion)) # convert 1.01e10 to 10100000000 + # println(_length_of_presicion) + number = format(number, precision = _length_of_presicion) + # println(number) + # println(number) else # It is an integer is scientific notation, treat normally without decimal precision considerations number = parse(BigFloat, str_number) end - if isinteger(number) + # println(number) + if isa(number, AbstractString) + # if the number is a string then it is a decimal, which is formatted precisely + # for correct precision with decimal places + return decimal_convert_en(number, british = british, dict = dict) + # println(DecFP.Dec64(number)) + # return decimal_convert_en(Dec128(number), british = british, dict = dict) + elseif isinteger(number) + # otherwise, it is an integer return spelled_out_en(BigInt(number), british = british, dict = dict) else - return decimal_convert_en(Dec128(number), british = british, dict = dict) + throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) end # try diff --git a/test/runtests.jl b/test/runtests.jl index 7124e9cf..ccea8c52 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -19,8 +19,9 @@ using SpelledOut @test spelled_out(1234567890123, lang = :en_UK, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" @test spelled_out(3.0, lang = :en) == "three" @test spelled_out(3, lang = :en) == "three" - @test spelled_out(3.141592653, lang = :en) == "three point one four one five nine two six five three" + @test spelled_out(3.141592653589793, lang = :en) == "three point one four one five nine two six five three five eight nine seven nine three" @test spelled_out(2^log2(3390000), lang = :en) == "three million, three hundred ninety thousand" # should convert 3.3899999999999986e6 to an integer + @test spelled_out(1000000.01, lang = :en) == "one million point zero one" # parse big floats correctly (i.e., avoid scientific notation. Caveat: this is slow) end nothing From 9a3f139bd9ee11eb4f6807d9f258e4e7d46c82b3 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 27 Jan 2021 23:22:51 +1300 Subject: [PATCH 049/120] Code cleanup after issue fix --- src/en.jl | 40 +++++----------------------------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/src/en.jl b/src/en.jl index 9e48a0cb..93e6556c 100644 --- a/src/en.jl +++ b/src/en.jl @@ -136,64 +136,34 @@ function decimal_convert_en(number::AbstractString; british::Bool = false, dict: return word end -function decimal_convert_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) - #=# decimal, whole = modf(number) - # whole = round(BigInt, whole) - whole, decimal = split(string(number), ".") - word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") - # word = spelled_out_en(whole, british=british, dict=dict) * string(" point") - - for i in decimal - word = word * " " * _small_number_dictionary[i] - end - - return word=# - return decimal_convert_en(format(number), british = british, dict = dict) -end - function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) str_number = format(number) if occursin('.', str_number) - # if ! isinteger(number) _decimal, _ = modf(Dec64(number)) - # println(_decimal) _length_of_presicion = length(string(_decimal)) - 2 # (ndigits(_whole) + 1) - # println(split(str_number, '.')) - # _length_of_presicion = length(last(split(str_number, '.'))) - # println(format(number, precision = _length_of_presicion)) - # number = parse(Dec128, format(number, precision = _length_of_presicion)) # convert 1.01e10 to 10100000000 - # println(_length_of_presicion) number = format(number, precision = _length_of_presicion) - # println(number) - # println(number) else # It is an integer is scientific notation, treat normally without decimal precision considerations - number = parse(BigFloat, str_number) + # E.g., 1e10 should be parsed as an integer (as should 1.0e10) + number = parse(BigInt, str_number) end - # println(number) if isa(number, AbstractString) # if the number is a string then it is a decimal, which is formatted precisely # for correct precision with decimal places return decimal_convert_en(number, british = british, dict = dict) - # println(DecFP.Dec64(number)) - # return decimal_convert_en(Dec128(number), british = british, dict = dict) elseif isinteger(number) # otherwise, it is an integer - return spelled_out_en(BigInt(number), british = british, dict = dict) + return spelled_out_en(number, british = british, dict = dict) else throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) end - # try - # return spelled_out_en(parse(BigInt, number), british = british, dict = dict) - # catch - # return decimal_convert_en(parse(Dec128, number), british = british, dict = dict) - # end - + # should never get here return nothing end +# Spell out complex numbers function spelled_out_en(number::Complex; british::Bool = false, dict::Symbol = :modern) return spelled_out_en(real(number), british = british, dict = dict) * " and " * spelled_out_en(imag(number), british = british, dict=dict) * " imaginaries" end From 30f05d8aecaddf24f9717ce0b46091ff1fa91ba7 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 27 Jan 2021 23:27:56 +1300 Subject: [PATCH 050/120] Added fallback to error for bad input type (closes #41) --- src/en.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/en.jl b/src/en.jl index 93e6556c..fc52dfe5 100644 --- a/src/en.jl +++ b/src/en.jl @@ -167,3 +167,8 @@ end function spelled_out_en(number::Complex; british::Bool = false, dict::Symbol = :modern) return spelled_out_en(real(number), british = british, dict = dict) * " and " * spelled_out_en(imag(number), british = british, dict=dict) * " imaginaries" end + +# Fallback method if we do not know how to handle the input +function spelled_out_en(number; british::Bool = false, dict::Symbol = :modern) + throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) +end From 62a0ee11fb2c50e108d271057d7761f16ab360f1 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 27 Jan 2021 23:32:10 +1300 Subject: [PATCH 051/120] Removed 32-bit linux support (DecFP was making tests fail; closes #46) --- .github/workflows/CI.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 70d800c1..a1c06a2d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -23,13 +23,6 @@ jobs: - windows-latest arch: - x64 - - x86 - exclude: - # Test 32-bit only on Linux - - os: macOS-latest - arch: x86 - - os: windows-latest - arch: x86 steps: - uses: actions/checkout@v2 - uses: julia-actions/setup-julia@v1 From cdba05fa26ba70b730dcdb0831ef1da414d585f6 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 27 Jan 2021 23:46:49 +1300 Subject: [PATCH 052/120] Added parsing for rational numbers (closes #39) --- src/en.jl | 43 ++++++++++++++++++++++++++++++++++ src/en/ordinal_dictionaries.jl | 4 ++++ test/runtests.jl | 12 ++++++++++ 3 files changed, 59 insertions(+) create mode 100644 src/en/ordinal_dictionaries.jl diff --git a/src/en.jl b/src/en.jl index 0eacc5d0..63d830a6 100644 --- a/src/en.jl +++ b/src/en.jl @@ -1,5 +1,6 @@ include(joinpath(@__DIR__, "en", "standard_dictionary_numbers_extended.jl")) include(joinpath(@__DIR__, "en", "large_standard_dictionary_numbers_extended.jl")) +include(joinpath(@__DIR__, "en", "ordinal_dictionaries.jl")) # convert a value < 100 to English. function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) @@ -124,6 +125,35 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : end end +# Need to print ordinal numbers for the irrational printing +function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + s = spelled_out_en(number, british = british, dict = dict) + + lastword = split(s)[end] + redolast = split(lastword, "-")[end] + + if redolast != lastword + lastsplit = "-" + word = redolast + else + lastsplit = " " + word = lastword + end + + firstpart = reverse(split(reverse(s), lastsplit, limit = 2)[end]) + firstpart = (firstpart == word) ? string() : firstpart * lastsplit + + if haskey(irregular, word) + word = irregular[word] + elseif word[end] == 'y' + word = word[1:end-1] * ysuffix + else + word = word * suffix + end + + return firstpart * word +end + # This method is an internal method used for spelling out floats function decimal_convert_en(number::AbstractString; british::Bool = false, dict::Symbol = :modern) # decimal, whole = modf(number) @@ -171,6 +201,19 @@ function spelled_out_en(number::Complex; british::Bool = false, dict::Symbol = : return spelled_out_en(real(number), british = british, dict = dict) * " and " * spelled_out_en(imag(number), british = british, dict=dict) * " imaginaries" end +function spelled_out_en(number::Rational; british::Bool = false, dict::Symbol = :modern) + _num, _den = number.num, number.den + + # return the number itself if the denomimator is one + isone(_den) && return spelled_out_en(_num, british = british, dict = dict) + + word = spelled_out_en(_num, british = british, dict = dict) * " " * spell_ordinal_en(_den, british = british, dict = dict) + + # account for pluralisation + return isone(_num) ? word : word * "s" +end + + # Fallback method if we do not know how to handle the input function spelled_out_en(number; british::Bool = false, dict::Symbol = :modern) throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) diff --git a/src/en/ordinal_dictionaries.jl b/src/en/ordinal_dictionaries.jl new file mode 100644 index 00000000..265f6db5 --- /dev/null +++ b/src/en/ordinal_dictionaries.jl @@ -0,0 +1,4 @@ +const irregular = Dict("one" => "first", "two" => "second", "three" => "third", "five" => "fifth", + "eight" => "eighth", "nine" => "ninth", "twelve" => "twelfth") +const suffix = "th" +const ysuffix = "ieth" diff --git a/test/runtests.jl b/test/runtests.jl index 57ba084d..666282f8 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -22,8 +22,20 @@ using SpelledOut @test spelled_out(3.141592653589793, lang = :en) == "three point one four one five nine two six five three five eight nine seven nine three" @test spelled_out(2^log2(3390000), lang = :en) == "three million, three hundred ninety thousand" # should convert 3.3899999999999986e6 to an integer @test spelled_out(1000000.01, lang = :en) == "one million point zero one" # parse big floats correctly (i.e., avoid scientific notation. Caveat: this is slow) + @test spelled_out(1//3, lang = :en_UK) == "one third" + @test spelled_out(1//5, lang = :en_UK) == "one fifth" + @test spelled_out(1//102, lang = :en_UK) == "one one hundred and second" + @test spelled_out(1//102, lang = :en_US) == "one one hundred second" + @test spelled_out(5//102, lang = :en_UK) == "five one hundred and seconds" + @test spelled_out(5//12, lang = :en_UK) == "five twelfths" + @test spelled_out(1//1, lang = :en_UK) == "one" + @test spelled_out(40//1, lang = :en_UK) == "forty" + @test spelled_out(40//2, lang = :en_UK) == "twenty" + @test spelled_out(40//6, lang = :en_UK) == "twenty thirds" end + + @testset "Spanish" begin @test spelled_out(585000, lang = :es) == "quinientos ochenta y cinco mil" From ddccd6be80506ecdcd437b0feb8c07df998baa71 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Wed, 27 Jan 2021 23:54:55 +1300 Subject: [PATCH 053/120] Added method handling irrational numbers (closes #38, but open question addressed in #48) --- src/en.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/en.jl b/src/en.jl index 63d830a6..153c466a 100644 --- a/src/en.jl +++ b/src/en.jl @@ -213,6 +213,9 @@ function spelled_out_en(number::Rational; british::Bool = false, dict::Symbol = return isone(_num) ? word : word * "s" end +function spelled_out_en(number::AbstractIrrational; british::Bool = false, dict::Symbol = :modern) + throw(error("Please round the input number, as we support floating point printing but cannot support irrational printing.")) +end # Fallback method if we do not know how to handle the input function spelled_out_en(number; british::Bool = false, dict::Symbol = :modern) From 282cbd35c231177dadff118fad11a9657954b601 Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Thu, 28 Jan 2021 00:04:13 +1300 Subject: [PATCH 054/120] Updated version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index bb3dc47f..a199ccaf 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.1.0" +version = "1.1.1" [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" From e81c4b2a139e79ed5c888171b4b5f98c6d1a08bc Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Thu, 28 Jan 2021 11:26:19 +1300 Subject: [PATCH 055/120] Added caveat about 32-bit systems --- docs/src/index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/src/index.md b/docs/src/index.md index 33aaa92f..4a2ef993 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -2,6 +2,9 @@ This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their language form. The process of **spelling out** a number has also been referred to as **set full out**, to write out in **long hand**, and — as a great mind once suggested — to **transnumerate**. +## Caveats +Unfortunately, as this library requires `DecFP` for spelling out floats as expected, we cannot support i686 (32-bit) systems. + ## Contents ```@contents ``` From 38ae94c8781f4b77c2e9d1bbdd6dfa5f69fe0b2f Mon Sep 17 00:00:00 2001 From: "Jake W. Ireland" Date: Sun, 22 Aug 2021 00:59:55 +1200 Subject: [PATCH 056/120] slight performance considerations while obtaining default language --- src/SpelledOut.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 98201d44..64d2cd3d 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -42,7 +42,7 @@ julia> spelled_out(112, lang = :es) """ function spelled_out( number::Number; - lang::Symbol = Symbol(first(split(ENV["LANG"], '.'))), + lang::Symbol = Symbol(ENV["LANG"][1:(findfirst(==('.'), ENV["LANG"]) - 1)]), # Symbol(first(split(ENV["LANG"], '.'))) dict::Symbol = :modern ) From 2fbebedb825504d419e44dfa51b5e8e73ca75e03 Mon Sep 17 00:00:00 2001 From: Paresh Mathur Date: Sat, 16 Oct 2021 01:35:46 +0530 Subject: [PATCH 057/120] correct syntax for british spell out in docs --- src/SpelledOut.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 64d2cd3d..8fce9543 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -30,7 +30,7 @@ julia> spelled_out(12, lang = :en) julia> spelled_out(112, lang = :en) "one hundred twelve" -julia> spelled_out(112, lang = :en, british = true) +julia> spelled_out(112, lang = :en_GB) "one hundred and twelve" julia> spelled_out(112, lang = :en, dict = :european) From 88c1e7517e38b1a2e74da8c373beada70ce938b5 Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Mon, 30 May 2022 15:56:19 -0300 Subject: [PATCH 058/120] added pt_BR --- .gitignore | 3 +- SpelledOut.jl.Rproj | 13 +++ docs/src/supported_languages.md | 1 + src/SpelledOut.jl | 12 ++- src/pt_BR.jl | 140 ++++++++++++++++++++++++++++++++ src/pt_BR/standard_pt_BR.jl | 82 +++++++++++++++++++ test/runtests.jl | 7 +- 7 files changed, 252 insertions(+), 6 deletions(-) create mode 100644 SpelledOut.jl.Rproj create mode 100644 src/pt_BR.jl create mode 100644 src/pt_BR/standard_pt_BR.jl diff --git a/.gitignore b/.gitignore index 88cdeb53..e2316af4 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ Manifest.toml .DS_Store # VS Code folder -.vscode \ No newline at end of file +.vscode +.Rproj.user diff --git a/SpelledOut.jl.Rproj b/SpelledOut.jl.Rproj new file mode 100644 index 00000000..8e3c2ebc --- /dev/null +++ b/SpelledOut.jl.Rproj @@ -0,0 +1,13 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX diff --git a/docs/src/supported_languages.md b/docs/src/supported_languages.md index d7a7bf4a..f931c0f5 100644 --- a/docs/src/supported_languages.md +++ b/docs/src/supported_languages.md @@ -7,3 +7,4 @@ Current languages to choose from are: - `:en_UK` (aliases: `:en_GB`; equivalencies: `:en_NZ`, `:en_AU`) - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. - Spanish (`:es`) + - Portuguese (`:pt_BR`) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 8fce9543..2f7fdc14 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -1,12 +1,13 @@ module SpelledOut -using DecFP: Dec64 +using DecFP: Dec64, Dec128 using Formatting: format export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") include("es.jl") +include("pt_BR.jl") """ ```julia @@ -38,6 +39,9 @@ julia> spelled_out(112, lang = :en, dict = :european) julia> spelled_out(112, lang = :es) "ciento doce" + +julia> spelled_out(112, lang = :pt_BR) +"cento e doze" ``` """ function spelled_out( @@ -51,7 +55,9 @@ function spelled_out( elseif lang ∈ (:en_UK, :en_GB, :en_NZ, :en_AU) return spelled_out_en(number, british = true, dict = dict) elseif lang ∈ (:es,) - return spelled_out_es(number,dict) + return spelled_out_es(number, dict) + elseif lang ∈ (:pt_BR,) + return spelled_out_pt_BR(number, dict) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) @@ -59,4 +65,4 @@ function spelled_out( return nothing end -end # end module +end # end module \ No newline at end of file diff --git a/src/pt_BR.jl b/src/pt_BR.jl new file mode 100644 index 00000000..d743f560 --- /dev/null +++ b/src/pt_BR.jl @@ -0,0 +1,140 @@ +include( joinpath( @__DIR__, "pt_BR", "standard_pt_BR.jl" ) ) + +#retuns a vector of ints, each of that +function split_numbers_10³( num::Integer ) + digits( num, base = 10^3) +end + +function split_numbers_10⁶( num::Integer ) + digits( num, base = 10^6) +end + +#function +function pt_BR_spell_1e3( number, short_one = false ) + if number <= 99 #0 - 99 + if number < 20 #1 - 20 + iszero(number) && return "" + if isone(number) && short_one + return "um" + else + return pt_BR_1_a_19[ number ] + end + else #20-99 + unit, dec = digits( number ) + if isone( unit ) && short_one + unit_text = " e um" + elseif iszero( unit ) + unit_text = "" + else + unit_text = " e " * pt_BR_1_a_19[ unit ] + end + return pt_BR_dezenas[ dec ] * unit_text + end + elseif 100 <= number <= 999 + number == 100 && return "cem" + unit, cent = digits( number, base = 100 ) + unit_text = pt_BR_spell_1e3( unit, short_one ) + return pt_BR_centenas[ cent ] * " e " * unit_text + end +end + +function pt_BR_spell_1e6( number, short_one = false ) + number = Int( number ) + number == 0 && return "" + number == 1000 && return "mil" + number <= 999 && return pt_BR_spell_1e3( number, short_one ) + low,high = digits( number, base = 1000 ) + low_txt = pt_BR_spell_1e3( low, short_one ) + if high == 1 + high_text = "mil e " + else + high_text = pt_BR_spell_1e3( high, false ) * " mil" + end + return high_text * low_txt +end + +#spells only decimals, including 0 +function pt_BR_spell_decimal( number, partitive = true ) + whole, decimal = split( string( number ), "." ) + decnum, wholenum = abs.( modf( number ) ) + decimal_length = length( decimal ) + decint = decnum*10^decimal_length + if partitive + if decimal_length > 6 + throw(error("""partitive pronunciation of Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . + If you want english-like decimals (zero ponto dois), try using partitive = false. + If the decimal part seems to differ from the perceived input number, try using big numbers: `big"123.23"`. + """)) + end + + dectext = pt_BR_spell_1e6( Dec128( decint ), false ) + res = strip( dectext ) * " " * pt_BR_decimais[ decimal_length ] + if decint != 1 + res = res * "s" + end + return res + else + res = digits( decint ) .|> z-> pt_BR_spell_1e3( z, true ) .|> strip |> reverse |> z-> join( z," " ) + res = "ponto " * res + end +end + +function pt_BR_spell_large_map( number, i ) + if isone( i ) + return pt_BR_spell_1e6( number, true ) + elseif isone( number ) + return "um " * pt_BR_multiplos_1e6_singular[ i - 1 ] + else + return pt_BR_spell_1e6( number, false ) * " " * pt_BR_multiplos_1e6_plural[ i - 1 ] + end +end + +function pt_BR_spell_large( _number ) + number = Int( abs( _number ) ) + list = digits( number, base = 1_000_000 ) + res = pt_BR_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) + ( _number < 0 ) && ( res = "menos " * res ) + return res +end + +function spelled_out_pt_BR( number, dict = :standard ) + if iszero( number ) + return "zero" + end + if isinteger( number ) + if dict in ( :standard, :large, :modern ) + res = pt_BR_spell_large( number ) + elseif dict in (:short,) + res = pt_BR_spell_short( number ) + else + throw( error( "unrecognized dict value: $dict" ) ) + end + return res + else #with decimals + partitive = true + _dec, _int = modf( number ) + _int = Dec128( _int ) + if ( _int == 0 ) & !partitive + intres = "zero" + + elseif ( _int == 0 ) & partitive + intres = "" + elseif dict in ( :standard, :large, :modern ) + intres = pt_BR_spell_large( _int ) * " con " + elseif dict in ( :short, ) + intres = pt_BR_spell_short( _int ) * " con " + else + throw( error( "unrecognized dict value: $dict" ) ) + end + + decres = pt_BR_spell_decimal( abs( _dec ) ) + return intres * decres + end +end + + + + + + + diff --git a/src/pt_BR/standard_pt_BR.jl b/src/pt_BR/standard_pt_BR.jl new file mode 100644 index 00000000..80aeb799 --- /dev/null +++ b/src/pt_BR/standard_pt_BR.jl @@ -0,0 +1,82 @@ +const pt_BR_1_a_19 =[ + "um" + "dois" + "três" + "quatro" + "cinco" + "seis" + "sete" + "oito" + "nove" + "dez" + "onze" + "doze" + "treze" + "catorze" + "quinze" + "dezesseis" + "dezessete" + "dezoito" + "dezenove" +] + +const pt_BR_dezenas = [ + "" + "vinte" + "trinta" + "quarenta" + "cinquenta" + "sessenta" + "setenta" + "oitenta" + "noventa" +] + +const pt_BR_centenas = [ + "cento" + "duzentos" + "trezentos" + "quatrocentos" + "quinhentos" + "seiscentos" + "setecentos" + "oitocentos" + "novecentos" +] + +const pt_BR_multiplos_1e6_singular = [ + "milhão" + "bilhão" + "trilhão" + "quatrilhão" + "quintilhão" + "sextilhão" + "septilhão" + "oitolhão" + "nonilhão" + "decilhão" + "undecilhão" + "duodecilhão" +] + +const pt_BR_multiplos_1e6_plural = [ + "milhões" + "bilhões" + "trilhões" + "quatrilhões" + "quintilhões" + "sextilhões" + "septilhões" + "oitolhões" + "nonilhões" + "decilhões" + "undecilhões" + "duodecilhões" +] + +const pt_BR_decimais = [ + "décimo" + "centésimo" + "milésimo" + "milionésimo" +] \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 666282f8..05a1a1bc 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -34,11 +34,14 @@ using SpelledOut @test spelled_out(40//6, lang = :en_UK) == "twenty thirds" end - - @testset "Spanish" begin @test spelled_out(585000, lang = :es) == "quinientos ochenta y cinco mil" end +@testset "Portuguese" begin + @test spelled_out(585000, lang = :pt_BR) == "quinhentos e oitenta e cinco mil" + +end + nothing From 06f115e9cd2547165636298eb0516b116ccadcac Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Mon, 30 May 2022 16:01:01 -0300 Subject: [PATCH 059/120] "deleting useless file" --- SpelledOut.jl.Rproj | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 SpelledOut.jl.Rproj diff --git a/SpelledOut.jl.Rproj b/SpelledOut.jl.Rproj deleted file mode 100644 index 8e3c2ebc..00000000 --- a/SpelledOut.jl.Rproj +++ /dev/null @@ -1,13 +0,0 @@ -Version: 1.0 - -RestoreWorkspace: Default -SaveWorkspace: Default -AlwaysSaveHistory: Default - -EnableCodeIndexing: Yes -UseSpacesForTab: Yes -NumSpacesForTab: 2 -Encoding: UTF-8 - -RnwWeave: Sweave -LaTeX: pdfLaTeX From 3fafa7d842adb9c0e058f5ca8bb678adbd6344b4 Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Mon, 30 May 2022 16:02:18 -0300 Subject: [PATCH 060/120] .gitignore --- .Rproj.user/49806DE7/sources/s-A9A11D40/lock_file | 0 .Rproj.user/shared/notebooks/patch-chunk-names | 0 .gitignore | 3 +-- 3 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 .Rproj.user/49806DE7/sources/s-A9A11D40/lock_file create mode 100644 .Rproj.user/shared/notebooks/patch-chunk-names diff --git a/.Rproj.user/49806DE7/sources/s-A9A11D40/lock_file b/.Rproj.user/49806DE7/sources/s-A9A11D40/lock_file new file mode 100644 index 00000000..e69de29b diff --git a/.Rproj.user/shared/notebooks/patch-chunk-names b/.Rproj.user/shared/notebooks/patch-chunk-names new file mode 100644 index 00000000..e69de29b diff --git a/.gitignore b/.gitignore index e2316af4..88cdeb53 100644 --- a/.gitignore +++ b/.gitignore @@ -27,5 +27,4 @@ Manifest.toml .DS_Store # VS Code folder -.vscode -.Rproj.user +.vscode \ No newline at end of file From 2e6f397e2e85e1bad3a227cf64cf8c09d4ef7bb4 Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Wed, 1 Jun 2022 15:34:31 -0300 Subject: [PATCH 061/120] removed files from Rstudio IDE --- .Rproj.user/49806DE7/sources/s-A9A11D40/lock_file | 0 .Rproj.user/shared/notebooks/patch-chunk-names | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .Rproj.user/49806DE7/sources/s-A9A11D40/lock_file delete mode 100644 .Rproj.user/shared/notebooks/patch-chunk-names diff --git a/.Rproj.user/49806DE7/sources/s-A9A11D40/lock_file b/.Rproj.user/49806DE7/sources/s-A9A11D40/lock_file deleted file mode 100644 index e69de29b..00000000 diff --git a/.Rproj.user/shared/notebooks/patch-chunk-names b/.Rproj.user/shared/notebooks/patch-chunk-names deleted file mode 100644 index e69de29b..00000000 From aaf5f548af6860cb091c34ed8d99ba30f5d68a7b Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 2 Jun 2022 22:05:22 +1200 Subject: [PATCH 062/120] Initial commit on optimisation branch --- src/en.jl | 89 ++++++------- src/en/ordinal_dictionaries.jl | 3 + src/en/utils.jl | 23 ++++ src/en_orig.jl | 223 +++++++++++++++++++++++++++++++++ test/Project.toml | 3 - test/runtests.jl | 3 +- 6 files changed, 286 insertions(+), 58 deletions(-) create mode 100644 src/en/utils.jl create mode 100644 src/en_orig.jl delete mode 100644 test/Project.toml diff --git a/src/en.jl b/src/en.jl index 153c466a..79a888e4 100644 --- a/src/en.jl +++ b/src/en.jl @@ -1,32 +1,30 @@ +# dictionaries include(joinpath(@__DIR__, "en", "standard_dictionary_numbers_extended.jl")) include(joinpath(@__DIR__, "en", "large_standard_dictionary_numbers_extended.jl")) include(joinpath(@__DIR__, "en", "ordinal_dictionaries.jl")) + +# utils +include(joinpath(@__DIR__, "en", "utils.jl")) # convert a value < 100 to English. function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # define scale type if number < 20 - word = _small_numbers[number + 1] - - return word + return _small_numbers[number + 1] end - v = 0 - while v < length(_tens) - d_cap = _tens[v + 1] - d_number = BigInt(20 + 10 * v) + for (v, d_cap) in enumerate(_tens) + d_number = BigInt(20 + 10 * (v - 1)) if d_number + 10 > number if mod(number, 10) ≠ 0 - word = d_cap * "-" * _small_numbers[mod(number, 10) + 1] - - return word + return d_cap * "-" * _small_numbers[mod(number, 10) + 1] end - return d_cap end - v += 1 end + + return nothing end # convert a value < 1000 to english, special cased because it is the level that excludes @@ -34,28 +32,28 @@ end # strings in the form of "forty-five hundred" if called directly. function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # define scale type - word = string() # initiate empty string + word_buf = IOBuffer() divisor = div(number, 100) modulus = mod(number, 100) if divisor > 0 - word = _small_numbers[divisor + 1] * " hundred" + print(word_buf, _small_numbers[divisor + 1], " hundred") if modulus > 0 - word = word * " " + print(word_buf, ' ') end end if british if ! iszero(divisor) && ! iszero(modulus) - word = word * "and " + print(word_buf, "and ") end end if modulus > 0 - word = word * small_convert_en(modulus, british=british, dict=dict) + print(word_buf, small_convert_en(modulus, british=british, dict=dict)) end - return word + return String(take!(word_buf)) end function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = :modern) @@ -66,42 +64,28 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : scale_numbers = _scale_traditional_european elseif isequal(dict, :modern) else - throw(error("unrecognized dict value: $dict")) + error("Unrecognized dict value: $dict") end number = big(number) - isnegative = false - if number < 0 - isnegative = true - end - + isnegative = number < 0 number = abs(number) + if number > limit - 1 - throw(error("""SpelledOut.jl does not support numbers larger than $(limit_str * " - 1"). Sorry about that!""")) + error("""SpelledOut.jl does not support numbers larger than $(limit_str * " - 1"). Sorry about that!""") end if number < 100 word = small_convert_en(number, british=british, dict=dict) - - if isnegative - word = "negative " * word - end - - return word + return isnegative ? "negative " * word : word end if number < 1000 word = large_convert_en(number, british=british, dict=dict) - - if isnegative - word = "negative " * word - end - - return word + return isnegative ? "negative " * word : word end - v = 0 - while v ≤ length(scale_numbers) + for v in 0:length(scale_numbers) d_idx = v d_number = BigInt(round(big(1000)^v)) @@ -114,34 +98,33 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : word = word * ", " * spelled_out_en(r, british=british, dict=dict) end - if isnegative - word = "negative " * word - end - - return word + return isnegative ? "negative " * word : word end - - v += 1 end + + error("Unreachable") end # Need to print ordinal numbers for the irrational printing function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = :modern) s = spelled_out_en(number, british = british, dict = dict) - - lastword = split(s)[end] - redolast = split(lastword, "-")[end] + + # lastword = split(s)[end] + # redolast = split(lastword, "-")[end] + lastword = lastsplit(isspace, s) + redolast = lastsplit('-', lastword) + if redolast != lastword - lastsplit = "-" + _lastsplit = '-' word = redolast else - lastsplit = " " + _lastsplit = ' ' word = lastword end - firstpart = reverse(split(reverse(s), lastsplit, limit = 2)[end]) - firstpart = (firstpart == word) ? string() : firstpart * lastsplit + firstpart = reverse(split(reverse(s), _lastsplit, limit = 2)[end]) + firstpart = (firstpart == word) ? "" : firstpart * _lastsplit if haskey(irregular, word) word = irregular[word] diff --git a/src/en/ordinal_dictionaries.jl b/src/en/ordinal_dictionaries.jl index 265f6db5..c9ac983e 100644 --- a/src/en/ordinal_dictionaries.jl +++ b/src/en/ordinal_dictionaries.jl @@ -2,3 +2,6 @@ const irregular = Dict("one" => "first", "two" => "second", "three" => "third", "eight" => "eighth", "nine" => "ninth", "twelve" => "twelfth") const suffix = "th" const ysuffix = "ieth" + +ordinal(n::Integer) = + string(n, (11 <= mod(n, 100) <= 13) ? "th" : (["th", "st", "nd", "rd", "th"][min(mod1(n, 10) + 1, 5)])) diff --git a/src/en/utils.jl b/src/en/utils.jl new file mode 100644 index 00000000..2053b11b --- /dev/null +++ b/src/en/utils.jl @@ -0,0 +1,23 @@ +function lastsplit(predicate, s::S) where {S <: AbstractString} + i = findlast(predicate, s) + return isnothing(i) ? SubString(s) : SubString(s, nextind(s, i)) +end + +Base.findall(c::Char, s::S) where {S <: AbstractString} = + Int[only(i) for i in findall(string(c), s)] + +function ithsplit(predicate, s::S, i::Int) where {S <: AbstractString} + j = 1 # firstindex(s) + for _ in 1:i + k = findnext(predicate, s, j) + if isnothing(k) + break + else + j = k + end + end + return SubString() +end + + +split(s, _lastsplit, limit = 2)[end] diff --git a/src/en_orig.jl b/src/en_orig.jl new file mode 100644 index 00000000..153c466a --- /dev/null +++ b/src/en_orig.jl @@ -0,0 +1,223 @@ +include(joinpath(@__DIR__, "en", "standard_dictionary_numbers_extended.jl")) +include(joinpath(@__DIR__, "en", "large_standard_dictionary_numbers_extended.jl")) +include(joinpath(@__DIR__, "en", "ordinal_dictionaries.jl")) + +# convert a value < 100 to English. +function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + scale_numbers = _scale_modern # define scale type + if number < 20 + word = _small_numbers[number + 1] + + return word + end + + v = 0 + while v < length(_tens) + d_cap = _tens[v + 1] + d_number = BigInt(20 + 10 * v) + + if d_number + 10 > number + if mod(number, 10) ≠ 0 + word = d_cap * "-" * _small_numbers[mod(number, 10) + 1] + + return word + end + + return d_cap + end + v += 1 + end +end + +# convert a value < 1000 to english, special cased because it is the level that excludes +# the < 100 special case. The rest are more general. This also allows you to get +# strings in the form of "forty-five hundred" if called directly. +function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + scale_numbers = _scale_modern # define scale type + word = string() # initiate empty string + divisor = div(number, 100) + modulus = mod(number, 100) + + if divisor > 0 + word = _small_numbers[divisor + 1] * " hundred" + if modulus > 0 + word = word * " " + end + end + + if british + if ! iszero(divisor) && ! iszero(modulus) + word = word * "and " + end + end + + if modulus > 0 + word = word * small_convert_en(modulus, british=british, dict=dict) + end + + return word +end + +function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + scale_numbers = _scale_modern # default to :modern + if isequal(dict, :british) + scale_numbers = _scale_traditional_british + elseif isequal(dict, :european) + scale_numbers = _scale_traditional_european + elseif isequal(dict, :modern) + else + throw(error("unrecognized dict value: $dict")) + end + + number = big(number) + isnegative = false + if number < 0 + isnegative = true + end + + number = abs(number) + if number > limit - 1 + throw(error("""SpelledOut.jl does not support numbers larger than $(limit_str * " - 1"). Sorry about that!""")) + end + + if number < 100 + word = small_convert_en(number, british=british, dict=dict) + + if isnegative + word = "negative " * word + end + + return word + end + + if number < 1000 + word = large_convert_en(number, british=british, dict=dict) + + if isnegative + word = "negative " * word + end + + return word + end + + v = 0 + while v ≤ length(scale_numbers) + d_idx = v + d_number = BigInt(round(big(1000)^v)) + + if d_number > number + modulus = BigInt(big(1000)^(d_idx - 1)) + l, r = divrem(number, modulus) + word = large_convert_en(l, british=british, dict=dict) * " " * scale_numbers[d_idx - 1] + + if r > 0 + word = word * ", " * spelled_out_en(r, british=british, dict=dict) + end + + if isnegative + word = "negative " * word + end + + return word + end + + v += 1 + end +end + +# Need to print ordinal numbers for the irrational printing +function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + s = spelled_out_en(number, british = british, dict = dict) + + lastword = split(s)[end] + redolast = split(lastword, "-")[end] + + if redolast != lastword + lastsplit = "-" + word = redolast + else + lastsplit = " " + word = lastword + end + + firstpart = reverse(split(reverse(s), lastsplit, limit = 2)[end]) + firstpart = (firstpart == word) ? string() : firstpart * lastsplit + + if haskey(irregular, word) + word = irregular[word] + elseif word[end] == 'y' + word = word[1:end-1] * ysuffix + else + word = word * suffix + end + + return firstpart * word +end + +# This method is an internal method used for spelling out floats +function decimal_convert_en(number::AbstractString; british::Bool = false, dict::Symbol = :modern) + # decimal, whole = modf(number) + # whole = round(BigInt, whole) + whole, decimal = split(number, ".") + word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") + # word = spelled_out_en(whole, british=british, dict=dict) * string(" point") + + for i in decimal + word = word * " " * _small_number_dictionary[i] + end + + return word +end + +function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) + str_number = format(number) + if occursin('.', str_number) + _decimal, _ = modf(Dec64(number)) + _length_of_presicion = length(string(_decimal)) - 2 # (ndigits(_whole) + 1) + number = format(number, precision = _length_of_presicion) + else + # It is an integer is scientific notation, treat normally without decimal precision considerations + # E.g., 1e10 should be parsed as an integer (as should 1.0e10) + number = parse(BigInt, str_number) + end + + if isa(number, AbstractString) + # if the number is a string then it is a decimal, which is formatted precisely + # for correct precision with decimal places + return decimal_convert_en(number, british = british, dict = dict) + elseif isinteger(number) + # otherwise, it is an integer + return spelled_out_en(number, british = british, dict = dict) + else + throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) + end + + # should never get here + return nothing +end + +# Spell out complex numbers +function spelled_out_en(number::Complex; british::Bool = false, dict::Symbol = :modern) + return spelled_out_en(real(number), british = british, dict = dict) * " and " * spelled_out_en(imag(number), british = british, dict=dict) * " imaginaries" +end + +function spelled_out_en(number::Rational; british::Bool = false, dict::Symbol = :modern) + _num, _den = number.num, number.den + + # return the number itself if the denomimator is one + isone(_den) && return spelled_out_en(_num, british = british, dict = dict) + + word = spelled_out_en(_num, british = british, dict = dict) * " " * spell_ordinal_en(_den, british = british, dict = dict) + + # account for pluralisation + return isone(_num) ? word : word * "s" +end + +function spelled_out_en(number::AbstractIrrational; british::Bool = false, dict::Symbol = :modern) + throw(error("Please round the input number, as we support floating point printing but cannot support irrational printing.")) +end + +# Fallback method if we do not know how to handle the input +function spelled_out_en(number; british::Bool = false, dict::Symbol = :modern) + throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) +end diff --git a/test/Project.toml b/test/Project.toml deleted file mode 100644 index 28bcb829..00000000 --- a/test/Project.toml +++ /dev/null @@ -1,3 +0,0 @@ -[deps] -DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/runtests.jl b/test/runtests.jl index 666282f8..a3bc6e70 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,3 @@ -# include(joinpath(dirname(dirname(@__FILE__)), "src", "SpelledOut.jl")); using .SpelledOut using Test using SpelledOut @@ -41,4 +40,4 @@ end end -nothing + From 67bac5238a7953d8dbea4bfdcfd254cdcce8a208 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 2 Jun 2022 22:33:09 +1200 Subject: [PATCH 063/120] Added variants subsection to support future addition of Portugal Pt --- docs/src/supported_languages.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/src/supported_languages.md b/docs/src/supported_languages.md index f931c0f5..04210599 100644 --- a/docs/src/supported_languages.md +++ b/docs/src/supported_languages.md @@ -7,4 +7,6 @@ Current languages to choose from are: - `:en_UK` (aliases: `:en_GB`; equivalencies: `:en_NZ`, `:en_AU`) - Dictionaries supported include `:modern`, `:british`, and `:european`, and default to the former. - Spanish (`:es`) - - Portuguese (`:pt_BR`) + - Portuguese + - Variants + - (`:pt_BR`) From 8259e0115fd242d1da9bfdde34ad3d625d55e36b Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 2 Jun 2022 22:45:10 +1200 Subject: [PATCH 064/120] Refactor pt_BR code structure to contain all Portuguese variants within one file --- src/SpelledOut.jl | 6 +-- src/{pt_BR.jl => pt.jl} | 40 ++++++++++--------- .../standard_pt_br.jl} | 0 test/runtests.jl | 2 - 4 files changed, 24 insertions(+), 24 deletions(-) rename src/{pt_BR.jl => pt.jl} (75%) rename src/{pt_BR/standard_pt_BR.jl => pt/standard_pt_br.jl} (100%) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 2f7fdc14..df815f14 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -7,7 +7,7 @@ export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") include("es.jl") -include("pt_BR.jl") +include("pt.jl") """ ```julia @@ -57,7 +57,7 @@ function spelled_out( elseif lang ∈ (:es,) return spelled_out_es(number, dict) elseif lang ∈ (:pt_BR,) - return spelled_out_pt_BR(number, dict) + return spelled_out_pt_br(number, dict) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) @@ -65,4 +65,4 @@ function spelled_out( return nothing end -end # end module \ No newline at end of file +end # end module diff --git a/src/pt_BR.jl b/src/pt.jl similarity index 75% rename from src/pt_BR.jl rename to src/pt.jl index d743f560..5aa9a6ce 100644 --- a/src/pt_BR.jl +++ b/src/pt.jl @@ -1,4 +1,6 @@ -include( joinpath( @__DIR__, "pt_BR", "standard_pt_BR.jl" ) ) +include(joinpath(@__DIR__, "pt", "standard_pt_br.jl")) + +## Implement Spelled Out for Brazilian Portuguese #retuns a vector of ints, each of that function split_numbers_10³( num::Integer ) @@ -10,7 +12,7 @@ function split_numbers_10⁶( num::Integer ) end #function -function pt_BR_spell_1e3( number, short_one = false ) +function pt_br_spell_1e3( number, short_one = false ) if number <= 99 #0 - 99 if number < 20 #1 - 20 iszero(number) && return "" @@ -33,28 +35,28 @@ function pt_BR_spell_1e3( number, short_one = false ) elseif 100 <= number <= 999 number == 100 && return "cem" unit, cent = digits( number, base = 100 ) - unit_text = pt_BR_spell_1e3( unit, short_one ) + unit_text = pt_br_spell_1e3( unit, short_one ) return pt_BR_centenas[ cent ] * " e " * unit_text end end -function pt_BR_spell_1e6( number, short_one = false ) +function pt_br_spell_1e6( number, short_one = false ) number = Int( number ) number == 0 && return "" number == 1000 && return "mil" - number <= 999 && return pt_BR_spell_1e3( number, short_one ) + number <= 999 && return pt_br_spell_1e3( number, short_one ) low,high = digits( number, base = 1000 ) - low_txt = pt_BR_spell_1e3( low, short_one ) + low_txt = pt_br_spell_1e3( low, short_one ) if high == 1 high_text = "mil e " else - high_text = pt_BR_spell_1e3( high, false ) * " mil" + high_text = pt_br_spell_1e3( high, false ) * " mil" end return high_text * low_txt end #spells only decimals, including 0 -function pt_BR_spell_decimal( number, partitive = true ) +function pt_br_spell_decimal( number, partitive = true ) whole, decimal = split( string( number ), "." ) decnum, wholenum = abs.( modf( number ) ) decimal_length = length( decimal ) @@ -67,43 +69,43 @@ function pt_BR_spell_decimal( number, partitive = true ) """)) end - dectext = pt_BR_spell_1e6( Dec128( decint ), false ) + dectext = pt_br_spell_1e6( Dec128( decint ), false ) res = strip( dectext ) * " " * pt_BR_decimais[ decimal_length ] if decint != 1 res = res * "s" end return res else - res = digits( decint ) .|> z-> pt_BR_spell_1e3( z, true ) .|> strip |> reverse |> z-> join( z," " ) + res = digits( decint ) .|> z-> pt_br_spell_1e3( z, true ) .|> strip |> reverse |> z-> join( z," " ) res = "ponto " * res end end -function pt_BR_spell_large_map( number, i ) +function pt_br_spell_large_map( number, i ) if isone( i ) - return pt_BR_spell_1e6( number, true ) + return pt_br_spell_1e6( number, true ) elseif isone( number ) return "um " * pt_BR_multiplos_1e6_singular[ i - 1 ] else - return pt_BR_spell_1e6( number, false ) * " " * pt_BR_multiplos_1e6_plural[ i - 1 ] + return pt_br_spell_1e6( number, false ) * " " * pt_BR_multiplos_1e6_plural[ i - 1 ] end end -function pt_BR_spell_large( _number ) +function pt_br_spell_large( _number ) number = Int( abs( _number ) ) list = digits( number, base = 1_000_000 ) - res = pt_BR_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) + res = pt_br_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) ( _number < 0 ) && ( res = "menos " * res ) return res end -function spelled_out_pt_BR( number, dict = :standard ) +function spelled_out_pt_br( number, dict = :standard ) if iszero( number ) return "zero" end if isinteger( number ) if dict in ( :standard, :large, :modern ) - res = pt_BR_spell_large( number ) + res = pt_br_spell_large( number ) elseif dict in (:short,) res = pt_BR_spell_short( number ) else @@ -120,14 +122,14 @@ function spelled_out_pt_BR( number, dict = :standard ) elseif ( _int == 0 ) & partitive intres = "" elseif dict in ( :standard, :large, :modern ) - intres = pt_BR_spell_large( _int ) * " con " + intres = pt_br_spell_large( _int ) * " con " elseif dict in ( :short, ) intres = pt_BR_spell_short( _int ) * " con " else throw( error( "unrecognized dict value: $dict" ) ) end - decres = pt_BR_spell_decimal( abs( _dec ) ) + decres = pt_br_spell_decimal( abs( _dec ) ) return intres * decres end end diff --git a/src/pt_BR/standard_pt_BR.jl b/src/pt/standard_pt_br.jl similarity index 100% rename from src/pt_BR/standard_pt_BR.jl rename to src/pt/standard_pt_br.jl diff --git a/test/runtests.jl b/test/runtests.jl index 05a1a1bc..8940d4e4 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -36,12 +36,10 @@ end @testset "Spanish" begin @test spelled_out(585000, lang = :es) == "quinientos ochenta y cinco mil" - end @testset "Portuguese" begin @test spelled_out(585000, lang = :pt_BR) == "quinhentos e oitenta e cinco mil" - end nothing From 60ac237f055ed941b7c6ef7eccde0a7bc9a8c734 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 2 Jun 2022 22:46:08 +1200 Subject: [PATCH 065/120] Removed unused functions --- src/es.jl | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/es.jl b/src/es.jl index bad01488..e0af3b5c 100644 --- a/src/es.jl +++ b/src/es.jl @@ -1,15 +1,5 @@ include(joinpath(@__DIR__, "es", "standard_es.jl")) -#retuns a vector of ints, each of that -function split_numbers_10³(num::Integer) - digits(num,base=10^3) -end - -function split_numbers_10⁶(num::Integer) - digits(num,base=10^6) -end - -#function function es_spell_1e3(number,short_one=false) if number <= 99 #0 - 99 if number<30 #1 - 30 From 91544a892dce836704dd664c97ff5e6b92d606ea Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 2 Jun 2022 22:49:30 +1200 Subject: [PATCH 066/120] Changed dict to keyword argument for consistency in interface --- src/SpelledOut.jl | 4 ++-- src/es.jl | 2 +- src/pt.jl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index df815f14..9b8454aa 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -55,9 +55,9 @@ function spelled_out( elseif lang ∈ (:en_UK, :en_GB, :en_NZ, :en_AU) return spelled_out_en(number, british = true, dict = dict) elseif lang ∈ (:es,) - return spelled_out_es(number, dict) + return spelled_out_es(number; dict = dict) elseif lang ∈ (:pt_BR,) - return spelled_out_pt_br(number, dict) + return spelled_out_pt_br(number; dict = dict) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) diff --git a/src/es.jl b/src/es.jl index e0af3b5c..d87bc358 100644 --- a/src/es.jl +++ b/src/es.jl @@ -92,7 +92,7 @@ function es_spell_large(_number) end -function spelled_out_es(number,dict=:standard) +function spelled_out_es(number; dict=:standard) if iszero(number) return "cero" end diff --git a/src/pt.jl b/src/pt.jl index 5aa9a6ce..225627cb 100644 --- a/src/pt.jl +++ b/src/pt.jl @@ -99,7 +99,7 @@ function pt_br_spell_large( _number ) return res end -function spelled_out_pt_br( number, dict = :standard ) +function spelled_out_pt_br( number; dict = :standard ) if iszero( number ) return "zero" end From 5ceb84f287583b18e100f1a4cbaba0657d89dbd0 Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Thu, 2 Jun 2022 13:58:58 -0300 Subject: [PATCH 067/120] pt_BR tests --- test/runtests.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 8940d4e4..4d31816e 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -40,6 +40,15 @@ end @testset "Portuguese" begin @test spelled_out(585000, lang = :pt_BR) == "quinhentos e oitenta e cinco mil" + @test spelled_out(0, lang = :pt_BR) == "zero" + @test spelled_out(0.9, lang = :pt_BR) == "nove décimos" + @test spelled_out(0.09, lang = :pt_BR) == "nove centésimos" + @test spelled_out(0.009, lang = :pt_BR) == "nove milésimos" + @test spelled_out(0.0009, lang = :pt_BR) == "nove milionésimos" + @test spelled_out(-10, lang = :pt_BR) == "menos dez" + @test spelled_out(-109, lang = :pt_BR) == "menos cento e nove" + @test spelled_out(100, lang = :pt_BR) == "cem" + @test spelled_out(105, lang = :pt_BR) == "cento e cinco" end nothing From 7cb2f491b3a1c41431e37d7de1d28d80cfb32cd4 Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Thu, 2 Jun 2022 19:03:26 -0300 Subject: [PATCH 068/120] fixing a bug and implementing pt-PT separately --- src/SpelledOut.jl | 10 ++- src/pt.jl | 71 ++++++++++---------- src/pt/pt_pt.jl | 82 +++++++++++++++++++++++ src/pt/standard_pt_br.jl | 6 +- src/pt_BR.jl | 139 +++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 10 +++ 6 files changed, 280 insertions(+), 38 deletions(-) create mode 100644 src/pt/pt_pt.jl create mode 100644 src/pt_BR.jl diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 9b8454aa..b2227a31 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -8,6 +8,7 @@ export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") include("es.jl") include("pt.jl") +include("pt_BR.jl") """ ```julia @@ -40,8 +41,11 @@ julia> spelled_out(112, lang = :en, dict = :european) julia> spelled_out(112, lang = :es) "ciento doce" -julia> spelled_out(112, lang = :pt_BR) -"cento e doze" +julia> spelled_out(19, lang = :pt_BR) +"dezenove" + +julia> spelled_out(19, lang = :pt) +"dezanove" ``` """ function spelled_out( @@ -58,6 +62,8 @@ function spelled_out( return spelled_out_es(number; dict = dict) elseif lang ∈ (:pt_BR,) return spelled_out_pt_br(number; dict = dict) + elseif lang ∈ (:pt,) + return spelled_out_pt_pt(number; dict = dict) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) diff --git a/src/pt.jl b/src/pt.jl index 225627cb..02654f38 100644 --- a/src/pt.jl +++ b/src/pt.jl @@ -1,6 +1,6 @@ -include(joinpath(@__DIR__, "pt", "standard_pt_br.jl")) +include(joinpath(@__DIR__, "pt", "pt_pt.jl")) -## Implement Spelled Out for Brazilian Portuguese +## Implement Spelled Out for Portugal Portuguese #retuns a vector of ints, each of that function split_numbers_10³( num::Integer ) @@ -12,14 +12,14 @@ function split_numbers_10⁶( num::Integer ) end #function -function pt_br_spell_1e3( number, short_one = false ) +function pt_pt_spell_1e3( number, short_one = false ) if number <= 99 #0 - 99 if number < 20 #1 - 20 iszero(number) && return "" if isone(number) && short_one return "um" else - return pt_BR_1_a_19[ number ] + return pt_PT_1_a_19[ number ] end else #20-99 unit, dec = digits( number ) @@ -28,86 +28,90 @@ function pt_br_spell_1e3( number, short_one = false ) elseif iszero( unit ) unit_text = "" else - unit_text = " e " * pt_BR_1_a_19[ unit ] + unit_text = " e " * pt_PT_1_a_19[ unit ] end - return pt_BR_dezenas[ dec ] * unit_text + return pt_PT_dezenas[ dec ] * unit_text end - elseif 100 <= number <= 999 - number == 100 && return "cem" + elseif number ∈ centenas_dicionario unit, cent = digits( number, base = 100 ) - unit_text = pt_br_spell_1e3( unit, short_one ) - return pt_BR_centenas[ cent ] * " e " * unit_text + unit_text = pt_pt_spell_1e3( unit, short_one ) + return pt_PT_centenas[ cent ] + elseif 100 <= number <= 999 + number == 100 && return "cem" + unit, cent = digits( number, base = 100 ) + unit_text = pt_pt_spell_1e3( unit, short_one ) + return pt_PT_centenas[ cent ] * " e " * unit_text end end -function pt_br_spell_1e6( number, short_one = false ) +function pt_pt_spell_1e6( number, short_one = false ) number = Int( number ) number == 0 && return "" number == 1000 && return "mil" - number <= 999 && return pt_br_spell_1e3( number, short_one ) + number <= 999 && return pt_pt_spell_1e3( number, short_one ) low,high = digits( number, base = 1000 ) - low_txt = pt_br_spell_1e3( low, short_one ) + low_txt = pt_pt_spell_1e3( low, short_one ) if high == 1 high_text = "mil e " else - high_text = pt_br_spell_1e3( high, false ) * " mil" + high_text = pt_pt_spell_1e3( high, false ) * " mil" end return high_text * low_txt end #spells only decimals, including 0 -function pt_br_spell_decimal( number, partitive = true ) +function pt_pt_spell_decimal( number, partitive = true ) whole, decimal = split( string( number ), "." ) decnum, wholenum = abs.( modf( number ) ) decimal_length = length( decimal ) decint = decnum*10^decimal_length if partitive if decimal_length > 6 - throw(error("""partitive pronunciation of Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . + throw(error("""partitive pronunciation of Portugal Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . If you want english-like decimals (zero ponto dois), try using partitive = false. If the decimal part seems to differ from the perceived input number, try using big numbers: `big"123.23"`. """)) end - dectext = pt_br_spell_1e6( Dec128( decint ), false ) - res = strip( dectext ) * " " * pt_BR_decimais[ decimal_length ] + dectext = pt_pt_spell_1e6( Dec128( decint ), false ) + res = strip( dectext ) * " " * pt_PT_decimais[ decimal_length ] if decint != 1 res = res * "s" end return res else - res = digits( decint ) .|> z-> pt_br_spell_1e3( z, true ) .|> strip |> reverse |> z-> join( z," " ) + res = digits( decint ) .|> z-> pt_pt_spell_1e3( z, true ) .|> strip |> reverse |> z-> join( z," " ) res = "ponto " * res end end -function pt_br_spell_large_map( number, i ) +function pt_pt_spell_large_map( number, i ) if isone( i ) - return pt_br_spell_1e6( number, true ) + return pt_pt_spell_1e6( number, true ) elseif isone( number ) - return "um " * pt_BR_multiplos_1e6_singular[ i - 1 ] + return "um " * pt_PT_multiplos_1e6_singular[ i - 1 ] else - return pt_br_spell_1e6( number, false ) * " " * pt_BR_multiplos_1e6_plural[ i - 1 ] + return pt_pt_spell_1e6( number, false ) end end -function pt_br_spell_large( _number ) - number = Int( abs( _number ) ) +function pt_pt_spell_large( _number ) + number = abs( _number ) list = digits( number, base = 1_000_000 ) - res = pt_br_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) + res = pt_pt_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) ( _number < 0 ) && ( res = "menos " * res ) return res end -function spelled_out_pt_br( number; dict = :standard ) +function spelled_out_pt_pt( number; dict = :standard ) if iszero( number ) return "zero" end if isinteger( number ) if dict in ( :standard, :large, :modern ) - res = pt_br_spell_large( number ) + res = pt_pt_spell_large( number ) elseif dict in (:short,) - res = pt_BR_spell_short( number ) + res = pt_pt_spell_short( number ) else throw( error( "unrecognized dict value: $dict" ) ) end @@ -122,14 +126,14 @@ function spelled_out_pt_br( number; dict = :standard ) elseif ( _int == 0 ) & partitive intres = "" elseif dict in ( :standard, :large, :modern ) - intres = pt_br_spell_large( _int ) * " con " + intres = pt_pt_spell_large( _int ) * " con " elseif dict in ( :short, ) - intres = pt_BR_spell_short( _int ) * " con " + intres = pt_PT_spell_short( _int ) * " con " else throw( error( "unrecognized dict value: $dict" ) ) end - decres = pt_br_spell_decimal( abs( _dec ) ) + decres = pt_pt_spell_decimal( abs( _dec ) ) return intres * decres end end @@ -137,6 +141,3 @@ end - - - diff --git a/src/pt/pt_pt.jl b/src/pt/pt_pt.jl new file mode 100644 index 00000000..816514b3 --- /dev/null +++ b/src/pt/pt_pt.jl @@ -0,0 +1,82 @@ +const pt_PT_1_a_19 =[ + "um" + "dois" + "três" + "quatro" + "cinco" + "seis" + "sete" + "oito" + "nove" + "dez" + "onze" + "doze" + "treze" + "catorze" + "quinze" + "dezasseis" + "dezassete" + "dezoito" + "dezanove" +] + +const pt_PT_dezenas = [ + "" + "vinte" + "trinta" + "quarenta" + "cinquenta" + "sessenta" + "setenta" + "oitenta" + "noventa" +] + +const pt_PT_centenas = [ + "cento" + "duzentos" + "trezentos" + "quatrocentos" + "quinhentos" + "seiscentos" + "setecentos" + "oitocentos" + "novecentos" +] + +const pt_PT_multiplos_1e6_singular = [ + "milhão" + "bilião" + "trilião" + "quatrilião" + "quintilião" + "sextilião" + "septilião" + "oitolião" + "nonilião" + "decilião" + "undecilião" + "duodecilião" +] + +const pt_PT_multiplos_1e6_plural = [ + "milhões" + "biliões" + "triliões" + "quatriliões" + "quintiliões" + "sextiliões" + "septiliões" + "oitoliões" + "noniliões" + "deciliões" + "undeciliões" + "duodeciliões" +] + +const pt_PT_decimais = [ + "décimo" + "centésimo" + "milésimo" + "milionésimo" +] \ No newline at end of file diff --git a/src/pt/standard_pt_br.jl b/src/pt/standard_pt_br.jl index 80aeb799..22f6441e 100644 --- a/src/pt/standard_pt_br.jl +++ b/src/pt/standard_pt_br.jl @@ -12,7 +12,7 @@ const pt_BR_1_a_19 =[ "onze" "doze" "treze" - "catorze" + "quatorze" "quinze" "dezesseis" "dezessete" @@ -44,6 +44,10 @@ const pt_BR_centenas = [ "novecentos" ] +const centenas_dicionario = Number[ + 200, 300, 400, 500, 600, 700, 800, 900 +] + const pt_BR_multiplos_1e6_singular = [ "milhão" "bilhão" diff --git a/src/pt_BR.jl b/src/pt_BR.jl new file mode 100644 index 00000000..c4e7dedb --- /dev/null +++ b/src/pt_BR.jl @@ -0,0 +1,139 @@ +include(joinpath(@__DIR__, "pt", "standard_pt_br.jl")) + +## Implement Spelled Out for Brazilian Portuguese + +#retuns a vector of ints, each of that +function split_numbers_10³( num::Integer ) + digits( num, base = 10^3) +end + +function split_numbers_10⁶( num::Integer ) + digits( num, base = 10^6) +end + +#function +function pt_br_spell_1e3( number, short_one = false ) + if number <= 99 #0 - 99 + if number < 20 #1 - 20 + iszero(number) && return "" + if isone(number) && short_one + return "um" + else + return pt_BR_1_a_19[ number ] + end + else #20-99 + unit, dec = digits( number ) + if isone( unit ) && short_one + unit_text = " e um" + elseif iszero( unit ) + unit_text = "" + else + unit_text = " e " * pt_BR_1_a_19[ unit ] + end + return pt_BR_dezenas[ dec ] * unit_text + end + elseif number ∈ centenas_dicionario + unit, cent = digits( number, base = 100 ) + unit_text = pt_br_spell_1e3( unit, short_one ) + return pt_BR_centenas[ cent ] + elseif 100 <= number <= 999 + number == 100 && return "cem" + unit, cent = digits( number, base = 100 ) + unit_text = pt_br_spell_1e3( unit, short_one ) + return pt_BR_centenas[ cent ] * " e " * unit_text + end +end + +function pt_br_spell_1e6( number, short_one = false ) + number = Int( number ) + number == 0 && return "" + number == 1000 && return "mil" + number <= 999 && return pt_br_spell_1e3( number, short_one ) + low,high = digits( number, base = 1000 ) + low_txt = pt_br_spell_1e3( low, short_one ) + if high == 1 + high_text = "mil e " + else + high_text = pt_br_spell_1e3( high, false ) * " mil" + end + return high_text * low_txt +end + +#spells only decimals, including 0 +function pt_br_spell_decimal( number, partitive = true ) + whole, decimal = split( string( number ), "." ) + decnum, wholenum = abs.( modf( number ) ) + decimal_length = length( decimal ) + decint = decnum*10^decimal_length + if partitive + if decimal_length > 6 + throw(error("""partitive pronunciation of Brazilian Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . + If you want english-like decimals (zero ponto dois), try using partitive = false. + If the decimal part seems to differ from the perceived input number, try using big numbers: `big"123.23"`. + """)) + end + + dectext = pt_br_spell_1e6( Dec128( decint ), false ) + res = strip( dectext ) * " " * pt_BR_decimais[ decimal_length ] + if decint != 1 + res = res * "s" + end + return res + else + res = digits( decint ) .|> z-> pt_br_spell_1e3( z, true ) .|> strip |> reverse |> z-> join( z," " ) + res = "ponto " * res + end +end + +function pt_br_spell_large_map( number, i ) + if isone( i ) + return pt_br_spell_1e6( number, true ) + elseif isone( number ) + return "um " * pt_BR_multiplos_1e6_singular[ i - 1 ] + else + return pt_br_spell_1e6( number, false ) + end +end + +function pt_br_spell_large( _number ) + number = abs( _number ) + list = digits( number, base = 1_000_000 ) + res = pt_br_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) + ( _number < 0 ) && ( res = "menos " * res ) + return res +end + +function spelled_out_pt_br( number; dict = :standard ) + if iszero( number ) + return "zero" + end + if isinteger( number ) + if dict in ( :standard, :large, :modern ) + res = pt_br_spell_large( number ) + elseif dict in (:short,) + res = pt_BR_spell_short( number ) + else + throw( error( "unrecognized dict value: $dict" ) ) + end + return res + else #with decimals + partitive = true + _dec, _int = modf( number ) + _int = Dec128( _int ) + if ( _int == 0 ) & !partitive + intres = "zero" + + elseif ( _int == 0 ) & partitive + intres = "" + elseif dict in ( :standard, :large, :modern ) + intres = pt_br_spell_large( _int ) * " con " + elseif dict in ( :short, ) + intres = pt_BR_spell_short( _int ) * " con " + else + throw( error( "unrecognized dict value: $dict" ) ) + end + + decres = pt_br_spell_decimal( abs( _dec ) ) + return intres * decres + end +end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 4d31816e..329e9bc9 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -49,6 +49,16 @@ end @test spelled_out(-109, lang = :pt_BR) == "menos cento e nove" @test spelled_out(100, lang = :pt_BR) == "cem" @test spelled_out(105, lang = :pt_BR) == "cento e cinco" + @test spelled_out(19, lang = :pt_BR) == "dezenove" + @test spelled_out(14, lang = :pt_BR) == "quatorze" + @test spelled_out(585000, lang = :pt) == "quinhentos e oitenta e cinco mil" + @test spelled_out(200, lang = :pt) == "duzentos" + @test spelled_out(19, lang = :pt) == "dezanove" + @test spelled_out(0.9, lang = :pt) == "nove décimos" + @test spelled_out(14, lang = :pt) == "catorze" + @test spelled_out(-10, lang = :pt) == "menos dez" + @test spelled_out(-109, lang = :pt) == "menos cento e nove" + @test spelled_out(105, lang = :pt) == "cento e cinco" end nothing From 1ea43b48c391f1d69640317ae04af291b45ebea9 Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Mon, 6 Jun 2022 20:33:07 -0300 Subject: [PATCH 069/120] implementing pt-PT and pt-BR together --- src/SpelledOut.jl | 5 +- src/pt.jl | 91 +++++++++++++++++------------- src/pt_BR.jl | 139 ---------------------------------------------- 3 files changed, 55 insertions(+), 180 deletions(-) delete mode 100644 src/pt_BR.jl diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index b2227a31..1244e0f7 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -8,7 +8,6 @@ export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") include("es.jl") include("pt.jl") -include("pt_BR.jl") """ ```julia @@ -61,9 +60,9 @@ function spelled_out( elseif lang ∈ (:es,) return spelled_out_es(number; dict = dict) elseif lang ∈ (:pt_BR,) - return spelled_out_pt_br(number; dict = dict) + return spelled_out_pt(number; portugal = false, dict = dict) elseif lang ∈ (:pt,) - return spelled_out_pt_pt(number; dict = dict) + return spelled_out_pt(number; portugal = true, dict = dict) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) diff --git a/src/pt.jl b/src/pt.jl index 02654f38..6d775582 100644 --- a/src/pt.jl +++ b/src/pt.jl @@ -1,6 +1,7 @@ +include(joinpath(@__DIR__, "pt", "standard_pt_br.jl")) include(joinpath(@__DIR__, "pt", "pt_pt.jl")) -## Implement Spelled Out for Portugal Portuguese +## Implement Spelled Out for Brazilian Portuguese and Portugal Portuguese #retuns a vector of ints, each of that function split_numbers_10³( num::Integer ) @@ -11,107 +12,123 @@ function split_numbers_10⁶( num::Integer ) digits( num, base = 10^6) end -#function -function pt_pt_spell_1e3( number, short_one = false ) +#function +function pt_spell_1e3( number; short_one = false, portugal::Bool = false ) if number <= 99 #0 - 99 - if number < 20 #1 - 20 - iszero(number) && return "" - if isone(number) && short_one + if number < 20 #1 - 19 + iszero( number ) && return "" + if isone( number ) && short_one return "um" + elseif portugal + return pt_PT_1_a_19[ number ] else - return pt_PT_1_a_19[ number ] - end + return pt_BR_1_a_19[ number ] + end else #20-99 unit, dec = digits( number ) if isone( unit ) && short_one unit_text = " e um" elseif iszero( unit ) unit_text = "" + elseif portugal + unit_text = " e " * pt_PT_1_a_19[ unit ] else - unit_text = " e " * pt_PT_1_a_19[ unit ] + unit_text = " e " * pt_BR_1_a_19[ unit ] end - return pt_PT_dezenas[ dec ] * unit_text + println( pt_BR_dezenas[ dec ] * unit_text ) end elseif number ∈ centenas_dicionario unit, cent = digits( number, base = 100 ) - unit_text = pt_pt_spell_1e3( unit, short_one ) - return pt_PT_centenas[ cent ] - elseif 100 <= number <= 999 + unit_text = pt_spell_1e3( unit; short_one ) + return pt_BR_centenas[ cent ] + elseif portugal == false & 100 <= number <= 999 + number == 100 && return "cem" + unit, cent = digits( number, base = 100 ) + unit_text = pt_spell_1e3( unit; short_one ) + return pt_BR_centenas[ cent ] * " e " * unit_text + elseif portugal & 100 <= number <= 999 number == 100 && return "cem" unit, cent = digits( number, base = 100 ) - unit_text = pt_pt_spell_1e3( unit, short_one ) + unit_text = pt_spell_1e3( unit; short_one, portugal = portugal ) return pt_PT_centenas[ cent ] * " e " * unit_text end end -function pt_pt_spell_1e6( number, short_one = false ) +function pt_spell_1e6( number; short_one = false, portugal::Bool = false ) number = Int( number ) number == 0 && return "" number == 1000 && return "mil" - number <= 999 && return pt_pt_spell_1e3( number, short_one ) + number <= 999 && return pt_spell_1e3( number; short_one = short_one, portugal = portugal ) low,high = digits( number, base = 1000 ) - low_txt = pt_pt_spell_1e3( low, short_one ) + low_txt = pt_spell_1e3( low; short_one = short_one, portugal = portugal ) if high == 1 high_text = "mil e " else - high_text = pt_pt_spell_1e3( high, false ) * " mil" + high_text = pt_spell_1e3( high; short_one = false, portugal = portugal ) * " mil" end return high_text * low_txt end #spells only decimals, including 0 -function pt_pt_spell_decimal( number, partitive = true ) +function pt_spell_decimal( number, partitive = true; portugal::Bool = false ) whole, decimal = split( string( number ), "." ) decnum, wholenum = abs.( modf( number ) ) decimal_length = length( decimal ) decint = decnum*10^decimal_length if partitive if decimal_length > 6 - throw(error("""partitive pronunciation of Portugal Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . + throw(error("""partitive pronunciation of Brazilian Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . If you want english-like decimals (zero ponto dois), try using partitive = false. If the decimal part seems to differ from the perceived input number, try using big numbers: `big"123.23"`. """)) end - dectext = pt_pt_spell_1e6( Dec128( decint ), false ) - res = strip( dectext ) * " " * pt_PT_decimais[ decimal_length ] + dectext = pt_spell_1e6( Dec128( decint ); short_one = false, portugal = portugal ) + res = strip( dectext ) * " " * pt_BR_decimais[ decimal_length ] if decint != 1 res = res * "s" end return res else - res = digits( decint ) .|> z-> pt_pt_spell_1e3( z, true ) .|> strip |> reverse |> z-> join( z," " ) + res = digits( decint ) .|> z-> pt_spell_1e3( z; short_one = true, portugal = portugal ) .|> strip |> reverse |> z-> join( z," " ) res = "ponto " * res end end -function pt_pt_spell_large_map( number, i ) +function pt_spell_large_map( number, i; portugal::Bool = false ) if isone( i ) - return pt_pt_spell_1e6( number, true ) - elseif isone( number ) + return pt_spell_1e6( number; short_one = true, portugal = portugal ) + elseif portugal == false & isone( number ) + return "um " * pt_BR_multiplos_1e6_singular[ i - 1 ] + elseif portugal & isone( number ) return "um " * pt_PT_multiplos_1e6_singular[ i - 1 ] else - return pt_pt_spell_1e6( number, false ) + return pt_spell_1e6( number; short_one = false, portugal = portugal ) * " " * pt_PT_multiplos_1e6_plural[ i - 1 ] end end -function pt_pt_spell_large( _number ) +function pt_spell_large( _number; portugal::Bool = false ) number = abs( _number ) list = digits( number, base = 1_000_000 ) - res = pt_pt_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) - ( _number < 0 ) && ( res = "menos " * res ) + if portugal + res = pt_spell_large_map.( list, 1:length( list ), portugal = portugal ) .|> strip |> reverse |> z-> join( z," " ) + ( _number < 0 ) && ( res = "menos " * res ) + else + res = pt_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) + ( _number < 0 ) && ( res = "menos " * res ) + end return res end -function spelled_out_pt_pt( number; dict = :standard ) +function spelled_out_pt( number; portugal::Bool = false, dict::Symbol = :standard ) if iszero( number ) return "zero" end if isinteger( number ) if dict in ( :standard, :large, :modern ) - res = pt_pt_spell_large( number ) + res = pt_spell_large( number; portugal = portugal ) elseif dict in (:short,) - res = pt_pt_spell_short( number ) + res = pt_spell_short( number; portugal = portugal ) else throw( error( "unrecognized dict value: $dict" ) ) end @@ -126,18 +143,16 @@ function spelled_out_pt_pt( number; dict = :standard ) elseif ( _int == 0 ) & partitive intres = "" elseif dict in ( :standard, :large, :modern ) - intres = pt_pt_spell_large( _int ) * " con " + intres = pt_spell_large( _int; portugal = portugal ) * " con " elseif dict in ( :short, ) - intres = pt_PT_spell_short( _int ) * " con " + intres = pt_spell_short( _int; portugal = portugal ) * " con " else throw( error( "unrecognized dict value: $dict" ) ) end - decres = pt_pt_spell_decimal( abs( _dec ) ) + decres = pt_spell_decimal( abs( _dec ); portugal = portugal ) return intres * decres end end - - diff --git a/src/pt_BR.jl b/src/pt_BR.jl deleted file mode 100644 index c4e7dedb..00000000 --- a/src/pt_BR.jl +++ /dev/null @@ -1,139 +0,0 @@ -include(joinpath(@__DIR__, "pt", "standard_pt_br.jl")) - -## Implement Spelled Out for Brazilian Portuguese - -#retuns a vector of ints, each of that -function split_numbers_10³( num::Integer ) - digits( num, base = 10^3) -end - -function split_numbers_10⁶( num::Integer ) - digits( num, base = 10^6) -end - -#function -function pt_br_spell_1e3( number, short_one = false ) - if number <= 99 #0 - 99 - if number < 20 #1 - 20 - iszero(number) && return "" - if isone(number) && short_one - return "um" - else - return pt_BR_1_a_19[ number ] - end - else #20-99 - unit, dec = digits( number ) - if isone( unit ) && short_one - unit_text = " e um" - elseif iszero( unit ) - unit_text = "" - else - unit_text = " e " * pt_BR_1_a_19[ unit ] - end - return pt_BR_dezenas[ dec ] * unit_text - end - elseif number ∈ centenas_dicionario - unit, cent = digits( number, base = 100 ) - unit_text = pt_br_spell_1e3( unit, short_one ) - return pt_BR_centenas[ cent ] - elseif 100 <= number <= 999 - number == 100 && return "cem" - unit, cent = digits( number, base = 100 ) - unit_text = pt_br_spell_1e3( unit, short_one ) - return pt_BR_centenas[ cent ] * " e " * unit_text - end -end - -function pt_br_spell_1e6( number, short_one = false ) - number = Int( number ) - number == 0 && return "" - number == 1000 && return "mil" - number <= 999 && return pt_br_spell_1e3( number, short_one ) - low,high = digits( number, base = 1000 ) - low_txt = pt_br_spell_1e3( low, short_one ) - if high == 1 - high_text = "mil e " - else - high_text = pt_br_spell_1e3( high, false ) * " mil" - end - return high_text * low_txt -end - -#spells only decimals, including 0 -function pt_br_spell_decimal( number, partitive = true ) - whole, decimal = split( string( number ), "." ) - decnum, wholenum = abs.( modf( number ) ) - decimal_length = length( decimal ) - decint = decnum*10^decimal_length - if partitive - if decimal_length > 6 - throw(error("""partitive pronunciation of Brazilian Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . - If you want english-like decimals (zero ponto dois), try using partitive = false. - If the decimal part seems to differ from the perceived input number, try using big numbers: `big"123.23"`. - """)) - end - - dectext = pt_br_spell_1e6( Dec128( decint ), false ) - res = strip( dectext ) * " " * pt_BR_decimais[ decimal_length ] - if decint != 1 - res = res * "s" - end - return res - else - res = digits( decint ) .|> z-> pt_br_spell_1e3( z, true ) .|> strip |> reverse |> z-> join( z," " ) - res = "ponto " * res - end -end - -function pt_br_spell_large_map( number, i ) - if isone( i ) - return pt_br_spell_1e6( number, true ) - elseif isone( number ) - return "um " * pt_BR_multiplos_1e6_singular[ i - 1 ] - else - return pt_br_spell_1e6( number, false ) - end -end - -function pt_br_spell_large( _number ) - number = abs( _number ) - list = digits( number, base = 1_000_000 ) - res = pt_br_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) - ( _number < 0 ) && ( res = "menos " * res ) - return res -end - -function spelled_out_pt_br( number; dict = :standard ) - if iszero( number ) - return "zero" - end - if isinteger( number ) - if dict in ( :standard, :large, :modern ) - res = pt_br_spell_large( number ) - elseif dict in (:short,) - res = pt_BR_spell_short( number ) - else - throw( error( "unrecognized dict value: $dict" ) ) - end - return res - else #with decimals - partitive = true - _dec, _int = modf( number ) - _int = Dec128( _int ) - if ( _int == 0 ) & !partitive - intres = "zero" - - elseif ( _int == 0 ) & partitive - intres = "" - elseif dict in ( :standard, :large, :modern ) - intres = pt_br_spell_large( _int ) * " con " - elseif dict in ( :short, ) - intres = pt_BR_spell_short( _int ) * " con " - else - throw( error( "unrecognized dict value: $dict" ) ) - end - - decres = pt_br_spell_decimal( abs( _dec ) ) - return intres * decres - end -end \ No newline at end of file From effd44c4797553bef8880b7d13d088fa10a2f3d7 Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Mon, 6 Jun 2022 20:58:50 -0300 Subject: [PATCH 070/120] Included pt on the supported language file --- docs/src/supported_languages.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/supported_languages.md b/docs/src/supported_languages.md index 04210599..b540936f 100644 --- a/docs/src/supported_languages.md +++ b/docs/src/supported_languages.md @@ -10,3 +10,4 @@ Current languages to choose from are: - Portuguese - Variants - (`:pt_BR`) + - (`:pt`) From 200978e0654f6f3b03e06a2d5dbbcce770b65c8c Mon Sep 17 00:00:00 2001 From: Gabrielforest Date: Mon, 20 Jun 2022 23:12:26 -0300 Subject: [PATCH 071/120] fixing print error --- src/pt.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pt.jl b/src/pt.jl index 6d775582..caba8b0b 100644 --- a/src/pt.jl +++ b/src/pt.jl @@ -33,9 +33,9 @@ function pt_spell_1e3( number; short_one = false, portugal::Bool = false ) elseif portugal unit_text = " e " * pt_PT_1_a_19[ unit ] else - unit_text = " e " * pt_BR_1_a_19[ unit ] + unit_text = " e " * pt_BR_1_a_19[ unit ] end - println( pt_BR_dezenas[ dec ] * unit_text ) + return pt_BR_dezenas[ dec ] * unit_text end elseif number ∈ centenas_dicionario unit, cent = digits( number, base = 100 ) @@ -77,7 +77,7 @@ function pt_spell_decimal( number, partitive = true; portugal::Bool = false ) decint = decnum*10^decimal_length if partitive if decimal_length > 6 - throw(error("""partitive pronunciation of Brazilian Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . + throw(error("""partitive pronunciation of Portuguese decimals is only supported to up to six decimals, the decimal part is $decimal . If you want english-like decimals (zero ponto dois), try using partitive = false. If the decimal part seems to differ from the perceived input number, try using big numbers: `big"123.23"`. """)) From fe7aee776a52fe833e9f28bddea6472ab44e44aa Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 21 Jun 2022 14:55:46 +1200 Subject: [PATCH 072/120] =?UTF-8?q?WIP:=20Implement=20spelled=20out=20for?= =?UTF-8?q?=20M=C4=81ori?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++ src/.#mi.jl | 1 + src/SpelledOut.jl | 3 ++ src/mi.jl | 46 +++++++++++++++++ src/mi/standard_dictionary_numbers_mi.jl | 13 +++++ test/runtests.jl | 65 ++++++++++++++++++++++++ 6 files changed, 132 insertions(+) create mode 120000 src/.#mi.jl create mode 100644 src/mi.jl create mode 100644 src/mi/standard_dictionary_numbers_mi.jl diff --git a/README.md b/README.md index 31532556..f17fad28 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,7 @@ ## Description This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, to write out in **long hand**, and — as a great mind once suggested — to **transnumerate**. + +## Contributing + +Each new language will require a language code to use it. This code is determined by [https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php](ISO-639-1).[[1]](https://www.wikiwand.com/en/ISO_639-1) \ No newline at end of file diff --git a/src/.#mi.jl b/src/.#mi.jl new file mode 120000 index 00000000..8850b414 --- /dev/null +++ b/src/.#mi.jl @@ -0,0 +1 @@ +jakeireland@jake-mbp2017.local.35989 \ No newline at end of file diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 8fce9543..ae486e54 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -7,6 +7,7 @@ export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") include("es.jl") +include("mi.jl") """ ```julia @@ -52,6 +53,8 @@ function spelled_out( return spelled_out_en(number, british = true, dict = dict) elseif lang ∈ (:es,) return spelled_out_es(number,dict) + elseif lang ∈ (:mi,) + return spelled_out_mi(number) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) diff --git a/src/mi.jl b/src/mi.jl new file mode 100644 index 00000000..b17adfa7 --- /dev/null +++ b/src/mi.jl @@ -0,0 +1,46 @@ +include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) + +function ones_convert_mi(n::I) where {I <: Integer} + @assert(n ≤ 10, "The internal function \"ones_convert_mi\" should only be used for numbers ≤ 10; number provided: $n") + return _mi_small_numbers[n + 1] +end + +function tens_convert_mi(n::I) where {I <: Integer} + @assert(10 < n < 20, "The internal function \"tens_convert_mi\" should only be used for numbers 10 < n < 20; number provided: $n") + return "$_mi_ten $_mi_ma $(ones_convert_mi(n - 10))" +end + +function small_convert_mi(n::I) where {I <: Integer} + @assert(n < 1000, "The internal function \"small_convert_mi\" should only be used for numbers < 1000; number provided: $n") + # 11, 12, ..., 19 + n < 20 && return tens_convert_mi(n) + # 10, 20, ..., 90 + s = "$(ones_convert_mi(fld(n, 10))) $(_mi_scale[1])" + if iszero(mod(n, 10)) && n < 100 + return s + end + + s *= " $_mi_ma " + # n′ = fld(n, 10) + n′ = mod(n, 10) + # while !iszero(n) + while (n - rem(n, n′)) != n′ + s += " $(ones_convert_mi(n))" + n′ = mod(n′, 10) + # s += " $(small_convert_mi(n))" + # _mi_ma + # ones_convert_mi(fld(n, 10)), _mi_scale[1] + # m = mod(n, 10v) + # return s * small_convert_mi(m) + end + return s +end + +function spelled_out_mi(n::I) where {I <: Integer} + # 1, 2, ..., 10 + n ≤ 10 && return ones_convert_mi(n) + # 11, 12, ..., 999 + n < 1000 && return small_convert_mi(n) + # 1000, ... + error("not yet implemented") +end diff --git a/src/mi/standard_dictionary_numbers_mi.jl b/src/mi/standard_dictionary_numbers_mi.jl new file mode 100644 index 00000000..a07728a6 --- /dev/null +++ b/src/mi/standard_dictionary_numbers_mi.jl @@ -0,0 +1,13 @@ +const _mi_ten = "tekau" +const _mi_ma = "mā" + +const _mi_small_numbers = String[ + "kore", "tahi", "rua", "toru", "whā", "rima", "ono", "whitu", "waru", "iwa", _mi_ten +] + +const _mi_100 = "kotahi" + +const _mi_scale = String[ + _mi_ten, "rau", "mano", "miriona", "piriona" +] + diff --git a/test/runtests.jl b/test/runtests.jl index 666282f8..54a3ff32 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -41,4 +41,69 @@ end end +@testset "Māori" begin + # Source: https://www.maori.cl/learn/numbers.htm + @test spelled_out(0, lang = :mi) == "kore" + @test spelled_out(1, lang = :mi) == "tahi" + @test spelled_out(2, lang = :mi) == "rua" + @test spelled_out(3, lang = :mi) == "toru" + @test spelled_out(4, lang = :mi) == "whā" + @test spelled_out(5, lang = :mi) == "rima" + @test spelled_out(6, lang = :mi) == "ono" + @test spelled_out(7, lang = :mi) == "whitu" + @test spelled_out(8, lang = :mi) == "waru" + @test spelled_out(9, lang = :mi) == "iwa" + @test spelled_out(10, lang = :mi) == "tekau" + @test spelled_out(11, lang = :mi) == "tekau mā tahi" + @test spelled_out(12, lang = :mi) == "tekau mā rua" + @test spelled_out(13, lang = :mi) == "tekau mā toru" + @test spelled_out(14, lang = :mi) == "tekau mā whā" + @test spelled_out(15, lang = :mi) == "tekau mā rima" + @test spelled_out(16, lang = :mi) == "tekau mā ono" + @test spelled_out(17, lang = :mi) == "tekau mā whitu" + @test spelled_out(18, lang = :mi) == "tekau mā waru" + @test spelled_out(19, lang = :mi) == "tekau mā iwa" + @test spelled_out(20, lang = :mi) == "rua tekau" + @test spelled_out(21, lang = :mi) == "rua tekau mā tahi" + @test spelled_out(22, lang = :mi) == "rua tekau mā rua" + @test spelled_out(23, lang = :mi) == "rua tekau mā toru" + @test spelled_out(30, lang = :mi) == "toru tekau" + @test spelled_out(35, lang = :mi) == "" # TODO + @test spelled_out(40, lang = :mi) == "whā tekau" + @test spelled_out(50, lang = :mi) == "rima tekau" + @test spelled_out(60, lang = :mi) == "ono tekau" + @test spelled_out(70, lang = :mi) == "whitu tekau" + @test spelled_out(80, lang = :mi) == "waru tekau" + @test spelled_out(90, lang = :mi) == "iwa tekau" + @test spelled_out(100, lang = :mi) == "kotahi rau" + @test spelled_out(101, lang = :mi) == "kotahi rau tahi" + @test spelled_out(111, lang = :mi) == "kotahi rau tekau mā tahi" + @test spelled_out(200, lang = :mi) == "rua rau" + @test spelled_out(234, lang = :mi) == "rua rau toru tekau mā whā" + @test spelled_out(300, lang = :mi) == "toru rau" + @test spelled_out(400, lang = :mi) == "whā rau" + @test spelled_out(500, lang = :mi) == "rima rau" + @test spelled_out(600, lang = :mi) == "ono rau" + @test spelled_out(700, lang = :mi) == "whitu rau" + @test spelled_out(800, lang = :mi) == "waru rau" + @test spelled_out(900, lang = :mi) == "iwa rau" + @test spelled_out(1000, lang = :mi) == "kotahi mano" + @test spelled_out(1982, lang = :mi) == "kotahi mano, iwa rau, waru tekau mā rua" + @test spelled_out(2000, lang = :mi) == "rua mano" + @test spelled_out(2016, lang = :mi) == "rua mano, tekau mā ono" + @test spelled_out(2022, lang = :mi) == "" # TODO + @test spelled_out(3000, lang = :mi) == "toru mano" + @test spelled_out(4000, lang = :mi) == "whā mano" + @test spelled_out(5000, lang = :mi) == "rima mano" + @test spelled_out(6000, lang = :mi) == "ono mano" + @test spelled_out(7000, lang = :mi) == "whitu mano" + @test spelled_out(8000, lang = :mi) == "waru mano" + @test spelled_out(9000, lang = :mi) == "iwa mano" + @test spelled_out(9100, lang = :mi) == "" # TODO + @test spelled_out(10_000, lang = :mi) == "tekau mano" + @test spelled_out(1_000_000, lang = :mi) == "kotahi miriona" + @test spelled_out(2_000_000, lang = :mi) == "rua miriona" + @test spelled_out(3_000_000_000, lang = :mi) == "toru piriona" +end + nothing From 5fd574cb0a73f13f7150aa2eaf3e222d55ef459d Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 21 Jun 2022 14:55:46 +1200 Subject: [PATCH 073/120] =?UTF-8?q?WIP:=20Implement=20spelled=20out=20for?= =?UTF-8?q?=20M=C4=81ori?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++ src/.#mi.jl | 1 + src/SpelledOut.jl | 3 ++ src/mi.jl | 46 +++++++++++++++++ src/mi/standard_dictionary_numbers_mi.jl | 13 +++++ test/runtests.jl | 65 ++++++++++++++++++++++++ 6 files changed, 132 insertions(+) create mode 120000 src/.#mi.jl create mode 100644 src/mi.jl create mode 100644 src/mi/standard_dictionary_numbers_mi.jl diff --git a/README.md b/README.md index 31532556..f17fad28 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,7 @@ ## Description This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, to write out in **long hand**, and — as a great mind once suggested — to **transnumerate**. + +## Contributing + +Each new language will require a language code to use it. This code is determined by [https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php](ISO-639-1).[[1]](https://www.wikiwand.com/en/ISO_639-1) \ No newline at end of file diff --git a/src/.#mi.jl b/src/.#mi.jl new file mode 120000 index 00000000..8850b414 --- /dev/null +++ b/src/.#mi.jl @@ -0,0 +1 @@ +jakeireland@jake-mbp2017.local.35989 \ No newline at end of file diff --git a/src/SpelledOut.jl b/src/SpelledOut.jl index 8fce9543..ae486e54 100644 --- a/src/SpelledOut.jl +++ b/src/SpelledOut.jl @@ -7,6 +7,7 @@ export spelled_out, Spelled_out, Spelled_Out, SPELLED_OUT include("en.jl") include("es.jl") +include("mi.jl") """ ```julia @@ -52,6 +53,8 @@ function spelled_out( return spelled_out_en(number, british = true, dict = dict) elseif lang ∈ (:es,) return spelled_out_es(number,dict) + elseif lang ∈ (:mi,) + return spelled_out_mi(number) end throw(error("We do not support $lang yet. Please make an issue and someone might be able to help you, or feel free to contribute.")) diff --git a/src/mi.jl b/src/mi.jl new file mode 100644 index 00000000..b17adfa7 --- /dev/null +++ b/src/mi.jl @@ -0,0 +1,46 @@ +include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) + +function ones_convert_mi(n::I) where {I <: Integer} + @assert(n ≤ 10, "The internal function \"ones_convert_mi\" should only be used for numbers ≤ 10; number provided: $n") + return _mi_small_numbers[n + 1] +end + +function tens_convert_mi(n::I) where {I <: Integer} + @assert(10 < n < 20, "The internal function \"tens_convert_mi\" should only be used for numbers 10 < n < 20; number provided: $n") + return "$_mi_ten $_mi_ma $(ones_convert_mi(n - 10))" +end + +function small_convert_mi(n::I) where {I <: Integer} + @assert(n < 1000, "The internal function \"small_convert_mi\" should only be used for numbers < 1000; number provided: $n") + # 11, 12, ..., 19 + n < 20 && return tens_convert_mi(n) + # 10, 20, ..., 90 + s = "$(ones_convert_mi(fld(n, 10))) $(_mi_scale[1])" + if iszero(mod(n, 10)) && n < 100 + return s + end + + s *= " $_mi_ma " + # n′ = fld(n, 10) + n′ = mod(n, 10) + # while !iszero(n) + while (n - rem(n, n′)) != n′ + s += " $(ones_convert_mi(n))" + n′ = mod(n′, 10) + # s += " $(small_convert_mi(n))" + # _mi_ma + # ones_convert_mi(fld(n, 10)), _mi_scale[1] + # m = mod(n, 10v) + # return s * small_convert_mi(m) + end + return s +end + +function spelled_out_mi(n::I) where {I <: Integer} + # 1, 2, ..., 10 + n ≤ 10 && return ones_convert_mi(n) + # 11, 12, ..., 999 + n < 1000 && return small_convert_mi(n) + # 1000, ... + error("not yet implemented") +end diff --git a/src/mi/standard_dictionary_numbers_mi.jl b/src/mi/standard_dictionary_numbers_mi.jl new file mode 100644 index 00000000..a07728a6 --- /dev/null +++ b/src/mi/standard_dictionary_numbers_mi.jl @@ -0,0 +1,13 @@ +const _mi_ten = "tekau" +const _mi_ma = "mā" + +const _mi_small_numbers = String[ + "kore", "tahi", "rua", "toru", "whā", "rima", "ono", "whitu", "waru", "iwa", _mi_ten +] + +const _mi_100 = "kotahi" + +const _mi_scale = String[ + _mi_ten, "rau", "mano", "miriona", "piriona" +] + diff --git a/test/runtests.jl b/test/runtests.jl index 666282f8..54a3ff32 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -41,4 +41,69 @@ end end +@testset "Māori" begin + # Source: https://www.maori.cl/learn/numbers.htm + @test spelled_out(0, lang = :mi) == "kore" + @test spelled_out(1, lang = :mi) == "tahi" + @test spelled_out(2, lang = :mi) == "rua" + @test spelled_out(3, lang = :mi) == "toru" + @test spelled_out(4, lang = :mi) == "whā" + @test spelled_out(5, lang = :mi) == "rima" + @test spelled_out(6, lang = :mi) == "ono" + @test spelled_out(7, lang = :mi) == "whitu" + @test spelled_out(8, lang = :mi) == "waru" + @test spelled_out(9, lang = :mi) == "iwa" + @test spelled_out(10, lang = :mi) == "tekau" + @test spelled_out(11, lang = :mi) == "tekau mā tahi" + @test spelled_out(12, lang = :mi) == "tekau mā rua" + @test spelled_out(13, lang = :mi) == "tekau mā toru" + @test spelled_out(14, lang = :mi) == "tekau mā whā" + @test spelled_out(15, lang = :mi) == "tekau mā rima" + @test spelled_out(16, lang = :mi) == "tekau mā ono" + @test spelled_out(17, lang = :mi) == "tekau mā whitu" + @test spelled_out(18, lang = :mi) == "tekau mā waru" + @test spelled_out(19, lang = :mi) == "tekau mā iwa" + @test spelled_out(20, lang = :mi) == "rua tekau" + @test spelled_out(21, lang = :mi) == "rua tekau mā tahi" + @test spelled_out(22, lang = :mi) == "rua tekau mā rua" + @test spelled_out(23, lang = :mi) == "rua tekau mā toru" + @test spelled_out(30, lang = :mi) == "toru tekau" + @test spelled_out(35, lang = :mi) == "" # TODO + @test spelled_out(40, lang = :mi) == "whā tekau" + @test spelled_out(50, lang = :mi) == "rima tekau" + @test spelled_out(60, lang = :mi) == "ono tekau" + @test spelled_out(70, lang = :mi) == "whitu tekau" + @test spelled_out(80, lang = :mi) == "waru tekau" + @test spelled_out(90, lang = :mi) == "iwa tekau" + @test spelled_out(100, lang = :mi) == "kotahi rau" + @test spelled_out(101, lang = :mi) == "kotahi rau tahi" + @test spelled_out(111, lang = :mi) == "kotahi rau tekau mā tahi" + @test spelled_out(200, lang = :mi) == "rua rau" + @test spelled_out(234, lang = :mi) == "rua rau toru tekau mā whā" + @test spelled_out(300, lang = :mi) == "toru rau" + @test spelled_out(400, lang = :mi) == "whā rau" + @test spelled_out(500, lang = :mi) == "rima rau" + @test spelled_out(600, lang = :mi) == "ono rau" + @test spelled_out(700, lang = :mi) == "whitu rau" + @test spelled_out(800, lang = :mi) == "waru rau" + @test spelled_out(900, lang = :mi) == "iwa rau" + @test spelled_out(1000, lang = :mi) == "kotahi mano" + @test spelled_out(1982, lang = :mi) == "kotahi mano, iwa rau, waru tekau mā rua" + @test spelled_out(2000, lang = :mi) == "rua mano" + @test spelled_out(2016, lang = :mi) == "rua mano, tekau mā ono" + @test spelled_out(2022, lang = :mi) == "" # TODO + @test spelled_out(3000, lang = :mi) == "toru mano" + @test spelled_out(4000, lang = :mi) == "whā mano" + @test spelled_out(5000, lang = :mi) == "rima mano" + @test spelled_out(6000, lang = :mi) == "ono mano" + @test spelled_out(7000, lang = :mi) == "whitu mano" + @test spelled_out(8000, lang = :mi) == "waru mano" + @test spelled_out(9000, lang = :mi) == "iwa mano" + @test spelled_out(9100, lang = :mi) == "" # TODO + @test spelled_out(10_000, lang = :mi) == "tekau mano" + @test spelled_out(1_000_000, lang = :mi) == "kotahi miriona" + @test spelled_out(2_000_000, lang = :mi) == "rua miriona" + @test spelled_out(3_000_000_000, lang = :mi) == "toru piriona" +end + nothing From 18c1f2910ee9db80ec558af52b3af100dfc51f0f Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 21 Jun 2022 15:09:11 +1200 Subject: [PATCH 074/120] Update package version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index a199ccaf..2c2603fa 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpelledOut" uuid = "4728c690-e668-4265-bc0d-51a8c0f93067" authors = ["Jake W. Ireland and contributors"] -version = "1.1.1" +version = "1.2.0" [deps] DecFP = "55939f99-70c6-5e9b-8bb0-5071ed7d61fd" From ed12c23d0da3f76992e04607596f0d146288503a Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 00:11:48 +1200 Subject: [PATCH 075/120] Added quick start section and elaborate on contributing section within README --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f17fad28..c53ad1e6 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,24 @@ ## Description -This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, to write out in **long hand**, and — as a great mind once suggested — to **transnumerate**. +This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, and to write out in **long hand**. Some people to whom I look up have suggested calling this **verbal depresentatoin**, to **digitate**, and —one of my favourites— to **transnumerate**. + +## Quick Start +```julia +julia> using SpelledOut + +julia> spelled_out(1234); + +julia> spelled_out(1234, lang = :en); + +julia> spelled_out(1234, lang = :en_UK); +``` + +See [here](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages) for a list of supported languages. ## Contributing +Each new language will require a language code to use it. This code is determined by [https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php](ISO-639-1).[[1]](https://www.wikiwand.com/en/ISO_639-1) + +When contributing, you should add a file and a directory: `src/.jl`, and `src//`. Within the latter, this is where you should store any language-specific dictionaries. -Each new language will require a language code to use it. This code is determined by [https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php](ISO-639-1).[[1]](https://www.wikiwand.com/en/ISO_639-1) \ No newline at end of file +Finally, ensure you update the documentation for [Supported Languages](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages). \ No newline at end of file From 7f2cc2ac4560f638f506553b28c61d3109a9fd71 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 00:11:48 +1200 Subject: [PATCH 076/120] Added quick start section and elaborate on contributing section within README --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f17fad28..c53ad1e6 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,24 @@ ## Description -This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, to write out in **long hand**, and — as a great mind once suggested — to **transnumerate**. +This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, and to write out in **long hand**. Some people to whom I look up have suggested calling this **verbal depresentatoin**, to **digitate**, and —one of my favourites— to **transnumerate**. + +## Quick Start +```julia +julia> using SpelledOut + +julia> spelled_out(1234); + +julia> spelled_out(1234, lang = :en); + +julia> spelled_out(1234, lang = :en_UK); +``` + +See [here](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages) for a list of supported languages. ## Contributing +Each new language will require a language code to use it. This code is determined by [https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php](ISO-639-1).[[1]](https://www.wikiwand.com/en/ISO_639-1) + +When contributing, you should add a file and a directory: `src/.jl`, and `src//`. Within the latter, this is where you should store any language-specific dictionaries. -Each new language will require a language code to use it. This code is determined by [https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php](ISO-639-1).[[1]](https://www.wikiwand.com/en/ISO_639-1) \ No newline at end of file +Finally, ensure you update the documentation for [Supported Languages](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages). \ No newline at end of file From d91f8d7090b5a00386ecf9d6e2db05f8bf5e601d Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 01:21:15 +1200 Subject: [PATCH 077/120] Removed non-function test line --- src/en/utils.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/en/utils.jl b/src/en/utils.jl index 2053b11b..e0424407 100644 --- a/src/en/utils.jl +++ b/src/en/utils.jl @@ -19,5 +19,4 @@ function ithsplit(predicate, s::S, i::Int) where {S <: AbstractString} return SubString() end - -split(s, _lastsplit, limit = 2)[end] +# split(s, _lastsplit, limit = 2)[end] From 4fe41d51974aa0d57d5f81beda611f925e1df435 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 02:23:28 +1200 Subject: [PATCH 078/120] Added benchmark testing script --- test/benchmark.jl | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 test/benchmark.jl diff --git a/test/benchmark.jl b/test/benchmark.jl new file mode 100644 index 00000000..9acc3c3d --- /dev/null +++ b/test/benchmark.jl @@ -0,0 +1,4 @@ +using SpelledOut +using BenchmarkTools + +@btime spelled_out($123456789, lang = $:en_UK) From cd6f81e527839d563d9a22f017b1741aee49393f Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 02:23:56 +1200 Subject: [PATCH 079/120] Prefer buffers over strings --- src/en.jl | 52 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/en.jl b/src/en.jl index 79a888e4..191ceb0b 100644 --- a/src/en.jl +++ b/src/en.jl @@ -56,7 +56,7 @@ function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = return String(take!(word_buf)) end -function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = :modern) +function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # default to :modern if isequal(dict, :british) scale_numbers = _scale_traditional_british @@ -67,24 +67,33 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : error("Unrecognized dict value: $dict") end - number = big(number) - isnegative = number < 0 + word_buf = IOBuffer() + if number_orig < 0 + print(word_buf, "negative ") + end + + number = big(number_orig) number = abs(number) if number > limit - 1 error("""SpelledOut.jl does not support numbers larger than $(limit_str * " - 1"). Sorry about that!""") end + if number < 100 word = small_convert_en(number, british=british, dict=dict) - return isnegative ? "negative " * word : word + print(word_buf, word) + return String(take!(word_buf)) end if number < 1000 word = large_convert_en(number, british=british, dict=dict) - return isnegative ? "negative " * word : word + print(word_buf, word) + return String(take!(word_buf)) end + tmp_word_buf = IOBuffer() + for v in 0:length(scale_numbers) d_idx = v d_number = BigInt(round(big(1000)^v)) @@ -92,13 +101,12 @@ function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = : if d_number > number modulus = BigInt(big(1000)^(d_idx - 1)) l, r = divrem(number, modulus) - word = large_convert_en(l, british=british, dict=dict) * " " * scale_numbers[d_idx - 1] - if r > 0 - word = word * ", " * spelled_out_en(r, british=british, dict=dict) - end + word = large_convert_en(l, british=british, dict=dict) + print(word_buf, word, " ", scale_numbers[d_idx - 1]) + r > 0 && print(word_buf, ", ", spelled_out_en(r, british=british, dict=dict)) - return isnegative ? "negative " * word : word + return String(take!(word_buf)) end end @@ -109,11 +117,8 @@ end function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = :modern) s = spelled_out_en(number, british = british, dict = dict) - # lastword = split(s)[end] - # redolast = split(lastword, "-")[end] lastword = lastsplit(isspace, s) redolast = lastsplit('-', lastword) - if redolast != lastword _lastsplit = '-' @@ -122,19 +127,22 @@ function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = _lastsplit = ' ' word = lastword end - - firstpart = reverse(split(reverse(s), _lastsplit, limit = 2)[end]) - firstpart = (firstpart == word) ? "" : firstpart * _lastsplit - + + word_buf = IOBuffer() + firstpart = reverse(last(split(reverse(s), _lastsplit, limit = 2))) + if firstpart != word + print(word_buf, firstpart, _lastsplit) + end + if haskey(irregular, word) - word = irregular[word] + print(word_buf, irregular[word]) elseif word[end] == 'y' - word = word[1:end-1] * ysuffix + print(word_buf, word[1:end-1], ysuffix) else - word = word * suffix + print(word_buf, word, suffix) end - - return firstpart * word + + return String(take!(word_buf)) end # This method is an internal method used for spelling out floats From 9f33c80fffac051be92b70c1070669a8467a161d Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 03:01:03 +1200 Subject: [PATCH 080/120] Use IOBuffer in small convert --- src/en.jl | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/en.jl b/src/en.jl index 191ceb0b..1cf41cc1 100644 --- a/src/en.jl +++ b/src/en.jl @@ -13,14 +13,16 @@ function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = return _small_numbers[number + 1] end - for (v, d_cap) in enumerate(_tens) + word_buf = IOBuffer() + for (v, d̂) in enumerate(_tens) d_number = BigInt(20 + 10 * (v - 1)) if d_number + 10 > number if mod(number, 10) ≠ 0 - return d_cap * "-" * _small_numbers[mod(number, 10) + 1] + print(word_buf, d̂, '-', _small_numbers[mod(number, 10) + 1]) + return String(take!(word_buf)) end - return d_cap + return d̂ end end @@ -30,6 +32,7 @@ end # convert a value < 1000 to english, special cased because it is the level that excludes # the < 100 special case. The rest are more general. This also allows you to get # strings in the form of "forty-five hundred" if called directly. +# TODO: make more efficient (#2) function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # define scale type word_buf = IOBuffer() @@ -37,25 +40,26 @@ function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = modulus = mod(number, 100) if divisor > 0 - print(word_buf, _small_numbers[divisor + 1], " hundred") + write(word_buf, _small_numbers[divisor + 1], " hundred") if modulus > 0 - print(word_buf, ' ') + write(word_buf, ' ') end end if british - if ! iszero(divisor) && ! iszero(modulus) - print(word_buf, "and ") + if !iszero(divisor) && !iszero(modulus) + write(word_buf, "and ") end end if modulus > 0 - print(word_buf, small_convert_en(modulus, british=british, dict=dict)) + write(word_buf, small_convert_en(modulus, british=british, dict=dict)) end return String(take!(word_buf)) end +# TODO: make more efficient (#1) function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # default to :modern if isequal(dict, :british) @@ -69,7 +73,7 @@ function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbo word_buf = IOBuffer() if number_orig < 0 - print(word_buf, "negative ") + write(word_buf, "negative ") end number = big(number_orig) @@ -82,13 +86,13 @@ function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbo if number < 100 word = small_convert_en(number, british=british, dict=dict) - print(word_buf, word) + write(word_buf, word) return String(take!(word_buf)) end if number < 1000 word = large_convert_en(number, british=british, dict=dict) - print(word_buf, word) + write(word_buf, word) return String(take!(word_buf)) end @@ -103,8 +107,8 @@ function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbo l, r = divrem(number, modulus) word = large_convert_en(l, british=british, dict=dict) - print(word_buf, word, " ", scale_numbers[d_idx - 1]) - r > 0 && print(word_buf, ", ", spelled_out_en(r, british=british, dict=dict)) + write(word_buf, word, " ", scale_numbers[d_idx - 1]) + r > 0 && write(word_buf, ", ", spelled_out_en(r, british=british, dict=dict)) return String(take!(word_buf)) end @@ -131,15 +135,15 @@ function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = word_buf = IOBuffer() firstpart = reverse(last(split(reverse(s), _lastsplit, limit = 2))) if firstpart != word - print(word_buf, firstpart, _lastsplit) + write(word_buf, firstpart, _lastsplit) end if haskey(irregular, word) - print(word_buf, irregular[word]) + write(word_buf, irregular[word]) elseif word[end] == 'y' - print(word_buf, word[1:end-1], ysuffix) + write(word_buf, word[1:end-1], ysuffix) else - print(word_buf, word, suffix) + write(word_buf, word, suffix) end return String(take!(word_buf)) From da97cce2ed60e390981b10768fc5f1a3f4259cf8 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 11:17:00 +1200 Subject: [PATCH 081/120] Work mostly with IOBuffers Instead of creating IOBuffers within each function, pass around IOBuffers to modifying functions and only take from them at the end of the process! This vastly reduces the allocations as we are no longer creating a new IOBuffer within each function. However, it is still not as fast as it was (but its memory usage is better). --- src/en.jl | 74 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/en.jl b/src/en.jl index 1cf41cc1..3488ee61 100644 --- a/src/en.jl +++ b/src/en.jl @@ -7,60 +7,70 @@ include(joinpath(@__DIR__, "en", "ordinal_dictionaries.jl")) include(joinpath(@__DIR__, "en", "utils.jl")) # convert a value < 100 to English. -function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) +function _small_convert_en!(io::IOBuffer, number::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # define scale type if number < 20 - return _small_numbers[number + 1] + write(io, _small_numbers[number + 1]) + return io end - word_buf = IOBuffer() for (v, d̂) in enumerate(_tens) d_number = BigInt(20 + 10 * (v - 1)) if d_number + 10 > number if mod(number, 10) ≠ 0 - print(word_buf, d̂, '-', _small_numbers[mod(number, 10) + 1]) - return String(take!(word_buf)) + write(io, d̂, '-', _small_numbers[mod(number, 10) + 1]) + return io end - return d̂ + write(io, d̂) + return io end end - return nothing + return io +end + +function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + word_buf = IOBuffer() + _small_convert_en!(word_buf, number; british=british, dict=dict) + return String(take!(word_buf)) end # convert a value < 1000 to english, special cased because it is the level that excludes # the < 100 special case. The rest are more general. This also allows you to get # strings in the form of "forty-five hundred" if called directly. -# TODO: make more efficient (#2) -function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) +function _large_convert_en!(io::IOBuffer, number::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # define scale type - word_buf = IOBuffer() divisor = div(number, 100) modulus = mod(number, 100) if divisor > 0 - write(word_buf, _small_numbers[divisor + 1], " hundred") + write(io, _small_numbers[divisor + 1], " hundred") if modulus > 0 - write(word_buf, ' ') + write(io, ' ') end end if british if !iszero(divisor) && !iszero(modulus) - write(word_buf, "and ") + write(io, "and ") end end if modulus > 0 - write(word_buf, small_convert_en(modulus, british=british, dict=dict)) + _small_convert_en!(io, modulus, british=british, dict=dict) end + return io +end + +function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) + word_buf = IOBuffer() + _large_convert_en!(word_buf, number; british=british, dict=dict) return String(take!(word_buf)) end -# TODO: make more efficient (#1) -function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbol = :modern) +function _spelled_out_en!(io::IOBuffer, number_orig::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # default to :modern if isequal(dict, :british) scale_numbers = _scale_traditional_british @@ -71,9 +81,8 @@ function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbo error("Unrecognized dict value: $dict") end - word_buf = IOBuffer() if number_orig < 0 - write(word_buf, "negative ") + write(io, "negative ") end number = big(number_orig) @@ -85,19 +94,15 @@ function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbo if number < 100 - word = small_convert_en(number, british=british, dict=dict) - write(word_buf, word) - return String(take!(word_buf)) + _small_convert_en!(io, number, british=british, dict=dict) + return io end if number < 1000 - word = large_convert_en(number, british=british, dict=dict) - write(word_buf, word) - return String(take!(word_buf)) + _large_convert_en!(io, number, british=british, dict=dict) + return io end - tmp_word_buf = IOBuffer() - for v in 0:length(scale_numbers) d_idx = v d_number = BigInt(round(big(1000)^v)) @@ -106,17 +111,26 @@ function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbo modulus = BigInt(big(1000)^(d_idx - 1)) l, r = divrem(number, modulus) - word = large_convert_en(l, british=british, dict=dict) - write(word_buf, word, " ", scale_numbers[d_idx - 1]) - r > 0 && write(word_buf, ", ", spelled_out_en(r, british=british, dict=dict)) + _large_convert_en!(io, l, british=british, dict=dict) + write(io, " ", scale_numbers[d_idx - 1]) + if r > 0 + write(io, ", ") + _spelled_out_en!(io, r, british=british, dict=dict) + end - return String(take!(word_buf)) + return io end end error("Unreachable") end +function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbol = :modern) + word_buf = IOBuffer() + _spelled_out_en!(word_buf, number_orig; british=british, dict=dict) + return String(take!(word_buf)) +end + # Need to print ordinal numbers for the irrational printing function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = :modern) s = spelled_out_en(number, british = british, dict = dict) From 06e7d77af4c010d7f97cb36a588808a891e4c31d Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 11:49:10 +1200 Subject: [PATCH 082/120] Remove unused kwargs to lesser functions --- src/en.jl | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/en.jl b/src/en.jl index 3488ee61..00cd9d13 100644 --- a/src/en.jl +++ b/src/en.jl @@ -7,8 +7,7 @@ include(joinpath(@__DIR__, "en", "ordinal_dictionaries.jl")) include(joinpath(@__DIR__, "en", "utils.jl")) # convert a value < 100 to English. -function _small_convert_en!(io::IOBuffer, number::Integer; british::Bool = false, dict::Symbol = :modern) - scale_numbers = _scale_modern # define scale type +function _small_convert_en!(io::IOBuffer, number::Integer) if number < 20 write(io, _small_numbers[number + 1]) return io @@ -19,7 +18,8 @@ function _small_convert_en!(io::IOBuffer, number::Integer; british::Bool = false if d_number + 10 > number if mod(number, 10) ≠ 0 - write(io, d̂, '-', _small_numbers[mod(number, 10) + 1]) + sn = _small_numbers[mod(number, 10) + 1] + write(io, d̂, '-', sn) return io end write(io, d̂) @@ -30,17 +30,16 @@ function _small_convert_en!(io::IOBuffer, number::Integer; british::Bool = false return io end -function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) +function small_convert_en(number::Integer) word_buf = IOBuffer() - _small_convert_en!(word_buf, number; british=british, dict=dict) + _small_convert_en!(word_buf, number) return String(take!(word_buf)) end # convert a value < 1000 to english, special cased because it is the level that excludes # the < 100 special case. The rest are more general. This also allows you to get # strings in the form of "forty-five hundred" if called directly. -function _large_convert_en!(io::IOBuffer, number::Integer; british::Bool = false, dict::Symbol = :modern) - scale_numbers = _scale_modern # define scale type +function _large_convert_en!(io::IOBuffer, number::Integer; british::Bool = false) divisor = div(number, 100) modulus = mod(number, 100) @@ -58,15 +57,15 @@ function _large_convert_en!(io::IOBuffer, number::Integer; british::Bool = false end if modulus > 0 - _small_convert_en!(io, modulus, british=british, dict=dict) + _small_convert_en!(io, modulus) end return io end -function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) +function large_convert_en(number::Integer; british::Bool = false) word_buf = IOBuffer() - _large_convert_en!(word_buf, number; british=british, dict=dict) + _large_convert_en!(word_buf, number; british=british) return String(take!(word_buf)) end @@ -77,6 +76,7 @@ function _spelled_out_en!(io::IOBuffer, number_orig::Integer; british::Bool = fa elseif isequal(dict, :european) scale_numbers = _scale_traditional_european elseif isequal(dict, :modern) + # This is the default condition else error("Unrecognized dict value: $dict") end @@ -94,12 +94,12 @@ function _spelled_out_en!(io::IOBuffer, number_orig::Integer; british::Bool = fa if number < 100 - _small_convert_en!(io, number, british=british, dict=dict) + _small_convert_en!(io, number) return io end if number < 1000 - _large_convert_en!(io, number, british=british, dict=dict) + _large_convert_en!(io, number, british=british) return io end @@ -111,7 +111,7 @@ function _spelled_out_en!(io::IOBuffer, number_orig::Integer; british::Bool = fa modulus = BigInt(big(1000)^(d_idx - 1)) l, r = divrem(number, modulus) - _large_convert_en!(io, l, british=british, dict=dict) + _large_convert_en!(io, l, british=british) write(io, " ", scale_numbers[d_idx - 1]) if r > 0 write(io, ", ") From d0c2ee76e33b9bd43083d455dfacfdf515e541c9 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 27 Jun 2022 11:57:48 +1200 Subject: [PATCH 083/120] Only work with bigints after we check if number is small --- src/en.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/en.jl b/src/en.jl index 00cd9d13..c42b4669 100644 --- a/src/en.jl +++ b/src/en.jl @@ -69,7 +69,7 @@ function large_convert_en(number::Integer; british::Bool = false) return String(take!(word_buf)) end -function _spelled_out_en!(io::IOBuffer, number_orig::Integer; british::Bool = false, dict::Symbol = :modern) +function _spelled_out_en!(io::IOBuffer, number_norm::Integer; british::Bool = false, dict::Symbol = :modern) scale_numbers = _scale_modern # default to :modern if isequal(dict, :british) scale_numbers = _scale_traditional_british @@ -81,28 +81,28 @@ function _spelled_out_en!(io::IOBuffer, number_orig::Integer; british::Bool = fa error("Unrecognized dict value: $dict") end - if number_orig < 0 + if number_norm < 0 write(io, "negative ") end - - number = big(number_orig) - number = abs(number) - if number > limit - 1 + if number_norm > limit - 1 error("""SpelledOut.jl does not support numbers larger than $(limit_str * " - 1"). Sorry about that!""") end - if number < 100 - _small_convert_en!(io, number) + if number_norm < 100 + _small_convert_en!(io, number_norm) return io end - if number < 1000 - _large_convert_en!(io, number, british=british) + if number_norm < 1000 + _large_convert_en!(io, number_norm, british=british) return io end + number = big(number_norm) + number = abs(number) + for v in 0:length(scale_numbers) d_idx = v d_number = BigInt(round(big(1000)^v)) From 0a30c3b0c24781bd8078717ad1b5fa275b68fb92 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 28 Jun 2022 02:09:11 +1200 Subject: [PATCH 084/120] Favour `print(io, ...)` over `write(io, ...)` --- src/en.jl | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/en.jl b/src/en.jl index c42b4669..c3b3caec 100644 --- a/src/en.jl +++ b/src/en.jl @@ -9,7 +9,7 @@ include(joinpath(@__DIR__, "en", "utils.jl")) # convert a value < 100 to English. function _small_convert_en!(io::IOBuffer, number::Integer) if number < 20 - write(io, _small_numbers[number + 1]) + print(io, _small_numbers[number + 1]) return io end @@ -19,10 +19,10 @@ function _small_convert_en!(io::IOBuffer, number::Integer) if d_number + 10 > number if mod(number, 10) ≠ 0 sn = _small_numbers[mod(number, 10) + 1] - write(io, d̂, '-', sn) + print(io, d̂, '-', sn) return io end - write(io, d̂) + print(io, d̂) return io end end @@ -44,15 +44,15 @@ function _large_convert_en!(io::IOBuffer, number::Integer; british::Bool = false modulus = mod(number, 100) if divisor > 0 - write(io, _small_numbers[divisor + 1], " hundred") + print(io, _small_numbers[divisor + 1], " hundred") if modulus > 0 - write(io, ' ') + print(io, ' ') end end if british if !iszero(divisor) && !iszero(modulus) - write(io, "and ") + print(io, "and ") end end @@ -82,7 +82,7 @@ function _spelled_out_en!(io::IOBuffer, number_norm::Integer; british::Bool = fa end if number_norm < 0 - write(io, "negative ") + print(io, "negative ") end if number_norm > limit - 1 @@ -112,9 +112,9 @@ function _spelled_out_en!(io::IOBuffer, number_norm::Integer; british::Bool = fa l, r = divrem(number, modulus) _large_convert_en!(io, l, british=british) - write(io, " ", scale_numbers[d_idx - 1]) + print(io, " ", scale_numbers[d_idx - 1]) if r > 0 - write(io, ", ") + print(io, ", ") _spelled_out_en!(io, r, british=british, dict=dict) end @@ -149,15 +149,15 @@ function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = word_buf = IOBuffer() firstpart = reverse(last(split(reverse(s), _lastsplit, limit = 2))) if firstpart != word - write(word_buf, firstpart, _lastsplit) + print(word_buf, firstpart, _lastsplit) end if haskey(irregular, word) - write(word_buf, irregular[word]) + print(word_buf, irregular[word]) elseif word[end] == 'y' - write(word_buf, word[1:end-1], ysuffix) + print(word_buf, word[1:end-1], ysuffix) else - write(word_buf, word, suffix) + print(word_buf, word, suffix) end return String(take!(word_buf)) From e313d205e03af985c35f59345ebb113525b17457 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 28 Jun 2022 02:22:59 +1200 Subject: [PATCH 085/120] Reduced liberal use of big integers --- src/en.jl | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/en.jl b/src/en.jl index c3b3caec..3e38d6c7 100644 --- a/src/en.jl +++ b/src/en.jl @@ -13,13 +13,15 @@ function _small_convert_en!(io::IOBuffer, number::Integer) return io end + m = mod(number, 10) + for (v, d̂) in enumerate(_tens) - d_number = BigInt(20 + 10 * (v - 1)) + d = 20 + 10 * (v - 1) - if d_number + 10 > number - if mod(number, 10) ≠ 0 - sn = _small_numbers[mod(number, 10) + 1] - print(io, d̂, '-', sn) + if d + 10 > number + if m ≠ 0 + n = _small_numbers[m + 1] + print(io, d̂, '-', n) return io end print(io, d̂) @@ -100,15 +102,14 @@ function _spelled_out_en!(io::IOBuffer, number_norm::Integer; british::Bool = fa return io end - number = big(number_norm) - number = abs(number) + number = abs(number_norm) for v in 0:length(scale_numbers) d_idx = v - d_number = BigInt(round(big(1000)^v)) + d_number = round(big(1000)^v) if d_number > number - modulus = BigInt(big(1000)^(d_idx - 1)) + modulus = big(1000)^(d_idx - 1) l, r = divrem(number, modulus) _large_convert_en!(io, l, british=british) From c3c5aa2ada4ab21f33ec89ffb4f308fa7a680613 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 28 Jun 2022 02:44:04 +1200 Subject: [PATCH 086/120] Better string manipulation and use buf for niche convert funcs Instead of using a weird `reverse` method for string manipulation in printing of ordinals, we use a util function. Also, use `IOBuffer` where practical for alt convert methods --- src/en.jl | 47 +++++++++++++++++++++++++---------------------- src/en/utils.jl | 5 +++++ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/en.jl b/src/en.jl index 3e38d6c7..fb8aec81 100644 --- a/src/en.jl +++ b/src/en.jl @@ -67,7 +67,7 @@ end function large_convert_en(number::Integer; british::Bool = false) word_buf = IOBuffer() - _large_convert_en!(word_buf, number; british=british) + _large_convert_en!(word_buf, number; british = british) return String(take!(word_buf)) end @@ -98,7 +98,7 @@ function _spelled_out_en!(io::IOBuffer, number_norm::Integer; british::Bool = fa end if number_norm < 1000 - _large_convert_en!(io, number_norm, british=british) + _large_convert_en!(io, number_norm, british = british) return io end @@ -112,11 +112,11 @@ function _spelled_out_en!(io::IOBuffer, number_norm::Integer; british::Bool = fa modulus = big(1000)^(d_idx - 1) l, r = divrem(number, modulus) - _large_convert_en!(io, l, british=british) + _large_convert_en!(io, l, british = british) print(io, " ", scale_numbers[d_idx - 1]) if r > 0 print(io, ", ") - _spelled_out_en!(io, r, british=british, dict=dict) + _spelled_out_en!(io, r, british = british, dict = dict) end return io @@ -128,13 +128,15 @@ end function spelled_out_en(number_orig::Integer; british::Bool = false, dict::Symbol = :modern) word_buf = IOBuffer() - _spelled_out_en!(word_buf, number_orig; british=british, dict=dict) + _spelled_out_en!(word_buf, number_orig; british = british, dict = dict) return String(take!(word_buf)) end # Need to print ordinal numbers for the irrational printing function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = :modern) - s = spelled_out_en(number, british = british, dict = dict) + word_buf = IOBuffer() + _spelled_out_en!(word_buf, number, british = british, dict = dict) + s = String(take!(word_buf)) lastword = lastsplit(isspace, s) redolast = lastsplit('-', lastword) @@ -147,8 +149,8 @@ function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = word = lastword end - word_buf = IOBuffer() - firstpart = reverse(last(split(reverse(s), _lastsplit, limit = 2))) + firstpart = firstlastsplit(_lastsplit, s) + if firstpart != word print(word_buf, firstpart, _lastsplit) end @@ -169,14 +171,15 @@ function decimal_convert_en(number::AbstractString; british::Bool = false, dict: # decimal, whole = modf(number) # whole = round(BigInt, whole) whole, decimal = split(number, ".") - word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") - # word = spelled_out_en(whole, british=british, dict=dict) * string(" point") + word_buf = IOBuffer() + _spelled_out_en!(word_buf, parse(BigInt, whole), british = british, dict = dict) + print(word_buf, " point") for i in decimal - word = word * " " * _small_number_dictionary[i] + print(word_buf, ' ', _small_number_dictionary[i]) end - return word + return String(take!(word_buf)) end function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) @@ -208,19 +211,19 @@ end # Spell out complex numbers function spelled_out_en(number::Complex; british::Bool = false, dict::Symbol = :modern) - return spelled_out_en(real(number), british = british, dict = dict) * " and " * spelled_out_en(imag(number), british = british, dict=dict) * " imaginaries" + return spelled_out_en(real(number), british = british, dict = dict) * " and " * spelled_out_en(imag(number), british = british, dict = dict) * " imaginaries" end function spelled_out_en(number::Rational; british::Bool = false, dict::Symbol = :modern) - _num, _den = number.num, number.den - - # return the number itself if the denomimator is one - isone(_den) && return spelled_out_en(_num, british = british, dict = dict) - - word = spelled_out_en(_num, british = british, dict = dict) * " " * spell_ordinal_en(_den, british = british, dict = dict) - - # account for pluralisation - return isone(_num) ? word : word * "s" + _num, _den = number.num, number.den + + # return the number itself if the denomimator is one + isone(_den) && return spelled_out_en(_num, british = british, dict = dict) + + word = spelled_out_en(_num, british = british, dict = dict) * " " * spell_ordinal_en(_den, british = british, dict = dict) + + # account for pluralisation + return isone(_num) ? word : word * "s" end function spelled_out_en(number::AbstractIrrational; british::Bool = false, dict::Symbol = :modern) diff --git a/src/en/utils.jl b/src/en/utils.jl index e0424407..b2bdde69 100644 --- a/src/en/utils.jl +++ b/src/en/utils.jl @@ -3,6 +3,11 @@ function lastsplit(predicate, s::S) where {S <: AbstractString} return isnothing(i) ? SubString(s) : SubString(s, nextind(s, i)) end +function firstlastsplit(predicate, s::S) where {S <: AbstractString} + i = findlast(predicate, s) + return isnothing(i) ? SubString(s) : SubString(s, 1, prevind(s, i)) +end + Base.findall(c::Char, s::S) where {S <: AbstractString} = Int[only(i) for i in findall(string(c), s)] From 06835dfa7e74cda9808127a5765e050e9040a928 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 28 Jun 2022 02:53:55 +1200 Subject: [PATCH 087/120] Update contributing section to include supported number types --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c53ad1e6..59c038ca 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,13 @@ Each new language will require a language code to use it. This code is determin When contributing, you should add a file and a directory: `src/.jl`, and `src//`. Within the latter, this is where you should store any language-specific dictionaries. -Finally, ensure you update the documentation for [Supported Languages](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages). \ No newline at end of file +When implementing the main function for your language (typically called `spelled_out_`), consider implementing methods on this function for the following types: + - `Integer` + - `Rational` + - `Float64` + - `Complex` + +You can also add a fallback method and throw an error, but this should be caught by a `MethodError` anyway. Now you can add to the main [`SpelledOut.jl`](src/SpelledOut.jl) function, in which you can add a branch for your language (following the trend). + +Finally, ensure you update the documentation for [Supported Languages](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages). + From 21041ae490ff24e47fd1e9b62e6e6396a523d810 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 28 Jun 2022 02:53:55 +1200 Subject: [PATCH 088/120] Update contributing section to include supported number types --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c53ad1e6..59c038ca 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,13 @@ Each new language will require a language code to use it. This code is determin When contributing, you should add a file and a directory: `src/.jl`, and `src//`. Within the latter, this is where you should store any language-specific dictionaries. -Finally, ensure you update the documentation for [Supported Languages](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages). \ No newline at end of file +When implementing the main function for your language (typically called `spelled_out_`), consider implementing methods on this function for the following types: + - `Integer` + - `Rational` + - `Float64` + - `Complex` + +You can also add a fallback method and throw an error, but this should be caught by a `MethodError` anyway. Now you can add to the main [`SpelledOut.jl`](src/SpelledOut.jl) function, in which you can add a branch for your language (following the trend). + +Finally, ensure you update the documentation for [Supported Languages](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages). + From a01a6fac0a5570f36e141b694a55aa39179ae69f Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 28 Jun 2022 03:07:39 +1200 Subject: [PATCH 089/120] Remove original copy backup --- src/en_orig.jl | 223 ------------------------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 src/en_orig.jl diff --git a/src/en_orig.jl b/src/en_orig.jl deleted file mode 100644 index 153c466a..00000000 --- a/src/en_orig.jl +++ /dev/null @@ -1,223 +0,0 @@ -include(joinpath(@__DIR__, "en", "standard_dictionary_numbers_extended.jl")) -include(joinpath(@__DIR__, "en", "large_standard_dictionary_numbers_extended.jl")) -include(joinpath(@__DIR__, "en", "ordinal_dictionaries.jl")) - -# convert a value < 100 to English. -function small_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) - scale_numbers = _scale_modern # define scale type - if number < 20 - word = _small_numbers[number + 1] - - return word - end - - v = 0 - while v < length(_tens) - d_cap = _tens[v + 1] - d_number = BigInt(20 + 10 * v) - - if d_number + 10 > number - if mod(number, 10) ≠ 0 - word = d_cap * "-" * _small_numbers[mod(number, 10) + 1] - - return word - end - - return d_cap - end - v += 1 - end -end - -# convert a value < 1000 to english, special cased because it is the level that excludes -# the < 100 special case. The rest are more general. This also allows you to get -# strings in the form of "forty-five hundred" if called directly. -function large_convert_en(number::Integer; british::Bool = false, dict::Symbol = :modern) - scale_numbers = _scale_modern # define scale type - word = string() # initiate empty string - divisor = div(number, 100) - modulus = mod(number, 100) - - if divisor > 0 - word = _small_numbers[divisor + 1] * " hundred" - if modulus > 0 - word = word * " " - end - end - - if british - if ! iszero(divisor) && ! iszero(modulus) - word = word * "and " - end - end - - if modulus > 0 - word = word * small_convert_en(modulus, british=british, dict=dict) - end - - return word -end - -function spelled_out_en(number::Integer; british::Bool = false, dict::Symbol = :modern) - scale_numbers = _scale_modern # default to :modern - if isequal(dict, :british) - scale_numbers = _scale_traditional_british - elseif isequal(dict, :european) - scale_numbers = _scale_traditional_european - elseif isequal(dict, :modern) - else - throw(error("unrecognized dict value: $dict")) - end - - number = big(number) - isnegative = false - if number < 0 - isnegative = true - end - - number = abs(number) - if number > limit - 1 - throw(error("""SpelledOut.jl does not support numbers larger than $(limit_str * " - 1"). Sorry about that!""")) - end - - if number < 100 - word = small_convert_en(number, british=british, dict=dict) - - if isnegative - word = "negative " * word - end - - return word - end - - if number < 1000 - word = large_convert_en(number, british=british, dict=dict) - - if isnegative - word = "negative " * word - end - - return word - end - - v = 0 - while v ≤ length(scale_numbers) - d_idx = v - d_number = BigInt(round(big(1000)^v)) - - if d_number > number - modulus = BigInt(big(1000)^(d_idx - 1)) - l, r = divrem(number, modulus) - word = large_convert_en(l, british=british, dict=dict) * " " * scale_numbers[d_idx - 1] - - if r > 0 - word = word * ", " * spelled_out_en(r, british=british, dict=dict) - end - - if isnegative - word = "negative " * word - end - - return word - end - - v += 1 - end -end - -# Need to print ordinal numbers for the irrational printing -function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = :modern) - s = spelled_out_en(number, british = british, dict = dict) - - lastword = split(s)[end] - redolast = split(lastword, "-")[end] - - if redolast != lastword - lastsplit = "-" - word = redolast - else - lastsplit = " " - word = lastword - end - - firstpart = reverse(split(reverse(s), lastsplit, limit = 2)[end]) - firstpart = (firstpart == word) ? string() : firstpart * lastsplit - - if haskey(irregular, word) - word = irregular[word] - elseif word[end] == 'y' - word = word[1:end-1] * ysuffix - else - word = word * suffix - end - - return firstpart * word -end - -# This method is an internal method used for spelling out floats -function decimal_convert_en(number::AbstractString; british::Bool = false, dict::Symbol = :modern) - # decimal, whole = modf(number) - # whole = round(BigInt, whole) - whole, decimal = split(number, ".") - word = spelled_out_en(parse(BigInt, whole), british=british, dict=dict) * string(" point") - # word = spelled_out_en(whole, british=british, dict=dict) * string(" point") - - for i in decimal - word = word * " " * _small_number_dictionary[i] - end - - return word -end - -function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symbol = :modern) - str_number = format(number) - if occursin('.', str_number) - _decimal, _ = modf(Dec64(number)) - _length_of_presicion = length(string(_decimal)) - 2 # (ndigits(_whole) + 1) - number = format(number, precision = _length_of_presicion) - else - # It is an integer is scientific notation, treat normally without decimal precision considerations - # E.g., 1e10 should be parsed as an integer (as should 1.0e10) - number = parse(BigInt, str_number) - end - - if isa(number, AbstractString) - # if the number is a string then it is a decimal, which is formatted precisely - # for correct precision with decimal places - return decimal_convert_en(number, british = british, dict = dict) - elseif isinteger(number) - # otherwise, it is an integer - return spelled_out_en(number, british = british, dict = dict) - else - throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) - end - - # should never get here - return nothing -end - -# Spell out complex numbers -function spelled_out_en(number::Complex; british::Bool = false, dict::Symbol = :modern) - return spelled_out_en(real(number), british = british, dict = dict) * " and " * spelled_out_en(imag(number), british = british, dict=dict) * " imaginaries" -end - -function spelled_out_en(number::Rational; british::Bool = false, dict::Symbol = :modern) - _num, _den = number.num, number.den - - # return the number itself if the denomimator is one - isone(_den) && return spelled_out_en(_num, british = british, dict = dict) - - word = spelled_out_en(_num, british = british, dict = dict) * " " * spell_ordinal_en(_den, british = british, dict = dict) - - # account for pluralisation - return isone(_num) ? word : word * "s" -end - -function spelled_out_en(number::AbstractIrrational; british::Bool = false, dict::Symbol = :modern) - throw(error("Please round the input number, as we support floating point printing but cannot support irrational printing.")) -end - -# Fallback method if we do not know how to handle the input -function spelled_out_en(number; british::Bool = false, dict::Symbol = :modern) - throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) -end From 8251a3c6ca030589c7bae24e261c2d06373dd08c Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 28 Jun 2022 03:09:26 +1200 Subject: [PATCH 090/120] Removed no-longer-needed benchmarking file --- test/benchmark.jl | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 test/benchmark.jl diff --git a/test/benchmark.jl b/test/benchmark.jl deleted file mode 100644 index 9acc3c3d..00000000 --- a/test/benchmark.jl +++ /dev/null @@ -1,4 +0,0 @@ -using SpelledOut -using BenchmarkTools - -@btime spelled_out($123456789, lang = $:en_UK) From 4ad05f4b01b1687f801bb1b1bfc6353730bc33c8 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 25 Jul 2022 14:39:16 +1200 Subject: [PATCH 091/120] Fixed ISO country code link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59c038ca..15da0b7e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ julia> spelled_out(1234, lang = :en_UK); See [here](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages) for a list of supported languages. ## Contributing -Each new language will require a language code to use it. This code is determined by [https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php](ISO-639-1).[[1]](https://www.wikiwand.com/en/ISO_639-1) +Each new language will require a language code to use it. This code is determined by [ISO-639-1](https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php).[[1]](https://www.wikiwand.com/en/ISO_639-1) When contributing, you should add a file and a directory: `src/.jl`, and `src//`. Within the latter, this is where you should store any language-specific dictionaries. From a7e63b874638faaaed67621c89178d353f145fca Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 25 Jul 2022 14:39:16 +1200 Subject: [PATCH 092/120] Fixed ISO country code link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59c038ca..15da0b7e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ julia> spelled_out(1234, lang = :en_UK); See [here](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages) for a list of supported languages. ## Contributing -Each new language will require a language code to use it. This code is determined by [https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php](ISO-639-1).[[1]](https://www.wikiwand.com/en/ISO_639-1) +Each new language will require a language code to use it. This code is determined by [ISO-639-1](https://www.loc.gov/standards/iso639-2/php/langcodes-keyword.php).[[1]](https://www.wikiwand.com/en/ISO_639-1) When contributing, you should add a file and a directory: `src/.jl`, and `src//`. Within the latter, this is where you should store any language-specific dictionaries. From e40d696a779fd0de9dde68206fe2b90681cf3e6c Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 19 Sep 2022 23:43:06 +1200 Subject: [PATCH 093/120] Remove accidental, temp emacs file --- src/.#mi.jl | 1 - 1 file changed, 1 deletion(-) delete mode 120000 src/.#mi.jl diff --git a/src/.#mi.jl b/src/.#mi.jl deleted file mode 120000 index 8850b414..00000000 --- a/src/.#mi.jl +++ /dev/null @@ -1 +0,0 @@ -jakeireland@jake-mbp2017.local.35989 \ No newline at end of file From 3474a6d304e6346b716a606f5375f095b96aad36 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Mon, 19 Sep 2022 23:43:06 +1200 Subject: [PATCH 094/120] Remove accidental, temp emacs file --- src/.#mi.jl | 1 - 1 file changed, 1 deletion(-) delete mode 120000 src/.#mi.jl diff --git a/src/.#mi.jl b/src/.#mi.jl deleted file mode 120000 index 8850b414..00000000 --- a/src/.#mi.jl +++ /dev/null @@ -1 +0,0 @@ -jakeireland@jake-mbp2017.local.35989 \ No newline at end of file From 7c392abbb0774478d3d9f71dfbdff3320c3e0b7c Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 00:02:38 +1200 Subject: [PATCH 095/120] Align tests cases by result Just for formatting reasons, I wanted to align test cases by their result (i.e., by `==`). --- test/runtests.jl | 176 +++++++++++++++++++++++------------------------ 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 54a3ff32..fec85322 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,35 +3,35 @@ using Test using SpelledOut @testset "English" begin - @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" - @test spelled_out(1234, lang = :en_US) == "one thousand, two hundred thirty-four" - @test spelled_out(1234, lang = :en_UK) == "one thousand, two hundred and thirty-four" - @test spelled_out(123456789, lang = :en) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, lang = :en_UK) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(0, lang = :en) == "zero" - @test spelled_out(0, lang = :en_UK) == "zero" - @test spelled_out(100, lang = :en) == "one hundred" - @test spelled_out(100, lang = :en_UK) == "one hundred" - @test spelled_out(123456789, lang = :en_UK, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(123456789, lang = :en, dict=:european) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, lang = :en_UK, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" + @test spelled_out(1234, lang = :en_US) == "one thousand, two hundred thirty-four" + @test spelled_out(1234, lang = :en_UK) == "one thousand, two hundred and thirty-four" + @test spelled_out(123456789, lang = :en) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, lang = :en_UK) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(0, lang = :en) == "zero" + @test spelled_out(0, lang = :en_UK) == "zero" + @test spelled_out(100, lang = :en) == "one hundred" + @test spelled_out(100, lang = :en_UK) == "one hundred" + @test spelled_out(123456789, lang = :en_UK, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(123456789, lang = :en, dict=:european) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, lang = :en_UK, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" @test spelled_out(1234567890123, lang = :en_UK, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" - @test spelled_out(1234567890123, lang = :en_UK, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" - @test spelled_out(3.0, lang = :en) == "three" - @test spelled_out(3, lang = :en) == "three" - @test spelled_out(3.141592653589793, lang = :en) == "three point one four one five nine two six five three five eight nine seven nine three" - @test spelled_out(2^log2(3390000), lang = :en) == "three million, three hundred ninety thousand" # should convert 3.3899999999999986e6 to an integer - @test spelled_out(1000000.01, lang = :en) == "one million point zero one" # parse big floats correctly (i.e., avoid scientific notation. Caveat: this is slow) - @test spelled_out(1//3, lang = :en_UK) == "one third" - @test spelled_out(1//5, lang = :en_UK) == "one fifth" - @test spelled_out(1//102, lang = :en_UK) == "one one hundred and second" - @test spelled_out(1//102, lang = :en_US) == "one one hundred second" - @test spelled_out(5//102, lang = :en_UK) == "five one hundred and seconds" - @test spelled_out(5//12, lang = :en_UK) == "five twelfths" - @test spelled_out(1//1, lang = :en_UK) == "one" - @test spelled_out(40//1, lang = :en_UK) == "forty" - @test spelled_out(40//2, lang = :en_UK) == "twenty" - @test spelled_out(40//6, lang = :en_UK) == "twenty thirds" + @test spelled_out(1234567890123, lang = :en_UK, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" + @test spelled_out(3.0, lang = :en) == "three" + @test spelled_out(3, lang = :en) == "three" + @test spelled_out(3.141592653589793, lang = :en) == "three point one four one five nine two six five three five eight nine seven nine three" + @test spelled_out(2^log2(3390000), lang = :en) == "three million, three hundred ninety thousand" # should convert 3.3899999999999986e6 to an integer + @test spelled_out(1000000.01, lang = :en) == "one million point zero one" # parse big floats correctly (i.e., avoid scientific notation. Caveat: this is slow) + @test spelled_out(1//3, lang = :en_UK) == "one third" + @test spelled_out(1//5, lang = :en_UK) == "one fifth" + @test spelled_out(1//102, lang = :en_UK) == "one one hundred and second" + @test spelled_out(1//102, lang = :en_US) == "one one hundred second" + @test spelled_out(5//102, lang = :en_UK) == "five one hundred and seconds" + @test spelled_out(5//12, lang = :en_UK) == "five twelfths" + @test spelled_out(1//1, lang = :en_UK) == "one" + @test spelled_out(40//1, lang = :en_UK) == "forty" + @test spelled_out(40//2, lang = :en_UK) == "twenty" + @test spelled_out(40//6, lang = :en_UK) == "twenty thirds" end @@ -43,66 +43,66 @@ end @testset "Māori" begin # Source: https://www.maori.cl/learn/numbers.htm - @test spelled_out(0, lang = :mi) == "kore" - @test spelled_out(1, lang = :mi) == "tahi" - @test spelled_out(2, lang = :mi) == "rua" - @test spelled_out(3, lang = :mi) == "toru" - @test spelled_out(4, lang = :mi) == "whā" - @test spelled_out(5, lang = :mi) == "rima" - @test spelled_out(6, lang = :mi) == "ono" - @test spelled_out(7, lang = :mi) == "whitu" - @test spelled_out(8, lang = :mi) == "waru" - @test spelled_out(9, lang = :mi) == "iwa" - @test spelled_out(10, lang = :mi) == "tekau" - @test spelled_out(11, lang = :mi) == "tekau mā tahi" - @test spelled_out(12, lang = :mi) == "tekau mā rua" - @test spelled_out(13, lang = :mi) == "tekau mā toru" - @test spelled_out(14, lang = :mi) == "tekau mā whā" - @test spelled_out(15, lang = :mi) == "tekau mā rima" - @test spelled_out(16, lang = :mi) == "tekau mā ono" - @test spelled_out(17, lang = :mi) == "tekau mā whitu" - @test spelled_out(18, lang = :mi) == "tekau mā waru" - @test spelled_out(19, lang = :mi) == "tekau mā iwa" - @test spelled_out(20, lang = :mi) == "rua tekau" - @test spelled_out(21, lang = :mi) == "rua tekau mā tahi" - @test spelled_out(22, lang = :mi) == "rua tekau mā rua" - @test spelled_out(23, lang = :mi) == "rua tekau mā toru" - @test spelled_out(30, lang = :mi) == "toru tekau" - @test spelled_out(35, lang = :mi) == "" # TODO - @test spelled_out(40, lang = :mi) == "whā tekau" - @test spelled_out(50, lang = :mi) == "rima tekau" - @test spelled_out(60, lang = :mi) == "ono tekau" - @test spelled_out(70, lang = :mi) == "whitu tekau" - @test spelled_out(80, lang = :mi) == "waru tekau" - @test spelled_out(90, lang = :mi) == "iwa tekau" - @test spelled_out(100, lang = :mi) == "kotahi rau" - @test spelled_out(101, lang = :mi) == "kotahi rau tahi" - @test spelled_out(111, lang = :mi) == "kotahi rau tekau mā tahi" - @test spelled_out(200, lang = :mi) == "rua rau" - @test spelled_out(234, lang = :mi) == "rua rau toru tekau mā whā" - @test spelled_out(300, lang = :mi) == "toru rau" - @test spelled_out(400, lang = :mi) == "whā rau" - @test spelled_out(500, lang = :mi) == "rima rau" - @test spelled_out(600, lang = :mi) == "ono rau" - @test spelled_out(700, lang = :mi) == "whitu rau" - @test spelled_out(800, lang = :mi) == "waru rau" - @test spelled_out(900, lang = :mi) == "iwa rau" - @test spelled_out(1000, lang = :mi) == "kotahi mano" - @test spelled_out(1982, lang = :mi) == "kotahi mano, iwa rau, waru tekau mā rua" - @test spelled_out(2000, lang = :mi) == "rua mano" - @test spelled_out(2016, lang = :mi) == "rua mano, tekau mā ono" - @test spelled_out(2022, lang = :mi) == "" # TODO - @test spelled_out(3000, lang = :mi) == "toru mano" - @test spelled_out(4000, lang = :mi) == "whā mano" - @test spelled_out(5000, lang = :mi) == "rima mano" - @test spelled_out(6000, lang = :mi) == "ono mano" - @test spelled_out(7000, lang = :mi) == "whitu mano" - @test spelled_out(8000, lang = :mi) == "waru mano" - @test spelled_out(9000, lang = :mi) == "iwa mano" - @test spelled_out(9100, lang = :mi) == "" # TODO - @test spelled_out(10_000, lang = :mi) == "tekau mano" - @test spelled_out(1_000_000, lang = :mi) == "kotahi miriona" - @test spelled_out(2_000_000, lang = :mi) == "rua miriona" + @test spelled_out(0, lang = :mi) == "kore" + @test spelled_out(1, lang = :mi) == "tahi" + @test spelled_out(2, lang = :mi) == "rua" + @test spelled_out(3, lang = :mi) == "toru" + @test spelled_out(4, lang = :mi) == "whā" + @test spelled_out(5, lang = :mi) == "rima" + @test spelled_out(6, lang = :mi) == "ono" + @test spelled_out(7, lang = :mi) == "whitu" + @test spelled_out(8, lang = :mi) == "waru" + @test spelled_out(9, lang = :mi) == "iwa" + @test spelled_out(10, lang = :mi) == "tekau" + @test spelled_out(11, lang = :mi) == "tekau mā tahi" + @test spelled_out(12, lang = :mi) == "tekau mā rua" + @test spelled_out(13, lang = :mi) == "tekau mā toru" + @test spelled_out(14, lang = :mi) == "tekau mā whā" + @test spelled_out(15, lang = :mi) == "tekau mā rima" + @test spelled_out(16, lang = :mi) == "tekau mā ono" + @test spelled_out(17, lang = :mi) == "tekau mā whitu" + @test spelled_out(18, lang = :mi) == "tekau mā waru" + @test spelled_out(19, lang = :mi) == "tekau mā iwa" + @test spelled_out(20, lang = :mi) == "rua tekau" + @test spelled_out(21, lang = :mi) == "rua tekau mā tahi" + @test spelled_out(22, lang = :mi) == "rua tekau mā rua" + @test spelled_out(23, lang = :mi) == "rua tekau mā toru" + @test spelled_out(30, lang = :mi) == "toru tekau" + @test spelled_out(35, lang = :mi) == "" # TODO + @test spelled_out(40, lang = :mi) == "whā tekau" + @test spelled_out(50, lang = :mi) == "rima tekau" + @test spelled_out(60, lang = :mi) == "ono tekau" + @test spelled_out(70, lang = :mi) == "whitu tekau" + @test spelled_out(80, lang = :mi) == "waru tekau" + @test spelled_out(90, lang = :mi) == "iwa tekau" + @test spelled_out(100, lang = :mi) == "kotahi rau" + @test spelled_out(101, lang = :mi) == "kotahi rau tahi" + @test spelled_out(111, lang = :mi) == "kotahi rau tekau mā tahi" + @test spelled_out(200, lang = :mi) == "rua rau" + @test spelled_out(234, lang = :mi) == "rua rau toru tekau mā whā" + @test spelled_out(300, lang = :mi) == "toru rau" + @test spelled_out(400, lang = :mi) == "whā rau" + @test spelled_out(500, lang = :mi) == "rima rau" + @test spelled_out(600, lang = :mi) == "ono rau" + @test spelled_out(700, lang = :mi) == "whitu rau" + @test spelled_out(800, lang = :mi) == "waru rau" + @test spelled_out(900, lang = :mi) == "iwa rau" + @test spelled_out(1000, lang = :mi) == "kotahi mano" + @test spelled_out(1982, lang = :mi) == "kotahi mano, iwa rau, waru tekau mā rua" + @test spelled_out(2000, lang = :mi) == "rua mano" + @test spelled_out(2016, lang = :mi) == "rua mano, tekau mā ono" + @test spelled_out(2022, lang = :mi) == "" # TODO + @test spelled_out(3000, lang = :mi) == "toru mano" + @test spelled_out(4000, lang = :mi) == "whā mano" + @test spelled_out(5000, lang = :mi) == "rima mano" + @test spelled_out(6000, lang = :mi) == "ono mano" + @test spelled_out(7000, lang = :mi) == "whitu mano" + @test spelled_out(8000, lang = :mi) == "waru mano" + @test spelled_out(9000, lang = :mi) == "iwa mano" + @test spelled_out(9100, lang = :mi) == "" # TODO + @test spelled_out(10_000, lang = :mi) == "tekau mano" + @test spelled_out(1_000_000, lang = :mi) == "kotahi miriona" + @test spelled_out(2_000_000, lang = :mi) == "rua miriona" @test spelled_out(3_000_000_000, lang = :mi) == "toru piriona" end From bd7ad2da743722c67a4a0392f87252d68ed9f5bd Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 00:02:38 +1200 Subject: [PATCH 096/120] Align tests cases by result Just for formatting reasons, I wanted to align test cases by their result (i.e., by `==`). --- test/runtests.jl | 176 +++++++++++++++++++++++------------------------ 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 54a3ff32..fec85322 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -3,35 +3,35 @@ using Test using SpelledOut @testset "English" begin - @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" - @test spelled_out(1234, lang = :en_US) == "one thousand, two hundred thirty-four" - @test spelled_out(1234, lang = :en_UK) == "one thousand, two hundred and thirty-four" - @test spelled_out(123456789, lang = :en) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, lang = :en_UK) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(0, lang = :en) == "zero" - @test spelled_out(0, lang = :en_UK) == "zero" - @test spelled_out(100, lang = :en) == "one hundred" - @test spelled_out(100, lang = :en_UK) == "one hundred" - @test spelled_out(123456789, lang = :en_UK, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" - @test spelled_out(123456789, lang = :en, dict=:european) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" - @test spelled_out(123456789, lang = :en_UK, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(1234, lang = :en) == "one thousand, two hundred thirty-four" + @test spelled_out(1234, lang = :en_US) == "one thousand, two hundred thirty-four" + @test spelled_out(1234, lang = :en_UK) == "one thousand, two hundred and thirty-four" + @test spelled_out(123456789, lang = :en) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, lang = :en_UK) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(0, lang = :en) == "zero" + @test spelled_out(0, lang = :en_UK) == "zero" + @test spelled_out(100, lang = :en) == "one hundred" + @test spelled_out(100, lang = :en_UK) == "one hundred" + @test spelled_out(123456789, lang = :en_UK, dict=:european) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" + @test spelled_out(123456789, lang = :en, dict=:european) == "one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine" + @test spelled_out(123456789, lang = :en_UK, dict=:british) == "one hundred and twenty-three million, four hundred and fifty-six thousand, seven hundred and eighty-nine" @test spelled_out(1234567890123, lang = :en_UK, dict=:british) == "one billion, two hundred and thirty-four thousand million, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" - @test spelled_out(1234567890123, lang = :en_UK, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" - @test spelled_out(3.0, lang = :en) == "three" - @test spelled_out(3, lang = :en) == "three" - @test spelled_out(3.141592653589793, lang = :en) == "three point one four one five nine two six five three five eight nine seven nine three" - @test spelled_out(2^log2(3390000), lang = :en) == "three million, three hundred ninety thousand" # should convert 3.3899999999999986e6 to an integer - @test spelled_out(1000000.01, lang = :en) == "one million point zero one" # parse big floats correctly (i.e., avoid scientific notation. Caveat: this is slow) - @test spelled_out(1//3, lang = :en_UK) == "one third" - @test spelled_out(1//5, lang = :en_UK) == "one fifth" - @test spelled_out(1//102, lang = :en_UK) == "one one hundred and second" - @test spelled_out(1//102, lang = :en_US) == "one one hundred second" - @test spelled_out(5//102, lang = :en_UK) == "five one hundred and seconds" - @test spelled_out(5//12, lang = :en_UK) == "five twelfths" - @test spelled_out(1//1, lang = :en_UK) == "one" - @test spelled_out(40//1, lang = :en_UK) == "forty" - @test spelled_out(40//2, lang = :en_UK) == "twenty" - @test spelled_out(40//6, lang = :en_UK) == "twenty thirds" + @test spelled_out(1234567890123, lang = :en_UK, dict=:modern) == "one trillion, two hundred and thirty-four billion, five hundred and sixty-seven million, eight hundred and ninety thousand, one hundred and twenty-three" + @test spelled_out(3.0, lang = :en) == "three" + @test spelled_out(3, lang = :en) == "three" + @test spelled_out(3.141592653589793, lang = :en) == "three point one four one five nine two six five three five eight nine seven nine three" + @test spelled_out(2^log2(3390000), lang = :en) == "three million, three hundred ninety thousand" # should convert 3.3899999999999986e6 to an integer + @test spelled_out(1000000.01, lang = :en) == "one million point zero one" # parse big floats correctly (i.e., avoid scientific notation. Caveat: this is slow) + @test spelled_out(1//3, lang = :en_UK) == "one third" + @test spelled_out(1//5, lang = :en_UK) == "one fifth" + @test spelled_out(1//102, lang = :en_UK) == "one one hundred and second" + @test spelled_out(1//102, lang = :en_US) == "one one hundred second" + @test spelled_out(5//102, lang = :en_UK) == "five one hundred and seconds" + @test spelled_out(5//12, lang = :en_UK) == "five twelfths" + @test spelled_out(1//1, lang = :en_UK) == "one" + @test spelled_out(40//1, lang = :en_UK) == "forty" + @test spelled_out(40//2, lang = :en_UK) == "twenty" + @test spelled_out(40//6, lang = :en_UK) == "twenty thirds" end @@ -43,66 +43,66 @@ end @testset "Māori" begin # Source: https://www.maori.cl/learn/numbers.htm - @test spelled_out(0, lang = :mi) == "kore" - @test spelled_out(1, lang = :mi) == "tahi" - @test spelled_out(2, lang = :mi) == "rua" - @test spelled_out(3, lang = :mi) == "toru" - @test spelled_out(4, lang = :mi) == "whā" - @test spelled_out(5, lang = :mi) == "rima" - @test spelled_out(6, lang = :mi) == "ono" - @test spelled_out(7, lang = :mi) == "whitu" - @test spelled_out(8, lang = :mi) == "waru" - @test spelled_out(9, lang = :mi) == "iwa" - @test spelled_out(10, lang = :mi) == "tekau" - @test spelled_out(11, lang = :mi) == "tekau mā tahi" - @test spelled_out(12, lang = :mi) == "tekau mā rua" - @test spelled_out(13, lang = :mi) == "tekau mā toru" - @test spelled_out(14, lang = :mi) == "tekau mā whā" - @test spelled_out(15, lang = :mi) == "tekau mā rima" - @test spelled_out(16, lang = :mi) == "tekau mā ono" - @test spelled_out(17, lang = :mi) == "tekau mā whitu" - @test spelled_out(18, lang = :mi) == "tekau mā waru" - @test spelled_out(19, lang = :mi) == "tekau mā iwa" - @test spelled_out(20, lang = :mi) == "rua tekau" - @test spelled_out(21, lang = :mi) == "rua tekau mā tahi" - @test spelled_out(22, lang = :mi) == "rua tekau mā rua" - @test spelled_out(23, lang = :mi) == "rua tekau mā toru" - @test spelled_out(30, lang = :mi) == "toru tekau" - @test spelled_out(35, lang = :mi) == "" # TODO - @test spelled_out(40, lang = :mi) == "whā tekau" - @test spelled_out(50, lang = :mi) == "rima tekau" - @test spelled_out(60, lang = :mi) == "ono tekau" - @test spelled_out(70, lang = :mi) == "whitu tekau" - @test spelled_out(80, lang = :mi) == "waru tekau" - @test spelled_out(90, lang = :mi) == "iwa tekau" - @test spelled_out(100, lang = :mi) == "kotahi rau" - @test spelled_out(101, lang = :mi) == "kotahi rau tahi" - @test spelled_out(111, lang = :mi) == "kotahi rau tekau mā tahi" - @test spelled_out(200, lang = :mi) == "rua rau" - @test spelled_out(234, lang = :mi) == "rua rau toru tekau mā whā" - @test spelled_out(300, lang = :mi) == "toru rau" - @test spelled_out(400, lang = :mi) == "whā rau" - @test spelled_out(500, lang = :mi) == "rima rau" - @test spelled_out(600, lang = :mi) == "ono rau" - @test spelled_out(700, lang = :mi) == "whitu rau" - @test spelled_out(800, lang = :mi) == "waru rau" - @test spelled_out(900, lang = :mi) == "iwa rau" - @test spelled_out(1000, lang = :mi) == "kotahi mano" - @test spelled_out(1982, lang = :mi) == "kotahi mano, iwa rau, waru tekau mā rua" - @test spelled_out(2000, lang = :mi) == "rua mano" - @test spelled_out(2016, lang = :mi) == "rua mano, tekau mā ono" - @test spelled_out(2022, lang = :mi) == "" # TODO - @test spelled_out(3000, lang = :mi) == "toru mano" - @test spelled_out(4000, lang = :mi) == "whā mano" - @test spelled_out(5000, lang = :mi) == "rima mano" - @test spelled_out(6000, lang = :mi) == "ono mano" - @test spelled_out(7000, lang = :mi) == "whitu mano" - @test spelled_out(8000, lang = :mi) == "waru mano" - @test spelled_out(9000, lang = :mi) == "iwa mano" - @test spelled_out(9100, lang = :mi) == "" # TODO - @test spelled_out(10_000, lang = :mi) == "tekau mano" - @test spelled_out(1_000_000, lang = :mi) == "kotahi miriona" - @test spelled_out(2_000_000, lang = :mi) == "rua miriona" + @test spelled_out(0, lang = :mi) == "kore" + @test spelled_out(1, lang = :mi) == "tahi" + @test spelled_out(2, lang = :mi) == "rua" + @test spelled_out(3, lang = :mi) == "toru" + @test spelled_out(4, lang = :mi) == "whā" + @test spelled_out(5, lang = :mi) == "rima" + @test spelled_out(6, lang = :mi) == "ono" + @test spelled_out(7, lang = :mi) == "whitu" + @test spelled_out(8, lang = :mi) == "waru" + @test spelled_out(9, lang = :mi) == "iwa" + @test spelled_out(10, lang = :mi) == "tekau" + @test spelled_out(11, lang = :mi) == "tekau mā tahi" + @test spelled_out(12, lang = :mi) == "tekau mā rua" + @test spelled_out(13, lang = :mi) == "tekau mā toru" + @test spelled_out(14, lang = :mi) == "tekau mā whā" + @test spelled_out(15, lang = :mi) == "tekau mā rima" + @test spelled_out(16, lang = :mi) == "tekau mā ono" + @test spelled_out(17, lang = :mi) == "tekau mā whitu" + @test spelled_out(18, lang = :mi) == "tekau mā waru" + @test spelled_out(19, lang = :mi) == "tekau mā iwa" + @test spelled_out(20, lang = :mi) == "rua tekau" + @test spelled_out(21, lang = :mi) == "rua tekau mā tahi" + @test spelled_out(22, lang = :mi) == "rua tekau mā rua" + @test spelled_out(23, lang = :mi) == "rua tekau mā toru" + @test spelled_out(30, lang = :mi) == "toru tekau" + @test spelled_out(35, lang = :mi) == "" # TODO + @test spelled_out(40, lang = :mi) == "whā tekau" + @test spelled_out(50, lang = :mi) == "rima tekau" + @test spelled_out(60, lang = :mi) == "ono tekau" + @test spelled_out(70, lang = :mi) == "whitu tekau" + @test spelled_out(80, lang = :mi) == "waru tekau" + @test spelled_out(90, lang = :mi) == "iwa tekau" + @test spelled_out(100, lang = :mi) == "kotahi rau" + @test spelled_out(101, lang = :mi) == "kotahi rau tahi" + @test spelled_out(111, lang = :mi) == "kotahi rau tekau mā tahi" + @test spelled_out(200, lang = :mi) == "rua rau" + @test spelled_out(234, lang = :mi) == "rua rau toru tekau mā whā" + @test spelled_out(300, lang = :mi) == "toru rau" + @test spelled_out(400, lang = :mi) == "whā rau" + @test spelled_out(500, lang = :mi) == "rima rau" + @test spelled_out(600, lang = :mi) == "ono rau" + @test spelled_out(700, lang = :mi) == "whitu rau" + @test spelled_out(800, lang = :mi) == "waru rau" + @test spelled_out(900, lang = :mi) == "iwa rau" + @test spelled_out(1000, lang = :mi) == "kotahi mano" + @test spelled_out(1982, lang = :mi) == "kotahi mano, iwa rau, waru tekau mā rua" + @test spelled_out(2000, lang = :mi) == "rua mano" + @test spelled_out(2016, lang = :mi) == "rua mano, tekau mā ono" + @test spelled_out(2022, lang = :mi) == "" # TODO + @test spelled_out(3000, lang = :mi) == "toru mano" + @test spelled_out(4000, lang = :mi) == "whā mano" + @test spelled_out(5000, lang = :mi) == "rima mano" + @test spelled_out(6000, lang = :mi) == "ono mano" + @test spelled_out(7000, lang = :mi) == "whitu mano" + @test spelled_out(8000, lang = :mi) == "waru mano" + @test spelled_out(9000, lang = :mi) == "iwa mano" + @test spelled_out(9100, lang = :mi) == "" # TODO + @test spelled_out(10_000, lang = :mi) == "tekau mano" + @test spelled_out(1_000_000, lang = :mi) == "kotahi miriona" + @test spelled_out(2_000_000, lang = :mi) == "rua miriona" @test spelled_out(3_000_000_000, lang = :mi) == "toru piriona" end From 1132d0e1e2df85266ccac7a2f560388d33be2130 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 00:03:46 +1200 Subject: [PATCH 097/120] Add nicer error messages for bounds checking internal mi functions I had a lot of repeated error messages, so just make that simpler --- src/mi.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index b17adfa7..aa0bfd02 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -1,17 +1,21 @@ include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) +_fn_bounds_err_msg(n::I, bounds::String, fname::Symbol) where {I <: Integer} = + "The internal function \"$fname\" should only be used for numbers $bounds; number provided: $n" +# _fn_bounds_err_msg(, Base.StackTraces.stacktrace()[1].func) # Get current function name using metaprogramming + function ones_convert_mi(n::I) where {I <: Integer} - @assert(n ≤ 10, "The internal function \"ones_convert_mi\" should only be used for numbers ≤ 10; number provided: $n") + @assert(n ≤ 10, _fn_bounds_err_msg(n, "≤ 10", Base.StackTraces.stacktrace()[1].func)) return _mi_small_numbers[n + 1] end function tens_convert_mi(n::I) where {I <: Integer} - @assert(10 < n < 20, "The internal function \"tens_convert_mi\" should only be used for numbers 10 < n < 20; number provided: $n") + @assert(10 < n < 20, _fn_bounds_err_msg(n, "10 < n < 20", Base.StackTraces.stacktrace()[1].func)) return "$_mi_ten $_mi_ma $(ones_convert_mi(n - 10))" end function small_convert_mi(n::I) where {I <: Integer} - @assert(n < 1000, "The internal function \"small_convert_mi\" should only be used for numbers < 1000; number provided: $n") + @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) # 11, 12, ..., 19 n < 20 && return tens_convert_mi(n) # 10, 20, ..., 90 From d7886be7b2da09f45176805d7432ec1a05735894 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 00:03:46 +1200 Subject: [PATCH 098/120] Add nicer error messages for bounds checking internal mi functions I had a lot of repeated error messages, so just make that simpler --- src/mi.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index b17adfa7..aa0bfd02 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -1,17 +1,21 @@ include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) +_fn_bounds_err_msg(n::I, bounds::String, fname::Symbol) where {I <: Integer} = + "The internal function \"$fname\" should only be used for numbers $bounds; number provided: $n" +# _fn_bounds_err_msg(, Base.StackTraces.stacktrace()[1].func) # Get current function name using metaprogramming + function ones_convert_mi(n::I) where {I <: Integer} - @assert(n ≤ 10, "The internal function \"ones_convert_mi\" should only be used for numbers ≤ 10; number provided: $n") + @assert(n ≤ 10, _fn_bounds_err_msg(n, "≤ 10", Base.StackTraces.stacktrace()[1].func)) return _mi_small_numbers[n + 1] end function tens_convert_mi(n::I) where {I <: Integer} - @assert(10 < n < 20, "The internal function \"tens_convert_mi\" should only be used for numbers 10 < n < 20; number provided: $n") + @assert(10 < n < 20, _fn_bounds_err_msg(n, "10 < n < 20", Base.StackTraces.stacktrace()[1].func)) return "$_mi_ten $_mi_ma $(ones_convert_mi(n - 10))" end function small_convert_mi(n::I) where {I <: Integer} - @assert(n < 1000, "The internal function \"small_convert_mi\" should only be used for numbers < 1000; number provided: $n") + @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) # 11, 12, ..., 19 n < 20 && return tens_convert_mi(n) # 10, 20, ..., 90 From b157f7c075f9d021c87233d6cfbc30633e710bbc Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 00:52:28 +1200 Subject: [PATCH 099/120] =?UTF-8?q?Implement=20spelled=5Fout=20for=20numbe?= =?UTF-8?q?rs=20up=20to=20999=20for=20M=C4=81ori?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm not sure how I was aiming to implement it previously, as it has been a while since I've worked on this project, but I implemented numbers up to 999 this evening. It certainly doesn't feel as though I am doing this the most efficient way, but premature optimisation is the root of all evil; I can optimise once it is working. Overall, this commit has made good progress. --- src/mi.jl | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index aa0bfd02..6651c634 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -18,12 +18,30 @@ function small_convert_mi(n::I) where {I <: Integer} @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) # 11, 12, ..., 19 n < 20 && return tens_convert_mi(n) - # 10, 20, ..., 90 - s = "$(ones_convert_mi(fld(n, 10))) $(_mi_scale[1])" - if iszero(mod(n, 10)) && n < 100 + + # 20, 21, ..., 99 + if n < 100 + d, r = divrem(n, 10) + s = ones_convert_mi(d) * " " * _mi_ten + if !iszero(r) + s *= " " * _mi_ma * " " * ones_convert_mi(r) + end return s end + # 100, 101, ..., 999 + d, r = divrem(n, 100) + s = ones_convert_mi(d) + if isone(d) + s = "ko" * s # _ko_tahi; i.e., _mi_100 + end + s *= " " * _mi_scale[floor(Int, log10(n))] + if !iszero(r) + s *= " " * spelled_out_mi(r) + end + return s + + # Don't know what I was doing with this code below! s *= " $_mi_ma " # n′ = fld(n, 10) n′ = mod(n, 10) From e233741c01c1528b37fe3ae84697b4a9cde00c14 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 00:52:28 +1200 Subject: [PATCH 100/120] =?UTF-8?q?Implement=20spelled=5Fout=20for=20numbe?= =?UTF-8?q?rs=20up=20to=20999=20for=20M=C4=81ori?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm not sure how I was aiming to implement it previously, as it has been a while since I've worked on this project, but I implemented numbers up to 999 this evening. It certainly doesn't feel as though I am doing this the most efficient way, but premature optimisation is the root of all evil; I can optimise once it is working. Overall, this commit has made good progress. --- src/mi.jl | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index aa0bfd02..6651c634 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -18,12 +18,30 @@ function small_convert_mi(n::I) where {I <: Integer} @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) # 11, 12, ..., 19 n < 20 && return tens_convert_mi(n) - # 10, 20, ..., 90 - s = "$(ones_convert_mi(fld(n, 10))) $(_mi_scale[1])" - if iszero(mod(n, 10)) && n < 100 + + # 20, 21, ..., 99 + if n < 100 + d, r = divrem(n, 10) + s = ones_convert_mi(d) * " " * _mi_ten + if !iszero(r) + s *= " " * _mi_ma * " " * ones_convert_mi(r) + end return s end + # 100, 101, ..., 999 + d, r = divrem(n, 100) + s = ones_convert_mi(d) + if isone(d) + s = "ko" * s # _ko_tahi; i.e., _mi_100 + end + s *= " " * _mi_scale[floor(Int, log10(n))] + if !iszero(r) + s *= " " * spelled_out_mi(r) + end + return s + + # Don't know what I was doing with this code below! s *= " $_mi_ma " # n′ = fld(n, 10) n′ = mod(n, 10) From e4516d2277e1c5992aef6fd194664db5a8a5f62a Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 01:09:57 +1200 Subject: [PATCH 101/120] Account for edge case at 1000 saying kotahi --- src/mi.jl | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index 6651c634..72d79a34 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -15,7 +15,7 @@ function tens_convert_mi(n::I) where {I <: Integer} end function small_convert_mi(n::I) where {I <: Integer} - @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) + # @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) # 11, 12, ..., 19 n < 20 && return tens_convert_mi(n) @@ -62,7 +62,28 @@ function spelled_out_mi(n::I) where {I <: Integer} # 1, 2, ..., 10 n ≤ 10 && return ones_convert_mi(n) # 11, 12, ..., 999 - n < 1000 && return small_convert_mi(n) + # return small_convert_mi(n) + # n < 1000 && return small_convert_mi(n) # 1000, ... - error("not yet implemented") + + n < 20 && return tens_convert_mi(n) + + # 20, 21, ..., 99 + if n < 100 + d, r = divrem(n, 10) + s = ones_convert_mi(d) * " " * _mi_ten + if !iszero(r) + s *= " " * _mi_ma * " " * ones_convert_mi(r) + end + return s + end + + # 100, 101, ..., 999 + d, r = divrem(n, 100) + s = isone(d) || d == 10 ? _mi_100 : ones_convert_mi(d) + s *= " " * _mi_scale[floor(Int, log10(n))] + if !iszero(r) + s *= " " * spelled_out_mi(r) + end + return s end From dc2d79adaeacedc5d0186c4ec2992ab621108412 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 01:09:57 +1200 Subject: [PATCH 102/120] Account for edge case at 1000 saying kotahi --- src/mi.jl | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index 6651c634..72d79a34 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -15,7 +15,7 @@ function tens_convert_mi(n::I) where {I <: Integer} end function small_convert_mi(n::I) where {I <: Integer} - @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) + # @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) # 11, 12, ..., 19 n < 20 && return tens_convert_mi(n) @@ -62,7 +62,28 @@ function spelled_out_mi(n::I) where {I <: Integer} # 1, 2, ..., 10 n ≤ 10 && return ones_convert_mi(n) # 11, 12, ..., 999 - n < 1000 && return small_convert_mi(n) + # return small_convert_mi(n) + # n < 1000 && return small_convert_mi(n) # 1000, ... - error("not yet implemented") + + n < 20 && return tens_convert_mi(n) + + # 20, 21, ..., 99 + if n < 100 + d, r = divrem(n, 10) + s = ones_convert_mi(d) * " " * _mi_ten + if !iszero(r) + s *= " " * _mi_ma * " " * ones_convert_mi(r) + end + return s + end + + # 100, 101, ..., 999 + d, r = divrem(n, 100) + s = isone(d) || d == 10 ? _mi_100 : ones_convert_mi(d) + s *= " " * _mi_scale[floor(Int, log10(n))] + if !iszero(r) + s *= " " * spelled_out_mi(r) + end + return s end From 7b913dc56fb26d8029b9f985a4a2faae229cb613 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 01:15:28 +1200 Subject: [PATCH 103/120] Further correction of 1xxx edge case for kotahi --- src/mi.jl | 46 +--------------------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index 72d79a34..944b0ec6 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -14,50 +14,6 @@ function tens_convert_mi(n::I) where {I <: Integer} return "$_mi_ten $_mi_ma $(ones_convert_mi(n - 10))" end -function small_convert_mi(n::I) where {I <: Integer} - # @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) - # 11, 12, ..., 19 - n < 20 && return tens_convert_mi(n) - - # 20, 21, ..., 99 - if n < 100 - d, r = divrem(n, 10) - s = ones_convert_mi(d) * " " * _mi_ten - if !iszero(r) - s *= " " * _mi_ma * " " * ones_convert_mi(r) - end - return s - end - - # 100, 101, ..., 999 - d, r = divrem(n, 100) - s = ones_convert_mi(d) - if isone(d) - s = "ko" * s # _ko_tahi; i.e., _mi_100 - end - s *= " " * _mi_scale[floor(Int, log10(n))] - if !iszero(r) - s *= " " * spelled_out_mi(r) - end - return s - - # Don't know what I was doing with this code below! - s *= " $_mi_ma " - # n′ = fld(n, 10) - n′ = mod(n, 10) - # while !iszero(n) - while (n - rem(n, n′)) != n′ - s += " $(ones_convert_mi(n))" - n′ = mod(n′, 10) - # s += " $(small_convert_mi(n))" - # _mi_ma - # ones_convert_mi(fld(n, 10)), _mi_scale[1] - # m = mod(n, 10v) - # return s * small_convert_mi(m) - end - return s -end - function spelled_out_mi(n::I) where {I <: Integer} # 1, 2, ..., 10 n ≤ 10 && return ones_convert_mi(n) @@ -80,7 +36,7 @@ function spelled_out_mi(n::I) where {I <: Integer} # 100, 101, ..., 999 d, r = divrem(n, 100) - s = isone(d) || d == 10 ? _mi_100 : ones_convert_mi(d) + s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(d) s *= " " * _mi_scale[floor(Int, log10(n))] if !iszero(r) s *= " " * spelled_out_mi(r) From 496ae974fbb78a17c301d203368dc0bb11338e6c Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 01:15:28 +1200 Subject: [PATCH 104/120] Further correction of 1xxx edge case for kotahi --- src/mi.jl | 46 +--------------------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index 72d79a34..944b0ec6 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -14,50 +14,6 @@ function tens_convert_mi(n::I) where {I <: Integer} return "$_mi_ten $_mi_ma $(ones_convert_mi(n - 10))" end -function small_convert_mi(n::I) where {I <: Integer} - # @assert(n < 1000, _fn_bounds_err_msg(n, "< 1000", Base.StackTraces.stacktrace()[1].func)) - # 11, 12, ..., 19 - n < 20 && return tens_convert_mi(n) - - # 20, 21, ..., 99 - if n < 100 - d, r = divrem(n, 10) - s = ones_convert_mi(d) * " " * _mi_ten - if !iszero(r) - s *= " " * _mi_ma * " " * ones_convert_mi(r) - end - return s - end - - # 100, 101, ..., 999 - d, r = divrem(n, 100) - s = ones_convert_mi(d) - if isone(d) - s = "ko" * s # _ko_tahi; i.e., _mi_100 - end - s *= " " * _mi_scale[floor(Int, log10(n))] - if !iszero(r) - s *= " " * spelled_out_mi(r) - end - return s - - # Don't know what I was doing with this code below! - s *= " $_mi_ma " - # n′ = fld(n, 10) - n′ = mod(n, 10) - # while !iszero(n) - while (n - rem(n, n′)) != n′ - s += " $(ones_convert_mi(n))" - n′ = mod(n′, 10) - # s += " $(small_convert_mi(n))" - # _mi_ma - # ones_convert_mi(fld(n, 10)), _mi_scale[1] - # m = mod(n, 10v) - # return s * small_convert_mi(m) - end - return s -end - function spelled_out_mi(n::I) where {I <: Integer} # 1, 2, ..., 10 n ≤ 10 && return ones_convert_mi(n) @@ -80,7 +36,7 @@ function spelled_out_mi(n::I) where {I <: Integer} # 100, 101, ..., 999 d, r = divrem(n, 100) - s = isone(d) || d == 10 ? _mi_100 : ones_convert_mi(d) + s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(d) s *= " " * _mi_scale[floor(Int, log10(n))] if !iszero(r) s *= " " * spelled_out_mi(r) From f34bbc2c5c84e6a3ae6decea69af6c9d7ac9fdb4 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 01:22:39 +1200 Subject: [PATCH 105/120] Fix initial word by accounting for order of magnitude in mi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Māori's (mi) implementation of spelled_out, there is a special case in which 1xx and 1xxx numbers start with _ko_tahi (rather than just tahi, which is the equivalent of one). If the number is > 99 and is not 1xx or 1xxx, we need to use the first digit. I initially wrote the first digit as d being n ÷ 10, however this is not correct when n > 1000, so we have to account for order of magnitude --- src/mi.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index 944b0ec6..7674eea2 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -36,8 +36,9 @@ function spelled_out_mi(n::I) where {I <: Integer} # 100, 101, ..., 999 d, r = divrem(n, 100) - s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(d) - s *= " " * _mi_scale[floor(Int, log10(n))] + m = floor(Int, log10(n)) + s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(div(n, 10^m)) + s *= " " * _mi_scale[m] if !iszero(r) s *= " " * spelled_out_mi(r) end From 7b8e491fc28bd1e033f55653df3e4f8e33758cea Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Tue, 20 Sep 2022 01:22:39 +1200 Subject: [PATCH 106/120] Fix initial word by accounting for order of magnitude in mi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Māori's (mi) implementation of spelled_out, there is a special case in which 1xx and 1xxx numbers start with _ko_tahi (rather than just tahi, which is the equivalent of one). If the number is > 99 and is not 1xx or 1xxx, we need to use the first digit. I initially wrote the first digit as d being n ÷ 10, however this is not correct when n > 1000, so we have to account for order of magnitude --- src/mi.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index 944b0ec6..7674eea2 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -36,8 +36,9 @@ function spelled_out_mi(n::I) where {I <: Integer} # 100, 101, ..., 999 d, r = divrem(n, 100) - s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(d) - s *= " " * _mi_scale[floor(Int, log10(n))] + m = floor(Int, log10(n)) + s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(div(n, 10^m)) + s *= " " * _mi_scale[m] if !iszero(r) s *= " " * spelled_out_mi(r) end From adb801f0b12a57fd2fa051b4927e237bf3c339c9 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 22 Sep 2022 20:32:01 +1200 Subject: [PATCH 107/120] Changed bounds in comment --- src/mi.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mi.jl b/src/mi.jl index 7674eea2..3473b64f 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -34,7 +34,7 @@ function spelled_out_mi(n::I) where {I <: Integer} return s end - # 100, 101, ..., 999 + # 100, 101, ..., 9999 d, r = divrem(n, 100) m = floor(Int, log10(n)) s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(div(n, 10^m)) From 58a00b58efdb6e2f74352ac26476c41cdc531008 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 22 Sep 2022 20:32:01 +1200 Subject: [PATCH 108/120] Changed bounds in comment --- src/mi.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mi.jl b/src/mi.jl index 7674eea2..3473b64f 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -34,7 +34,7 @@ function spelled_out_mi(n::I) where {I <: Integer} return s end - # 100, 101, ..., 999 + # 100, 101, ..., 9999 d, r = divrem(n, 100) m = floor(Int, log10(n)) s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(div(n, 10^m)) From 12b0497df0437c66c5f0a2e69585c40944ce4862 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 22 Sep 2022 20:34:49 +1200 Subject: [PATCH 109/120] Added tests for Julia 1.0 and 1.6 --- .github/workflows/CI.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a1c06a2d..71ca9ae4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -15,8 +15,9 @@ jobs: fail-fast: false matrix: version: - - "1.5" # current - - "nightly" # Latest Release + - "1.0" # Old version + - "1.6" # Recent LTS version + - "nightly" # Latest release os: - ubuntu-latest - macOS-latest From fc9f07f00389755bd8b5cb5fa67eb70d4681e434 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 22 Sep 2022 20:34:49 +1200 Subject: [PATCH 110/120] Added tests for Julia 1.0 and 1.6 --- .github/workflows/CI.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a1c06a2d..71ca9ae4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -15,8 +15,9 @@ jobs: fail-fast: false matrix: version: - - "1.5" # current - - "nightly" # Latest Release + - "1.0" # Old version + - "1.6" # Recent LTS version + - "nightly" # Latest release os: - ubuntu-latest - macOS-latest From 176212851d5d95c60c64244691582b78896bb8f7 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Wed, 29 Mar 2023 23:27:19 +1300 Subject: [PATCH 111/120] =?UTF-8?q?More=20progress=20on=20spelling=20out?= =?UTF-8?q?=20postive=20integers=20in=20Te=20Reo=20(M=C4=81ori)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Requires heavy cleaning, but still just uncovering patterns etc. In fact, the basic implementation is nearly complete! Aside from a stray comma that may or may not be needed, and some larger number scales, this is done. Then I will be able to clean it up and decouple some patterns. I'm really pleased with how this is turning out. It's neat that I can't find any implementation of this before now, and I'm pleased that it's almost finished, despite my busy schedule (I haven't worked on it in a while, but picked it up again tonight in the spirit of procrastination). Once the basic implementation is done, I will be able to ensure this works for negative numbers, and possibly ordinal numbers (we will see). After that I should be able to merge it into trunk and make a release! There are also a few semantics I need to check on, but these would be minor changes. --- src/mi.jl | 115 ++++++++++++++++++----- src/mi/standard_dictionary_numbers_mi.jl | 6 +- test/runtests.jl | 15 ++- 3 files changed, 100 insertions(+), 36 deletions(-) diff --git a/src/mi.jl b/src/mi.jl index 3473b64f..f6af4604 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -1,46 +1,109 @@ include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) -_fn_bounds_err_msg(n::I, bounds::String, fname::Symbol) where {I <: Integer} = +# TODO: kotahi vs tahi (https://animations.tewhanake.maori.nz/te-kakano/te-wahanga-tuatahi/30) +# TODO: Ordinal numbers (https://omniglot.com/language/numbers/maori.htm) +# TODO: negatives +# TODO: kotahi or kotahi rau? + +_fn_bounds_err_msg(n::I, bounds::String, fname::Symbol) where {I <: Integer} = "The internal function \"$fname\" should only be used for numbers $bounds; number provided: $n" # _fn_bounds_err_msg(, Base.StackTraces.stacktrace()[1].func) # Get current function name using metaprogramming -function ones_convert_mi(n::I) where {I <: Integer} +function _ones_convert_mi(n::I) where {I <: Integer} @assert(n ≤ 10, _fn_bounds_err_msg(n, "≤ 10", Base.StackTraces.stacktrace()[1].func)) return _mi_small_numbers[n + 1] end -function tens_convert_mi(n::I) where {I <: Integer} +function _teens_convert_mi(n::I) where {I <: Integer} @assert(10 < n < 20, _fn_bounds_err_msg(n, "10 < n < 20", Base.StackTraces.stacktrace()[1].func)) - return "$_mi_ten $_mi_ma $(ones_convert_mi(n - 10))" + return "$_mi_ten $_mi_ma $(_ones_convert_mi(n - 10))" end -function spelled_out_mi(n::I) where {I <: Integer} - # 1, 2, ..., 10 - n ≤ 10 && return ones_convert_mi(n) - # 11, 12, ..., 999 - # return small_convert_mi(n) - # n < 1000 && return small_convert_mi(n) - # 1000, ... - - n < 20 && return tens_convert_mi(n) - - # 20, 21, ..., 99 - if n < 100 - d, r = divrem(n, 10) - s = ones_convert_mi(d) * " " * _mi_ten - if !iszero(r) - s *= " " * _mi_ma * " " * ones_convert_mi(r) - end - return s +function _tens_convert_mi(n::I) where {I <: Integer} + @assert(20 ≤ n < 100, _fn_bounds_err_msg(n, "20 ≤ n < 100", Base.StackTraces.stacktrace()[1].func)) + d, r = divrem(n, 10) + s = _ones_convert_mi(d) * " " * _mi_ten + if !iszero(r) + s *= " " * _mi_ma * " " * _ones_convert_mi(r) + end + return s +end + +function _hundreds_convert_mi(n::I) where {I <: Integer} + @assert(100 ≤ n < 1000, _fn_bounds_err_msg(n, "100 ≤ n < 1000", Base.StackTraces.stacktrace()[1].func)) + d, r = divrem(n, 100) + s = isone(d) ? _mi_kotahi : _spelled_out_mi(d) + s *= " "* _mi_100 + if !iszero(r) + s *= " " * _spelled_out_mi(r) end - - # 100, 101, ..., 9999 + return s +end + +function _large_convert_mi(n::I) where {I <: Integer} + # TODO: might not be used + s = isone(mod(n, 10)) ? _mi_kotahi : _ones_convert_mi(n) + return "$s $_mi_100 $(_spelled_out_mi(mod(n, 10)))" + # @assert(10 < n < 20, _fn_bounds_err_msg(n, "", Base.StackTraces.stacktrace()[1].func)) d, r = divrem(n, 100) m = floor(Int, log10(n)) - s = isone(d) || isone(div(n, 1000)) ? _mi_100 : spelled_out_mi(div(n, 10^m)) + s = isone(d) || isone(div(n, 1000)) ? _mi_100 : _spelled_out_mi(div(n, 10^m)) + # println(n, " ", m, " ", divrem(n, 100)) s *= " " * _mi_scale[m] if !iszero(r) - s *= " " * spelled_out_mi(r) + s *= " " * _spelled_out_mi(r) end return s end + +function _spelled_out_mi(n::I) where {I <: Integer} + n ≤ 10 && return _ones_convert_mi(n) # 1, 2, ..., 10 + n < 20 && return _teens_convert_mi(n) # 11, 12, ..., 19 + n < 100 && return _tens_convert_mi(n) # 20, 21, ..., 99 + n < 1000 && return _hundreds_convert_mi(n) # 101, 102, ..., 999 + + # 1000, 1001, ... + n′ = abs(n) # TODO: negatives + s = "" + + for v in 0:length(_mi_scale_large) + d_number = round(big(1000)^v) + # println(" skipping $v") + + if d_number > n′ + modulus = big(1000)^(v - 1) + l, r = divrem(n′, modulus) + # println("modulus=$modulus, n=$(n′), l=$l, l′=$(mod(l, 100)), r=$r, v=$v, d_number=$d_number, s=\"$s\"") + + l′ = mod(l, 100) + + # if isone(l′) + # s *= _mi_kotahi + # elseif isone(mod(l, 10)) + # s *= + # else + # s *= _spelled_out_mi(l′) + # end + s *= isone(l′) ? _mi_kotahi : _spelled_out_mi(l) + r′ = div(l, 100) + if isone(l′) && !iszero(r′) + s *= _spelled_out_mi(r′) + end + # s *= _spelled_out_mi(mod(l, 1000)) + s *= " " * _mi_scale_large[v - 1] + # s *= " " * (l > 1000 ? _mi_scale_large[v - 1] : _mi_scale[v - 1]) + + if r > 0 + s *= ", " * _spelled_out_mi(r) + end + + return s + end + end + + error("Unreachable") +end + +function spelled_out_mi(n::I) where {I <: Integer} + return _spelled_out_mi(n) +end diff --git a/src/mi/standard_dictionary_numbers_mi.jl b/src/mi/standard_dictionary_numbers_mi.jl index a07728a6..bbf57aed 100644 --- a/src/mi/standard_dictionary_numbers_mi.jl +++ b/src/mi/standard_dictionary_numbers_mi.jl @@ -5,9 +5,11 @@ const _mi_small_numbers = String[ "kore", "tahi", "rua", "toru", "whā", "rima", "ono", "whitu", "waru", "iwa", _mi_ten ] -const _mi_100 = "kotahi" +const _mi_kotahi = "kotahi" +const _mi_100 = "rau" const _mi_scale = String[ - _mi_ten, "rau", "mano", "miriona", "piriona" + _mi_ten, _mi_100, "mano", "miriona", "piriona" ] +const _mi_scale_large = _mi_scale[3:end] diff --git a/test/runtests.jl b/test/runtests.jl index c7dff2c7..36267559 100755 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -44,8 +44,8 @@ end @test spelled_out(19, lang = :pt) == "dezanove" @test spelled_out(0.9, lang = :pt) == "nove décimos" @test spelled_out(14, lang = :pt) == "catorze" - @test spelled_out(-10, lang = :pt) == "menos dez" - @test spelled_out(-109, lang = :pt) == "menos cento e nove" + @test spelled_out(-10, lang = :pt) == "menos dez" + @test spelled_out(-109, lang = :pt) == "menos cento e nove" @test spelled_out(105, lang = :pt) == "cento e cinco" end @testset "Brazilian Portuguese" begin @@ -55,8 +55,8 @@ end @test spelled_out(0.09, lang = :pt_BR) == "nove centésimos" @test spelled_out(0.009, lang = :pt_BR) == "nove milésimos" @test spelled_out(0.0009, lang = :pt_BR) == "nove milionésimos" - @test spelled_out(-10, lang = :pt_BR) == "menos dez" - @test spelled_out(-109, lang = :pt_BR) == "menos cento e nove" + @test spelled_out(-10, lang = :pt_BR) == "menos dez" + @test spelled_out(-109, lang = :pt_BR) == "menos cento e nove" @test spelled_out(100, lang = :pt_BR) == "cem" @test spelled_out(105, lang = :pt_BR) == "cento e cinco" @test spelled_out(19, lang = :pt_BR) == "dezenove" @@ -91,7 +91,7 @@ end @test spelled_out(22, lang = :mi) == "rua tekau mā rua" @test spelled_out(23, lang = :mi) == "rua tekau mā toru" @test spelled_out(30, lang = :mi) == "toru tekau" - @test spelled_out(35, lang = :mi) == "" # TODO + @test spelled_out(35, lang = :mi) == "toru tekau mā rima" # TODO: check that this is correct @test spelled_out(40, lang = :mi) == "whā tekau" @test spelled_out(50, lang = :mi) == "rima tekau" @test spelled_out(60, lang = :mi) == "ono tekau" @@ -114,7 +114,7 @@ end @test spelled_out(1982, lang = :mi) == "kotahi mano, iwa rau, waru tekau mā rua" @test spelled_out(2000, lang = :mi) == "rua mano" @test spelled_out(2016, lang = :mi) == "rua mano, tekau mā ono" - @test spelled_out(2022, lang = :mi) == "" # TODO + @test spelled_out(2022, lang = :mi) == "rua mano, rua tekau mā rua" # TODO: check that this is correct @test spelled_out(3000, lang = :mi) == "toru mano" @test spelled_out(4000, lang = :mi) == "whā mano" @test spelled_out(5000, lang = :mi) == "rima mano" @@ -122,10 +122,9 @@ end @test spelled_out(7000, lang = :mi) == "whitu mano" @test spelled_out(8000, lang = :mi) == "waru mano" @test spelled_out(9000, lang = :mi) == "iwa mano" - @test spelled_out(9100, lang = :mi) == "" # TODO + @test spelled_out(9100, lang = :mi) == "iwa mano, kotahi rau" # TODO: check that this is correct @test spelled_out(10_000, lang = :mi) == "tekau mano" @test spelled_out(1_000_000, lang = :mi) == "kotahi miriona" @test spelled_out(2_000_000, lang = :mi) == "rua miriona" @test spelled_out(3_000_000_000, lang = :mi) == "toru piriona" end - From f9b9beda1333a1d1313bf7f91783d73c387ce243 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Thu, 6 Apr 2023 00:26:16 +1200 Subject: [PATCH 112/120] Add author and timeline information to top of main lang files --- src/en.jl | 65 +++++++++++++++++++++++++++++-------------------------- src/es.jl | 19 ++++++---------- src/mi.jl | 2 ++ src/pt.jl | 38 ++++++++++++++++---------------- src/ru.jl | 4 +++- 5 files changed, 65 insertions(+), 63 deletions(-) diff --git a/src/en.jl b/src/en.jl index fb8aec81..1e0eb064 100644 --- a/src/en.jl +++ b/src/en.jl @@ -1,3 +1,6 @@ +# Jake Ireland (October–November, 2020) +# https://github.com/jakewilliami/SpelledOut.jl/commit/f0248d944de20804aae9f3eeb6a6ff1c1853ac99#diff-4933f64df61b24196bb1770cdc1ef08c680da0f45b3486d633a2ad180ffb417f + # dictionaries include(joinpath(@__DIR__, "en", "standard_dictionary_numbers_extended.jl")) include(joinpath(@__DIR__, "en", "large_standard_dictionary_numbers_extended.jl")) @@ -5,19 +8,19 @@ include(joinpath(@__DIR__, "en", "ordinal_dictionaries.jl")) # utils include(joinpath(@__DIR__, "en", "utils.jl")) - + # convert a value < 100 to English. function _small_convert_en!(io::IOBuffer, number::Integer) if number < 20 print(io, _small_numbers[number + 1]) return io end - + m = mod(number, 10) - + for (v, d̂) in enumerate(_tens) d = 20 + 10 * (v - 1) - + if d + 10 > number if m ≠ 0 n = _small_numbers[m + 1] @@ -28,7 +31,7 @@ function _small_convert_en!(io::IOBuffer, number::Integer) return io end end - + return io end @@ -44,7 +47,7 @@ end function _large_convert_en!(io::IOBuffer, number::Integer; british::Bool = false) divisor = div(number, 100) modulus = mod(number, 100) - + if divisor > 0 print(io, _small_numbers[divisor + 1], " hundred") if modulus > 0 @@ -57,11 +60,11 @@ function _large_convert_en!(io::IOBuffer, number::Integer; british::Bool = false print(io, "and ") end end - + if modulus > 0 _small_convert_en!(io, modulus) end - + return io end @@ -82,47 +85,47 @@ function _spelled_out_en!(io::IOBuffer, number_norm::Integer; british::Bool = fa else error("Unrecognized dict value: $dict") end - + if number_norm < 0 print(io, "negative ") end - + if number_norm > limit - 1 error("""SpelledOut.jl does not support numbers larger than $(limit_str * " - 1"). Sorry about that!""") end - - + + if number_norm < 100 _small_convert_en!(io, number_norm) return io end - + if number_norm < 1000 _large_convert_en!(io, number_norm, british = british) return io end - + number = abs(number_norm) - + for v in 0:length(scale_numbers) d_idx = v d_number = round(big(1000)^v) - + if d_number > number modulus = big(1000)^(d_idx - 1) l, r = divrem(number, modulus) - + _large_convert_en!(io, l, british = british) - print(io, " ", scale_numbers[d_idx - 1]) + print(io, " ", scale_numbers[d_idx - 1]) if r > 0 print(io, ", ") _spelled_out_en!(io, r, british = british, dict = dict) end - + return io end end - + error("Unreachable") end @@ -137,7 +140,7 @@ function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = word_buf = IOBuffer() _spelled_out_en!(word_buf, number, british = british, dict = dict) s = String(take!(word_buf)) - + lastword = lastsplit(isspace, s) redolast = lastsplit('-', lastword) @@ -148,13 +151,13 @@ function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = _lastsplit = ' ' word = lastword end - + firstpart = firstlastsplit(_lastsplit, s) if firstpart != word print(word_buf, firstpart, _lastsplit) end - + if haskey(irregular, word) print(word_buf, irregular[word]) elseif word[end] == 'y' @@ -162,7 +165,7 @@ function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = else print(word_buf, word, suffix) end - + return String(take!(word_buf)) end @@ -174,11 +177,11 @@ function decimal_convert_en(number::AbstractString; british::Bool = false, dict: word_buf = IOBuffer() _spelled_out_en!(word_buf, parse(BigInt, whole), british = british, dict = dict) print(word_buf, " point") - + for i in decimal print(word_buf, ' ', _small_number_dictionary[i]) end - + return String(take!(word_buf)) end @@ -193,7 +196,7 @@ function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symb # E.g., 1e10 should be parsed as an integer (as should 1.0e10) number = parse(BigInt, str_number) end - + if isa(number, AbstractString) # if the number is a string then it is a decimal, which is formatted precisely # for correct precision with decimal places @@ -204,7 +207,7 @@ function spelled_out_en(number::AbstractFloat; british::Bool = false, dict::Symb else throw(error("Cannot parse type $(typeof(number)). Please make an issue.")) end - + # should never get here return nothing end @@ -216,12 +219,12 @@ end function spelled_out_en(number::Rational; british::Bool = false, dict::Symbol = :modern) _num, _den = number.num, number.den - + # return the number itself if the denomimator is one isone(_den) && return spelled_out_en(_num, british = british, dict = dict) - + word = spelled_out_en(_num, british = british, dict = dict) * " " * spell_ordinal_en(_den, british = british, dict = dict) - + # account for pluralisation return isone(_num) ? word : word * "s" end diff --git a/src/es.jl b/src/es.jl index d87bc358..100755bb 100644 --- a/src/es.jl +++ b/src/es.jl @@ -1,3 +1,5 @@ +# Andrés Riedemann (January, 2021) + include(joinpath(@__DIR__, "es", "standard_es.jl")) function es_spell_1e3(number,short_one=false) @@ -22,7 +24,7 @@ function es_spell_1e3(number,short_one=false) end return es_decenas[dec] * unit_text end - elseif 100 <= number <= 999 + elseif 100 <= number <= 999 number == 100 && return "cien" unit,cent = digits(number,base=100) unit_text = es_spell_1e3(unit,short_one) @@ -78,7 +80,7 @@ function es_spell_large_map(number,i) elseif isone(number) return "un " * es_multiplos_1e6_singular[i-1] else - + return es_spell_1e6(number,false) * " " * es_multiplos_1e6_plural[i-1] end end @@ -106,14 +108,14 @@ function spelled_out_es(number; dict=:standard) end return res else #with decimals - + #delete this when proper separate keywords are implemented partitive = true _dec,_int = modf(number) _int = Dec128(_int) if (_int == 0) & !partitive intres = "cero" - + elseif (_int == 0) & partitive intres = "" elseif dict in (:standard,:large,:modern) @@ -123,15 +125,8 @@ function spelled_out_es(number; dict=:standard) else throw(error("unrecognized dict value: $dict")) end - + decres = es_spell_decimal(abs(_dec)) return intres * decres end end - - - - - - - diff --git a/src/mi.jl b/src/mi.jl index f6af4604..966f1c75 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -1,3 +1,5 @@ +# Jake Ireland (June, 2022–April, 2023) + include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) # TODO: kotahi vs tahi (https://animations.tewhanake.maori.nz/te-kakano/te-wahanga-tuatahi/30) diff --git a/src/pt.jl b/src/pt.jl index caba8b0b..cfa2a286 100644 --- a/src/pt.jl +++ b/src/pt.jl @@ -1,15 +1,17 @@ -include(joinpath(@__DIR__, "pt", "standard_pt_br.jl")) -include(joinpath(@__DIR__, "pt", "pt_pt.jl")) +# Gabriel de Freitas Pereira (May–June, 2022) + +include(joinpath(@__DIR__, "pt", "standard_pt_br.jl")) +include(joinpath(@__DIR__, "pt", "pt_pt.jl")) ## Implement Spelled Out for Brazilian Portuguese and Portugal Portuguese -#retuns a vector of ints, each of that +#retuns a vector of ints, each of that function split_numbers_10³( num::Integer ) - digits( num, base = 10^3) + digits( num, base = 10^3) end function split_numbers_10⁶( num::Integer ) - digits( num, base = 10^6) + digits( num, base = 10^6) end #function @@ -20,10 +22,10 @@ function pt_spell_1e3( number; short_one = false, portugal::Bool = false ) if isone( number ) && short_one return "um" elseif portugal - return pt_PT_1_a_19[ number ] + return pt_PT_1_a_19[ number ] else - return pt_BR_1_a_19[ number ] - end + return pt_BR_1_a_19[ number ] + end else #20-99 unit, dec = digits( number ) if isone( unit ) && short_one @@ -35,19 +37,19 @@ function pt_spell_1e3( number; short_one = false, portugal::Bool = false ) else unit_text = " e " * pt_BR_1_a_19[ unit ] end - return pt_BR_dezenas[ dec ] * unit_text + return pt_BR_dezenas[ dec ] * unit_text end elseif number ∈ centenas_dicionario unit, cent = digits( number, base = 100 ) unit_text = pt_spell_1e3( unit; short_one ) return pt_BR_centenas[ cent ] elseif portugal == false & 100 <= number <= 999 - number == 100 && return "cem" + number == 100 && return "cem" unit, cent = digits( number, base = 100 ) unit_text = pt_spell_1e3( unit; short_one ) return pt_BR_centenas[ cent ] * " e " * unit_text elseif portugal & 100 <= number <= 999 - number == 100 && return "cem" + number == 100 && return "cem" unit, cent = digits( number, base = 100 ) unit_text = pt_spell_1e3( unit; short_one, portugal = portugal ) return pt_PT_centenas[ cent ] * " e " * unit_text @@ -108,13 +110,13 @@ function pt_spell_large_map( number, i; portugal::Bool = false ) end function pt_spell_large( _number; portugal::Bool = false ) - number = abs( _number ) + number = abs( _number ) list = digits( number, base = 1_000_000 ) if portugal - res = pt_spell_large_map.( list, 1:length( list ), portugal = portugal ) .|> strip |> reverse |> z-> join( z," " ) + res = pt_spell_large_map.( list, 1:length( list ), portugal = portugal ) .|> strip |> reverse |> z-> join( z," " ) ( _number < 0 ) && ( res = "menos " * res ) - else - res = pt_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) + else + res = pt_spell_large_map.( list, 1:length( list ) ) .|> strip |> reverse |> z-> join( z," " ) ( _number < 0 ) && ( res = "menos " * res ) end return res @@ -139,7 +141,7 @@ function spelled_out_pt( number; portugal::Bool = false, dict::Symbol = :standar _int = Dec128( _int ) if ( _int == 0 ) & !partitive intres = "zero" - + elseif ( _int == 0 ) & partitive intres = "" elseif dict in ( :standard, :large, :modern ) @@ -149,10 +151,8 @@ function spelled_out_pt( number; portugal::Bool = false, dict::Symbol = :standar else throw( error( "unrecognized dict value: $dict" ) ) end - + decres = pt_spell_decimal( abs( _dec ); portugal = portugal ) return intres * decres end end - - diff --git a/src/ru.jl b/src/ru.jl index 707f1d1d..26720d25 100644 --- a/src/ru.jl +++ b/src/ru.jl @@ -1,3 +1,5 @@ +# Jake Ireland (initial commit: January, 2021; actual work: April, 2023–) + function spelled_out_ru(number::Number) - + end From db572b3ba8235a1b173ac11a1be006573fa77e33 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Sat, 21 Oct 2023 15:57:58 +1300 Subject: [PATCH 113/120] =?UTF-8?q?WIP:=20Add=20notes=20on=20M=C4=81ori?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mi/standard_dictionary_numbers_mi.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/mi/standard_dictionary_numbers_mi.jl b/src/mi/standard_dictionary_numbers_mi.jl index bbf57aed..56c10b58 100644 --- a/src/mi/standard_dictionary_numbers_mi.jl +++ b/src/mi/standard_dictionary_numbers_mi.jl @@ -1,6 +1,13 @@ const _mi_ten = "tekau" const _mi_ma = "mā" +# "kao" = no +# short for "kaore" = no +# Can be used to refer to nothing +# kotahi is used in context, so like "one of x" (whereas tahi is +# literally the number one) +# in counting context, kotahi, e rua, e toru, etc. up to e iwa. +# ordinal is tuatahi, tuarua, etc., up to tuaiwa const _mi_small_numbers = String[ "kore", "tahi", "rua", "toru", "whā", "rima", "ono", "whitu", "waru", "iwa", _mi_ten ] From 5dc66d4d0eaafa8db245dd67485e0e41f4da6b4a Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Sun, 8 Sep 2024 14:00:19 +1200 Subject: [PATCH 114/120] Broaden explanation of the SpelledOut function Not all spelled out outputs are in Anglo-Saxon form --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 15da0b7e..21a04b7e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Description -This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their Anglo-Saxan form. The process of **spelling out** a number has also been referred to as **set full out**, and to write out in **long hand**. Some people to whom I look up have suggested calling this **verbal depresentatoin**, to **digitate**, and —one of my favourites— to **transnumerate**. +This is a minimal package for a pure Julia implementation of converting numbers in their Arabic form to numbers in their natural language form. The process of **spelling out** a number has also been referred to as **set full out**, and to write out in **long hand**. Some people to whom I look up have suggested calling this **verbal depresentation**, to **digitate**, and—one of my favourites—to **transnumerate**. ## Quick Start ```julia @@ -39,4 +39,3 @@ When implementing the main function for your language (typically called `spelled You can also add a fallback method and throw an error, but this should be caught by a `MethodError` anyway. Now you can add to the main [`SpelledOut.jl`](src/SpelledOut.jl) function, in which you can add a branch for your language (following the trend). Finally, ensure you update the documentation for [Supported Languages](https://jakewilliami.github.io/SpelledOut.jl/dev/supported_languages/#Supported-Languages). - From be6f8da9fd90fa4e83f84f290cf810542730b5b7 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Sun, 8 Sep 2024 14:15:16 +1200 Subject: [PATCH 115/120] =?UTF-8?q?Add=20further=20TODO=20notes=20for=20M?= =?UTF-8?q?=C4=81ori?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mi.jl | 3 +++ src/mi/standard_dictionary_numbers_mi.jl | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mi.jl b/src/mi.jl index 966f1c75..207489de 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -3,9 +3,12 @@ include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) # TODO: kotahi vs tahi (https://animations.tewhanake.maori.nz/te-kakano/te-wahanga-tuatahi/30) +# TODO: KOTAHI WITH MACRON? # TODO: Ordinal numbers (https://omniglot.com/language/numbers/maori.htm) # TODO: negatives # TODO: kotahi or kotahi rau? +# TODO: implement missing/nothing?? +# TODO: implement float etc? _fn_bounds_err_msg(n::I, bounds::String, fname::Symbol) where {I <: Integer} = "The internal function \"$fname\" should only be used for numbers $bounds; number provided: $n" diff --git a/src/mi/standard_dictionary_numbers_mi.jl b/src/mi/standard_dictionary_numbers_mi.jl index 56c10b58..4eb8c9cd 100644 --- a/src/mi/standard_dictionary_numbers_mi.jl +++ b/src/mi/standard_dictionary_numbers_mi.jl @@ -3,7 +3,7 @@ const _mi_ma = "mā" # "kao" = no # short for "kaore" = no -# Can be used to refer to nothing +# Can be used to refer to nothing (kore) # kotahi is used in context, so like "one of x" (whereas tahi is # literally the number one) # in counting context, kotahi, e rua, e toru, etc. up to e iwa. From b882f1a9beee410fa9abf386bdb3461a08ee3875 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Sun, 8 Sep 2024 14:19:01 +1200 Subject: [PATCH 116/120] Remove Travis CI config We don't use this anymore --- .old_travis.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .old_travis.yml diff --git a/.old_travis.yml b/.old_travis.yml deleted file mode 100644 index 6d68357d..00000000 --- a/.old_travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -## Documentation: http://docs.travis-ci.com/user/languages/julia/ -language: julia - -os: - - linux - - osx - - windows - - bsd - -julia: - - 1.5 - - nightly - -notifications: - email: false - -sudo: false - -git: - depth: 99999999 - -jobs: - include: - - stage: test - script: - - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' - - julia --color=yes --project=. test/runtests.jl - julia: 1.5 - - - stage: test - script: - - julia --color=yes --project=. -e 'using Pkg; Pkg.instantiate()' - - julia --color=yes --project=. test/runtests.jl - julia: nightly From 960f2b12b0627efa29147b65e9ce61d41dcee30a Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Sun, 8 Sep 2024 14:21:18 +1200 Subject: [PATCH 117/120] Update copyright date in LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 2ffe2a23..62a18c66 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Jake W. Ireland and contributors +Copyright (c) 2020–2024 Jake W. Ireland and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From a1479c5f9e4d6bb2a69c72f05b7ca74e52a002a9 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Sun, 8 Sep 2024 14:23:55 +1200 Subject: [PATCH 118/120] Standardise project spacing Ensure we use spaces over tabs, and consistently --- src/en.jl | 12 +-- ...ge_standard_dictionary_numbers_extended.jl | 2 +- .../standard_dictionary_numbers_extended.jl | 12 +-- src/es/standard_es.jl | 80 +++++++++---------- src/pt/pt_pt.jl | 8 +- src/pt/standard_pt_br.jl | 8 +- 6 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/en.jl b/src/en.jl index 1e0eb064..88d2a168 100644 --- a/src/en.jl +++ b/src/en.jl @@ -141,8 +141,8 @@ function spell_ordinal_en(number::Integer; british::Bool = false, dict::Symbol = _spelled_out_en!(word_buf, number, british = british, dict = dict) s = String(take!(word_buf)) - lastword = lastsplit(isspace, s) - redolast = lastsplit('-', lastword) + lastword = lastsplit(isspace, s) + redolast = lastsplit('-', lastword) if redolast != lastword _lastsplit = '-' @@ -218,15 +218,15 @@ function spelled_out_en(number::Complex; british::Bool = false, dict::Symbol = : end function spelled_out_en(number::Rational; british::Bool = false, dict::Symbol = :modern) - _num, _den = number.num, number.den + _num, _den = number.num, number.den # return the number itself if the denomimator is one - isone(_den) && return spelled_out_en(_num, british = british, dict = dict) + isone(_den) && return spelled_out_en(_num, british = british, dict = dict) - word = spelled_out_en(_num, british = british, dict = dict) * " " * spell_ordinal_en(_den, british = british, dict = dict) + word = spelled_out_en(_num, british = british, dict = dict) * " " * spell_ordinal_en(_den, british = british, dict = dict) # account for pluralisation - return isone(_num) ? word : word * "s" + return isone(_num) ? word : word * "s" end function spelled_out_en(number::AbstractIrrational; british::Bool = false, dict::Symbol = :modern) diff --git a/src/en/large_standard_dictionary_numbers_extended.jl b/src/en/large_standard_dictionary_numbers_extended.jl index c8f14db8..9e82355f 100644 --- a/src/en/large_standard_dictionary_numbers_extended.jl +++ b/src/en/large_standard_dictionary_numbers_extended.jl @@ -30,6 +30,6 @@ const _large_scale_traditional_european = String[ "sesquinquagintillion", "sexagintilliard", "unsexagintillion", "quinsexagintilliard", "septuagintilliard", "quinseptuagintilliard", "octogintilliard", "quinoctogintilliard", "nonagintilliard", "quinnonagintilliard", "centilliard", "quinquagintacentilliard", - "ducentilliard", "quinquagintaducentilliard", "trecentilliard", "quinquagintatrecentilliard", + "ducentilliard", "quinquagintaducentilliard", "trecentilliard", "quinquagintatrecentilliard", "quadringentilliard", "quinquagintaquadringentilliard", "quingentilliard" ] diff --git a/src/en/standard_dictionary_numbers_extended.jl b/src/en/standard_dictionary_numbers_extended.jl index 264ec93a..3ce57b57 100644 --- a/src/en/standard_dictionary_numbers_extended.jl +++ b/src/en/standard_dictionary_numbers_extended.jl @@ -1,14 +1,14 @@ const _small_numbers = String[ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"] - + const _small_number_dictionary = Dict{Char, String}( '0' => "zero", '1' => "one", '2' => "two", '3' => "three", '4' => "four", '5' => "five", '6' => "six", '7' => "seven", '8' => "eight", '9' => "nine") - + const _tens = String[ "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"] - + # The scale_numbers are US, Canada and modern British (short scale) const _scale_modern = String[ "thousand", "million", "billion", "trillion", "quadrillion", @@ -21,7 +21,7 @@ const _scale_modern = String[ "quintrigintillion", "sestrigintillion", "septentrigintillion", "octotrigintillion", "noventrigintillion", "quadragintillion" ] - + const _scale_traditional_british = String[ "thousand", "million", "thousand million", "billion", "thousand billion", "trillion", "thousand trillion", "quadrillion", "thousand quadrillion", "quintillion", @@ -32,7 +32,7 @@ const _scale_traditional_british = String[ "octodecillion", "thousand octodecillion","novendecillion", "thousand novendecillion", "vigintillion", "thousand vigintillion" ] - + const _scale_traditional_european = String[ "thousand", "million", "milliard", "billion", "billiard", "trillion", "trilliard", "quadrillion", "quadrilliard", "quintillion", @@ -44,6 +44,6 @@ const _scale_traditional_european = String[ "octodecillion", "octodecilliard", "novendecillion", "novendecilliard", "vigintillion", "vigintilliard" ] - + const limit = BigInt(big(10)^120) const limit_str = "10^120" diff --git a/src/es/standard_es.jl b/src/es/standard_es.jl index db66bcad..c0f69981 100644 --- a/src/es/standard_es.jl +++ b/src/es/standard_es.jl @@ -1,33 +1,33 @@ const es_1_a_29 =[ -"un" -"dos" -"tres" -"cuatro" -"cinco" -"seis" -"siete" -"ocho" -"nueve" -"diez" -"once" -"doce" -"trece" -"catorce" -"quince" -"dieciséis" -"diecisiete" -"dieciocho" -"diecinueve" -"veinte" -"veintiun" -"veintidós" -"veintitrés" -"veinticuatro" -"veinticinco" -"veintiséis" -"veintisiete" -"veintiocho" -"veintinueve" + "un" + "dos" + "tres" + "cuatro" + "cinco" + "seis" + "siete" + "ocho" + "nueve" + "diez" + "once" + "doce" + "trece" + "catorce" + "quince" + "dieciséis" + "diecisiete" + "dieciocho" + "diecinueve" + "veinte" + "veintiun" + "veintidós" + "veintitrés" + "veinticuatro" + "veinticinco" + "veintiséis" + "veintisiete" + "veintiocho" + "veintinueve" ] const es_decenas = [ @@ -44,16 +44,16 @@ const es_decenas = [ const es_centenas = [ -"ciento" -"doscientos" -"trescientos" -"cuatrocientos" -"quinientos" -"seiscientos" -"setecientos" -"ochocientos" -"novecientos" -] + "ciento" + "doscientos" + "trescientos" + "cuatrocientos" + "quinientos" + "seiscientos" + "setecientos" + "ochocientos" + "novecientos" +] const es_multiplos_1e6_singular = [ "millón" @@ -92,4 +92,4 @@ const es_decimales = [ "diezmilésimo" "cienmilésimo" "millonésimo" -] \ No newline at end of file +] diff --git a/src/pt/pt_pt.jl b/src/pt/pt_pt.jl index 816514b3..cbe82592 100644 --- a/src/pt/pt_pt.jl +++ b/src/pt/pt_pt.jl @@ -42,7 +42,7 @@ const pt_PT_centenas = [ "setecentos" "oitocentos" "novecentos" -] +] const pt_PT_multiplos_1e6_singular = [ "milhão" @@ -51,9 +51,9 @@ const pt_PT_multiplos_1e6_singular = [ "quatrilião" "quintilião" "sextilião" - "septilião" + "septilião" "oitolião" - "nonilião" + "nonilião" "decilião" "undecilião" "duodecilião" @@ -79,4 +79,4 @@ const pt_PT_decimais = [ "centésimo" "milésimo" "milionésimo" -] \ No newline at end of file +] diff --git a/src/pt/standard_pt_br.jl b/src/pt/standard_pt_br.jl index 22f6441e..8519dbea 100644 --- a/src/pt/standard_pt_br.jl +++ b/src/pt/standard_pt_br.jl @@ -42,7 +42,7 @@ const pt_BR_centenas = [ "setecentos" "oitocentos" "novecentos" -] +] const centenas_dicionario = Number[ 200, 300, 400, 500, 600, 700, 800, 900 @@ -55,9 +55,9 @@ const pt_BR_multiplos_1e6_singular = [ "quatrilhão" "quintilhão" "sextilhão" - "septilhão" + "septilhão" "oitolhão" - "nonilhão" + "nonilhão" "decilhão" "undecilhão" "duodecilhão" @@ -83,4 +83,4 @@ const pt_BR_decimais = [ "centésimo" "milésimo" "milionésimo" -] \ No newline at end of file +] From 2f08287c3a62e874168b7af0419b95da41426ff4 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Sun, 8 Sep 2024 14:24:16 +1200 Subject: [PATCH 119/120] =?UTF-8?q?Update=20dates=20spend=20in=20M=C4=81or?= =?UTF-8?q?i=20SpelledOut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mi.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mi.jl b/src/mi.jl index 207489de..2706790d 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -1,4 +1,4 @@ -# Jake Ireland (June, 2022–April, 2023) +# Jake Ireland (June, 2022–) include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) From 01ce4fa53e9c6c0bae8f72d3f2de946a1d064974 Mon Sep 17 00:00:00 2001 From: Jake Ireland Date: Sun, 8 Sep 2024 14:42:14 +1200 Subject: [PATCH 120/120] Add GitHub handles to author attribution --- src/en.jl | 3 +-- src/es.jl | 2 +- src/mi.jl | 2 +- src/pt.jl | 2 +- src/ru.jl | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/en.jl b/src/en.jl index 88d2a168..16a86465 100644 --- a/src/en.jl +++ b/src/en.jl @@ -1,5 +1,4 @@ -# Jake Ireland (October–November, 2020) -# https://github.com/jakewilliami/SpelledOut.jl/commit/f0248d944de20804aae9f3eeb6a6ff1c1853ac99#diff-4933f64df61b24196bb1770cdc1ef08c680da0f45b3486d633a2ad180ffb417f +# Jake Ireland (@jakewilliami; October–November, 2020) # dictionaries include(joinpath(@__DIR__, "en", "standard_dictionary_numbers_extended.jl")) diff --git a/src/es.jl b/src/es.jl index 100755bb..26f834b5 100644 --- a/src/es.jl +++ b/src/es.jl @@ -1,4 +1,4 @@ -# Andrés Riedemann (January, 2021) +# Andrés Riedemann (@longemen3000; January, 2021) include(joinpath(@__DIR__, "es", "standard_es.jl")) diff --git a/src/mi.jl b/src/mi.jl index 2706790d..29c5ab61 100644 --- a/src/mi.jl +++ b/src/mi.jl @@ -1,4 +1,4 @@ -# Jake Ireland (June, 2022–) +# Jake Ireland (@jakewilliami; June, 2022–) include(joinpath(@__DIR__, "mi", "standard_dictionary_numbers_mi.jl")) diff --git a/src/pt.jl b/src/pt.jl index cfa2a286..0d1580ad 100644 --- a/src/pt.jl +++ b/src/pt.jl @@ -1,4 +1,4 @@ -# Gabriel de Freitas Pereira (May–June, 2022) +# Gabriel de Freitas Pereira (@Gabrielforest; May–June, 2022) include(joinpath(@__DIR__, "pt", "standard_pt_br.jl")) include(joinpath(@__DIR__, "pt", "pt_pt.jl")) diff --git a/src/ru.jl b/src/ru.jl index 26720d25..0356ab96 100644 --- a/src/ru.jl +++ b/src/ru.jl @@ -1,4 +1,4 @@ -# Jake Ireland (initial commit: January, 2021; actual work: April, 2023–) +# Jake Ireland (@jakewilliami; initial commit: January, 2021; actual work: April, 2023–) function spelled_out_ru(number::Number)