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

bu420
Novice

Jan 19, 2016, 3:32 AM

Views: 3960
 Print numbers between 1 and 9999
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

Views: 3941
 Re: [bu420] Print numbers between 1 and 9999
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

Views: 3926
 Re: [BillKSmith] Print numbers between 1 and 9999
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...

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

Views: 3919
 Re: [bu420] Print numbers between 1 and 9999
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

Views: 3906
 Re: [bu420] Print numbers between 1 and 9999
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

Views: 3886
 Re: [Chris Charley] Print numbers between 1 and 9999
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

Views: 3885
 Re: [BillKSmith] Print numbers between 1 and 9999
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

Views: 3878
 Re: [bu420] Print numbers between 1 and 9999
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

Views: 3876
 Re: [bu420] Print numbers between 1 and 9999
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

Views: 3865
 Re: [FishMonger] Print numbers between 1 and 9999
Is this a programming class homework assignment, or is it for your employer?

Yes, class-homework....

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

Views: 3756
 Re: [bu420] Print numbers between 1 and 9999
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)