Friday, July 31, 2009

My 73 lines of code

The perl code provided below is used for converting a numeric value to string value in bahasa Indonesia which is commonly used in quittance.


#!/usr/bin/perl

use strict;

my $value = ($ARGV[0])? $ARGV[0] : 1101000;
print STDOUT &terbilang($value),"\n";

exit;

sub terbilang {
my $value = shift;
my $result = '';
$value += 0;
my @part = ();
while($value) {
push(@part, substr($value, -3, 3));
substr($value, -3, 3, '');
}
@part = reverse @part;
for(my $i=0; $i<=$#part; $i++) {
(length($part[$i])==1) and $result .= &_terbilang1($part[$i]).' '.(($part[$i] ne '000')? &_terbilang_satuan($#part-$i).' ' : '');
(length($part[$i])==2) and $result .= &_terbilang2($part[$i]).' '.(($part[$i] ne '000')? &_terbilang_satuan($#part-$i).' ' : '');
(length($part[$i])==3) and $result .= &_terbilang3($part[$i]).' '.(($part[$i] ne '000')? &_terbilang_satuan($#part-$i).' ' : '');
}
$result =~ s/(?<!puluh |ratus )satu ribu/ seribu/g; # replace 'satu ribu' with 'seribu', except when 'puluh' or 'ratus' precedes 'satu ribu'
$result =~ s/\s{2,}/ /g; # replace extra space with one single space
$result =~ s/\s+$//g; # replace extra space in the end of line
$result =~ s/^\s+//g; # replace extra space in the beginning of line
$result =~ s/\b(\w)/\u$1/g; # capitalize first letter in every word
return $result;
}

sub _terbilang_satuan {
($_[0] == 1) and return 'ribu';
($_[0] == 2) and return 'juta';
($_[0] == 3) and return 'miliar';
($_[0] == 4) and return 'triliun';
}

sub _terbilang3 {
my $value=shift;
my $result = '';
$result .= (substr($value,0,1) eq '1')? 'seratus ' : ((substr($value,0,1) ne '0')? &_terbilang1(substr($value,0,1)).' ratus ':'');

if(substr($value,1,1) eq '0') {
$result .= &_terbilang1(substr($value,2,1));
} else {
$result .= (substr($value,1,1) eq '1')? &_terbilang2(substr($value,1,2)) : &_terbilang1(substr($value,1,1)).' puluh '.&_terbilang1(substr($value,2,1));
}
}

sub _terbilang2 {
(substr($_[0],0,1) eq '0') and return &_terbilang1(substr($_[0],1,1));
if (substr($_[0], 0, 1) eq '1') {
(substr($_[0], 1, 1) eq '0') and return 'sepuluh';
(substr($_[0], 1, 1) eq '1') and return 'sebelas';
return &_terbilang1(substr($_[0],1,1)).' belas';
} else {
return &_terbilang1(substr($_[0],0,1,)).' puluh '.&_terbilang1(substr($_[0],1,1));
}
}

sub _terbilang1 {
($_[0] eq '1') and return 'satu';
($_[0] eq '2') and return 'dua';
($_[0] eq '3') and return 'tiga';
($_[0] eq '4') and return 'empat';
($_[0] eq '5') and return 'lima';
($_[0] eq '6') and return 'enam';
($_[0] eq '7') and return 'tujuh';
($_[0] eq '8') and return 'delapan';
($_[0] eq '9') and return 'sembilan';
}


Who needs 172 lines when the same result can be accomplished with only 73 lines of code ;)