Converter um decimal repetido em uma fração

23

Esta questão não precisa ser aplicada apenas ao final de decimais - os decimais repetidos também podem ser convertidos em frações por meio de um algoritmo.

Sua tarefa é criar um programa que use um decimal repetido como entrada e faça a saída do numerador e denominador correspondente (em termos mais baixos) que produz essa expansão decimal. Frações maiores que 1 devem ser representadas como frações impróprias 9/5. Você pode assumir que a entrada será positiva.

O decimal repetido será fornecido neste formato:

5.3.87

com tudo depois do segundo ponto repetido, assim:

5.3878787878787...

Seu programa produzirá dois números inteiros representando o numerador e o denominador, separados por uma barra (ou a forma equivalente no seu idioma, se você não produzir texto sem formatação):

889/165

Observe que os decimais finais não terão nada após o segundo ponto, e os decimais sem parte decimal não repetida não terão nada entre os dois pontos.

Casos de teste

Esses casos de teste cobrem todos os casos de canto necessários:

0..3 = 1/3
0.0.3 = 1/30
0.00.3 = 1/300
0.6875. = 11/16
1.8. = 9/5
2.. = 2/1
5..09 = 56/11
0.1.6 = 1/6
2..142857 = 15/7
0.01041.6 = 1/96
0.2.283950617 = 37/162
0.000000.1 = 1/9000000
0..9 = 1/1
0.0.9 = 1/10
0.24.9 = 1/4

Se desejar, você também pode assumir que frações sem partes inteiras não têm nada à esquerda do primeiro ponto. Você pode testar isso com estes casos de teste opcionais:

.25. = 1/4
.1.6 = 1/6
..09 = 1/11
.. = 0/1
Joe Z.
fonte
1
É necessário simplificar a fração? Ou é razoável deixá-lo de forma não simplificada (por exemplo:) 9/99?
Justin Justin
3
(in lowest terms)isto é, a fração deve ser simplificada.
Joe Z.
2
Tenho permissão para produzir em 13vez de 13/1?
Mniip
4
Certifique-se de lidar com essa entrada 1.9999...e de saída2/1
Thomas Eding
3
@ThomasEding 1.9999.é 19999/10000, para 2/1você precisar 1..9, não é?
precisa saber é o seguinte

Respostas:

8

Dyalog APL ( 75 73 69 68 caracteres)

Aqui está outra e quinta tentativa (provavelmente a minha última); Passei o dia tentando escrever um pedaço de código com menos de 80 caracteres e sendo totalmente consistente com as regras. Este desafio fez o meu dia!

Finalmente, recebi uma linha de APL composta por 75 caracteres, trabalhando com o Dyalog APL (mas não na página do interpretador on-line porque usando a função execute ), que é a seguinte:

