Converta uma fração para um decimal repetido

17

Quase o oposto polar se esse desafio, e eu suspeito que será um pouco mais fácil.

Sua tarefa é pegar dois números inteiros no formato a/b(Formando um número racional) e, em seguida, imprimir o número exatamente em decimal.

Por exemplo, se você inserir 1/3, ele produzirá:

0.33333333333333333

E continuaria imprimindo 3s até o final dos tempos, com um 0. inicial opcional (você também pode imprimir um caractere por linha se e somente se o seu idioma não permitir a impressão na mesma linha.)

O comportamento para x/0será indefinido. Para um número que parece que não se repete (como, digamos 5/4), na verdade se repete. Qualquer um dos dois formulários a seguir seria aceitável para 5/4:

1.25000000000000000
1.24999999999999999

(O mesmo com números inteiros 1.9999999ou 2.000000)

A fração pode não estar em sua forma mais simples, e aou bpode ser negativo (Nota -a/b = -(a/b), -a/-b = a/b, a/-b = -a/b, e -.6249999é inválido, mas -0.6249999é aceitável, mas você ainda pode usar.

Comunidade
fonte
Podemos usar o Unix bcou isso é trapaça?
David R Tribble
Antes de continuar jogando golfe, minha resposta: pode ae / ou pode bser negativa?
Dennis
@Dennis Sim, mas um aou b(ou ambos) podem ser negativos)
@DavidRTribble Eu acho que é uma brecha padrão, então não.
A sua edição mais recente diz que os zeros à esquerda são bons com números positivos, mas não negativos? Se sim, qual o motivo disso?
Geobits

Respostas:

2

CJam, 38 37 bytes

l'/%:i2*~*0<'-*o:Dmd\zo'.{oA*Dmd\z1}g

Como funciona

l     e# Read line from STDIN.            STACK '17/-13'
'/%   e# Split at '/'.                    STACK ['17' '-13']
:i    e# Cast each element to int.        STACK [17 -13]
2*~   e# Duplicate and dump the array.    STACK 17 -13 17 -13
*     e# Multiply.                        STACK 17 -13 -221
0<    e# Compare with zero.               STACK 17 -13 1
'-*o  e# Print '-' that many times.       STACK 17 -13
:D    e# Save the topmost integer in D.   STACK 17 -13
md    e# Perform modular division.        STACK -1 4
\z    e# Swap and take absolute value.    STACK 4 1
o'.   e# Print and push '.'.              STACK 4 '.'
{     e# do:
  o   e#   Print.                         STACK 4
  A*  e#   Multiply by 10.                STACK 40
  Dmd e#   Divide modulo D.               STACK -3 1
  \z  e#   Swap and take absolute value.  STACK 1 3
  o   e#   Print.                         STACK 1
1}g   e# while(1)
Dennis
fonte
Desde que você usa divisão dupla, isso não é totalmente quebrado para grandes números?
Orlp 05/05
@orlp: Totalmente. Está consertado agora.
Dennis
6

C, 108 79

Editar Modificado para trabalhar com números negativos.

Entrada de stdin. Antigo estilo K&R.

main(a,b){char*s="-%d.";scanf("%d/%d",&a,&b);for(a*b<0?(a<0?a=-a:(b=-b)):++s;printf(s,a/b);s="%d")a=a%b*10;}
edc65
fonte
4

Ruby, 83 69 102 91 89 bytes

->s{a,b=s.scan(/\d+/).map &:to_i
eval(s+?r)<0&&$><<?-
$><<a/b<<?.
loop{a=a%b*10
$><<a/b}}

Implementação simples da divisão inteira manual com base na divisão inteira do computador.

Obrigado a @blutorange pela ajuda no golfe.

Editar: Corrigida a solução para incluir números negativos.

rorlork
fonte
2
Usando alguns atalhos no ruby, você pode reduzir para 66 bytes: ->s{a,b=s.split(?/).map &:to_i;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}}eu simplesmente amo isso no ruby.
Blotange
Uau, acabei de aprender muitas coisas, obrigado! Não me lembrava ?/de indicar caracteres nem sabia $><<imprimir ou a looppalavra - chave. Muito obrigado!!
Rorlork 4/15
11
De nada, eu também não conhecia muitos desses truques até que alguém o apontou. $>é a abreviação de $stdoute <<é um operador. Você pode salvar mais um byte na segunda linha, alterando-o para c*d<0&&$><<?-; alguns bytes combinando a 3ª / 4ª linha em $><<a/b<<?.e mais um removendo o espaço depois <<da última linha. E aqui está uma idéia para trazê-lo para baixo para 91 bytes: ->s{a,b=s.scan(/\d+/).map &:to_i;1==s.count(?-)&&$><<?-;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}}(rubi 2.2.0)
blutorange
A sintaxe para $><<a/bnão funcionou corretamente, é por isso que coloquei o espaço lá. O resto parece bom, muito obrigado!
Rorlork 4/15
11
Se você ainda estiver interessado, também há um literal racional ( Rational(2,3) == 2/3r) desde o ruby ​​2.1 (que aprendi há cerca de 10 minutos) que pode ser usado para reduzir a segunda linha:eval(s+?r)<0&&$><<?-
blutorange
2

