Compare commits

...

20 Commits

Author SHA1 Message Date
052edf14f5 Added personnal notes 2022-08-27 18:06:19 +02:00
9376ca48ea Seems to work 2022-04-11 15:54:09 +02:00
42b8fa388b WiP 2022-04-10 11:58:17 +02:00
253633f09d Annulation des 3 dernier commits 2021-05-24 15:57:02 +02:00
4658be437b Trying anothe way 2021-05-24 15:44:21 +02:00
e484d4a777 Typo 2021-05-24 15:39:51 +02:00
dd0bfdb5d8 Try another way to write upload artifact 2021-05-24 15:36:32 +02:00
1ac1681bcd Correct artifact name 2021-05-24 15:14:09 +02:00
6ae72e4fc5 Adapt artifact names 2021-05-24 15:05:37 +02:00
5bb8a94c2f nbr.exe is nbr on linux 2021-05-24 14:50:41 +02:00
8cfbfb6274 Essai uploads 2021-05-24 14:45:18 +02:00
469c836ea0 Update README.md 2021-05-24 14:11:55 +02:00
8877cc54cc Enregistrement fichier opam 2021-05-24 14:06:33 +02:00
5e50900165 setup-ocaml@v2, sans test 2021-05-24 13:56:42 +02:00
abd5278719 Update blank.ml with ocaml-setup 2021-05-24 13:49:41 +02:00
f88594dd12 Essai actions 2021-05-24 13:45:29 +02:00
c50e512184 Small updates 2021-05-24 11:02:34 +02:00
ad72fdeb0b Amélioration aide 2020-01-18 09:27:11 +01:00
b324162a12 Essai 2020-01-18 09:24:02 +01:00
d2cf323e19 Added opam file 2020-01-18 09:20:36 +01:00
9 changed files with 445 additions and 65 deletions

50
.github/workflows/blank.yml vendored Normal file
View File

@ -0,0 +1,50 @@
name: CI
# Controls when the action will run.
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
ocaml-compiler:
- 4.12.x
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Use OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
- run: opam install . --deps-only
- run: opam exec -- dune build
- name: Upload a Windows Build Artifact
uses: actions/upload-artifact@v2.2.3
if: runner.os == 'Windows'
with:
name: nbr-win32
# A file, directory or wildcard pattern that describes what to upload
path: _build/install/default/bin/nbr.exe
retention-days: 1
- name: Upload a Linux Build Artifact
uses: actions/upload-artifact@v2.2.3
if: runner.os == 'Linux'
with:
name: nbr-linux
# A file, directory or wildcard pattern that describes what to upload
path: _build/install/default/bin/nbr
retention-days: 1

View File

@ -1,13 +1,15 @@
Nombres
=========
Convert ints into french.
Convert integers into french.
Some references:
Provided as a 1-function library and a basic command-line utility (`nbr` — will
certainly be renamed to something longer and less likely to name clash).
More advanced functionnalities could be added when needed. Here are some
references:
- https://leconjugueur.lefigaro.fr/frlesnombres.php
- https://www.miakinen.net/vrac/nombres
- https://www.dcode.fr/ecriture-nombre-lettres
Provided as a 1-function library, and a basic command-line utility (`nbr` — will
certainly be renamed to something longer and less likely to name clash).
[![CI](https://github.com/ttamttam/nombres/actions/workflows/blank.yml/badge.svg)](https://github.com/ttamttam/nombres/actions/workflows/blank.yml)

View File

@ -1,17 +1,19 @@
let rec parse_and_print () =
print_string "Entier ? > ";
print_string "Entier (Ou [Q]uitter [H]elp) ? > ";
flush stdout;
input_line stdin |> function
| "q" | "Q" -> ()
| "h" | "?" | "H" ->
print_endline "Je n'accepte que des entiers. 'q' ou 'Q' pour quitter.";
print_endline
"Je n'accepte que des entiers positifs. Et pas trop grands…\n\
'q' ou 'Q' pour quitter.";
flush stdout;
parse_and_print ()
| str ->
str |> int_of_string
|> (fun i ->
match i with
| i -> i |> Nombres.nombre_of_int |> print_endline
| i -> i |> Nombres.nombre |> print_endline
| exception _ -> ())
|> parse_and_print

View File

@ -1,14 +1,27 @@
(lang dune 2.0)
(lang dune 3.0)
(name nombres)
(version 0.9)
(generate_opam_files true)
(source (github ttamttam/nombres))
(license ISC)
(authors "Matthieu Dubuget")
(maintainers "matthieu.dubuget@gmail.com")
(package
(name nombres)
(synopsis "Conversion of integers to french.")
(description
"\| Convert ints into french.
"\| Convert integers into french.
"\|
"\| Some references:
"\| - https://leconjugueur.lefigaro.fr/frlesnombres.php
"\| - https://www.miakinen.net/vrac/nombres
"\| - https://www.dcode.fr/ecriture-nombre-lettres
))
)
(depends
fmt
(qtest :with-test)
)
)