(N,D)÷D∨N←(⍎'0',1↓I/⍨2=+\P)+(⍎'0',I/⍨2>+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I← '1.2.3'

É claro que eu poderia torná-lo um pouco mais curto, mas os casos especiais em que um, dois ou três campos estão ausentes. Meu código pode até lidar com o ..caso de entrada.

Sei que a APL é difícil de ler e, como as pessoas gostam de entender como um pedaço de código realmente funciona, aqui estão algumas explicações. Basicamente, calculo o denominador final na variável D e o numerador final na variável N.

O APL é analisado da direita para a esquerda.

  • Primeiro, a string é armazenada na variável I ( I←).
  • Em seguida, é mapeado para um vetor de booleanos, indicando onde está um ponto, e esse vetor é chamado P ( P←'.'=). Por exemplo, '1.2.3' será mapeado para 0 1 0 1 0.
  • Este vetor é dígitos na base 10 ( 10⊥); agora '1.2.3' é 1010.
  • Então 1 é subtraído deste número (com 1-⍨ou com ¯1+, aqui eu escolhi o segundo). Agora '1.2.3' é 1009.
  • Então este número é convertido em uma string ( ), dois dígitos iniciais são removidos ( 2↓), o que faz 09 do nosso exemplo inicial '1.2.3'; a string é invertida ( ).
  • Aqui, como caso especial, adiciono um caractere 0 inicial na frente da string; '0',fico triste ao usar os quatro caracteres, mas fiz isso para evitar um erro quando os campos segundo e terceiro estão vazios. A sequência é convertida novamente em um número ( ) e é armazenada em D, que é o denominador, exceto quando os dois últimos campos estão vazios, porque nesse caso D é igual a 0.
  • O D←D+0=trecho de código definido D como 1 se atualmente for nulo e agora D contém o denominador (antes da divisão GCD).
  • Esse denominador é multiplicado ( ×) pelo conteúdo da cadeia inicial I até o segundo ponto com o (⍎'0',I/⍨2>+\P)qual começa novamente P (0 1 0 1 0 no meu exemplo), adiciona os números sucessivos acumulando-os (o que torna 0 1 1 2 2 no meu exemplo), verifique quais valores são menores que 2 (criando o vetor booleano 1 1 1 0 0) e usando os caracteres correspondentes em I; outro 0 é adicionado na frente da sequência para impedir outra interceptação (se os dois campos iniciais estiverem vazios) e o todo é convertido em um número.
  • A última parte da string de entrada é adicionada ao produto anterior com (⍎'0',1↓I/⍨2=+\P), o que leva P novamente, adiciona ao acumular novamente, verifica quais valores são iguais a 2 (veja a explicação anterior), pega os caracteres, remove o primeiro que é um ponto , adiciona um caractere 0 inicial impeditivo e converte em um número.
  • Este produto seguido de uma soma é armazenado em N, que é o numerador.
  • Finalmente, o GCD é calculado com D∨N e os dois números são divididos por este GCD.

edit: Aqui está uma correção para 73 caracteres:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I←

A idéia desse hack é computar primeiro o caso em que a adição cumulativa tem valores iguais a 2, armazenando-os para mais tarde e invertendo essa máscara bit a bit para obter o primeiro caso; assim, calcular o próximo caso precisa de menos caracteres.

edit: Aqui está outra correção para 69 caracteres:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽2↓⍕¯1+10⊥P←'.'=I←

A idéia desse hack é incorporar o caso especial mais complicado como código APL na string a ser avaliada (no estágio de conversão de string para número).

edit: Aqui está outra correção para 68 caracteres:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽3↓⍕1-10⊥P←'.'=I←

A idéia desse hack é substituir a adição de -1 ao valor para subtrair 1 a esse valor pela operação subtrair esse valor para 1 e depois remover mais um caractere no início (que será o sinal de menos).

editar: Mudança cosmética:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←1⌈⍎'0',⌽3↓⍕1-10⊥P←'.'=I←

Nenhuma melhoria no tamanho, mas mais satisfeito em obter a função máxima do código a ser avaliado.

Thomas Baruchel
fonte
Tentei executar isso com o tryapl.org e ele reclama INVALID TOKEN. Você sabe por quê?
Peter Taylor
@ Peter Taylor: Sim, é mesmo dito na minha mensagem; isso ocorre porque eu uso o operador "execute", o que não seria seguro para o servidor do Dyalog e foi desativado on-line (modo de segurança). Você precisa experimentá-lo em uma versão instalada do Dyalog APL.
Thomas Baruchel 22/03
Ah, que vergonha. Não vou gastar 60 € para poder testar um envio ocasional de PCG. Encontrei um testador de APL on-line alternativo, mas parece haver algo específico do Dyalog no seu código, pois ele fornece erros de classificação ou de comprimento.
Peter Taylor
@ Peter Taylor; não ;-) Por favor, use meu próprio site (ainda experimental e não oficial) com o GNU APL; mas eu tive que adicionar dois personagens para torná-lo compatível (parêntese em torno de um I): ver este permalink
Thomas Baruchel
15

Perl 6 (93 101 100 80 68 66 bytes)

$/=split ".",get;say ($0+($1+$2/(9 x$2.comb||1))/10**$1.comb).nude

O tamanho foi aumentado para lidar com nada, em vez de apenas falhar. Mouq propôs usar $/, então agora está sendo usado, e o código é 20 bytes mais curto. Ayiko propôs substituir /por , então o código é ainda mais curto (em 12 bytes). Então Mouq propôs a substituição charspor comb(no contexto numérico, eles são idênticos, porque a lista de caracteres após a conversão para número é o número de caracteres).

Saída de amostra:

$ perl6 script.p6
5.3.87
889 165
$ perl6 script.p6
2.0.0
2 1
$ perl6 script.p6
0..3
1 3
$ perl6 script.p6
0.0.3
1 30
$ perl6 script.p6
0.0.0
0 1
$ perl6 script.p6
0.1.6
1 6
$ perl6 script.p6
0.01041.6
1 96
$ perl6 script.p6
0.2.283950617
37 162
$ perl6 script.p6
123.456.789
41111111 333000
Konrad Borowski
fonte
Infelizmente, verifica-se que usar zero como espaço reservado entre dois pontos não é permitido. 0..09retorna 1/11, mas 0.0.09retorna 1/110.
Joe Z.
@JoeZ. Ah ok. Atualizei meu código para lidar com o caso quando nada é digitado.
21978 Konrad Borowski
Eu não conheço Perl 6, mas estou certo ao supor que, dado 'abc', seu programa usa aritmética racional exata para calcular c / 99 ... 9, mas usa apenas ponto flutuante para calcular ab? Nesse caso, se b tiver muitos dígitos, dará uma resposta incorreta.
Omar
@ OmarAntolín-Camarena: Não é bem assim. No Perl 6, os racionais são padrão, não números de ponto flutuante. Por exemplo, 0.1 + 0.2 == 0.3no Perl 6.
Konrad Borowski 14/03
2
Golfed to 80 chars: $/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude:)
Mouq 15/03
6

J ( 85 90 89 caracteres)

Minha função original, que era 5 caracteres menor que a segunda, tinha alguns bugs: não produzia números inteiros como "n / 1" e deu a resposta errada em números com mais de uma dúzia de dígitos. Aqui está uma função corrigida em J que também incorpora a sugestão de Eelvex de salvar um personagem:

f=:3 :0
'a t'=.|:(".@('0','x',~]),10x^#);._1'.',y
(,'/'&,)&":/(,%+.)&1+/a%*/\1,0 1-~}.t
)

Ele recebe uma string e retorna uma string. Aqui está uma sessão de amostra:

   f '..'
0/1
   f '0.0.0'
0/1
   f '3..'
3/1
   f '..052631578947368421'
1/19
   f '0.2.283950617'
37/162
   f '.0.103092783505154639175257731958762886597938144329896907216494845360824742268041237113402061855670'
1/97
Omar
fonte
Você deve corrigir a sua função para saída 0/1e 3/1inf dois primeiros casos de teste, consulte este comentário
mniip
Corrigi a saída para números inteiros ao custo de 5 caracteres, @mniip.
Omar
Use ('0','x',~])e salve um byte.
Eelvex
5

C, 171

Bastante tempo. Pode ser ainda mais reduzido. Não scanf, o que realmente não aguenta se não houver números entre os pontos. Não strtol. Apenas trituração de números:

a,b,c,d,q;main(){while((q=getchar()-48)>-3)q<0?(d=b>0,b+=!b):d?(c=c*10+q,d*=10):(a=a*10+q,b*=10);for(a=a*--d+c,q=b*=d;q>1;a%q+b%q?--q:(a/=q,b/=q));printf("%d/%d\n",a,b);}

Teste:

rfc <<< "2..142857"
15/7
orion
fonte
5

DC (não totalmente geral, reduzido para 76 caracteres)

Não totalmente geral, mas, por favor, considere que eu fiz isso com uma das coisas mais antigas do mundo:

5.3.87 dsaX10r^d1-rla*sasbdscX10r^dlc*rlb*rlb*la+snsdlnld[dSarLa%d0<a]dsax+dldr/rlnr/f

Editar: eu edito minha solução; não é mais geral, mas um pouco mais curto:

sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f

Use-o como:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • O primeiro campo não é obrigatório:

    .1.3 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
    

    está bem.

  • O segundo e o campo sede requerem pelo menos um dígito

Thomas Baruchel
fonte
5

Javascript, 203

Muito tempo, mas ainda assim divertido. Novas linhas porque ponto e vírgula são ilegíveis.

