[Question]
  [
There was a challenge to [convert a number to its numeral in English](https://codegolf.stackexchange.com/q/32151/29750), but that was too straightforward. Given a number 0–100, your task is to output the corresponding numeral in French. The French numeral system has a more complex logic behind it compared to the English one:
```
Number  Numeral
---------------
 0      zéro (note the accent)
 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
17      dix-sept (literally ten seven)
18      dix-huit
19      dix-neuf
20      vingt
21      vingt et un (no hyphens)
22      vingt-deux
...
30      trente
...
40      quarante
...
50      cinquante
...
60      soixante
...
70      soixante-dix (literally sixty ten)
71      soixante et onze
...
80      quatre-vingts (note the s; literally four twenties)
81      quatre-vingt-un (note the hyphens)
...
90      quatre-vingt-dix
91      quatre-vingt-onze
...
99      quatre-vingt-dix-neuf (4*20+10+9)
100     cent
```
For a complete list, follow <http://quizlet.com/996950/> (<http://www.webcitation.org/6RNppaJx0>).
## Further rules/explanations
* There will always be a hyphen between words EXCEPT when the number ends in 1.
* When the number ends in 1, the word *et* (meaning *and*) is added before the *un* or *onze*. (31 = trente et un)
* However, 81 and 91 are formatted the same as the other numbers. (81 = quatre-vingt-un)
* At 60, the system switches from base 10 to base 20.
* There are some minor discrepancies across the web about this; refer to the list linked above for questions.
* [Loopholes that are forbidden by default](https://codegolf.meta.stackexchange.com/q/1061/29750) are not allowed.
* Using an external source such as a website, as well as any libraries, APIs, functions, or the like that convert numbers to numerals or translate to French are not allowed.
* This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the answer with the fewest bytes wins.
* If available, please link to an online compiler to allow for easy testing of your code.
## Input
* Input shall be taken from however your language takes input. (STDIN, command line, etc.)
* Input will be a single string, consisting of a whole number between 0 and 100 inclusive (leading zeroes optional).
* You can assume the input will always be well-formed.
## Output
* The result shall be output to the most convenient method for your language. (STDOUT, dialog box, etc.)
* Case does not matter in the output.
## Examples
Test your code against these:
```
Input  Output
-------------
0      zéro
18     dix-huit
51     cinquante et un
80     quatre-vingts
91     quatre-vingt-onze
99     quatre-vingt-dix-neuf
```
  
[Answer]
# JavaScript (ES6) 318 ~~321~~
*Edit* Bug fix (managing leading 0s) and golfed more
*Credit for the camel case trick* [@Core1024](https://codegolf.stackexchange.com/questions/35036/what-is-your-star-sign/35271#comment77106_35050)
**With input/output via popup**
```
alert((n=prompt(),w='ZéroUnDeuxTroisQuatreCinqSixSeptHuitNeufDixOnzeDouzeTreizeQuatorzeQuinzeSeizeDix-septDix-huitDix-neufVingtTrenteQuaranteCinquanteSoixante'.match(/[A-Z][^A-Z]+/g),
u=n%10,s=u-1|n>80?d='-':' et ',n>99?'Cent':n<21?w[n|0]:n<70?w[18+n/10|0]+(u?s+w[u]:''):(n<80?w[24]:w[4]+d+w[20])+(n-80?s+w[n%20]:'s')))
```
**As a testable function**
```
F=n=>(
  w='ZéroUnDeuxTroisQuatreCinqSixSeptHuitNeufDixOnzeDouzeTreizeQuatorzeQuinzeSeizeDix-septDix-huitDix-neufVingtTrenteQuaranteCinquanteSoixante'
  .match(/[A-Z][^A-Z]+/g),
  u=n%10,s=u-1|n>80?d='-':' et ',
  n>99?'Cent':
  n<21?w[n|0]:
  n<70?w[18+n/10|0]+(u?s+w[u]:''):
  (n<80?w[24]:w[4]+d+w[20])+(n-80?s+w[n%20]:'s')
)
```
**To Test** In FireFox console or FireBug
```
for (i = 0; i < 100; console.log(r),i+= 10) 
  for (j=0, r=''; j < 10; j++)
    r+=(i+j)+':'+F(i+j+'')+", "; // specific: input is a string
F('100')
```
**Test Output**
```
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, 17:Dix-sept, 18:Dix-huit, 19:Dix-neuf,
20:Vingt, 21:Vingt et Un, 22:Vingt-Deux, 23:Vingt-Trois, 24:Vingt-Quatre, 25:Vingt-Cinq, 26:Vingt-Six, 27:Vingt-Sept, 28:Vingt-Huit, 29:Vingt-Neuf,
30:Trente, 31:Trente et Un, 32:Trente-Deux, 33:Trente-Trois, 34:Trente-Quatre, 35:Trente-Cinq, 36:Trente-Six, 37:Trente-Sept, 38:Trente-Huit, 39:Trente-Neuf,
40:Quarante, 41:Quarante et Un, 42:Quarante-Deux, 43:Quarante-Trois, 44:Quarante-Quatre, 45:Quarante-Cinq, 46:Quarante-Six, 47:Quarante-Sept, 48:Quarante-Huit, 49:Quarante-Neuf,
50:Cinquante, 51:Cinquante et Un, 52:Cinquante-Deux, 53:Cinquante-Trois, 54:Cinquante-Quatre, 55:Cinquante-Cinq, 56:Cinquante-Six, 57:Cinquante-Sept, 58:Cinquante-Huit, 59:Cinquante-Neuf,
60:Soixante, 61:Soixante et Un, 62:Soixante-Deux, 63:Soixante-Trois, 64:Soixante-Quatre, 65:Soixante-Cinq, 66:Soixante-Six, 67:Soixante-Sept, 68:Soixante-Huit, 69:Soixante-Neuf,
70:Soixante-Dix, 71:Soixante et Onze, 72:Soixante-Douze, 73:Soixante-Treize, 74:Soixante-Quatorze, 75:Soixante-Quinze, 76:Soixante-Seize, 77:Soixante-Dix-sept, 78:Soixante-Dix-huit, 79:Soixante-Dix-neuf,
80:Quatre-Vingts, 81:Quatre-Vingt-Un, 82:Quatre-Vingt-Deux, 83:Quatre-Vingt-Trois, 84:Quatre-Vingt-Quatre, 85:Quatre-Vingt-Cinq, 86:Quatre-Vingt-Six, 87:Quatre-Vingt-Sept, 88:Quatre-Vingt-Huit, 89:Quatre-Vingt-Neuf,
90:Quatre-Vingt-Dix, 91:Quatre-Vingt-Onze, 92:Quatre-Vingt-Douze, 93:Quatre-Vingt-Treize, 94:Quatre-Vingt-Quatorze, 95:Quatre-Vingt-Quinze, 96:Quatre-Vingt-Seize, 97:Quatre-Vingt-Dix-sept, 98:Quatre-Vingt-Dix-huit, 99:Quatre-Vingt-Dix-neuf, 
"Cent"
```
[Answer]
# Haskell, 390 bytes
```
b=(words"zéro un deux trois quatre cinq six sept huit neuf dix onze douze treize quatorze quinze seize vingt trente quarante cinquante soixante"!!)
a!b=a++"-"++b
f 0=b 0
f 71=f 60++" et onze"
f 80=f 4!b 17++"s"
f 100="cent"
f x|x<17=b x|x<20=b 10!b(x-10)|x>80=b 4!b 17!f(x-80)|m==1=f(x-1)++" et un"|x>60=f 60!f(x-60)|m==0=b(15+div x 10)|1<2=f(x-m)!f m where m=mod x 10
main=interact$f.read
```
Ungolfed
```
base :: Int -> String
--              0    1  2    3     4      5    6   7    8    9    10  11   12     13     14       15     16    17    18     19       20        21      
base i = words "zéro un deux trois quatre cinq six sept huit neuf dix onze douze  treize quatorze quinze seize vingt trente quarante cinquante soixante" !! i
hyphen :: String -> String -> String
a `hyphen` b = a ++ "-" ++ b
say :: Int -> String
say 0 = base 0
say 71 = say 60 ++ " et onze"
say 80 = say 4 `hyphen` base 17 ++ "s"
say 100 = "cent"
say x
  | x < 17 = base x
  | x < 20 = base 10 `hyphen` base (x - 10)
  | x > 80 = base 4 `hyphen` base 17 `hyphen` say (x - 80)
  | m == 1 = say (x - 1) ++ " et un"
  | x > 60 = say 60 `hyphen` say (x - 60)
  | m == 0 = base (div x 10 + 15)
  | otherwise = say (x - m) `hyphen` say m
  where m = mod x 10
main = putStr.say.read=<<getLine
```
Functional programming languages are quite suitable for this job.
[Answer]
# Python - 344 ~~(348)(380)(445)(537)~~ bytes
Thanks to grc, Ray and isaacg for their help in the golfing process.
The code consists of the initial dictionary definition and a list comprehension that fills in the blanks with the junction of the dictionary's elements.
You can check the code online at [repl.it](http://repl.it/WLD/2)
```
r=range
def f(a):b=a/60*10+10;d[a]=d[a-a%b]+(' et ','-')[a%10!=1or a>80]+d[a%b]
d=dict(zip(r(17)+r(20,70,10)+[80,100],'zéro un deux trois quatre cinq six sept huit neuf dix onze douze treize quatorze quinze seize vingt trente quarante cinquante soixante quatre-vingt cent'.split()))
[f(v)for v in r(100)if(v in d)<1]
d[80]+='s'
print d[input()]
```
My latest attempts to golf this code have been to forgo the generation process and with that reduction refine the function to just generate the requested number on the spot. However, since the 60 and 80's numbers need uncalculated elements, the struggle has been to create such a function while decreasing code.
[Answer]
## Ruby, 333 bytes
```
l=['']+%w{un deux trois quatre cinq six sept huit neuf dix onze douze treize quatorze quinze seize}
d=%w{vingt trente quarante cinquante soixante _ quatre-vingt}+['']*2
n=gets.to_i
v=n%20
t=n%10
puts n<1?'zéro':n>99?'cent':d[(n<70?n:n-v)/10-2]+(n<21||t<1&&n<61?'':v<1??s:t==1&&n<80?' et ':?-)+(n>60||n<20?v<17?l[v]:'dix-'+l[t]:l[t])
```
It's mostly just two look up tables and a bunch of ternary operators that encode all of the weird rules and tell you which lookup table to use when. Let me know if you want to know more. ;)
[Answer]
# Python - 392 bytes
It has a list with base numbers which it uses to generate the other numbers. Most of the generation logic is in the list comprehension on line 2, using list indexing for conditionals. Once the list is generated it then looks up the inputted number and prints it.
Edit: Shortened from 426 bytes using grc's tip.
```
a='_un_deux_trois_quatre_cinq_six_sept_huit_neuf_dix_onze_douze_treize_quatorze_quinze_seize_dix-sept_dix-huit_dix-neut'.split('_')
a+=[[['vingt','trente'],['quarante','cinquante'],['soixante']*2,[a[4]+'-vingt']*2][b][c>9]+['','-',' et '][(c%[10,20][b>1]>0)+(c%10==1)*(b<3)]+a[c%[10,20][b>1]]for b in[0,1,2,3]for c in range(20)]
a[0]='zéro'
a[80]+='s'
a+=['cent']
print(a[int(input())])
```
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), ~~150~~ 149 bytes
```
`UV7*Y8÷6*xsYαƵΓYåi<6LXåDX«U_}X8+).•2!ÛÄÒÁw§#Kºγ‚¼8&òo£Ù0ÿM¾…hTвcтv›IÈΩ{т3)`pñ"O|BεÆõ¿-∍£¸±<¥Ð~„Ñzä₂-bζÅ'á`†^=/Rú÷hÕS»•#ÁsèõK…-ˆÆ ć‚R7L1«IåèýI_i"zéro
```
[Try it online!](https://tio.run/##Ae8AEP9vc2FiaWX//2BVVjcqWTjDtzYqeHNZzrHGtc6TWcOlaTw2TFjDpURYwqtVX31YOCspLuKAojIhw5vDhMOSw4F3wqcjS8K6zrPigJrCvDgmw7JvwqPDmTDDv03CvuKApmhU0LJj0YJ24oC6ScOIzql70YIzKWBww7EiT3xCzrXDhsO1wr8t4oiNwqPCuMKxPMKlw5B@4oCew5F6w6TigoItYs62w4Unw6Fg4oCgXj0vUsO6w7dow5VTwrvigKIjw4Fzw6jDtUvigKYty4bDhiDEh@KAmlI3TDHCq0nDpcOow71JX2kiesOpcm///zA3MQ "05AB1E – Try It Online") or [validate all possible inputs](https://tio.run/##Af4AAf9vc2FiaWX/0YLGkk7igoQrwqb/YFVWNypZOMO3Nip4c1nOsca1zpNZw6VpPDZMWMOlRFjCq1VffVg4Kyku4oCiMiHDm8OEw5LDgXfCpyNLwrrOs@KAmsK8OCbDsm/Co8OZMMO/TcK@4oCmaFTQsmPRgnbigLpJw4jOqXvRgjMpYHDDsSJPfELOtcOGw7XCvy3iiI3Co8K4wrE8wqXDkH7igJ7DkXrDpOKCgi1izrbDhSfDoWDigKBePS9Sw7rDt2jDlVPCu@KAoiPDgXPDqMO1S@KApi3LhsOGIMSH4oCaUjdMMcKrTsOlw6jDvU5faSJ6w6lyb/8iwqh9LClc/w)
Takes input 0-padded to length 3.
[Answer]
# Python 3, (503 bytes)
Compress the table using bzip2 and then use ascii85 encoding to store the result. The table is:
```
zéro
un
deux
trois
quatre
cinq
...
cent
```
Very naive method, but it's not that bad.
# Golfed
```
import bz2,base64 as B
print(bz2.decompress(B.a85decode('6<\\%_0gSqh;d"=$\\VU:fOjTBn&3p:MiVu^S+:%s4!Q6o8\\8%r<Bp,5\\LT&Q+19!OmJC@3n\'bD<]UHekq<8OP<;]9BZ,;>836X4<[@KJ,)FsD^8j9Q=]O]&/8\'rjSK&0Sh0W[ru0E0!!M-tL69NZF6N\'Lc#$Q=?S_P0+uEZP"[H;%Ucch??nYC76\'k<)isZIBqqOKi(,IHp""^8d/EqRpc_I<IRj[\'4KB`/."%5,"pjr&27q+&t.6J+ik=Jdd2A)j]\'jt5ts0>:sr9.@E>V0F9L?9r&pX\'E.NUP:r&?>\'*(gKmd;/1QkUb*1&JhfWiE7Kl,P,o1go+.3O&l))Y,$/PO)%"al^4H2,n-l\\PuM!W1rBB9t.,U>DhAs83burMn(%%-qHG<gr+^')).decode().split('\n')[int(input())])
```
## Ungolfed
```
import bz2, base64
s = '6<\\%_0gSqh;d"=$\\VU:fOjTBn&3p:MiVu^S+:%s4!Q6o8\\8%r<Bp,5\\LT&Q+19!OmJC@3n\'bD<]UHekq<8OP<;]9BZ,;>836X4<[@KJ,)FsD^8j9Q=]O]&/8\'rjSK&0Sh0W[ru0E0!!M-tL69NZF6N\'Lc#$Q=?S_P0+uEZP"[H;%Ucch??nYC76\'k<)isZIBqqOKi(,IHp""^8d/EqRpc_I<IRj[\'4KB`/."%5,"pjr&27q+&t.6J+ik=Jdd2A)j]\'jt5ts0>:sr9.@E>V0F9L?9r&pX\'E.NUP:r&?>\'*(gKmd;/1QkUb*1&JhfWiE7Kl,P,o1go+.3O&l))Y,$/PO)%"al^4H2,n-l\\PuM!W1rBB9t.,U>DhAs83burMn(%%-qHG<gr+^'
table = bz2.decompress(base64.a85decode(s)).decode().split('\n')
num = int(input())
print(table[num])
```
---
## Bonus
Can you find the word "Vim" in the compressed string ?
[Answer]
# Bash, ~~456 440 421~~ 408
Assumes valid input (integer from 0 to 100 with any number of leading zeroes).
```
v=`sed 's/0*//'<<<$1`
f=('' dix vingt trente quarante cinquante soixante soixante-dix quatre-vingts quatre-vingt-dix)
s=('' ' et un' -deux -trois -quatre -cinq -six -sept -huit -neuf)
o=${f[${v: -2:1}]}${s[${v: -1:1}]}
[ "${o:0:1}" = \  ]&&o=un
((v>99))&&o=cent
sed 's/^-//
s/s-/-/
s/s et /-/
s/dix et un/onze/
s/di.*ux/douze/
s/d.*s$/treize/
s/d.*re/quatorze/
s/d.*q/quinze/
s/di.*ix/seize/'<<<${o:-zéro}
```
[Answer]
# JavaScript 459 (No Camel Casing)
@edc65 can't take that from you... ;)
`A="0un0deux0trois0quatre0cinq0six0sept0huit0neuf0dix0onze0douze0treize0quatorze0quinze0seize0dix-sept0dix-huit0dix-neuf".split(0);S="soixante";Q=A[4]+"-vingt";T=10;V=20;N=59;for(b=5;1<b--;)for(c=V;c--;)X=b*V+c,A[X]=[,["vingt","trente"],["quarante","cinquante"],[S,S],[Q,Q]][b][c/T|0]+(X%T?X>N?X%V==T?"-dix":"":"":"")+(1>X%T?"":(1==X%(X>N?V:T)|71==X)&81!=X?" et ":"-")+(X>N&X%V==T?"-dix":A[c%(X>N?V:T)]);A[0]="zéro";A[80]+="s";A[100]="cent";alert(A[prompt()])`
]