Skip to content

Instantly share code, notes, and snippets.

@Gro-Tsen
Created November 18, 2021 17:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gro-Tsen/86bae83676def7072689a78de6083f1b to your computer and use it in GitHub Desktop.
Save Gro-Tsen/86bae83676def7072689a78de6083f1b to your computer and use it in GitHub Desktop.
Convert a decimal number to its literal expression in French
#! /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