s=prompt(b=1).split(".")
P=Math.pow
a=s[0]
c=s[1]
d=P(10,l=c.length)
f=(P(10,s[2].length)-1)*P(10,l)||1
e=s[2]=+s[2]
a=d*a+b*c;b*=d
a=f*a+b*e;b*=f
function g(a,b){return b?g(b,a%b):a}g=g(a,b);a/g+"/"+b/g
tomsmeding
fonte
Estou ficando 889/NaNquando corro 5.3.87... Estou fazendo algo errado?
Rafaelcastrocouto 17/03
Não sei ... Se eu apenas colar esse código no console do Safari (o Firefox ou o Chrome também deve fazer), pressione enter e digite "5.3.87", acabei de entrar "889/165"no console. Como você está executando isso? @rafaelcastrocouto
tomsmeding
deixa pra lá ... Eu acho que eu fiz algo errado, uma vez que está trabalhando agora ...
rafaelcastrocouto
1
Você pode salvar 1 caractere movendo a b=1peça para dentro prompt().
usar o seguinte comando
1
f=(P(10,s[2].length)-1)*P(10,l),f=f?f:1=>f=(P(10,s[2].length)-1)*P(10,l)||1
f.ardelian
3

J (método diferente)

Outra solução baseada em um método muito diferente; desta vez é totalmente geral; somente falta o denominador 1 quando um número inteiro é enviado:

   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.3'
2r15
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.'
1r10
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..'
1
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..3'
4r3
Thomas Baruchel
fonte
3

GolfScript (67 caracteres)

`{'.'/1$=.10\,?@-).!+0@+~}+3,/1$4$*]-1%~;*+*+].~{.@\%.}do;{/}+/'/'@

NB Suporta partes inteiras vazias.

Se a sequência for do formato 'n.p.q', o valor será n + p/E + q/(DE) = ((nD + p)E + q)/DEonde D = 10^(len p)e E = 10^(len q) - 1, exceto quando len q = 0, nesse caso E = 1(para evitar a divisão por 0).

Dissecação:

           # Stack: 'n.p.q'
`{         # Combined with the }+ below this pulls the value into the block
           # Stack: idx 'n.p.q'
    '.'/   # Stack: idx ['n' 'p' 'q']
    1$=    # Stack: idx str   (where str is the indexed element of ['n' 'p' 'q'])
    .10\,? # Stack: idx str 10^(len str)
    @-)    # Stack: str 10^(len str)-idx+1
           #   If idx = 0 we don't care about the top value on the stack
           #   If idx = 1 we compute D = 10^(len 'p')
           #   If idx = 2 we compute E' = 10^(len 'q') - 1
    .!+    # Handle the special case E'=0; note that D is never 0
    0@+~   # Stack: 10^(len str)-idx+1 eval('0'+str) (GolfScript doesn't treat 011 as octal)
}+         # See above
3,/        # Run the block for idx = 0, 1, 2
           # Stack: _ n D p E q
1$4$*      # Stack: _ n D p E q D*E
]-1%~;     # Stack: D*E q E p D n
*+*+       # Stack: D*E q+E*(p+D*n)
].~        # Stack: [denom' num'] denom' num'
{.@\%.}do; # Stack: [denom' num'] gcd
{/}+/      # Stack: denom num
'/'@       # Stack: num '/' denom

Demonstração online que simula a execução do programa com cada uma das entradas de teste, uma de cada vez.

Peter Taylor
fonte
Eu tentei e parece que não segue todas as regras: "Observe que decimais finais não terão nada após o segundo ponto, e decimais sem nenhuma parte decimal não repetida não terão nada entre os dois pontos". Eu não poderia fazer o seu trabalho de código com o ser de entrada0.1.
Thomas Baruchel
-1. Tentei novamente outra vez depois de ter notado que você tinha os +300 pontos. Não é justo, porque outras soluções fizeram o possível para seguir todas as regras, o que você obviamente não fez.
Thomas Baruchel 22/03
@ ברוכאל, oponho-me à sua afirmação de que não tentei seguir as regras. A posição dos casos de teste opcionais me confundiu ao pensar que o bloco final cobria todos os casos necessários; acontece que eu estava errado, e vou editar a pergunta em breve para evitar que outras pessoas cometam o mesmo erro. Atualizei meu código para lidar com os casos de canto não tratados anteriormente e atualizei meu link para um teste para demonstrar isso.
22414 Peter Peter Taylor
isso está ok. Você provavelmente merece os 300 pontos. Sendo novo no CodeGolf, esses 300 pontos foram um alvo desafiador para mim, e ainda estou decepcionado por não tê-los conseguido enquanto ainda penso que, no prazo final, meu código era o mais curto para se encaixar perfeitamente nas regras. Enfim, tenho toda a minha vida por ganhar pontos. Saudações.
Thomas Baruchel 22/03
@ ברוכאל: Eu queria começar 500 pontos (sim, sou generoso assim, não é que eu possa dar menos) recompensa, e dou a você esses pontos, mas acho que já existe uma recompensa iniciada. Bem, tanto faz. Gostaria de saber quando essa recompensa terminará e quem receberá esses pontos.
22914 Konrad Borowski
2

