g | x | w | all
Bytes Lang Time Link
039APLNARS250113T220539ZRosario
008Vyxal210405T020321Zlyxal
087Retina210405T011738ZNeil
01805AB1E legacy211110T095003ZKevin Cr
104R210405T224214ZDominic
099Perl 5 apl210408T021840ZKirill M
091R + MASS210405T150757ZKirill L
092R210405T084936Zpajonk
070APL Dyalog Extended210406T224044ZAndrew O
061JavaScript Node.js210406T070809Ztsh
011Jelly fork210405T213200Zcaird co
013M210405T212448Zcaird co
092Clojure210405T134140ZKirill L
076JavaScript ES7210405T010916ZArnauld
055Charcoal210405T104356ZNeil
058Haskell210405T012416ZDelfad0r
033Wolfram Language Mathematica210405T051319Zatt
025J210405T023134ZBubbler
nanJ210405T010840ZJonah
020Jelly210405T003029Zhyperneu

APL(NARS), 39 chars

{k←-(⍎⍺)÷¯1+10x*≢⍺⋄⍵≡'':k⋄(⍎⍵)+k×10*≢⍵}

Implement the formula show Bubbler in J solution, in APL... It use rational 2r9 means 2/9. The notation x'y is traslated as x is the argument of function on the left seen as a string, and y is the argument of function on the right seen as string. If argument on the right y not exist, it will be rapresented from void string ''.

test:

  f←{k←-(⍎⍺)÷¯1+10x*≢⍺⋄⍵≡'':k⋄(⍎⍵)+k×10*≢⍵}
  '31' f '491'
17609r99 
  '844' f '80'
¯4480r999 
  '4' f '128'
¯2848r9 
  '247' f '0'
¯2470r999 
  '0'   f '716'
716 
  '592' f ''
¯16r27 
  '3' f '45'
35r3 
  '9' f '7'
¯3 
  '9' f ''
¯1 
  '3' f '0'
¯10r3 
  '764'f'31'
¯45431r999 
  '81'f'09'
¯801r11 
  '81'f'9'
9r11 
  '123456'f''
¯41152r333333 
  '9'f'0'
¯10 
  
 

Vyxal, 8 bytes

⌊?@↵÷⌐/β

Try it Online!

-3 bytes thanks to emanresu

Old Answer

vL↵‡⌐/R?⌊$β

Haha rationals go brrr. Obligatory port of Jelly, M and Bubbler.

Explained

vL↵‡⌐/R?⌊$β  # Full program, takes ["x", "y"]
vL           # vectorise length over each
  ↵          # and raise 10 to the power of each
   ‡⌐/       # lambda x, y: x / 1 - y
      R      # reduce the above list by that
       ?⌊    # cast each string in input to it
         $β  # and convert to the result of reducing the lambda

Retina, 96 92 87 bytes

(.+)'(.*)
$($($.1*9)*$2*)-$($1$.2*0)*_/$($.1*9)*
+`_-_
-
-/
/
(\b_+|\1)+/(\1)+$
$#1/$#2

Try it online! Link includes faster test cases. Explanation:

(.+)'(.*)
$($($.1*9)*$2*)-$($1$.2*0)*_/$($.1*9)*

Write out yw-xz/w. (Edit: I don't actually multiply x by z, I just suffix the appropriate number of 0s to it, which saves on a 1 amongst other things.)

+`_-_
-
-/
/

Perform the subtraction, slowly.

(\b_+|\1)+/(\1)+$
$#1/$#2

Slowly divide by the GCD and convert to decimal.

Just for completeness, optimising for speed results in code that readily dispatches all of the test cases. Try it online!

05AB1E (legacy), 18 bytes

ÂI‚JÆ-нID®ì+н>‚D¿÷

Despite 05AB1E's name (when 05AB1E converted to hexadecimal is interpret as base64 it spells Base), it can't do base conversion from decimal values, so @Bubbler's approach won't work for it.
Instead, this is a port of @tsh's JavaScript answer, so make sure to upvote that answer as well!

