Soletrar números em francês

23

Houve um desafio em converter um número para seu numeral em inglês , mas isso era muito simples. Dado um número de 0 a 100, sua tarefa é produzir o número correspondente em francês. O sistema numérico francês tem uma lógica mais complexa por trás do que o inglês:

Número Numeral
---------------
 0 zéro (observe o sotaque)
 1 un
 2 deux
 3 trois
 4 quatre
 5 cinq
 6 seis
 7 set
 8 huit
 9 neuf
10 dix
11 onze
12 douze
13 treize
14 quatorze
15 quinze
16 apreender
17 dix-sept (literalmente dez sete)
18 dix-huit
19 dix-neuf
20 vingt
21 vingt et un (sem hífens)
22 vingt-deux
...
30 trente
...
40 quarante
...
50 cinquante
...
60 soixante
...
70 soixante-dix (literalmente sessenta e dez)
71 Soixante e Onze
...
80 quatre-vingts (observe os; literalmente quatro anos vinte)
81 quatre-vingt-un (observe os hífens)
...
90 quatre-vingt-dix
91 quatre-vingt-onze
...
99 quatre-vingt-dix-neuf (4 * 20 + 10 + 9)
100 cêntimos

Para obter uma lista completa, siga http://quizlet.com/996950/ ( http://www.webcitation.org/6RNppaJx0 ).

Regras / explicações adicionais

  • Sempre haverá um hífen entre as palavras EXCETO quando o número termina em 1.
  • Quando o número termina em 1, a palavra et (significado e ) é adicionada antes do un ou onze . (31 = tres et un)
  • No entanto, 81 e 91 são formatados da mesma forma que os outros números. (81 = quatre-vingt-un)
  • Aos 60, o sistema alterna da base 10 para a base 20.
  • Existem algumas pequenas discrepâncias na web sobre isso; consulte a lista vinculada acima para perguntas.
  • As brechas proibidas por padrão não são permitidas.
  • Não é permitido o uso de uma fonte externa, como um site, bem como de bibliotecas, APIs, funções ou similares que convertam números em números ou que traduzam para o francês.
  • Isso é , então a resposta com o menor número de bytes vence.
  • Se disponível, vincule a um compilador online para facilitar o teste do seu código.

Entrada

  • A entrada deve ser obtida do modo que seu idioma receber entrada. (STDIN, linha de comando, etc.)
  • A entrada será uma única sequência, consistindo em um número inteiro entre 0 e 100, inclusive (zeros à esquerda opcionais).
  • Você pode assumir que a entrada sempre será bem formada.

Saída

  • O resultado será impresso no método mais conveniente para o seu idioma. (STDOUT, caixa de diálogo etc.)
  • O case não importa na saída.

Exemplos

Teste seu código com relação a eles:

Saída de entrada
-------------
0 zéro
18 dix-huit
51 cinquante e um
80 quatre-vingts
91 quatre-vingt-onze
99 quatre-vingt-dix-neuf
NinjaBearMonkey
fonte
3
Observe que os belgas de língua francesa usam "septante", "octante" e "nonante" em vez de soixante-dix, quatre-vingts, quatre-vingt-dix. Deve ser usado na antiga colônia belga.
Emmanuel
8
+1 pela genialidade de fazer isso em francês. Como um colega alemão disse: "Os alemães dizem os números de trás para frente. Mas para entender os franceses, você precisa de uma calculadora".
Level River St
1
Parece que zéro é o único número acentuado no intervalo de 0 a 100. Este não é um caractere ASCII padrão. Presumo que qualquer formato (página de código 437, UTF-8, etc) que possa gerar esse caractere seja aceitável.
Level River St
1
@ Martin As regras declaram "Você pode assumir que a entrada sempre será bem formada", para que a entrada> 100 possa resultar em qualquer comportamento.
NinjaBearMonkey
3
Não existe absolutamente nenhuma lógica por trás do sistema francês. Tenho certeza de que há um erro em 99% dos cheques franceses, isso é ainda mais complicado depois das 100. A conjugação também é um pesadelo. Confie em mim, sou francesa.
Michael M.

Respostas:

7

JavaScript (ES6) 318 321

Edite a correção de bugs (gerenciando os 0s principais) e jogue mais

Crédito para o truque de camelo @ Core1024

Com entrada / saída via pop-up

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')))

Como uma função testável

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')
)

Para testar no console do FireFox ou no 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')

