Cody Pendant has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to learn vietnamese, and I thought I'd write a little Perl script which would help me learn at least the numbers. Hit a key, get a number, have to translate it into english, or vice-versa.

Vietnamese numbers, with a couple of exceptions, are very very logical.

The number twelve is just (word-for-ten)(word-for-two) for instance. The number thirty is just (word-for-three)(word-for-ten) and the number thirty-two is just (word-for-three)(word-for-ten)(word-for-two).

The one main exception therefore is that numbers after twenty go two-ten-two, two-ten-three, etc, and the numbers between ten and twenty just go ten-one, ten-two, not one-ten-two.

However, despite the language being logical, I'm not so logical, obviously.

Here's what I came up with. Reverse the digits of the numbers, push the words, using a hash, onto an array, and then reverse the array and print it.

The code below works up to a hundred, but not after that.

I'm sure I'm missing some easy way to do this. Any help gratefully recieved.

%numbers = ( 0, '', 1, 'mot', 2, 'hai', 3, 'ba', 4, 'bon', 5, 'nam', 6, 'sau', 7, 'bay', 8, 'tam', 9, 'chin', 10, 'muoi', 100, 'tram', 1000, 'ngan' ); sub translate { my $number = $_[0]; my @output = (); if (defined($numbers{$number})) { $text_version = $numbers{$number}; print "$text_version \n"; } else { $reverse_number = reverse($number); $places = 1; @digits = split ('', $reverse_number); foreach $digit (@digits) { if ($places == 1) { push (@output, $numbers{$digit}); } else { push (@output, $numbers{$places}); unless ($number < 20) { push (@output, $numbers{$digit}); } } $places *= 10; } @output = reverse(@output); print "@output \n"; } }

--
($_='jjjuuusssttt annootthheer pppeeerrrlll haaaccckkeer')=~y/a-z//s;print;

Replies are listed 'Best First'.
Re: Vietnamese Numbers
by Abigail-II (Bishop) on Jul 31, 2002 at 10:16 UTC
    It isn't clear from your description what the vietnamese for '110' is. Should it be 'mot tram mot muoi', or 'mot tram muoi'? If it's the former, the following fix will work:
    use strict; use warnings 'all'; my %numbers = ( 0, '', 1, 'mot', 2, 'hai', 3, 'ba', 4, 'bon', 5, 'nam', 6, 'sau', 7, 'bay', 8, 'tam', 9, 'chin', 10, 'muoi', 100, 'tram', 1000, 'ngan' ); sub translate { my $number = $_[0]; my @output = (); if (defined($numbers{$number})) { my $text_version = $numbers{$number}; print "$text_version \n"; } else { my $reverse_number = reverse($number); my $places = 1; my @digits = split ('', $reverse_number); foreach my $digit (@digits) { next unless $digit; if ($places == 1) { push (@output, $numbers{$digit}); } else { push (@output, $numbers{$places}); unless ($number < 20) { push (@output, $numbers{$digit}); } } } continue { $places *= 10; } @output = reverse(@output); print "@output \n"; } }
    You were having a problem for dealing with the digit '0'. You were parsing '101' as '1 times 100, 0 times 10, and 1', and the '0 times 10' was emitted as "vietnamese for zero" followed by "vietnamese for ten", resulting in "muoi".

    Abigail

      Thank you both very much for your help. It's all working fine now.

      For the record, those aren't the actual correct numbers as written -- Vietnamese has so many diacritical marks, often two to a vowel, that you have to download special fonts and keyboard layouts.

      It's hard to program in Perl when the "{" comes out "À"
      --

      ($_='jjjuuusssttt annootthheer pppeeerrrlll haaaccckkeer')=~y/a-z//s;print;
Re: Vietnamese Numbers
by spurperl (Priest) on Jul 31, 2002 at 06:48 UTC
    Hi Cody ! Try the following translation routine:
    sub translate_take2 { my $number = shift; my $output = ""; for (my $order = 1000; $order >= 1; $order /= 10) { my $howmany = int($number / $order); if ($howmany != 0) { # No need to say "one tens" $output .= "$numbers{$howmany} " if ($order != 10 or $howmany +!= 1); # No need to say how many "ones" there are $output .= "$numbers{$order} " if ($order != 1); } $number %= $order; } return $output; }
    I tried to make it as clear as I could. Hope I got your Vietnamese instructions right.