Skip to content

Instantly share code, notes, and snippets.

@Gro-Tsen
Created January 15, 2024 12:11
Show Gist options
  • Save Gro-Tsen/f4a9911e7f922a28f1c9ed98f5dd7c5e to your computer and use it in GitHub Desktop.
Save Gro-Tsen/f4a9911e7f922a28f1c9ed98f5dd7c5e to your computer and use it in GitHub Desktop.
Numbers to text
#! /usr/local/bin/perl -w
# Convert a decimal number to its literal expression in English.
use strict;
use warnings;
use Getopt::Std;
my %opts;
getopts("u", \%opts);
my @units = ( "zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine" );
my @teens = ( "ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen" );
my @tens = ( "", "ten", "twenty", "thirty", "forty",
"fifty", "sixty", "seventy", "eighty", "ninety" );
sub name100 {
use integer;
my $n = shift;
die "Bad input to name100" unless $n >= 0 && $n < 100 && $n == ($n/10)*10+($n%10);
if ( $n < 10 ) {
return $units[$n];
} elsif ( $n < 20 ) {
return $teens[$n%10];
} else {
my $s = $tens[$n/10];
$s .= "-".$units[$n%10];
return $s;
}
}
sub name1000 {
use integer;
my $n = shift;
die "Bad input to name1000" unless $n >= 0 && $n < 1000 && $n == ($n/100)*100+($n%100);
if ( $n < 100 ) {
return name100($n);
} else {
my $s = $units[$n/100] . " hundred";
if ( $n%100 == 0 ) {
} else {
$s .= ($opts{u}?" ":" and ").name100($n%100);
}
return $s;
}
}
sub namemillion {
use integer;
my $n = shift;
die "Bad input to namemillion" unless $n >= 0 && $n < 1000000 && $n == ($n/1000)*1000+($n%1000);
if ( $n < 1000 ) {
return name1000($n);
} else {
my $s = name1000($n/1000) . " thousand";
my $t = name1000($n%1000);
$t = "and ".$t unless $t =~ /\band\b/ || $opts{u};
$s .= " ".$t if $n%1000;
return $s;
}
}
sub namebillion {
use integer;
my $n = shift;
die "Bad input to namebillion" unless $n >= 0 && $n < 1000000000 && $n == ($n/1000000)*1000000+($n%1000000);
if ( $n < 1000000 ) {
return namemillion($n);
} else {
my $s = name1000($n/1000000) . " million";
my $t = namemillion($n%1000000);
$t = "and ".$t unless $t =~ /\band\b/ || $opts{u};
$s .= " ".$t if $n%1000000;
return $s;
}
}
binmode STDOUT, ":utf8";
while ( <> ) {
chop;
printf "%s\n", namebillion($_);
}
#! /usr/local/bin/perl -w
# Convert a decimal number (integer or number of euros) to its literal
# expression in French (or, with the -o option, Swiss French).
use strict;
use warnings;
use Getopt::Std;
my %opts;
getopts("oe", \%opts);
my @units = ( "z\x{E9}ro", "un", "deux", "trois", "quatre",
"cinq", "six", "sept", "huit", "neuf" );
my @teens = ( "dix", "onze", "douze", "treize", "quatorze",
"quinze", "seize", "dix-sept", "dix-huit", "dix-neuf" );
my @tens = ( "", "dix", "vingt", "trente", "quarante",
"cinquante", "soixante", "septante", "huitante", "nonante" );
sub name100 {
use integer;
my $n = shift;
my $oldstyle = shift;
die "Bad input to name100" unless $n >= 0 && $n < 100 && $n == ($n/10)*10+($n%10);
if ( $n < 10 ) {
return $units[$n];
} elsif ( $n < 20 ) {
return $teens[$n%10];
} elsif ( $oldstyle || $n < 70 ) {
my $s = $tens[$n/10];
if ( $n%10 == 1 ) {
$s .= " et ".$units[$n%10];
} elsif ( $n%10 >= 2 ) {
$s .= "-".$units[$n%10];
}
return $s;
} elsif ( $n < 80 ) {
my $s = $tens[6];
if ( $n%10 == 1 ) {
$s .= " et ".$teens[$n%10];
} else {
$s .= "-".$teens[$n%10];
}
return $s;
} else {
my $s = "quatre-vingt";
if ( $n%20 == 0 ) {
$s .= "s";
} elsif ( $n%20 < 10 ) {
$s .= "-".$units[$n%10];
} else {
$s .= "-".$teens[$n%10];
}
return $s;
}
}
sub name1000 {
use integer;
my $n = shift;
my $oldstyle = shift;
die "Bad input to name1000" unless $n >= 0 && $n < 1000 && $n == ($n/100)*100+($n%100);
if ( $n < 100 ) {
return name100($n,$oldstyle);
} elsif ( $n < 200 ) {
my $s = "cent";
$s .= " ".name100($n%100,$oldstyle) if $n%100;
return $s;
} else {
my $s = $units[$n/100] . " cent";
if ( $n%100 == 0 ) {
$s .= "s";
} else {
$s .= " ".name100($n%100,$oldstyle);
}
return $s;
}
}
sub namemillion {
use integer;
my $n = shift;
my $oldstyle = shift;
die "Bad input to namemillion" unless $n >= 0 && $n < 1000000 && $n == ($n/1000)*1000+($n%1000);
if ( $n < 1000 ) {
return name1000($n,$oldstyle);
} elsif ( $n < 2000 ) {
my $s = "mille";
$s .= " et" if $n%1000 == 1;
$s .= " ".name1000($n%1000,$oldstyle) if $n%1000;
return $s;
} else {
my $s = name1000($n/1000,$oldstyle) . " mille";
$s .= " ".name1000($n%1000,$oldstyle) if $n%1000;
return $s;
}
}
sub namebillion {
use integer;
my $n = shift;
my $oldstyle = shift;
die "Bad input to namebillion" unless $n >= 0 && $n < 1000000000 && $n == ($n/1000000)*1000000+($n%1000000);
if ( $n < 1000000 ) {
return namemillion($n,$oldstyle);
} else {
my $s = name1000($n/1000000,$oldstyle) . " million";
$s .= "s" if $n/1000000 >= 2;
$s .= " ".namemillion($n%1000000,$oldstyle) if $n%1000000;
return $s;
}
}
sub nameeuros {
my $v = shift;
my $oldstyle = shift;
die "Bad input to nameeuros" unless $v >= 0 && $v < 1000000000;
my $eur = int($v);
my $frc = int(100*($v-$eur)+0.5);
if ( $frc == 100 ) {
$eur++;
$frc = 0;
}
my $s = "";
if ( $eur || ! $frc ) {
$s = namebillion($eur,$oldstyle);
$s .= " ";
$s .= "d'" if $eur%1000000 == 0 && $eur > 0;
$s .= "euro";
$s .= "s" unless $eur == 1;
}
if ( $frc ) {
$s .= " et " if $eur;
$s .= name100($frc,$oldstyle);
$s .= " ";
$s .= "centime";
$s .= "s" unless $frc == 1;
}
return $s;
}
my $oldstyle = $opts{o};
my $euros = $opts{e};
binmode STDOUT, ":utf8";
while ( <> ) {
chop;
if ( $euros ) {
printf "%s\n", nameeuros($_, $oldstyle);
} else {
printf "%s\n", namebillion($_, $oldstyle);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment