CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Print numbers between 1 and 9999

 



bu420
Novice

Jan 19, 2016, 3:32 AM

Post #1 of 11 (2564 views)
Print numbers between 1 and 9999 Can't Post

Hello, folks
As a beginner,

Q:
Read an integer in between with command line argument & print that into words:

As per script,

I am having difficulties in printing:
-value between "11" & "19"
-can not display 10 as it only give output "one" instead of "one zero"
-same goes for "zero" of hundred digit, like if enter 1005 -> one thousand zero hundred five which is not the proper way to read...


Code
#!/usr/bin/perl -w 

%thousand = (0,"zero",1,"one",2,"two",3,"three",4,"four",5,"five",6,"six",7,"seven",8,"eight",9,"nine",10,"ten");

%ten = (0,"",1,"one",2,"twenty",3,"thirty",4,"fourty",5,"fifty",6,"sixty",7,"seventy",8,"eighty",9,"ninty",10,"ten");

%last = (0,"",1,"one",2,"two",3,"three",4,"four",5,"five",6,"six",7,"seven",8,"eight",9,"nine",10,"ten");

$value = $ARGV[0];
@array = split(//,$value);
$size=@array;
$tab="\t";

if($size==4)
{
$string=$thousand{$array[0]}.$tab.Thousand.$tab.$thousand{$array[1]}.$tab.Hundread.$tab.$ten{$array[2]}.$tab.$last{$array[3]}
}
elsif($size==3)
{
$string=$thousand{$array[0]}.$tab.Hundread.$tab.$ten{$array[1]}.$tab.$last{$array[2]};
}
elsif($size==2)
{
$string=$ten{$array[0]}.$tab.$last{$array[1]};
}
elsif($size==1)
{
$string=$last{$array[0]};
}

print "$string\n";


Any suggestions as how can i modified current script?


BillKSmith
Veteran

Jan 19, 2016, 6:58 AM

Post #2 of 11 (2545 views)
Re: [bu420] Print numbers between 1 and 9999 [In reply to] Can't Post

The first thing you must do is clearly state your requirements:

  • You need a program that convert the integers 1 through 9999 to their English names.

  • Can the input contain leading zero's (or spaces)? Or trailing whitespace?

  • Should the 'names' be the formal names or the idiomatic ones such as "nineteen-ninety-seven" for the year 1997 or "one hundred and seventeen" for 117?

  • Where does your input come from? Your code suggests the command line


  • Your strategy of splitting the number into digits is a good start, but there are more special cases than you have found. If the last two digits are between 01 and 19, those last two digits are named with a single word.

    I do not know a clever solution. I suspect that it is easier to work backward from the units digit. I will continue to look into this and get back to you later. In the mean time, please think about my questions and post your answers.
    Good Luck,
    Bill


    bu420
    Novice

    Jan 19, 2016, 10:46 AM

    Post #3 of 11 (2530 views)
    Re: [BillKSmith] Print numbers between 1 and 9999 [In reply to] Can't Post

    Hi Smith,

    thanks for looking into scenario...
    I will explain the possible scenario:
    - You need a program that convert the integers 1 through 9999 to their English names:
    yes, if i enter any number between 1 to 9999, output must be their respective name.

    -Can the input contain leading zero's (or spaces)? Or trailing whitespace?:
    Yes, user can add 0001 or 001 or 01 or 1 -> output must be same as "one".
    About space & while-space, i haven't thought of it, but somehow if such scenario comes & perl script runs, then it would be icing on cake... (personaly, i have neglected it)

    -Should the 'names' be the formal names or the idiomatic ones such as "nineteen-ninety-seven" for the year 1997 or "one hundred and seventeen" for 117?:
    I have tried both way, formal & just modified as idiomatic way, but i prefer idiomatic as it covers almost all possible fact scenarios(Script above i have written is formal, & now what i have just added is same as idiomatic)

    -Where does your input come from? Your code suggests the command line:
    Correct, it comes from command line argument instead of standard input.

    I hope i have covered all question, but i have missed any pls let me know...

    I wonder, we can have a script for exactly opposite of this: means what if user enter twenty five & output will be "25". i guess then i have to slightly alter reading process although doesn't look easy... Crazy

    Now, since past couple hours i have been trying to modify perl script into more idiomatic way & i have almost got except,
    if number is in 4 digit & cover, x010-x019 (like, 1019,1010), i am not able get as "one thousand ten or one thousand nineteen, instead of i am getting one thousand zero nineteen or one thousand zero ten".

    I am sure, there is just one if-else loop modification or addition is missing, but tbh i am lost now... in my code...as i am exhausted today, will do further modifications tomorrow.

    If one can have better/optimized approach than i have presented pls, share your knowledge...



    Code
    #!/usr/bin/perl -w 

    %thousand = (0,"zero",1,"one",2,"two",3,"three",4,"four",5,"five",6,"six",7,"seven",8,"eight",9,"nine",10,"ten");

    %ten = (0,"",1,"one",2,"twenty",3,"thirty",4,"fourty",5,"fifty",6,"sixty",7,"seventy",8,"eighty",9,"ninty",10,"ten");

    %last = (0,"",1,"one",2,"two",3,"three",4,"four",5,"five",6,"six",7,"seven",8,"eight",9,"nine",10,"ten");

    %teen = (0,"ten",1,"eleven",2,"twelve",3,"thirteen",4,"fourteen",5,"fifteen",6,"sixteen",7,"seventeen",8,"eighteen",9,"nineteen");

    $value = $ARGV[0];
    @array = split(//,$value);
    $size=@array;
    $tab="\t";

    if($size==4)
    {
    if($size==4 && $array[2]==1)
    {
    $string=$thousand{$array[0]}.$tab.Thousand.$tab.$thousand{$array[1]}.$tab.$teen{$array[3]}
    }
    elsif($size==4 && $array[1]==0)
    {
    if($size==4 && $array[1]==0 && $array[2]==1)
    {
    $string=$thousand{$array[0]}.$tab.Thousand.$tab.$teen{$array[3]}
    }
    else
    {
    $string=$thousand{$array[0]}.$tab.Thousand.$tab.$ten{$array[2]}.$tab.$last{$array[3]}
    }
    }
    else
    {
    $string=$thousand{$array[0]}.$tab.Thousand.$tab.$thousand{$array[1]}.$tab.Hundread.$tab.$ten{$array[2]}.$tab.$last{$array[3]}
    }
    }
    elsif($size==3)
    {
    if($size==3 && $array[1]==1)
    {
    $string=$thousand{$array[0]}.$tab.Hundred.$tab.$teen{$array[2]};
    }
    else
    {
    $string=$thousand{$array[0]}.$tab.Hundread.$tab.$ten{$array[1]}.$tab.$last{$array[2]};
    }
    }
    elsif($size==2)
    {
    if($size==2 && $array[0]==1)
    {
    $string=$teen{$array[1]};
    }
    else
    {
    $string=$ten{$array[0]}.$tab.$last{$array[1]};
    }
    }
    elsif($size==1)
    {
    $string=$last{$array[0]};
    }

    print "$string\n"



    (This post was edited by bu420 on Jan 19, 2016, 10:59 AM)


    Chris Charley
    User

    Jan 19, 2016, 11:27 AM

    Post #4 of 11 (2523 views)
    Re: [bu420] Print numbers between 1 and 9999 [In reply to] Can't Post

    Not a solution if you want to roll your own, but Lingua::EN::Numbers will do this for you.


    BillKSmith
    Veteran

    Jan 19, 2016, 4:00 PM

    Post #5 of 11 (2510 views)
    Re: [bu420] Print numbers between 1 and 9999 [In reply to] Can't Post

    So far, I only have solutions up to 99. Your approach is quite different from mine, but actually shorter.

    I warned you to specify your output format before you started. Without that, you solution can never truly be judged right (or wrong!). I do not know of any naming scheme that includes the word 'zero'. I doubt that you intend your inconsistent use of it. (e.g. '0101' yields 'zero thousand one'). I have never seen TAB used as a separation between the words of a name. Other than this, your solution appears generate formal names. I do not see any attempt to handle English idioms.
    Good Luck,
    Bill


    bu420
    Novice

    Jan 20, 2016, 4:31 AM

    Post #6 of 11 (2490 views)
    Re: [Chris Charley] Print numbers between 1 and 9999 [In reply to] Can't Post


    In Reply To
    Not a solution if you want to roll your own, but Lingua::EN::Numbers will do this for you.


    Hi, Chris,
    Thanks you for taking interest in thread,

    Well, i have heard of it, but i am not able to use in my perl script...
    pls provide the installation/how to use, procedure if possible...


    bu420
    Novice

    Jan 20, 2016, 4:40 AM

    Post #7 of 11 (2489 views)
    Re: [BillKSmith] Print numbers between 1 and 9999 [In reply to] Can't Post


    In Reply To
    So far, I only have solutions up to 99. Your approach is quite different from mine, but actually shorter.

    I warned you to specify your output format before you started. Without that, you solution can never truly be judged right (or wrong!). I do not know of any naming scheme that includes the word 'zero'. I doubt that you intend your inconsistent use of it. (e.g. '0101' yields 'zero thousand one'). I have never seen TAB used as a separation between the words of a name. Other than this, your solution appears generate formal names. I do not see any attempt to handle English idioms.


    Hello bill,

    Yes, we must have a specific output before start scripting in perl, but since i have just started to learn perl... my intention is to print any number in between 1-9999 in words...(Yes, there are many holes for output like caps on/off & many other... but i will improve it eventually, with optimize code...)

    So, far, i have done as:
    -any input in between 1-9999,(did not set boundary for more than 4 digit)
    -if user enter 0001/001/01...it will not give proper output
    Note: i have not focused on, as how output should be... as long as i can get words from 1-9999...
    Attachments: perlex1_5.pl (2.00 KB)


    FishMonger
    Veteran / Moderator

    Jan 20, 2016, 6:43 AM

    Post #8 of 11 (2482 views)
    Re: [bu420] Print numbers between 1 and 9999 [In reply to] Can't Post

    Is this a programming class homework assignment, or is it for your employer?


    (This post was edited by FishMonger on Jan 20, 2016, 6:45 AM)


    FishMonger
    Veteran / Moderator

    Jan 20, 2016, 6:57 AM

    Post #9 of 11 (2480 views)
    Re: [bu420] Print numbers between 1 and 9999 [In reply to] Can't Post

    The first step is to add 2 pragmas which should be in EVERY perl script you write. Every script should begin like this:

    Code
    #!/usr/bin/perl 

    use strict;
    use warnings;


    The strict pragma will require you to declare your vars before they are used, which is done with the my keyword.

    Code
    my %thousand = ( ... );

    Do that for all of the vars.

    You should also fix the indentation of the code blocks and use the "fat comma" between the hash keys and values.

    Code that is more readable is more maintainable.


    bu420
    Novice

    Jan 20, 2016, 8:21 AM

    Post #10 of 11 (2469 views)
    Re: [FishMonger] Print numbers between 1 and 9999 [In reply to] Can't Post


    In Reply To
    Is this a programming class homework assignment, or is it for your employer?


    Yes, class-homework....


    In Reply To
    The first step is to add 2 pragmas which should be in EVERY perl script you write. Every script should begin like this:

    Code
    #!/usr/bin/perl 

    use strict;
    use warnings;


    The strict pragma will require you to declare your vars before they are used, which is done with the my keyword.

    Code
    my %thousand = ( ... );

    Do that for all of the vars.

    You should also fix the indentation of the code blocks and use the "fat comma" between the hash keys and values.

    Code that is more readable is more maintainable.


    Yes, correct i think thats why i have beg Thousand every time had i used my to declare variable as local i guess...


    (This post was edited by bu420 on Jan 20, 2016, 8:23 AM)


    Chris Charley
    User

    Jan 24, 2016, 10:04 AM

    Post #11 of 11 (2360 views)
    Re: [bu420] Print numbers between 1 and 9999 [In reply to] Can't Post

    if user enter 0001/001/01...it will not give proper output

    When the user enters a number that begins with '0', it makes '$size ' longer. That is, '0014' will have a size of '4' and your code processes in the '$size == 4' section. You really want to strip those 2 leading zeros so that your code will process it in the '$size == 2' section.

    You could modify your code to do this by using the substitution operator. (Also, you do not handle the case of zero). The code to do this would be:


    Code
    ($value = $ARGV[0]) =~ s/^0+//; #strip leading zeros 
    print "zero\n" and exit if $value eq '';

    ... rest of your code unchanged


    Update: After reading your post, I realized you didn't need to check for zero. But it wouldn't hurt to leave the check in even if you don't enter a zero on the command line.

    Update 2A better solution than the one above would be to add '0' to $ARGV[0]. It is at first a string but when you add to it, it becomes a number (and drops the leading zeros).


    Code
    $value = $ARGV[0] + 0; 
    print 'zero' and exit if $value == 0;



    (This post was edited by Chris Charley on Jan 24, 2016, 10:17 PM)

     
     


    Search for (options) Powered by Gossamer Forum v.1.2.0

    Web Applications & Managed Hosting Powered by Gossamer Threads
    Visit our Mailing List Archives