Saída de teste

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-etze, 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-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-Quatorze, 96: Quatre-Vingt-Quinze, 96: Quatre-Vingt-Seize, 97: Quatre-Vingt-Dix-sept, 98: Quatre-Vingt-Dix-huit, 99: Quatre-Vingt-Dix-neuf, 
"Cent"
edc65
fonte
2
Truque legal com o estojo de camelo!
tomsmeding
@tomsmeding muito legal, obviamente, não tão elaborado por mim (crédito adicionado no post)
edc65
@ edc65 Você se importa se eu tentar melhorar minha resposta Ruby com isso? Eu nem vi que a saída sem distinção entre maiúsculas e minúsculas é permitida quando escrevi a minha. ^^
Martin Ender
@ MartinBüttner claro que pode
edc65
6

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

Linguagens de programação funcional são bastante adequadas para este trabalho.

Raio
fonte
Tenha um voto positivo, você foi mais rápido que eu. Você pode substituir seu principal por main=interact$f.reade salvar alguns caracteres.
Gxtaillon
@ gxtaillon Sim, eu esqueci interact. Atualizada.
Ray
5

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])

Na maioria das vezes, são apenas duas tabelas de pesquisa e vários operadores ternários que codificam todas as regras estranhas e informam qual tabela de pesquisa usar quando. Deixe-me saber se você quiser saber mais. ;)

Martin Ender
fonte
1
Odeio ser exigente, mas 80deve gerar quatre-vingts, com um s no final.
31413 NinjaBearMonkey
@hsl corrigido e encurtado um pouco.
Martin Ender
5

Python - 344 (348) (380) (445) (537) bytes

Graças ao grc, Ray e isaacg por sua ajuda no processo de golfe.

O código consiste na definição inicial do dicionário e uma compreensão da lista que preenche os espaços em branco com a junção dos elementos do dicionário.

Você pode verificar o código on-line em repl.it

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()]

Minhas últimas tentativas de jogar golfe nesse código foram renunciar ao processo de geração e, com essa redução, refinar a função para gerar apenas o número solicitado no local. No entanto, como os números dos anos 60 e 80 precisam de elementos não calculados, a luta tem sido criar essa função enquanto diminui o código.

Doktoro Reichard
fonte
3
Você poderia usar r=range, este truque para as linhas 2 e 3, e apenas um espaço para recuo. E você pode salvar 65 bytes comd=dict(zip(r(17)+r(20,70,10)+[80,100],'zéro un deux ... quatre-vingt cent'.split()))
grc
O r=rangetruque que eu conhecia, mas esqueci de adicioná-lo quando escrevi a 1ª revisão. Tudo o resto era relativamente novo para mim, então, obrigado. Uma observação, porém, o código não funciona no Python 3.x, a menos que a printinstrução seja transformada em uma função e as rfunções no dict sejam transformadas em listas.
Doktoro Reichard 31/07
No python 2 você não precisa int(input()), input()é suficiente.
Raio
1
Alguns mais dicas: Eu acho que se você colocar b=a/60*10+10em f(a)seguida, você poderia usar a-a%bea%b para as suas chaves de dicionário. Além disso, você não precisa do espaço 1 or, e a quarta linha pode ser reduzida para [f(v)for v in r(100)if v not in d]. Eu ainda não tentei nada disso.
grc
1
if v not in d-> if(v in d)<1salva um personagem. Se você separar o ponto-e-vírgula das duas partes da sua função, poderá colocar tudo em uma linha.
Isaacg
4

Python - 392 bytes

Possui uma lista com números de base que utiliza para gerar os outros números. A maior parte da lógica de geração está na compreensão da lista na linha 2, usando a indexação de lista para condicionais. Depois que a lista é gerada, ela pesquisa o número inserido e o imprime.

Edit: Encurtado de 426 bytes usando a dica do grc.

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())])
faubi
fonte
1
Você pode salvar 23 bytes coma='_un_deux_trois ... quinze_seize'.split('_')
grc
5
Há um erro de digitação: ciquante , falta um n .
AL
A contagem de bytes é, na verdade, 420, menor que o indicado.
Raio
1

Python 3, (503 bytes)

Compacte a tabela usando bzip2 e use a codificação ascii85 para armazenar o resultado. A tabela é:

zéro
un
deux
trois
quatre
cinq
...
cent

Método muito ingênuo, mas não é tão ruim assim.

Golfe

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])

Bônus

Você consegue encontrar a palavra "Vim" na string compactada?

Raio
fonte
1
Eu gosto bastante Sh0W. Não foi possível encontrar o Vim, nem você.
tomsmeding
@tomsmeding Que pena! Vim desapareceu após a minha última edição.
Ray
1

Bater, 456 440 421 408

Assume entrada válida (número inteiro de 0 a 100 com qualquer número de zeros à esquerda).

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}

fonte
1

JavaScript 459 (sem revestimento de camelo)

@ edc65 não pode tirar isso de você ...;)

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()])

WallyWest
fonte