2
\$\begingroup\$

I am extremely new to programming, and I am a really fast learner if I am interested, I have only started using PowerShell in less than a month, to improve my programming skill, this is a script I have written a few days ago, to do what I said in title, I developped it all by myself, completely without help(because when I asked for help online, no one ever bothered to deliver), as a self-imposed challenge.

Like I said, the script converts numbers in the form of English nouns to Arabic numeric values, I am on Windows 10 x64 using PowerShell 7.1 and have confirmed it is working, without bugs, here I will post this:"thirty-seven million eight hundred ninety-one thousand six hundred ninety-three" as sample input, it will correctly output this number 37891693, the goal of this question is to shorten the code while still maintain readability and clarity, without changing the logic, feel free to contribute if you'd like to help me improve my progamming skills, now I will post the script below:

    function Str-Num {
    param(
    [Parameter(ValueFromPipeline=$true)]
    [System.String]$String,
    [System.Double]$number,
    [System.Double]$digit
    )
    
    Process{
    $lt100 = @{
        'Zero'=0
        'One'=1
        'Two'=2
        'Three'=3
        'Four'=4
        'Five'=5
        'Six'=6
        'Seven'=7
        'Eight'=8
        'Nine'=9
        'Ten'=10
        'Eleven'=11
        'Twelve'=12
        'Thirteen'=13
        'Fourteen'=14
        'Fifteen'=15
        'Sixteen'=16
        'Seventeen'=17
        'Eighteen'=18
        'Nineteen'=19
        'Twenty'=20
        'Thirty'=30
        'Forty'=40
        'Fifty'=50
        'Sixty'=60
        'Seventy'=70
        'Eighty'=80
        'Ninety'=90
        }
    $gt100 =@{
        'Thousand'=1e3
        'Million'=1e6
        'Billion'=1e9
        'Trillion'=1e12
        'Quadrillion'=1e15
        'Quintillion'=1e18
        'Sextillion'=1e21
        'Septillion'=1e24
        'Octillion'=1e27
        'Nonillion'=1e30
        'Decillion'=1e33
        'Undecillion'=1e36
        'Duodecillion'=1e39
        'Tredecillion'=1e42
        'Quattuordecillion'=1e45
        'Quindecillion'=1e48
        'Sexdecillion'=1e51
        'Septendecillion'=1e54
        'Octodecillion'=1e57
        'Novemdecillion'=1e60
        'Vigintillion'=1e63
        'Googol'=1e100
        'Centillion'=1e303
        }
        $number=0
        $digit=0
        [System.Boolean]$negative=$false
        [System.Boolean]$decimal=$false
        if ($string -match '\-') {$string = $string -replace "-", " "}
        if ($string -match ' and ') {$string = $string -replace " and ", " "}
        if ($string.split( )[0] -eq "Negative") {
            $string = $string -replace "Negative "
            $negative=$true
        }
        if ($gt100.Keys -contains($string.split( )[0]) -or $string.split( )[0] -eq "Hundred") { $string = "one " + $string}
        $count = $string.split( ).count
        for ($i=0;$i -lt $count;$i++) {
            $word = $string.split( )[$i]
            if ($decimal -eq $false) {
                if ($lt100.Keys -contains($word)){
                    $digit+=$lt100.$word
                }
                elseif ($word -eq "Hundred" -and $digit -ne 0) {
                    $digit*=100
                }
                elseif ($gt100.Keys -contains($word)) {
                    $number+=$digit*$gt100.$word
                    $digit=0
                }
            }
            if ($word -eq "point") {
                $decimal = $true
                $point=$i
            }
            if ($decimal -eq $true -and $lt100.Keys -contains $word) {
                $number+=$lt100.$word * [math]::pow(10,-($i-$point))
            }
        }
        $number=$number+$digit
    if ($negative -eq $true) {$number=-$number}
    Return "$number"
    }
}
$string = Read-Host "Please input string"
Str-Num $string

