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

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.


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

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

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

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


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

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

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.


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

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.


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

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);}

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)

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

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 ...

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


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

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.


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

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);
}

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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.