This uses the legacy version of 05AB1E, because the GCD builtin ¿ will always result in a positive integer in the new version of 05AB1E (the D¿÷ should be Ð.±s¿*ß÷ as workaround in that case).

Try it online or verify all test cases.

Explanation:

Uses the formula:

$$(x,y) = [x-(y\mathbin\Vert x-x\mathbin\Vert y), \text{-1}\mathbin\Vert x + x + 1]$$

integer-divided by their \$\gcd\$ afterwards; where \$\mathbin\Vert\$ is concatenation, taking precedence over the other operators.

        # Reverse the (implicit) input-pair (without popping)
 I‚      # Pair it with the input-pair
   J     # Join both inner pairs together
    Æ    # Reduce this pair by subtracting
     -   # Subtract this integer from both values of the input-pair
      н  # Pop and only keep the first one
ID       # Push the input-pair twice again
  ®ì     # Prepend both integers in the top pair with "-1"
    +    # Add both to the input-pair at the same positions
     н   # Pop and only keep the first one
      >  # Increase it by 1
‚        # Pair the two values together
 D       # Duplicate this pair
  ¿      # Get the GCD (Greatest Common Divisor)
   ÷     # Integer-divide the values in the pair by this GCD
         # (after which the pair is output implicitly as result)

R, 114 110 109 107 104 bytes

Edit: -4 and then -2 more bytes thanks to Giuseppe's comments on pajonk's answer, and then -3 bytes after copying a trick from Robin Ryder's answer here

function(s,z=10^nchar(s)-1:0,n=scan(t=pmax(s,0)),a=c(diff(n*z[2:1]),z[1]),c=1:z)a/max(c[!a%%c&!a[2]%%c])

Try it online!

Input is a vector of two strings representing x and y.

I tried to answer this without peeking at the other R answers, but now I realise that pajonk's answer is probably golfier... Bah!

Perl 5 -apl, 99 bytes

($w,$z)=map s/./9/gr,@F;@e=($F[1]*$w-$F[0]*($z+1),$w);$w--while grep$_%$w,@e;$_=join"/",map$_/$w,@e

Takes two space separated strings from stdin, outputs a fraction.

Try it online!

R + MASS, 99 91 bytes

function(x,y,`[`=gsub)MASS::fractions(eval(parse(t=paste0(y,"-",x,"."[0,y],"/","."[9,x]))))

Try it online!

Takes input as two strings (y possibly empty), outputs a rational fraction or an integer.

R, 118 116 108 103 98 92 bytes

function(x,y,`+`=nchar,B=10^+x-1,A=el(max(y,0):0)*B-x*10^+y,q=1:x)c(A,B)/max(q[!A%%q&!B%%q])

Try it online!

Takes first input as integer and second as string (empty if no \$y\$).

GCD implementation borrowed from here: https://codegolf.stackexchange.com/a/48845/55372

-8 bytes thanks to @Kirill & @Dominic;
-5 and another -6 bytes thanks to @Giuseppe

APL (Dyalog Extended), 70 bytes

Not great, but I felt like submitting it anyway

{⍺←⍬⋄{⍵÷⊃⌽⊃∩⍥(⍸0=⊢|⍨⍳)/|⍵}((W×⍎'0',⍺)-(⍎⍵)×⍎'1','0'\⍨⍴,⍺),W←⍎'9'\⍨⍴,⍵}

Not sure why, but my code to handle single arguments works in TryAPL.org but not in tio.run

Also, because of how APL handles default arguments, I had to swap the order on input...like I said, not the best solution :|