Python

Nenhuma biblioteca - 156 caracteres

_=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),
(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)

Usando fractions- 127 caracteres

from fractions import*;a,b,c=raw_input().split('.');print Fraction(int(a+b+c)-bool(c)*int(a+b
),(10**len(c)-bool(c))*10**len(b))
Oberon
fonte
A fractionsversão imprime coisas como "Fração (7, 5)" em vez de "7/5", não é?
Omar
Não faz; A propósito, não estou conseguindo que o primeiro funcione. _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b), ValueError: need more than 1 value to unpack
tomsmeding
@ OmarAntolín-Camarena AFAIK, printusa strquando disponível, não repr. Esta é a saída do meu lado: puu.sh/7w64w.png
Oberon
@tomsmeding Ambos estão em uma linha; a quebra de linha foi adicionada para ajustá-las à resposta. _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)deve ir tudo em uma linha.
Oberon
Ah, certo, @Oberon, como você provavelmente pode imaginar, eu não estava no meu computador e não conseguia executar o código.
Omar
2

Mathematica, 143

Como sempre, o Mathematica oferece muitas funções de alto nível para realizar o trabalho, mas fornece nomes detalhados.

x=StringTake;c=ToExpression;p=s~StringPosition~".";{o,t}=First/@p;u=StringLength@s-t;d=t-o-1;Rationalize@(c@x[s,t-1]+c@x[s,-u]/((10^u)-1)/10^d)

Saída de amostra a ser adicionada mais tarde quando tiver tempo.

