18
\$\begingroup\$

Almost the polar opposite if this challenge, and I suspect it will be slightly easier.

Your task is to take two integers in the format a/b (Forming a rational number) then output the number in decimal exactly.

For example, if you were to input 1/3, it would output:

0.33333333333333333

And would keep on printing 3s until the end of time, with an optional leading 0. (You could also print one character per line if and only if your language does not allow printing on the same line.)

The behaviour for x/0 will be undefined. For a number that looks like it doesn't repeat (Like, say 5/4) it actually does repeat. Either of the following two forms would be acceptable for 5/4:

1.25000000000000000
1.24999999999999999

(The same with whole numbers, 1.9999999 or 2.000000)

The fraction may not be in its simplest form, and a or b may be negative (Note -a/b = -(a/b), -a/-b = a/b, a/-b = -a/b, and -.6249999 is invalid, but -0.6249999 is acceptable, but you still can use.

\$\endgroup\$
8
  • \$\begingroup\$ Can we use Unix bc, or is that cheating? \$\endgroup\$ May 4, 2015 at 15:32
  • \$\begingroup\$ Before I keep golfing my answer: Can a and/or b be negative? \$\endgroup\$
    – Dennis
    May 4, 2015 at 16:18
  • \$\begingroup\$ @Dennis Yes, but either a or b (or both) can be negative) \$\endgroup\$
    – user34736
    May 4, 2015 at 16:34
  • \$\begingroup\$ @DavidRTribble I think that's a standard loophole, so no. \$\endgroup\$
    – user34736
    May 4, 2015 at 16:34
  • \$\begingroup\$ Does your latest edit say that leading zeroes are okay with positive numbers, but not negative ones? If so, what's the reason for that? \$\endgroup\$
    – Geobits
    May 4, 2015 at 16:56

7 Answers 7

6
\$\begingroup\$

C, 108 79

Edit Modified to work with negative numbers.

Input from stdin. Old K&R style.

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;}
\$\endgroup\$
4
\$\begingroup\$

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

Simple implementation of manual integer division based on the computer's integer division.

Thanks to @blutorange for the help in golfing.

Edit: Fixed the solution to include negative numbers.

\$\endgroup\$
8
  • 2
    \$\begingroup\$ By making use of some shortcuts in ruby, you can bring this down to 66 bytes: ->s{a,b=s.split(?/).map &:to_i;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}} I just love this about ruby. \$\endgroup\$
    – blutorange
    May 4, 2015 at 15:31
  • \$\begingroup\$ Wow, I just learned many things, thank you! I didn't remember about ?/ to denote characters, nor did I know about $><< to print or the loop keyword. Thanks a lot!! \$\endgroup\$
    – rorlork
    May 4, 2015 at 15:36
  • 1
    \$\begingroup\$ You're welcome, I didn't know about many of these tricks either until somebody pointed it out. $> is short for $stdout, and << is an operator. You can save one more byte in the second line by changing it to c*d<0&&$><<?-; a few bytes by combining the 3rd/4th line to $><<a/b<<?., and one more by removing the space after << in the last line. And here's an idea to bring it down to 91 bytes: ->s{a,b=s.scan(/\d+/).map &:to_i;1==s.count(?-)&&$><<?-;$><<a/b<<?.;loop{a=a%b*10;$><<a/b}} (ruby 2.2.0) \$\endgroup\$
    – blutorange
    May 4, 2015 at 18:45
  • \$\begingroup\$ The syntax for $><<a/b didn't work correctly, that's why I put the space there. The rest seems good, thank you very much! \$\endgroup\$
    – rorlork
    May 4, 2015 at 21:36
  • 1
    \$\begingroup\$ If you're still interested, there's also a rational literal (Rational(2,3) == 2/3r) since ruby 2.1 (that I learned about 10 mins ago) that can be used to shorten the second line: eval(s+?r)<0&&$><<?- \$\endgroup\$
    – blutorange
    May 5, 2015 at 0:03
2
\$\begingroup\$

CJam, 38 37 bytes

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

How it works

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)
\$\endgroup\$
2
  • \$\begingroup\$ Since you use double division isn't this totally broken for big numbers? \$\endgroup\$
    – orlp
    May 5, 2015 at 1:18
  • \$\begingroup\$ @orlp: Totally. It's fixed now. \$\endgroup\$
    – Dennis
    May 5, 2015 at 13:10
2
\$\begingroup\$

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

The algorithm is straightforward; the tricky part was getting the printing to work. In the end, I had the computer sleep for a second between each step so it could print.

Expanded, runnable version

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");
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ While the output does have a flushing problem, I was able to get it to show output by sleeping for 9ms which would shave two bytes. \$\endgroup\$
    – user18932
    May 4, 2015 at 15:37
  • \$\begingroup\$ @Snowman It probably depends on the hardware or OS; my computer won't work with less than 250ms or so. \$\endgroup\$
    – Ypnypn
    May 4, 2015 at 17:02
2
\$\begingroup\$

R, 103 137 109 103

Bit happier with this now. Using scan with a separator save a lot of bytes. May still have some room for improvement. Replaced <- with =. Haven't always had the best of luck with this, but it worked this time.

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

Test runs

> 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...
\$\endgroup\$
0
1
\$\begingroup\$

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

Pretty straightforward:

  • Input the numerator and denominator
  • Output the the quotient with 1 digit after the decimal point, then take off the last digit (e.g. -1/3 -> -0.)
  • Take absolute values*
  • Loop:
    • Numerator is remainder after dividing out denominator
    • Multiply numerator by 10
    • Output integer quotient as next digit

* (Though the calculation for a was moved inside the loop to save a few bytes.)

Edit: Fixed bug with negative fractions > -1.

\$\endgroup\$
0
0
\$\begingroup\$

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

edit:

Now outputs all characters on the same line, as asked.

edit2:

Now reads the fraction from commandline argument, as requested :)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ A few tips: 1) Using map instead of the list comprehension saves quite a bit; 2) don't need the parentheses around m*a in any of its locations, as *, %, and / are all the same precedence and left-associative; 3) the 0-or-dot logic on line 3 can be simplified to "0."[m==1], since you're just printing it anyway; 4) probably will save chars to merely set o=stdout.write and convert numeric arguments to string with backticks as needed. \$\endgroup\$
    – DLosc
    May 4, 2015 at 21:41
  • 1
    \$\begingroup\$ Also, the code doesn't appear to work with negatives: 1/-3 gives -1.666666666 instead of -0.333333333. \$\endgroup\$
    – DLosc
    May 4, 2015 at 21:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.