⍺←⍬⋄ ⍝ assign Empty Set to the default value for the left argument (Y from the problem statement)
 ⍵÷⊃⌽ ⍝ divide the 2-tuple (a and b from the problem statement) by their gcd
  ⊃ ⍝ pick (removes one layer of nesting)
   ∩ ⍝ intersection
    ⍥ ⍝ function composition operator (Over)
     (⍸0=⊢|⍨⍳)/ ⍝ fold/reduce by finding divisors
      |⍵ ⍝ absolute value of 2-tuple (a and b from the problem statement)
       W×⍎'0',⍺ ⍝ W (from problem statement) times the integer representation of the left argument (Y from the problem statement) or zero if alpha is the empty set
        -(⍎⍵) ⍝ subtract the integer representation of the right argument (X from the problem statement)
         ×⍎ ⍝ decode then multiply
          '1', ⍝ concatenate the character 1
           '0'\⍨⍴ ⍝ expand the character 0 by the number of characters in Y
             ,⍺ ⍝ ravel Y (effectively making single characters into singleton arrays)
              , ⍝ concatenate
                W←⍎'9'\⍨⍴ ⍝ assign the integer representation of the expansion of the character 9 by the number of characters in X
                 ,⍵ ⍝ ravel X

Try it online!

JavaScript (Node.js), 61 bytes

x=>y=>(G=(a,b)=>b?G(b,a%b):[x/a,z/a])(z=-1+x-~x,x-=y+x-(x+y))

Try it online!

Take input as two strings, output an array with two numbers.

JavaScript use + for both number plus and string concatenation. When any operand is string, it works as string concatenation.

Jelly (fork), 11 bytes

ḌḅẈ⁵*C÷@¥/Ʋ

Try it online!, or rather, don't