Java, 177 176 170

s->{try{int x=new Integer(s.split("/")[0]),y=new Integer(s.split("/")[1]),z=1;for(;;x=x%y*10,Thread.sleep(999))System.out.print(x/y+(z-->0?".":""));}catch(Exception e){}}

O algoritmo é direto; a parte complicada foi fazer a impressão funcionar. No final, o computador parou por um segundo entre cada etapa para que ele pudesse imprimir.

Versão expandida e executável

public class RepeatedDecimal {
    public static void main(String[] args) {
        java.util.function.Consumer<String> f = s -> {
                try {
                    int x = new Integer(s.split("/")[0]),
                        y = new Integer(s.split("/")[1]),
                        z = 1;
                    for (;; x = x % y * 10, Thread.sleep(999)) {
                        System.out.print(x / y + (z-- > 0 ? "." : ""));
                    }
                } catch (Exception e) { }
                };

        f.accept("5/7");
    }
}
Ypnypn
fonte
Enquanto a saída tem um problema de descarga, consegui mostrar a saída dormindo por 9ms, o que reduziria dois bytes.
@ Snowman Provavelmente depende do hardware ou sistema operacional; meu computador não funcionará com menos de 250ms ou mais.
Ypnypn
2

R, 103 137 109 103

Um pouco mais feliz com isso agora. O uso da digitalização com um separador economiza muitos bytes. Ainda pode haver espaço para melhorias. Substituído <-por =. Nem sempre tivemos muita sorte com isso, mas funcionou desta vez.

cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)

Execuções de teste

> cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)
1: -1/3
3: 
Read 2 items
-0.33333333333333333333...
> cat(if(prod(i=scan(sep='/'))<0)'-',(n=(i=abs(i))[1])%/%(d=i[2]),'.',sep='');repeat cat((n=n%%d*10)%/%d)
1: -5/-4
3: 
Read 2 items
1.250000000000000000000...
MickyT
fonte
1

Python 3, 107 115 bytes

a,b=map(int,input().split("/"))
print(("%.1f"%(a/b))[:-1],end="")
b=abs(b)
while 1:a=abs(a)%b*10;print(a//b,end="")

Bem direto:

  • Insira o numerador e o denominador
  • Emita o quociente com 1 dígito após o ponto decimal e retire o último dígito (por exemplo, -1/3 - -> -0.)
  • Tome valores absolutos *
  • Ciclo:
    • O numerador é o restante após dividir o denominador
    • Multiplique o numerador por 10
    • Quociente inteiro de saída como próximo dígito

* (Embora o cálculo para tenha asido movido dentro do loop para salvar alguns bytes.)

Edit: Corrigido o erro com frações negativas> -1.

DLosc
fonte
0

Python 2.7, 209 bytes

from sys import*;m,o=1,lambda x:stdout.write(str(x));a,b=[int(x)for x in argv[1].split('/')]
o(str(a*b)[0]);a,b=abs(a),abs(b);o('0'*(b>a))
while 1:
 while not((m*a)/b):o('0.'[m==1]);m*=10
 o((m*a)/b);a=(m*a)%b

editar:

Agora gera todos os caracteres na mesma linha, conforme solicitado.

edit2:

Agora lê a fração do argumento da linha de comandos, conforme solicitado :)

dieter
fonte
11
Algumas dicas: 1) Usar em mapvez da compreensão da lista economiza bastante; 2) não precisa dos parênteses em torno m*aem qualquer de suas localidades, como *, %, e /são todos a mesma precedência e associativos à esquerda; 3) a lógica de 0 ou ponto na linha 3 pode ser simplificada "0."[m==1], pois você a está imprimindo de qualquer maneira; 4) provavelmente salvará caracteres para definir o=stdout.writee converter argumentos numéricos em string com backticks, conforme necessário.
DLosc
11
Além disso, o código não parece funcionar com negativos: 1/-3dá em -1.666666666vez de -0.333333333.
DLosc