[Question]
  [
[Quote notation](https://en.wikipedia.org/wiki/Quote_notation) is a way of expressing rational numbers based on the concept of [\$p\$-adic numbers](https://en.wikipedia.org/wiki/P-adic_number), written in the form \$x'y\$.
The quote indicates that the number to it's left (\$x\$) is "repeated" infinitely to the left, then prefixed to the number on the right (\$y\$). For example \$3' = \: ...3333\$ and \$764'31 = \: ...76476431\$. We can then consider the geometric series:
$$\cdots + 10^{3k} + 10^{2k} + 10^{k} + 10^{0} = \frac 1 {1 - 10^k}$$
By setting \$k\$ to be equal to the number of digits of \$x\$, we can transform this "infinite" number into a value which converges:
$$\begin{align}
3' & = \: ...333
& 764'31 & = \: ...76476431 \\
 &
& & = 31 + 764'00 \\
 & = \cdots + 3\cdot10^3 + 3\cdot10^2 + 3\cdot10^1 + 3\cdot10^0
& & = 31 + 100 \times 764'\\
 & = 3(\cdots + 10^3 + 10^2 + 10^1 + 10^0)
& & = 31 + 100 \times 764(\cdots + 10^9 + 10^6 + 10^3 + 10^0)\\
 & = 3\left( \frac 1 {1 - 10} \right) 
& & = 31 + 76400\left( \frac 1 {1 - 10^3} \right) \\
 & = \frac {3} {-9}
& & = 31 - \frac {76400} {999}\\
 & = - \frac 1 3
& & = - \frac {45431} {999}
\end{align}$$
Note that \$9'0 \ne 9'\$ as the first equals \$-10\$ and the second \$-1\$. Additionally, note that leading zeros on \$y\$ do affect the output: \$81'09 = -\frac {801} {11} \ne \frac {9} {11} = 81'9\$ Therefore, a value after the \$'\$ (\$y\$) may be omitted in the input.
You are to take, in any reasonable format, up to 2 non-negative integers \$x\$ and \$y\$, and output the fraction \$\frac a b\$ represented by \$x'y\$. Reasonable formats include:
* A string, delimited by a non-digit character, such as `'`, e.g. `9'` or `9'0`. The string will always begin with a digit; if there is no \$x\$ value, it will be a \$0\$ (e.g. `0'3`)
* A list of either 1 or 2 non-negative integers, represented as strings or lists of digits. If there is only 1, it represents \$x'\$. 2 integers represent \$x'y\$.
* A list of 2 elements. The last element may be either a non-negative integer (as a string or digit list), or a consistent value that is not a non-negative integer (e.g. `null` or `None` or `-1` etc.) that indicates that there is no \$y\$ value. The first value will always be a non-negative integer.
This is not an exhaustive list, if you have another method, feel free to ask.
You may output the two integers \$a\$ and \$b\$ instead of the fraction \$\frac a b\$. The fraction must be exact, and fully simplified (i.e. \$a\$ and \$b\$ are coprime). If \$b\$ is 1, outputting just \$a\$ is acceptable. For negative outputs, if outputting \$a\$ and \$b\$ separately, either may have the negative sign, but not both.
You may input and output in any [convenient method](https://codegolf.meta.stackexchange.com/questions/2447/default-for-code-golf-input-output-methods). This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") so the shortest code in bytes wins.
---
Modified from the linked Wikipedia page:
> 
> Let \$x\$ and \$y\$ be sequences of digits, as in \$x'y\$
> 
> 
> Let \$z\$ be the digit \$1\$ followed by a sequence of zeros of the same length as \$y\$.
> 
> 
> Let \$w\$ be a sequence of \$9\$s of the same length as \$x\$.
> 
> 
> Then the number represented by \$x'y\$ is given by \$y-\frac{xz}w\$
> 
> 
> 
## Test cases
```
x'y    = a / b
31'491 = 17609 / 99
844'80 = -4480 / 999
4'128  = -2848 / 9
247'0  = -2470 / 999
0'716  = 716 / 1
592'   = -16 / 27
3'45   = 35 / 3
9'7    = -3 / 1
9'     = -1 / 1
3'0    = -10 / 3
764'31 = -45431 / 999
81'09  = -801 / 11
81'9   = 9 / 11
123456' = -41152 / 333333
```
  
[Answer]
# [J](http://jsoftware.com/), 25 bytes
```
(%-.)~/@(10^#&>)#.10#.&>]
```
[Try it online!](https://tio.run/##y/qvpKegnqZga6WgrqNgoGAFxLp6Cs5BPm7/NVR19TTr9B00DA3ilNXsNJX1DA2U9dTsYv9r/k9TsKhQMKxQsFYwqFCwrOBC8MEcS7CMigGIbQxRBWSZVyiYVSiYgPjGINUA "J ‚Äì 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](http://jsoftware.com/), 23 bytes
```
(%-.)~&(10x^#)#.,&{.&".
```
[Try it online!](https://tio.run/##bY7NCoJAEIDvPsWg5CjoMqOj7gqegk6deoA8hBJdAk9B0Ktvu2tJhxYGdr5v/m42VjjD0ANCAQS9i1LB/nQ82GxXqvyVZkyPc5InqkifKo2VzaNoulzvgDUjzIBiGFfCXUtmMQYG@GNHEU3Oeo1aJGhNX1tJt1n3D3aT7KkJ7IM6bj2jwFyyLWFuqqUOzxdwVUvT/naOmnjhMFGvN5JB@wY "J ‚Äì Try It Online")
Modification of [Jonah's solution](https://codegolf.stackexchange.com/a/222886/78410) 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 `{.`.
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), ~~37~~ 33 bytes
```
d[#/d[0#-9]]~d~#2&
d=Fold[9#+##&]
```
[Try it online!](https://tio.run/##TY47C4MwFIV3f0XggktvqSa@MlicOrd0DA5ilArVQrFTSP66zcPB7ZyPc889c7e@hrlbp77bxnqTAi5SJHDmbWukARpHsr593lJwOAHE7fb4TcPa3L/Tsgo4X8emgTY2z75bjIqUYkhSjSpDwp3SaFmFxPpMI3EyCdDbFAlFUgVCfax0fM8kTpe2B0kRSO57qeMBMCftWR4s9xcHfUjtpbav2New48TUZ2x/IGEa85ty99@XRXr7Aw "Wolfram Language (Mathematica) ‚Äì Try It Online")
Input two lists of digits.
`Fold[9#+##&]` is longer than `FromDigits`, but has more flexibility with its input.
[Answer]
# [Vyxal v2.6.0pre1](https://github.com/Vyxal/Vyxal/releases/tag/v2.6.0pre1), ~~15~~ 11 bytes
```
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
```
## History
I spent roughly an hour on this, trying to arrange it to work properly. Took me a few re-reads of the specs, but I got there in the end.
Input taken as:
```
y
x
```
where `y` and `x` are strings (done by surrounding them with `""`s), and if `y` isn't provided, `[]` is used.
## Explained
```
L‚Üµ‚Å∞I*‚Å∞L‚Üµ‚Äπ/¬πI$-∆í
L‚Üµ               # 10 ** length(y)
  ‚Å∞I             # int(x)
    *            # ‚Üë * ‚Üë‚Üë (we'll call this W)
     ‚Å∞L‚Üµ         # 10 ** length(x)
        ‚Äπ        # ‚Üë - 1
         /       #  W / ‚Üë
          ¬πI     # int(y) # on an empty list, this will return 0
            $-   # ‚Üë‚Üë - ‚Üë
              ∆í  # fractionify(‚Üë) # this built-in has been around for a long time before this challenge --> it turns a decimal into the most simple fraction
```
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), 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!](https://tio.run/##VY/JTsMwEIbvfgoLCY2tZnPsLKZyOKE@AMdSqU4XSJUmURqhtAhePdgOPeDDLJ/@f2Z80p/6suurbvCbdn@YjmoaVXFVBVkpor2SqqJ8XpHS048lfVqPofZuod5QclM@W4z@z@iNvrqaioyLK6XTgBXeIs5ASGZKlqWRxCGWEuVCQB4Z5gthsmUSCWBxji2Mc5FbiGKRQTQjkd11EWQstdCmEDOUyBiwUzkQZ4iDSBzhiQEcScjwrODOIa1@drie2y1zHzlDlgrgzB2YCM7@NucMzA8szSNnZBZJ55Rzz2IukhSck7EkttPcQ9tg6KszocGlq6uBwFsDNDjrjtRYFbi@YwV0HW3@ax/ggdIlGoJj27/o3cds@UIY79rm0taHoG7fSR2c2qpx4qDT@9dB9wNhEfUwqAI8fCS1mUxNZBs6a8GcB3b0N11Ovw "JavaScript (Node.js) ‚Äì 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.
[Answer]
# [R](https://www.r-project.org/), ~~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!](https://tio.run/##Jc1RC4IwEMDxdz@FGqtNJ92VpCfswX2NKCZSFJShFMxPvzZ9OY7f/eEmZ9iOGeXuv6H/Pj8Dt3KWJjdq6B/dJLVCuOa2QNmq24u/O8tnCaIBkenCZuE4y1FhY0XPW6nFPiTjOWkZG7eJ9vMi3BH9k7QkTOMNViegeB8TRYeyCg5eC7/DohTVSw0UuAb0ihhRsDRCxHVZo9DQErg/ "R ‚Äì 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](https://codegolf.stackexchange.com/users/78274/kirill-l) & [@Dominic](https://codegolf.stackexchange.com/users/95126/dominic-van-essen);  
-5 and another -6 bytes thanks to [@Giuseppe](https://codegolf.stackexchange.com/users/67312/giuseppe)*
[Answer]
# [R](https://www.r-project.org/), ~~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](https://codegolf.stackexchange.com/a/223168/95126)*
```
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!](https://tio.run/##fdJha4QgGAfw9/sUHuOWjo7zUUsN/CTRhniLHWzeVh2MvnzTGK0Nu16IwY9//3zsps/rZXg5PXd2OF@8fTNTe/Uu7nGfjwbok3evtsM9OUBFc296Zz0ezMe7/QqCEpJb4/Dp3LbYP441q6Ah@VjH1RmoRmKPkbp6Z/d797CzNWvCpiH/v4wdzjhkeSY0ZIgQdI8MAllSjY5I67sEV0IEr@jCD0IoOvOkjxqYytDimRIq@pRmQgZP11rIG@k0aAnlrw8vQUPKFpoFHeiSPVsmU5jHQylWmBfB8hTVsUOUSy7fqqB/Cqwq3KL0TyrQLcvTNtlWlnEiHFbzKwSH7SNW8X5QvRqJonPrZBVgXBRl/M0lHqBgsc38TN8 "R ‚Äì 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](https://www.r-project.org/) answers, but now I realise that [pajonk's answer](https://codegolf.stackexchange.com/a/222898/95126) is ~~probably~~ golfier... Bah!
[Answer]
# [J](http://jsoftware.com/), 39 32 30 27 bytes
```
{.@".@]-".@[*(%<:)~&(10x^#)
```
[Try it online!](https://tio.run/##bY7BCsIwDEDv@4qgaDZxJdm6rR0OhoIn8eBVdAdxiBdhJ0Hw12vb6VAwkNC8l7S9mpHAFqoSEOZAUNqMBax2m7V5iHok6kNsy34WThZl9JyGTPfjODJRsF0K@JkIgvPpcgNMGaEFlJqxJ1zkpDutoYI/tpFSkbVOo5LSa0Ufm8hisPbs7SDZUe3ZGxWcO0ae2WZ4hDlLutSHG@AklVn@vdko4o79jar/I2k0Lw "J ‚Äì Try It Online")
-5 thanks to Bubbler. Also go upvote [his j answer](https://codegolf.stackexchange.com/a/222891/15469), 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`:
* `(%&x:<:)~&(10^#)`
	+ `&(1>.10^#)` Convert each string input by raising 10 to the power of its length `10^#` (which will be 1 when length is 0).
	+ `(%&x:<:)~` Next swap the argument order `~` and subtract 1 `<:` from the new right arg, to get a number whose digits are all nines. Divide the left argument by that `%`.
[Answer]
# [Haskell](https://www.haskell.org/), 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!](https://tio.run/##NY9Pc8IgEMXvfAqMdtBqDATyh4701ltPvVo7EkXNFImTMNPk06dAWi47@9v3dh832X0rrcfxNOsEwV9amau9wS4@gQvsRavkeYEweunX6@iJRKCfD@ICh9gNn/FsSMisH@@yNlDAcwMg3JuN3FSHXfzTtOdue6m1Ve3yaBr7ptX9GIkkWu0Wr1dl32ujnEEru@w3w0p0D2mWiUCfCK3MNNhLt6s6CNt8SFs3RuqtD@T8e3/EiR5tbexCyqSqhOjnVtYaDo77SCMliHHikpEixxwmkHNQMoZK7FjMmKueccAQSUvoYVqy0kOQsgLhCbHiX4dRQXIPfUkgARlPEQyqANICUMSyQGjmAAUcFXBS0ODgXj85Qk/9lanHwVDkDFESAmaMkr/LJUHuB56WOBgJICllWY6CkpAs9e7wfgE "Haskell ‚Äì 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](https://codegolf.meta.stackexchange.com/a/12747/82619) 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](https://www.haskell.org/), 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!](https://tio.run/##XY/LbsMgEEX3fAV5SJNUcQwGP6hCd9111W2aKjghiVUHRzZS7a93AbebshnNmXvnDjfVfem6Hsd@McgLHqIL7p/IbIjprEenWScp@ay1udob7qITclNpm3dlq8aoettqdV4Cged@vKvKYInPDcJ4bzZqUx520XfTnrvtpaqtbldH09jXWt@PcxnP17vly1Xbt8poZ6i1XfWbYS27hzKrWMIHwNpMg71yu8rD/1jn3/sQJ3q0lbFLpeKylLJfWFXVeHDcnzQyClxQdxnNMyJwjIVABedQEMcizl31TCAONCmwh0nBCw9RwnMgE@L5n45ATjMPfYkxRalIAAdVAEmOGPA0EJY6wJCAHE8KFhzC6ydH6JlPmXoSDHnGgdFwYMoZ/U0uKLgfeFqQYKSIJoynGQQlpWni3eH9AA "Haskell ‚Äì Try It Online")
[Answer]
# 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!](https://tio.run/##NY/LboMwEEX3fMUoUmWbEMDYvFqZrtp@QJZJVDkJJFSUdytQ1W@nxlAvxqOjc8fjD/ktu0ub1/2urK7plIlpEMkoEvwmsLTORCTn5zd8tuTDmTweakdajSNPBDeC7qhrmoNdpOWtv1u1GM1mO5gzHFdIpjZtvvI2xSjrELHbVF5f8yLdj@UFu8Tuq33f5uUNE7uri7zH6FgqLavaF3m54w5EAj8GQJH2cIB3CwYLRjiBgM7@lL1SHHy8bglS1SQOeVLupSq7qkjtorrhAbawQRtVx7k79iLZWJDhgeCRKPuXTIwiHlNQI2kYuDE4EMdGxDmK3BnuOFfNDGODI@pFoKkX8WimhsdD5K6Mh/@mi0IaaDrfDlDDjz0Ei6eJFxoMcX9BzFeEGTEKYXWYDsU6soQ0YPqtBbg6EwYcMbps6nNG1wUiitRfNI5cnaUG9Rj3A6RVSn1vzuvzBw "JavaScript (Node.js) ‚Äì 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   //
  )                        //
```
[Answer]
# [R](https://www.r-project.org/) `+ MASS`, ~~99~~ 91 bytes
```
function(x,y,`[`=gsub)MASS::fractions(eval(parse(t=paste0(y,"-",x,"."[0,y],"/","."[9,x]))))
```
[Try it online!](https://tio.run/##TdBNboMwEAXgfU9huRsjmWbGP9iOyqIH6CrLKFJoBVWlKo2AVHB66jExrVfwPs1jTL907LlkS3e7vI@f3xcxyVmej@f6Y7i9Fa8vh8N@3/VNskG0P82XuDb90IqxvjbD2IKYJS@5nCR/4keQ80nyHU8vQU6nIp6lE1xjzExAXjyymqGrILAdC@EhmjcmoofVSmM8JEtIhMqTESpvPCGRMi4ibGTcvzmI5LC6Y3yKhAQ2qEgpp6kEypFoWtFm0TaCpjxQ1RrThM5NYetZm3Kut63WHHKRq@g2GvNFrdH4t7GnXwQhX8dDKkyNqLSx1f1zNIloFbWms/wC "R ‚Äì Try It Online")
Takes input as two strings (`y` possibly empty), outputs a rational fraction or an integer.
[Answer]
# [Jelly (fork)](https://github.com/https://github.com/cairdcoinheringaahing/jellylanguage), 11 bytes
```
·∏å·∏Ö·∫à‚Åµ*C√∑@¬•/∆≤
```
[Try it online!](https://tio.run/##ASsA1P9qZWxsef//4biM4biF4bqI4oG1KkPDt0DCpS/Gsv///1s4LDFdLFswLDld "Jelly ‚Äì Try It Online"), or rather, don't
As of last week, my fork now includes symbolic math support! Unfortunately, [M](https://codegolf.stackexchange.com/a/222926/66833) (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](https://codegolf.stackexchange.com/a/222891/66833) 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)
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 20 bytes
```
9·πÅ·∏å+√ò.¬µ√ó¬≥·∏åU¬§_/,·∏¢:g/$
```
[Try it online!](https://tio.run/##y0rNyan8/9/y4c7Ghzt6tA/P0Du09fD0Q5uBnNBDS@L1dR7uWGSVrq/y////aGMdw1idaBMdSyANAA "Jelly ‚Äì Try It Online")
Seems very bad ¬Ø\\_(„ÉÑ)\_/¬Ø
[Answer]
# [Retina](https://github.com/m-ender/retina/wiki/The-Language), ~~96~~ 92 bytes
```
(.+)'(.*)
$($($.1*9)*$2*)-$($1$.2*0)*_/$($.1*9)*
+`_-_
-
-/
/
(_+)(\1)*/(\1)*$
$.(_$#2*)/$#3
```
[Try it online!](https://tio.run/##PYtLDsIwEEP3vkYHzafKZ9JCmxNwCaSUBQs2LBD3DxELZNl6luX34/N83b2f5Hp0ibOyRFOQDEW3qkbFNIzmFItltZb@E@ajhYaAkJAgbVa5uVr6JYGiNJrGPdG09L6ylx1l3Tgj8@YXnGthLLyeUXkbHpyxO@f6BQ "Retina ‚Äì 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 `0`s to it, which saves on a `1` amongst other things.)
```
+`_-_
-
-/
/
```
Perform the subtraction, slowly.
```
(_+)(\1)*/(\1)*$
$.(_$#2*)/$#3
```
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!](https://tio.run/##PYs7csMwDET7vYaRgKCGIkFCH1YqcwmNpRQp3KTw5Gw@gC@m0Co8GOws9i3uP3@33289PtzXfri@E3a9F5Br06uv4il7Ce1S6rNP4rf4Rrjvqwa3eYmIuLqtk7AqAq5hAfHzQZ/o9jOPq/pXEZQjKeJyhsvz4cIiblXp4qmN06VEuthxFGWritmM5wRjzTOyTZyQeNIRQ82Mwjag8tS2@YRpNC7tSTlVaC42jPwP "Retina ‚Äì Try It Online")
[Answer]
# [APL (Dyalog Extended)](https://github.com/abrudz/dyalog-apl-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!](https://tio.run/##SyzI0U2pTMzJT9dNrShJzUtJTfn/P@1R24TqR727gNSj3jWPuluAnK2Htz/qan7UsxdEdqx81LtU41HvDgPbR12Lah71rnjUu1lTH8jYWquhEX54@qPePnUDdR2gGZq6QHV9QAlNiKihug5QJgasZQtYgU442J4@dUsk4a21//@rm1gaqiukKagbG6pzqVsYgNkWJiZAjqGRBZgHYkPEjUzMgWxzQzMwzwDINjGFaAYJg1mWcMUgMWOI2eZmYDMsIYaDLEIwgZSppRGYtgSThkbGJqZm6gA "APL (Dyalog Extended) ‚Äì Try It Online")
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 55 bytes
```
Ôº¶‚™™Ôº≥'¬´‚âîŒ∂Œ∑‚âîŒπŒ∂¬ª‚âîÔº©‚≠ÜŒ∑‚ÅπŒ¥‚âî‚Åª√óÔº©Œ∂Œ¥Ôº©‚Å∫Œ∑‚≠ÜŒ∂‚Å∞Œµ‚äûœÖŒµ‚äûœÖŒ¥Ôº∑Ôπ™ŒµŒ¥¬´‚âîŒ¥Œµ‚âîŒπŒ¥¬ª‚™´√∑œÖ‚ÜîŒ¥/
```
[Try it online!](https://tio.run/##VY/NqsIwEIXX@hShGycQ0btTXMl1o1Ao6Av0mmgGcpPSJAoVnz1OWvFnl5M555szR123R1eblE6uZbBvDAbY2iaGfWjRnoELVkwKzm7j0dp7PFvoBNN89ZIoWEfyPn7q39oHGMJl3YAWbMkJIsnzdJRoo4cD/is/uLt@LlgvKkNDSr0RtHDOeYYoglTRa4jf7wy/ajSKQelkNA5U/vxsLYfER2vZt65oS4CdQ0tnhw1eUKqMXP95Z2JQIPPiYlZwvkpp8TOZL9P0Yh4 "Charcoal ‚Äì Try It Online") Link is to verbose version of code. Explanation:
```
Ôº¶‚™™Ôº≥'¬´‚âîŒ∂Œ∑‚âîŒπŒ∂¬ª
```
Split the input string on `'` and save the parts into separate variables.
```
‚âîÔº©‚≠ÜŒ∑‚ÅπŒ¥
```
Change the digits of the first part to `9`s and save the result as an integer.
```
‚âî‚Åª√óÔº©Œ∂Œ¥Ôº©‚Å∫Œ∑‚≠ÜŒ∂‚Å∞Œµ
```
Multiply that by the second part as an integer, then change the digits of the second part to `0`s, append that to the first part, and subtract the integer value.
```
‚äûœÖŒµ‚äûœÖŒ¥
```
Save the fraction to the predefined empty list.
```
Ôº∑Ôπ™ŒµŒ¥¬´‚âîŒ¥Œµ‚âîŒπŒ¥¬ª
```
Find the GCD.
```
‚™´√∑œÖ‚ÜîŒ¥/
```
Reduce the fraction to its lowest terms and output it with a `/` separator.
[Answer]
# [Clojure](https://clojure.org/), 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!](https://tio.run/##PZFNboMwEIX3PsWIKPK4UhL/AXarngSxgZiICgEFR01Pn9qY1Kvx5/fGTzPtMH3dF/fEq@ugex5wcL5qoOlv/ejdzS0wYzdWjxrP8/SDDQjOsJ3uo4cHY6zGEzY4LXCUwBnDC74FzZHhHEi4X10bSxbPkxG8Tqv7hsq71UNFMiWotiL7gE8QZcEtXMBakhmtqeEbPmlt@IYD11RIE3Dk0mgTOcmkLil/UV3@qzktRZF4KAIVJMutpBFF7cZkGVJQne9Q5YEpkllabiTqVLLaZEzWhFT6NyGenGWhqRJ79lwr8YpjBOV2j2n41iG0EFLpvKC7XohcxjbbITW8x21UD/itAdu0qfPql368XdZ56D1sgzxkNGN1TXAOL34YATsInjjyPw "Clojure ‚Äì 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.
[Answer]
# [M](https://github.com/DennisMitchell/m), 13 bytes
```
Cƒ∞√ó
L‚Ç¨‚Åµ*√ß/·∏Ö@·∏å
```
[Try it online!](https://tio.run/##ASkA1v9t//9DxLDDlwpM4oKs4oG1KsOnL@G4hUDhuIz///9bOCwxXSxbMCw5XQ "M ‚Äì Try It Online")
Implements [Bubbler's method](https://codegolf.stackexchange.com/a/222891/66833)
## 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)
```
[Answer]
# [Perl 5](https://www.perl.org/) `-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!](https://tio.run/##HczdCsIgGIDhW5HxBbo0k/4IETzaTcSQHXwsw6a4QNjFZ9LZy3PwJszhUiuFwmFj5j0lssqDvMs5cztoi4bC8FBjD0W0OI49hW2vGIfCdDNRnj4gmTMmcLt2sajBmVf0Syc73n7g5J9rvV3P5KS@MX18XNYqphR@ "Perl 5 ‚Äì Try It Online")
[Answer]
# [05AB1E (legacy)](https://github.com/Adriandmen/05AB1E/wiki/Commands), 18 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
√Ç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](https://codegolf.stackexchange.com/a/222891/52210) won't work for it.  
Instead, this is a port of [*@tsh*'s JavaScript answer](https://codegolf.stackexchange.com/a/222951/52210), 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](https://tio.run/##MzBNTDJM/f//cJPno4ZZXofbdC/s9XQ5tO7wGu0Le@2AQi6H9h/e/v9/tLGhjomlYSwA) or [verify all test cases](https://tio.run/##MzBNTDJM/V9Waa@k8KhtkoKSfeXhCaH/DzdFPGqY5XW4TffC3giXQ@sOr9G@sNcOKORyaP/h7f91/kdHGxvqmFgaxupEW5iY6FgYABkmOoZGFkDayMRcB8Q30DE3NAPSppZGOkpKQIaxjokpkLLUMQeTUDGQUnMzEx1jsGGGOkoGlkoQliWQMjQyNjE1A6mNBQA).
**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)
```
]