As of last week, my fork now includes symbolic math support! Unfortunately, M (Jelly's version with symbolic math) only implements this in the İ atom, not in the ÷ division atom. My fork does both.

Again, implements Bubbler's strategy to evaluate \$[x, y]\$ in base \$-\frac z w\$.

How it works

ḌḅẈ⁵*C÷@¥/Ʋ - Main link. Takes [x, y] as lists of digits on the left
Ḍ           - Convert [x, y] to integers
          Ʋ - Do the following to [x, y]:
  Ẉ         -   Lengths of each
   ⁵*       -   Raise 10 to the power of each length
        ¥/  -   Reduce by the following:
     C      -     Complement; 1 - a
      ÷@    -     Divide b by that; b / (1 - a)

M, 13 bytes

Cİ×
L€⁵*ç/ḅ@Ḍ

Try it online!

Implements Bubbler's method

How it works

Cİ× - Helper link. Takes a on the left and b on the right
C   - Yield 1-a
 İ  - Inverse; Yield 1 / (1-a)
  × - Times; Yield b / (1-a)

L€⁵*ç/ḅ@Ḍ - Main link. Takes [x, y] as lists of digits
L€        - Length of each
  ⁵*      - Raise 10 to the power of the lengths
    ç/    - Run the helper link with the powers of 10 as a and b
        Ḍ - Convert [x, y] into integers
      ḅ@  - Evaluate [x, y] as base b / (1-a)

Clojure, 92 bytes

#(let[b biginteger p(fn[x](.pow(b 10)(count x)))](-(b(or %2 0))(/(*(b %)(p %2))(dec(p %)))))

Try it online!

Relies on the formula from Wikipedia. Takes input as two strings (nil when there is no y), outputs a rational fraction, or a bigint when denominator is 1.

JavaScript (ES7),  80  76 bytes

Expects (x)(y) as strings (y may be an empty string) and returns [numerator, denominator].

x=>y=>(G=(a,b)=>b?G(b,a%b):[p/a,q/a])(q=1-10**x.length,p=y*q+x*10**y.length)

Try it online!

Commented

x =>                       // outer function taking x
y =>                       // inner function taking y
  ( G = (a, b) =>          // G is a helper function which takes 2 integers,
      b ? G(b, a % b)      // computes their GCD a
        : [ p / a, q / a ] // and eventually returns [ p / a, q / a ]
  )(                       // we invoke G with (q, p) defined as follows:
    q =                    //   q =
      1 -                  //   1 - 10 ** len(x)
      10 ** x.length,      //
    p =                    //   p =
      y * q +              //   y * q + x * 10 ** len(y)
      x * 10 ** y.length   //
  )                        //

Charcoal, 55 bytes

F⪪S'«≔ζη≔ιζ»≔I⭆η⁹δ≔⁻×IζδI⁺η⭆ζ⁰ε⊞υε⊞υδW﹪εδ«≔δε≔ιδ»⪫÷υ↔δ/

Try it online! Link is to verbose version of code. Explanation:

F⪪S'«≔ζη≔ιζ»

Split the input string on ' and save the parts into separate variables.

≔I⭆η⁹δ

Change the digits of the first part to 9s and save the result as an integer.

≔⁻×IζδI⁺η⭆ζ⁰ε

Multiply that by the second part as an integer, then change the digits of the second part to 0s, append that to the first part, and subtract the integer value.

⊞υε⊞υδ

Save the fraction to the predefined empty list.

W﹪εδ«≔δε≔ιδ»

Find the GCD.

⪫÷υ↔δ/

Reduce the fraction to its lowest terms and output it with a / separator.

Haskell, 58 bytes

x#y=f y-f x*0!y/1!x
c!s=10^length s-c
f x=read$'0':x++"%1"

Try it online!

The relevant function is (#), which takes x and y as strings, with y possibly empty. Returns a Rational.

DISCLAIMER: the compiler is unable to correctly deduce the type of (#), unless it is specified by some other part of the program, either explicitly (i.e. ::Rational) or implicitly (i.e. by using the return value as if it were a Rational). Based on this Meta answer I believe this should be allowed, but since I'm quite inexperienced I'm not sure. If that's not the case, then the best I can do is:

Haskell, 63 bytes

x#y=f y-f x*0!y/1!x
c!s=10^length s-c
f x=toRational.read$'0':x

Try it online!

Wolfram Language (Mathematica), 37 33 bytes

d[#/d[0#-9]]~d~#2&
d=Fold[9#+##&]

Try it online!

Input two lists of digits.

Fold[9#+##&] is longer than FromDigits, but has more flexibility with its input.

J, 25 bytes

(%-.)~/@(10^#&>)#.10#.&>]

Try it online!

Takes a boxed 2-item vector containing the digit vectors of \$x\$ and \$y\$, and returns a rational number. The digits must be given in extended precision. \$y\$ may be an empty vector. I guess it's pretty well golfed when Jelly is at 20 bytes :)

How it works

Uses the formula at the end of the challenge. If we define \$\#x\$ as the number of digits of \$x\$,

$$ z = 10^{\#y}, \quad w=10^{\#x}-1, \quad x'y = -\frac{z}{w}x+y, $$

and observe that the result is the same as the 2-vector \$[x,y]\$ evaluated in base \$-\frac{z}{w}\$.

(%-.)~/@(10^#&>)#.10#.&>]    NB. Monadic train; input = (digits of x;digits of y)
                  10#.&>]    NB. Evaluate each in base 10 to get [x,y]
                #.           NB. Evaluate in base...
        (10^#&>)    NB. 10 raised to the power of length of each; [10^#x, 10^#y]
(%-.)~/@            NB. (10^#y) / (1 - 10^#x) = -z/w

J, 23 bytes

(%-.)~&(10x^#)#.,&{.&".

Try it online!

Modification of Jonah's solution to use the same base trick. This one is a dyadic function accepting plain strings as its two args. One caveat is that eval(".) of an empty string is an empty vector, so we need to make it a 0 explicitly using {..

J, 39 32 30 27 bytes

{.@".@]-".@[*(%<:)~&(10x^#)

Try it online!

-5 thanks to Bubbler. Also go upvote his j answer, which is more creative and has delightful application of base #.

The wikipedia formula translated into J. The only part that might be of some interest is the calculation of z/w:

Jelly, 20 bytes

9ṁḌ+Ø.µ×³ḌU¤_/,Ḣ:g/$

Try it online!

Seems very bad ¯\_(ツ)_/¯