Update: I expanded the script to output non-garbage if informal pronounciation of years is inputed(i.e. input "nine eighty-one" output 981, input "one oh sixty-six" output 1066, input "one oh oh one" output 1001, input "nineteen eighty four" output 1984, input "twenty twenty" output 2020, and input "ninety nine ninety nine" output 9999); I did this because someone made a joking comment below, it really annoyed me... Now I will post it below:

    function Str-Num {
    param(
    [Parameter(ValueFromPipeline=$true)]
    [System.String]$String,
    [System.Double]$number,
    [System.Double]$digit
    )
    
    Process{
    $lt100 = @{
        'Oh'=0
        'Zero'=0
        'One'=1
        'Two'=2
        'Three'=3
        'Four'=4
        'Five'=5
        'Six'=6
        'Seven'=7
        'Eight'=8
        'Nine'=9
        'Ten'=10
        'Eleven'=11
        'Twelve'=12
        'Thirteen'=13
        'Fourteen'=14
        'Fifteen'=15
        'Sixteen'=16
        'Seventeen'=17
        'Eighteen'=18
        'Nineteen'=19
        'Twenty'=20
        'Thirty'=30
        'Forty'=40
        'Fifty'=50
        'Sixty'=60
        'Seventy'=70
        'Eighty'=80
        'Ninety'=90
        }
    $gt100 =@{
        'Thousand'=1e3
        'Million'=1e6
        'Billion'=1e9
        'Trillion'=1e12
        'Quadrillion'=1e15
        'Quintillion'=1e18
        'Sextillion'=1e21
        'Septillion'=1e24
        'Octillion'=1e27
        'Nonillion'=1e30
        'Decillion'=1e33
        'Undecillion'=1e36
        'Duodecillion'=1e39
        'Tredecillion'=1e42
        'Quattuordecillion'=1e45
        'Quindecillion'=1e48
        'Sexdecillion'=1e51
        'Septendecillion'=1e54
        'Octodecillion'=1e57
        'Novemdecillion'=1e60
        'Vigintillion'=1e63
        'Googol'=1e100
        'Centillion'=1e303
        }
        $number=0
        $digit=0
        [System.Boolean]$negative=$false
        [System.Boolean]$decimal=$false
        [System.Boolean]$invalid=$false
        if ($string -match '\-') {$string = $string -replace "-", " "}
        if ($string -match ' and ') {$string = $string -replace " and ", " "}
        if ($string.split( )[0] -eq "Negative") {
            $string = $string -replace "Negative "
            $negative=$true
        }
        if ($gt100.Keys -contains($string.split( )[0]) -or $string.split( )[0] -eq "Hundred") { $string = "one " + $string}
        $count = $string.split( ).count
        if ($count -eq 2 -or $count -eq 3 -or $count -eq 4){
            $n=0
            $array = $string.split( )
            foreach ($arra in $array){
                if ($lt100.Keys -contains($arra)){
                $n+=1
                }
            }
            if ($n -eq $count) {
                if ($count -eq 2) {
                    if ($lt100.($string.split( )[0]) -lt 20 -or $lt100.($string.split( )[1]) -ge 10){
                        $fault=$string
                        $string=$string.split( )[0]+" Hundred "+$string.split( )[1]
                        $invalid=$true
                    }
                }
                elseif ($count -eq 3 -or $count -eq 4) {
                    $fault=$string
                    $invalid=$true
                    if ($count -eq 3){
                        $string=$string.split( )[0]+" Hundred "+$string.split( )[1]+" "+$string.split( )[2]
                    }
                    elseif ($count -eq 4) {
                        if ($lt100.($string.split( )[0]) -ge 20){
                        $string=$string.split( )[0]+" "+$string.split( )[1]+" Hundred "+$string.split( )[2]+" "+$string.split( )[3]
                        }
                        elseif ($lt100.($string.split( )[0]) -lt 10){
                            $string=$string.split( )[0]+" Thousand "+$string.split( )[1]+" "+$string.split( )[2]+" "+$string.split( )[3]
                        }
                    }
                }
                if ($invalid -eq $true) {
                    Write-Warning "Invalid expression detected, $fault is not a valid expression for numbers, it has been recognized as an English informal way to pronounce years;$fault has been adjusted to this valid expression: $string so this program can process it."
                }
            }
        }
        $count = $string.split( ).count
        for ($i=0;$i -lt $count;$i++) {
            $word = $string.split( )[$i]
            if ($decimal -eq $false) {
                if ($lt100.Keys -contains($word)){
                    $digit+=$lt100.$word
                }
                elseif ($word -eq "Hundred" -and $digit -ne 0) {
                    $digit*=100
                }
                elseif ($gt100.Keys -contains($word)) {
                    $number+=$digit*$gt100.$word
                    $digit=0
                }
            }
            if ($word -eq "point") {
                $decimal = $true
                $point=$i
            }
            if ($decimal -eq $true -and $lt100.Keys -contains $word) {
                $number+=$lt100.$word * [math]::pow(10,-($i-$point))
            }
        }
        $number=$number+$digit
    if ($negative -eq $true) {$number=-$number}
    Return "$number"
    }
}
$string = Read-Host "Please input string"
Str-Num $string
\$\endgroup\$
3
  • \$\begingroup\$ what's the output from nine eighty one? \$\endgroup\$ Commented Dec 4, 2020 at 11:55
  • \$\begingroup\$ What? Somebody made a nonsensical comment when I was away? @OhMyGoodness, are you serious? You know that saying, garbage in, garbage out, my algorithm is designed to convert valid English number expressions to numerical values, the informal way of pronouncing years is wrong, invalid, nonsense, sorry, but garbage is garbage, but did you think I couldn't implement it? You underestimated me.. \$\endgroup\$ Commented Dec 5, 2020 at 5:18
  • \$\begingroup\$ I do appreciate the implementation, but you could've sounded a bit less like an anime protagonist about it. \$\endgroup\$
    – Maybe
    Commented Oct 25, 2022 at 8:32

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.