Jonathan Van Matre
fonte
Parece-me que isso gera números inteiros como n, em vez de n / 1. Isso esta certo? (Minha solução tem o mesmo erro ... :()
Omar
Ah, agora eu vejo .... especificado nos comentários. Que requisito estranho ... se qualquer outra fração for reduzida, por que não permitir n/1reduzir a n? Adicionarei ~ 50 bytes extras para converter números inteiros mais tarde.
22416 Jonathan Van Matre
Sua abordagem está bem. O meu faz uso, FromDigitsentão eu decidi publicá-lo também.
DavidC
2

Ruby - 112

x,y,z=gets.chop.split".";y||='0';z||='0';puts((y.to_i+Rational(z.to_i,10**z.length-1))/10**y.length+x.to_i).to_s

Esta é a minha primeira experiência com ruby, então fique à vontade para sugerir melhorias.

$ ruby20 % <<< '5.3.87'
889/165
$ ruby20 % <<< '0..3'
1/3
$ ruby20 % <<< '0.0.3'
1/30
$ ruby20 % <<< '0.00.3'
1/300
$ ruby20 % <<< '0.6875.0'
11/16
$ ruby20 % <<< '1.8.0'
9/5
$ ruby20 % <<< '2..'
2/1
$ ruby20 % <<< '..'
0/1
mniip
fonte
Removendo o suporte" ..' e" .1.2" significa que você não está seguindo a especificação, certo? (Eu preferiria removê-los também.)
Omar
@ OmarAntolín-Camarena No que determinado ponto, a especificação diz, If you wish. Eu não desejo, então não estou suportando frações sem o primeiro ou o terceiro grupo de dígitos. No entanto, estou suportando frações sem o segundo grupo de dígitos, que corresponde à especificação.
Mniip 14/03
@ minip, você interpretou mal a especificação: ela não diz "se você deseja suportar .. e .1.2", diz: "se você desejar, pode assumir que 0 .. e 0.1.2 são sempre dados como .. e .1.2 ".
Omar
@ OmarAntolín-Camarena Ponto tomado. Editado.
Mniip 14/03
2

C, 164

Isso é semelhante à solução C da orion, embora eu tenha feito isso do zero. Confesso, no entanto, roubar várias de suas otimizações. Não é muito mais curto, mas suporta 0,25. = 1/4 e 0.000000.1 = 1/9000000.

long a,b,c,d,e;main(){while((c=getchar()-48)>-3)c+2?a=a*10+c,b*=10:b?e=a,d=b:(b=1);
b>d?a-=e,b-=d:0;for(d=2;d<=a;)a%d+b%d?d++:(a/=d,b/=d);printf("%ld/%ld\n",a,b);}
Florian F
fonte
2

Duas respostas em python usando nenhuma biblioteca. Primeiro lida com a entrada opcional sem um dígito antes do primeiro. e é 162 caracteres

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int((i+t+r)or 0)-b*int((i+t)or 0);f=_(d,n);print "%i/%i"%(n,d)

O segundo não lida com nada antes do primeiro dígito, mas lida com todas as entradas necessárias corretamente e tem 150 caracteres

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int(i+t+r)-b*int(i+t);f=_(d,n);print "%i/%i"%(n,d)
staircase27
fonte
2

Haskell

import Data.Ratio
f n=case s '.' n of
    [x,y,z]->(r x)%1+(r y)%(10^(length y))+(r z)%((10^t-1)*(10^(length y)))
        where
            r ""=0
            r n=read n
            t = if length z==0 then 9 else length z
s _ []=[[]]
s n (x:xs) | x==n = []:(s n xs)
           | otherwise = let (l:ls)=s n xs in (x:l):ls
PyRulez
fonte
Ei, isso é código-golfe, você nem está tentando!
Mniip
@ mniip Eu não sou bom em código de golfe. Pelo menos eu usei nomes de variáveis ​​de caracteres únicos.
PyRulez
1
Você nunca especificou o idioma ou a quantidade total de caracteres / bytes usados.
perfil completo de Justin Fay
2
Use {;} para economizar espaço nos recuos, spanimplementar s, adicionar aliases curtos para funções, remover espaço sempre que possível. import Data.Ratio v=span(/='.');w=tail;l=length;f n=(r x)%1+(r y)%p+(r z)%((10^t-1)*p)where{(x,b)=v n;(y,d)=v(w b);z=w d;p=10^(l y);r""=0;r n=read n;t=if null z then 9 else l z}- 178 caracteres, abaixo de 321. NB Trueé sinônimo de otherwise, null zélength z==0
bazzargh
2

JavaScript (ECMASCript 6) 180 175

G=(a,d)=>d?G(d,a%d):a;P=a=>+("1e"+a);L=a=>a.length;f=prompt().split(".");B=P(L(b=f[1]));D=P(L(b)+L(c=f[2]))-P(L(b))||1;alert((m=(f[0]+b||0)*D+B*(c||0))/(g=G(m,n=B*D))+"/"+n/g)

Embora não seja um vencedor claro para a recompensa de 300 ... este é o menor tempo possível:

  • Alterações da versão anterior: algumas pequenas alterações na lógica e alterações na Pfunção Power , alterando-a para em +("1e"+a)vez de Math.pow(10,a)salvar mais alguns caracteres ...
WallyWest
fonte
1

Mathematica 175

f@i_:=
If[IntegerQ[g=FromDigits[Map[IntegerDigits@ToExpression@#&,StringSplit[i,"."]/.""-> {}]
/.{a_,b_,c_}:> {{Sequence@@Join[a,b],c},Length@a}]],HoldForm[Evaluate@g]/HoldForm@1,g]

A maior parte da rotina vai para massagear a entrada. Aproximadamente 50 caracteres foram para manipulação de números inteiros.


Exemplos

f["7801.098.765"]

frac1

Mais exemplos:

TableForm[
 Partition[{#, f[#]} & /@ {"19..87", "19.3.87", "5.3.87", "0.0.3", "0..3", "0.2.283950617", 
"123.456.789", "6666.7777.8888", "2.0.0","0.0.0"}, 5], TableSpacing -> {5, 5}]

frac2


Como isso normalmente seria realizado no Mathematica

FromDigitspode obter uma fração diretamente de um decimal recorrente e de repetição, desde que a entrada tenha uma forma específica. Inteiros são exibidos como inteiros.

z={{{1, 9, {8, 7}}, 2}, {{1, 9, 3, {8, 7}}, 2}, {{5, 3, {8, 7}}, 1}, {{{3}}, -1}, {{{3}}, 0}, 
{{2, {2, 8, 3, 9, 5, 0, 6, 1, 7}}, 0}, {{1, 2, 3, 4, 5, 6, {7, 8, 9}}, 3}, 
{{6, 6, 6, 6, 7, 7, 7, 7, {8}}, 4}, {{2}, 1}, {{0}, 1}}

FromDigits/@z

z

DavidC
fonte
Sua saída está no formato errado, é bonita demais.
Omar
Estranhamente, este é o formato padrão para expressar frações no Mathematica. Levaria vários caracteres para alterar esse formato para o mais simples.
DavidC
1

J (96 caracteres)

Eu não uso o símbolo de barra como separador (mas a solução no Mathematica também não usa, pois usa uma representação gráfica que é melhor de qualquer maneira); em linguagem J a fracção é exibida com rem vez de /:

   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '1..3'
4r3
   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '123.456.789'
41111111r333000
Thomas Baruchel
fonte
1

APL (não totalmente geral)

Não é totalmente geral (como minha solução para dc); funciona com o Dyalog APL (mas não na versão online do Dyalog APL, não sei por que):

(R,F)÷(F←D×N)∨R←(⍎C)+D×(⍎I/⍨2>+\P)×N←10*¯1++/≠\P⊣D←¯1+10*⍴C←1↓I/⍨2=+\P←'.'=I← '123.456.789'

O primeiro campo é opcional, mas pelo menos um dígito é necessário para os outros dois campos.

Thomas Baruchel
fonte
1

JavaScript (189)

i=prompt().split(".");a=i[0];b=i[1];c=i[2];B=b.length;p=Math.pow;n=a+b+c-(a+b);d=p(10,B+c.length)-p(10,B);f=1;while(f){f=0;for(i=2;i<=n;i++)if(n%i==0&&d%i==0){n/=i;d/=i;f=1}};alert(n+"/"+d)

Exemplo:

Entrada:

5.3.87

Saída:

889/165
kitcar2000
fonte
1

C (420 caracteres conforme gravado; menos após remover espaços em branco desnecessários)

Observe que isso assume 64 bits long(por exemplo, Linux de 64 bits); falhará no caso de teste 0.2.283950617em sistemas que usam 32 bits long. Isso pode ser corrigido com o custo de alguns caracteres, alterando o tipo long longe alterando a printfsequência de formatação de acordo.

#include <stdio.h>

long d[3], n[3], i;

int main(int c, char** v)
{
  while (c = *v[1]++)
    switch(c)
    {
    case '.':
      n[++i] = 1;
      break;
    default:
      d[i] = 10 * d[i] + c - '0';
      n[i] *= 10;
    }

  n[2] -= n[2] != 1;

  while (i--)
    d[2] += d[i] * n[i+1], n[i]*=n[i+1];

  i = d[2];
  *n = n[1];

  while (i)
    *d = i, i = *n%i, *n = *d;
  printf("%ld/%ld\n", d[2]/ *n, n[1]/ *n);
}
celtschk
fonte
Agradável. Você pode cortar um caractere alterando '0'para 48.
21415 Todd Lehman
Eu acho que você também pode economizar um pouco mais, reescrevendo a switchdeclaração como if(c==46) n[++i]=1; else d[i]=10*d[i]+c-48,n[i]*=10;.
Todd Lehman
-3

GTB , 81

`_:s;_,1,l?_)-S;_,"."
s;A;,1,S;_,".")-1
s;_,1+S;_,"."),l?_)-S;_,"."))→_
x?A;+_)►Frac

Exemplo

?3.25.
            13/4
Timtech
fonte
4
Até que um compilador seja disponibilizado gratuitamente para esse idioma, eu votarei contra todas as respostas que o usarem.
Gareth
1
Parece haver um compilador na página vinculada acima?
skibrianski
@skibrianski Veja este post em meta
mniip 14/03
2
@Gareth, há algumas respostas do Mathematica para você também votar. : P
Omar
2
@ OmarAntolín-Camarena Existe um compilador / intérprete para o Mathematica. GTB não tem nenhum. Siga o GTBlink acima se você não acredita em mim. Você obterá algumas informações compactadas para um programa proprietário, depois pesquisará esse programa e descobrirá que o site que pretende fornecer um download diz que não está disponível. Então, como podemos compilá-lo?
Gareth