View File

@ -1,2 +1,8 @@
(library
(name nombres))
(name nombres)
(public_name nombres)
(libraries fmt)
(inline_tests
(backend qtest.lib)
(executable
(flags :standard -warn-error -a -w -33))))

View File

@ -1,56 +1,224 @@
let rec nombre_of_int = function
| 0 -> "zéro"
| 1 -> "un"
| 2 -> "deux"
| 3 -> "trois"
| 4 -> "quatre"
| 5 -> "cinq"
| 6 -> "six"
| 7 -> "sept"
| 8 -> "huit"
| 9 -> "neuf"
| 10 -> "dix"
| 11 -> "onze"
| 12 -> "douze"
| 13 -> "treize"
| 14 -> "quatorze"
| 15 -> "quinze"
| 16 -> "seize"
| 20 -> "vingt"
| 30 -> "trente"
| 40 -> "quarante"
| 50 -> "cinquante"
| 60 -> "soixante"
| 80 -> "quatre-vingts"
| 100 -> "cent"
| 1000 -> "mille"
| n when n < 70 -> jusqua_70 n
| n when n < 80 -> jusqua_100 "soixante" n
| n when n < 100 -> jusqua_100 "quatre-vingt" n
| n when n < 1_000 -> jusqua_1000 n
| n when n < 1_000_000 -> jusqua_1000000 n
| _ -> "--------------------"
type options =
| Septante
| Huitante
| Nonante
| Belgique (* Septante Nonante *)
| VVF (* Septante Huitante Nonante *)
and jusqua_70 n =
let dizaine = nombre_of_int (n / 10 * 10) in
let unite = n mod 10 in
[ dizaine; nombre_of_int unite ]
|> String.concat (if unite = 1 then " et " else "-")
(* let int_of_options = function *)
(* | Septante -> 0x1 *)
(* | Huitante -> 0x2 *)
(* | Nonante -> 0x8 *)
(* | Belgique -> 0x1 lor 0x8 *)
(* | VVF -> 0x1 lor 0x2 lor 0x8 *)
and jusqua_100 dizaine n =
let unite = n mod 10 in
[ dizaine; nombre_of_int (n mod 20) ]
|> String.concat (if unite = 1 && n < 80 then " et " else "-")
(* type mode = [ `Belgique | `VVF | `France ] *)
and jusqua_1000 n =
let centaine = n / 100 and reste = n mod 100 in
let cent = if centaine > 1 && reste = 0 then "cents" else "cent" in
( (if centaine = 1 then [ cent ] else [ nombre_of_int centaine; cent ])
@ if reste = 0 then [] else [ nombre_of_int reste ] )
|> String.concat " "
(* let options_of_mode = function *)
(* | `Belgique -> [ Belgique ] *)
(* | `VVF -> [ VVF ] *)
(* | `France -> [] *)
and jusqua_1000000 n =
let milliers = n / 1000 and reste = n mod 1000 in
( (if milliers = 1 then [ "mille" ] else [ nombre_of_int milliers; "mille" ])
@ if reste = 0 then [] else [ nombre_of_int reste ] )
|> String.concat " "
(* let int_of_mode m = *)
(* m |> options_of_mode |> List.map int_of_options *)
(* |> ListLabels.fold_left ~f:( + ) ~init:0 *)
(* let mode_of_int = function *)
(* | 0 -> `France *)
(* | 1 -> `Belgique *)
(* | 2 -> `VVF *)
(* | _ -> assert false *)
let opts options lst = List.exists (fun opt -> List.mem opt options) lst
let nombre ?(options = []) n =
let has_opts = opts options in
if n = min_int then invalid_arg "Nombre hors domaine"
else
(* if debug then Fmt.pr "@[<v 2>nombre %d:@," n; *)
let rec schu =
[|
"";
"un";
"deux";
"trois";
"quatre";
"cinq";
"six";
"sept";
"huit";
"neuf";
"dix";
"onze";
"douze";
"treize";
"quatorze";
"quinze";
"seize";
|]
and schd =
[|
"";
"dix";
"vingt";
"trente";
"quarante";
"cinquante";
"soixante";
"soixante";
|]
and nombre_of_int ?(singular = false) ?(accu = []) current () =
match current with
| 0 ->
if accu <> [] then accu |> List.rev |> String.concat " " else "zéro"
| n when n < 0 -> nombre_of_int ~accu (-n) ()
| n when n < 17 -> unroll (schu.(n) :: accu)
| n when n mod 10 = 0 && n < 61 -> unroll (schd.(n / 10) :: accu)
| 80 ->
let nom, noms =
if has_opts [ Huitante; VVF ] then ("huitante", "huitante")
else ("quatre-vingt", "quatre-vingts")
in
unroll ((if singular then nom else noms) :: accu)
| 100 -> unroll ("cent" :: accu)
| 1000 -> unroll ("mille" :: accu)
| n when n < 70 ->
let dizaines = nombre_of_int (n / 10 * 10) () in
let unites = n mod 10 in
let accu =
([
dizaines;
(if unites = 1 then " et " else "-");
nombre_of_int unites ();
]
|> String.concat "")
:: accu
in
unroll accu
| n when n < 80 ->
let unites = n mod 10 in
let accu =
if has_opts [ Septante; Belgique; VVF ] then
([
(if n < 70 then "soixante" else "septante");
(if unites = 1 && n < 80 then " et "
else if unites > 0 then "-"
else "");
(if unites > 0 then nombre_of_int unites () else "");
]
|> String.concat "")
:: accu
else
([
"soixante";
(if unites = 1 && n < 80 then " et " else "-");
nombre_of_int (n mod 20) ();
]
|> String.concat "")
:: accu
in
unroll accu
| n when n < 100 ->
let unites = n mod 10 in
let accu =
if has_opts [ Huitante; VVF ] && n < 90 then
([
"huitante";
(if unites = 1 then " et " else if unites > 0 then "-" else "");
(if unites > 0 then nombre_of_int unites () else "");
]
|> String.concat "")
:: accu
else if has_opts [ Nonante; VVF; Belgique ] && n >= 90 then
([
"nonante";
(if unites = 1 then " et " else if unites > 0 then "-" else "");
(if unites > 0 then nombre_of_int unites () else "");
]
|> String.concat "")
:: accu
else
([
"quatre-vingt";
(if unites = 1 && n < 80 then " et " else "-");
nombre_of_int (n mod 20) ();
]
|> String.concat "")
:: accu
in
unroll accu
| n when n < 1_000 -> jusqua_x ~singular accu 100 ~nom:"cent" ~un:false n
| n when n < 1_000_000 -> jusqua_x accu 1000 ~nom:"mille" ~un:false n
| n when n < 1_000_000_000 ->
jusqua_x accu 1_000_000 ~nom:"million" ~un:true n
| n when n < 1_000_000_000_000 ->
jusqua_x accu 1_000_000_000 ~nom:"milliard" ~un:true n
| n when n < 1_000_000_000_000_000 ->
jusqua_x accu 1_000_000_000_000 ~nom:"billion" ~un:true n
| n when n < 1_000_000_000_000_000_000 ->
jusqua_x accu 1_000_000_000_000_000 ~nom:"billiard" ~un:true n
| n when n <= max_int ->
jusqua_x accu 1_000_000_000_000_000_000 ~nom:"trillion" ~un:true n
| _ -> assert false
and unroll accu = List.rev accu |> String.concat " "
and jusqua_x ?(singular = false) accu lim ~nom ~un n =
let un = if un then "un" else "" in
let noms =
match (nom, singular) with
| "mille", _ -> "mille"
| nom, true -> nom
| nom, false -> nom ^ "s"
in
let count = n / lim and reste = n mod lim in
let accu =
match count with
| 1 -> nom :: un :: accu |> List.filter (( <> ) "")
| _ ->
let noms = if lim = 100 && reste <> 0 then nom else noms in
noms
:: nombre_of_int ~singular:(singular || lim = 1000) count ()
:: accu
in
nombre_of_int ~singular ~accu reste ()
in
nombre_of_int n ()
(*$= nombre & ~printer:(fun x -> "\"" ^ x ^ "\"")
"zéro" (nombre 0)
"un" (nombre 1)
"deux" (nombre 2)
"trois" (nombre 3)
"trente et un" (nombre 31)
"trente-deux" (nombre 32)
"soixante-dix" (nombre 70)
"quatre-vingts" (nombre 80)
"quatre-vingt-un" (nombre 81)
"quatre-vingt-trois" (nombre 83)
"quatre-vingt-dix" (nombre 90)
"quatre-vingt-onze" (nombre 91)
"cent" (nombre 100)
"quatre cents" (nombre 400)
"quatre cent vingt et un" (nombre 421)
"mille" (nombre 1000)
"mille cent" (nombre 1100)
"mille deux cents" (nombre 1200)
"mille deux cent trente" (nombre (-1230))
"mille deux cent trente" (nombre 1230)
"quatre-vingt mille" (nombre 80_000)
"deux cent mille" (nombre 200_000)
"deux cent mille trois cent quarante" (nombre 200_340)
"quatre-vingts millions" (nombre 80_000_000)
"quatre-vingts millions un" (nombre 80_000_001)
"deux cents millions" (nombre 200_000_000)
"deux cents millions trois cent quarante" (nombre 200_000_340)
"deux cents milliards" (nombre 200_000_000_000)
"deux cents billiards" (nombre 200_000_000_000_000_000)
"deux trillions" (nombre 2_000_000_000_000_000_000)
"deux trillions un" (nombre 2_000_000_000_000_000_001)
"deux trillions quatre cent mille un" (nombre 2_000_000_000_000_400_001)
"deux trillions quatre cents millions un" (nombre 2_000_000_000_400_000_001)
"deux trillions cent billions quatre cents millions un" (nombre 2_000_100_000_400_000_001)
*)

8
lib/nombres.mli Normal file
View File

@ -0,0 +1,8 @@
type options =
| Septante
| Huitante
| Nonante
| Belgique (* Septante Nonante *)
| VVF (* Septante Huitante Nonante *)
val nombre : ?options:options list -> int -> string

38
nombres.opam Normal file
View File

@ -0,0 +1,38 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
version: "0.9"
synopsis: "Conversion of integers to french."
description: """
Convert integers into french.
Some references:
- https://leconjugueur.lefigaro.fr/frlesnombres.php
- https://www.miakinen.net/vrac/nombres
- https://www.dcode.fr/ecriture-nombre-lettres
"""
maintainer: ["matthieu.dubuget@gmail.com"]
authors: ["Matthieu Dubuget"]
license: "ISC"
homepage: "https://github.com/ttamttam/nombres"
bug-reports: "https://github.com/ttamttam/nombres/issues"
depends: [
"dune" {>= "3.0"}
"fmt"
"qtest" {with-test}
"odoc" {with-doc}
]
build: [
["dune" "subst"] {dev}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
dev-repo: "git+https://github.com/ttamttam/nombres.git"

93
notes.org Normal file
View File

@ -0,0 +1,93 @@
* Simples
≤ 16
10, 20, 30, 40, 50, 60
100
1000
* trait union
< 100 : "-"
Mais ceux qui se terminent par 1 : " et "
SAUF 81 et 91
* rectif 1990
'-' de partout, sauf millier, millions, milliard
* cent
invariable sauf si multiplié et final
200 000 deux cent mille
200 000 000 deux cents millions
(car mille = cardinal, mais millions = nom)
80 000 quatre-vingt mille
80 000 000 quatre-vingts millions
* Échelle longue/courte
Depuis 1961 : échelle longue en France
Échelle longue :
- million (6)
- milliard (9)
- billion (12)
- billiard (15)
- trillion (18)
- trilliard (21)
Échelle courte :
- million (6 = 3×2)
- billion (9 = 3×3)
- trillion (12 = 3×4)
- quadrillion (15 = 3×5)
- quintillion (18 = 3×6)
- sextillion (21 = 3×7)
* 70 80 90
Belgique + Suisse : septante et nonante
Suisse Romande (cantons de Vaud, du Valais et de Frubourg) : huitante
* Accords
20 et 100 saccordent sils sont multipliés sans être suivis par un autre
nombre
- quatre-vingts
- quatre-vingt-trois
- quatre cents
- quatre cent vingt et un
- mille cent
- mille deux cents
- mille deux cent trente
- deux cent mille
- deux cents millions
- deux cents milliards
- quatre-vingt mille
- quatre-vingts millions
1000 : « mille » est invariable
« un » est invariable en nombre (mais pas en genre)
million et milliard sont des noms et non des adjectifs. Ils
saccordent.
- quatre cents millions
- deux cent mille
* Options
- rectif_1990 :
Seuls les noms tels que millier, million ou milliard ne sont
ni précédés ni suivis d'un trait d'union.
- vingt-et-un
- cent-soixante-huit
- cent-mille-deux-cent-cinquante-huit
- deux millions huit-cents
- septante, huitante, octante, nonante
- belgique = septante | nonante : Belgique, Suisse romande
- vvf = septante|huitante|nonante : Cantons de Vaud, Valais Fribourg
- archaique = septante| octante | nonante : Plus employé