[Question]
  [
# Challenge
Write a program or function that takes in 4 non-negative integers, A, B, C, and D, that represent two fractions, A/B and C/D, where B and D are non-zero and A <= B and C <= D.
Output an ASCII art depiction of the fractions made of `|x-` characters on two lines as follows:
* The lines will always be the same, minimal length for the input, and both always start and end with `|`.
* The top line will depict A/B by having B sections of `-`'s separated by `|`'s with A of the sections replaced by `x`'s as if they are filling up the 1 whole of the full line.
* Likewise, the bottom line will depict C/D by having D sections of `-`'s separated by `|`'s with C of the sections replaced by `x`'s as if they are filling up the 1 whole of the full line.
It will probably make the most sense if I show an example. Suppose A/B = 2/5 and C/D = 1/3, then the output should be:
```
|xx|xx|--|--|--|
|xxxx|----|----|
```
Here the lines are the same length, as required, and the top one depicts 2 out of 5 sections filled with `x`'s while the bottom one depicts 1 out of 3 sections filled with `x`'s.
As another example, A/B = 1/2 and C/D = 5/8 would give:
```
|xxxxxxx|-------|
|x|x|x|x|x|-|-|-|
```
Notice how the number of `x`'s or `-`'s in each section between `|`'s is the same in any one line but can vary depending on the fractions and the requirement that the two lines are the same length overall.
In the first example it'd be impossible to just have 1 character between the `|`'s for 2/5
```
|x|x|-|-|-|    (2/5 with 1 character between bars)
|xx|--|--|     (invalid for 1/3 paired with 2/5 since line too short)
|xxx|---|---|  (invalid for 1/3 paired with 2/5 since line too long)
```
but with 2 characters between `|`'s it works as shown above.
**Your program must use the shortest lines possible.** This keeps them easy to read.
The cool idea here is that it's super easy to look as these ASCII art depictions of fractions and see which one is greater or if they are equal, just by how the sections line up.
So for the first A/B = 2/5 and C/D = 1/3 example, this output
```
|xxxxx|xxxxx|-----|-----|-----|
|xxxxxxxxx|---------|---------|
```
would be invalid, as, even though the lines are the same length and depict the correct fractions, they can be shorter as shown above.
# Scoring
This is a [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") challenge so the shortest program wins!
Additional notes and rules:
* As stated, B and D will be positive, and A will be from 0 to B inclusive, and C will be from 0 to D inclusive.
* There must be at least one `x` or `-` between each pair of `|` as otherwise it's impossible to tell how much of the fraction is filled.
* The output can have a trailing newline or not, doesn't matter.
* You can take in two fractions directly instead of 4 integers if it makes sense for your language.
# Testcases
Each testcase is 3 lines, the input `A B C D` on one line, followed by the two lines of the output. Empty lines separate testcases.
```
2 5 1 3
|xx|xx|--|--|--|
|xxxx|----|----|
1 2 5 8
|xxxxxxx|-------|
|x|x|x|x|x|-|-|-|
0 1 0 1
|-|
|-|
0 1 0 2
|---|
|-|-|
1 3 1 2
|x|-|-|
|xx|--|
1 2 1 3
|xx|--|
|x|-|-|
1 2 2 4
|xxx|---|
|x|x|-|-|
1 2 2 2
|x|-|
|x|x|
3 3 1 9
|xxxxx|xxxxx|xxxxx|
|x|-|-|-|-|-|-|-|-|
3 5 4 7
|xxxxxx|xxxxxx|xxxxxx|------|------|
|xxxx|xxxx|xxxx|xxxx|----|----|----|
28 30 29 30
|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|-|-|
|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|-|
7 28 2 8
|x|x|x|x|x|x|x|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|xxxxxx|xxxxxx|------|------|------|------|------|------|
1 7 2 13
|xxxxxxxxxxxx|------------|------------|------------|------------|------------|------------|
|xxxxxx|xxxxxx|------|------|------|------|------|------|------|------|------|------|------|
1 7 2 14
|xxx|---|---|---|---|---|---|
|x|x|-|-|-|-|-|-|-|-|-|-|-|-|
0 10 0 11
|----------|----------|----------|----------|----------|----------|----------|----------|----------|----------|
|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
3 10 4 11
|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|----------|----------|----------|----------|----------|----------|----------|
|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|---------|---------|---------|---------|---------|---------|---------|
10 10 11 11
|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|xxxxxxxxxx|
|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|
```
  
[Answer]
# Excel (ms365), 134 bytes
Credits to @[JosWooley](https://codegolf.stackexchange.com/users/116680/jos-woolley) for this is essentially his answer.
[![enter image description here](https://i.stack.imgur.com/BDlDL.png)](https://i.stack.imgur.com/BDlDL.png)
Formula in `E2`:
```
="|"&TEXTJOIN({"";"
|"},0,REPT(REPT({"x","-"},(1+(MOD(D1,B1)=0))*LCM(B1,D1)/VSTACK(B1,D1)-1)&"|",CHOOSE({1,2;3,4},A1,B1-A1,C1,D1-C1)))
```
---
**2nd Answer**: 74 + 81 = 155 bytes
Credits to @[EngineerToast](https://codegolf.stackexchange.com/users/38183/engineer-toast) for this is essentially his answer.
Formula in `E2`:
```
=LET(x,2-SIGN(MOD(D1,B1)),z(A1,B1,LCM(B1,D1)*x)&"
"&z(C1,D1,LCM(B1,D1)*x))
```
Note that there should be a literal newline character pieces this together, where `z()` refers to a named function:
```
=LAMBDA(a,b,m,LET(x,m/b-1,"|"&REPT(REPT("x",x)&"|",a)&REPT(REPT("-",x)&"|",b-a)))
```
---
***Original Answer:** 118 + 138 = 256 bytes*
Formula in `E2`:
```
=z(TEXTJOIN("|",0,,IF(SEQUENCE(B1)<=A1,"x","-"),),TEXTJOIN("|",0,,IF(SEQUENCE(D1)<=C1,"x","-"),))
```
This refers to a named function called 'z':
```
=LAMBDA(a,b,LET(x,LEN(a),y,LEN(b),q,SUBSTITUTE(SUBSTITUTE(IF(x<y,a,b),"|-","|--"),"|x","|xx"),IF(x=y,a&CHAR(10)&b,IF(x<y,z(q,b),z(a,q)))))
```
The idea here is that we create two strings with single 'x' and '-' between pipe-symbols. Z is a named function that will now check the length of both strings and will replace '|x' and '|-' with '|xx' and '|--' respectively for the shortest of the two. It will do so untill the strings have the same length. When found the same length, just concat them together with a newline.
[Answer]
# Python, 152 bytes
Here's the program I used to generate the testcases. I'm sure someone more skilled could golf it down more (and I'd be interested to see!).
```
import math
def p(a,b,c,d):
 L=math.lcm(b,d)
 if L==max(b,d):L*=2
 def f(l,x,d):print('|'+f'{"x"*l}|'*x+f'{"-"*l}|'*d)
 f(L//b-1,a,b-a)
 f(L//d-1,c,d-c)
```
It defines the function `p` so calling `p(A, B, C, D)` produces the output.
The idea is to imagine all but the first `|` in each line as part of the `x` or `-` sections to simplify the math, and then put the `|`'s back in later.
The lcm of the denominators L is the length of the lines, not counting the first `|`. When L is equal to the larger of B or D then each section would be length 1 which would end up looking like `||||||` so the `if L==max(b,d):L*=2` line fixes that situation. Other than that trick it's mostly doing some f-string fanciness to print the lines with the correct values.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), 32 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
√∏`¬©.¬øD¬Æ√†Q>*¬Æ√∑<‚Äûx-SŒ¥√ó'|√¨sI√≠√Ü√∏√óJ‚Ç¨ƒÜ
```
Port of [*@blaketyro*'s Python answer](https://codegolf.stackexchange.com/a/260823/52210), so make sure to upvote him/her as well!
Input as a pair of pairs `[[a,b],[c,d]]`, output as a pair of strings.
[Try it online](https://tio.run/##AUoAtf9vc2FiaWX//8O4YMKpLsK/RMKuw6BRPirCrsO3POKAnngtU860w5cnfMOsc0nDrcOGw7jDl0rigqzEhv//W1syLDVdLFsxLDNdXQ) or [verify all test cases](https://tio.run/##yy9OTMpM/V@m5JlXUFpipaBkX6nDpeRfWgLh6VT@P7wj4dBKvUP7XQ6tO7wg0E4LSG23edQwr0I3@NyWw9PVaw6vKa48vPZw2@Edh6d7PWpac6Tt/6HdOoe22f@Pjo420jGN1Yk21DGOjdVRiAYyjIBcUx0LCNdAxxDIBZEoXCOYYmOwXiNkvWhGGemYoHKhio2hei1hXJAzTHTMIVwjCx1jA5BySxANFjLXMbIAG2ABM88czDU0RuObwN1qAHG7IcwKsIAJXMAQqsTQECwUCwA).
**Explanation:**
```
√∏              # Zip/transpose the (implicit) input-matrix, swapping rows/columns:
               #  [[a,b],[c,d]] ‚Üí [[a,c],[b,d]]
 `             # Pop and push both rows separated to the stack
  ¬©            # Store the top pack [b,d] in variable `¬Æ` (without popping)
   .¬ø          # Pop and get its Least Common Multiple
     D         # Duplicate that
      ¬Æ√†       # Push the maximum from pair [b,d]
        Q      # Check if it's equal to the LCM
         >     # Increase that 0 or 1 by 1
          *    # Multiply it to the LCM
           ¬Æ/  # Divide it by the values of pair `¬Æ`
             < # Decrease both by 1
  ‚Äûx-          # Push string ["x-"]
     S         # Convert it to a pair ["x","-"]
        Œ¥      # Apply double-vectorized on the two pairs:
         √ó     #  Repeat the string the integer amount of times
          '|√¨ '# Then prepend a "|" in front of each of the four strings
  s            # Swap so the pair of numerators is at the top of the stack
   I           # Push the input-matrix again
    √≠          # Reverse each inner row
     √Ü         # Reduce each inner list by subtracting
      √∏        # Create pairs of the two top pairs
               #  [a,c] and [b-a,d-c] ‚Üí [[a,b-a],[c,d-c]]
       √ó       # Repeat the earlier strings that many times
J              # Join the inner pair of strings together
 ‚Ç¨             # Map over both strings in this pair:
  ƒÜ            #  Enclose it; appending its own head (the "|")
               # (after which the pair of strings is output implicitly as result)
```
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal) `j`, ~~31 29~~ 27 bytes
```
yD‚àÜƒø~c√üdŒµ»Æ/‚Äü Å‚â§‚Äõx-i*∆õ\|j\|√∏.
```
[Try it Online!](https://vyxal.pythonanywhere.com/?v=1#WyJqIiwiIiwieUTiiIbEv35jw59kzrXIri/igJ/KgeKJpOKAm3gtaSrGm1xcfGpcXHzDuC4iLCIiLCJbMywgNSwgMiwgM10iXQ==) or [Verify some test cases](https://vyxal.pythonanywhere.com/?v=1#WyJBIiwiIiwieUTiiIbEv35jw59kzrXIri/igJ/KgeKJpOKAm3gtaSrGm1xcfGpcXHzDuC4iLCI74oGLwrbDuC4gIyBmb3JtYXQgdGVzdCBjYXNlcyIsIlszLCA1LCAyLCAzXVxuWzEsIDIsIDUsIDhdXG5bMCwgMSwgMCwgMV1cblszLCAzLCAxLCA5XVxuWzI4LCAzMCwgMjksIDMwXSJd)
-2 bytes thanks to lyxal :)
I'm aware of Vyncode but I'm probably going to stick to regular SBCS bytes in my answers for the time being.
| Code | Stack (bottom to top) |
| --- | --- |
| Implicit input | `(3 | 5 | 2 | 3)` |
| `y` Every other, and the rest | `(3 | 2) (5 | 3)` |
| `D` Push top of stack twice | `(3 | 2) (5 | 3) (5 | 3) (5 | 3)` |
| `‚àÜƒø` Least Common Multiple | `(3 | 2) (5 | 3) (5 | 3) 15` |
| `~c` Execute without pop: Is A in B? | `(3 | 2) (5 | 3) (5 | 3) 15 0` |
| `√üd` If so, double, otherwise don't | `(3 | 2) (5 | 3) (5 | 3) 15` |
| `Œµ` Absolute difference | `(3 | 2) (5 | 3) (10 | 12)` |
| `»Æ` Carry second-to-top over | `(3 | 2) (5 | 3) (10 | 12) (5 | 3)` |
| `/` Divide | `(3 | 2) (5 | 3) (2 | 4)` |
| `‚Äü` Rotate stack right | `(2 | 4) (3 | 2) (5 | 3)` |
| `Å` Range [0, n) | `(2 | 4) (3 | 2) ((0 | 1 | 2 | 3 | 4) | (0 | 1 | 2))` |
| `‚â§` Greater than or equal to? | `(2 | 4) ((0 | 0 | 0 | 1 | 1) | (0 | 0 | 1))` |
| `‚Äõx-` String literal "x-" | `(2 | 4) ((0 | 0 | 0 | 1 | 1) | (0 | 0 | 1)) "x-"`  |
| `i` Index into | `(2 | 4) (("x" | "x" | "x" | "-" | "-") | ("x" | "x" | "-"))` |
| `*` Repeat string n times | `(("xx" | "xx" | "xx" | "--" | "--") | ("xxxx" | "xxxx" | "----"))` |
| `∆õ` Map over each item: | Showing first pass through: |
| `\|j` Join by "|" | `"xx|xx|xx|--|--"` |
| `\|√∏.` Enclose in "|" | `"|xx|xx|xx|--|--|"` |
| `j` flag: Join final result by newlines | Implicit output of result |
Let me know if this format of explanation is good, by the way. I'm trying to experiment with doing it in a method that is more obvious what is happening, but it does take up a lot of space.
[Answer]
# JavaScript (ES6), 113 bytes
```
(p,q,P,Q)=>(F=w=>(n=q*w-Q*W)?F(w+=n<0||!++W):(g=w=>n>q*w?n=`
`:'x-|'[n++%w?n>p*w|0:2]+g(w))(w)+g(W,p=P,q=Q))(W=2)
```
[Try it online!](https://tio.run/##Zc9Ba4MwFAfwu58iO5QmJopGh60u9rSe68mDCBVb3UaJ2o45mPvs7ql1pAgxhl/@eXn5yL6yW359rz8NWZ3OfSF6XLOGHVhERIj3ooVZikZvjUiPyW6PWyrki9V1T5TGxMflkJAhBHZSHLWjv/42unUiKV2BhLXedpbPU1rilhD4YBGzWhxYIyKAWHDSB4mGUII4Q88M2Qw5KGWjwHrCzSzWGBjmhXDllDMif6yzrAzDXcj/KWeus1UEmnEZ8mbhGwgNl2@H/6weGze40jiU8aYunCW56mOs6X22culgrmr2PWjbk2qpZhbV9TXL33CGRIh@UF7JW3U5m5eqxKZpZiR4oGJC0F8S9H8 "JavaScript (Node.js) ‚Äì Try It Online")
### Commented
```
( p, q,                // p / q = 1st fraction
  P, Q                 // P / Q = 2nd fraction
) => (                 //
  F = w =>             // F is a recursive function taking a first width w
                       // explicitly and a second width W implicitly
  (n = q * w - Q * W)  // let n be the difference between q * w and Q * W
                       // (NB: n is reused as a counter in the 2nd phase)
  ?                    // if n is not equal to 0:
    F(                 //   do a recursive call to F:
      w += n < 0       //     increment w if n is negative
           || !++W     //     increment W if n is positive
    )                  //   end of recursive call
  :                    // else (n = 0):
    ( g = w =>         //   g is a recursive function taking w
      n > q * w ?      //   if n is greater than q * w:
        n = `\n`       //     append a linefeed and reset n to a 0'ish value
      :                //   else:
        'x-|'[         //     append one of these characters:
          n++ % w      //       if w is not a divisor of n (which is
          ?            //       incremented afterwards):
            n > p * w  //         append '-' if n > p * w, or 'x' otherwise
            | 0        //
          :            //       else:
            2          //         append the separator '|'
        ] + g(w)       //     append the result of a recursive call
    )(w) +             //   1st call to g, using (w, p, q)
    g(W, p = P, q = Q) //   2nd call to g, using (W, P, Q)
)(W = 2)               // initial call to F with w = W = 2
```
[Answer]
# [APL (Dyalog APL)](https://www.dyalog.com/products.htm), 45 [bytes](https://github.com/abrudz/SBCS)
Call as `A C f B D`.
```
{'-x|'[2,‚ç®‚Üë‚ç∫(>‚åà2√ó1,2‚â†/‚ä¢)¬®‚åä‚çµ√ó‚äÇ√∑‚ç®‚àò‚ç≥‚ç®(‚àß‚åà2√ó‚åà)/‚çµ]}
```
[Attempt This Online!](https://ato.pxeger.com/run?1=XZHPSsNAEMbxmqeYW1JoaXaT0j8HL1WwFwXbi5QisUlEqLWQCkrtRSXE2BRFpIKXIIqhVymCx_Yp9DhP4uxGWvCQye_75tuZhX2e2udW5-Rw3-p14mll2zp2vJ7Vdt5O-26u9N0YqLmzC7XJsxgl6N9j9KWt4yjgiwnLcryJ8xi-ZOYJjkKMZosJhpeLTxENnjD6INAweE_zVDN5CrWGr95B2_tZ21DtI6-nAo4fq3ug2m7XUxUStR3073TFpYrRGMMrhv4D-fXdKtXGVq2u9B2vD9SHATkyNwO8vYZUibFANyG3qQNvgQsCGRitoSLPzhPQOBSArAxoDASXiHRy6FsSl12DmP_lVic4mEsSXUPmypIKYEKRiJfAoCllqqSKQJrLRQyKYpixQjNdqov9TA4hNlNmssGYUIpS2eza_94pjtP_Lw)
Or, for the same length:
```
{'-x|'[2,‚ç®‚Üë,¬®2,¬®(¬Ø1+‚äÉ(,√∑‚ç®‚àß‚åà2√ó‚åà)/‚çµ)/¬®‚ç™¬®‚ç∫>‚ç≥¬®‚çµ]}
```
[Attempt This Online!](https://ato.pxeger.com/run?1=XZG_S8NAFMdxzV_xtiSY0twlpT8GlyrYQQXrIqVIbBoRai1cBaV2USmlNUURcXDpoBi6OEgQHNO_Qsf3l_juIi043Pc-733ffd9wzzP_wmudHh14ndZ0Vtr2Tpqi4zWar2fdIFP43urpmfNLvcYtDCMc3FtJxOkYyTtbxdG1Yc0_pTF8w9shnz-RmlkMYzObRBjOpHytYfghIa73X8RhQ_ysrOv-sejogJPH8j7oftAWukZFZQcHd7YWkGI4oXiGgwfqV3fLpHublarWbYoukA896qi5GHB8A2klYwFHV9St2cDrEIBEBk69r6m3SQQGhxxQywSDgeQCkU0dOgviynWI-d_c8gUHd0HSddRcUVEOXMgT8QI4lFIkpSoPVHO1iEFehjlLdNOlttzPVAixmzJTBmOy0rTSRtv_90HTaXr_Ag)
[Answer]
# [AWK](https://www.gnu.org/software/gawk/manual/gawk.html), ~~265 253 248 239~~ 230 bytes
```
function g(p,q){return q?g(q,p%q):p}function l(s,j){a=s;for(i=1;i++<M;)a=a s;b=a=j?a"|":z;for(i=1;i++<j;)b=b a;return b}L+=(L=(B=$2)*(D=$4)/g(B,D))==(B<D?D:B)?L:0,$0="|"l("x",$1,M=L/B-1)l("-",B-$1)"\n|"l("x",$3,M=L/D-1)l("-",D-$3)
```
[Try it online!](https://tio.run/##VY1fa4MwFMXf/RQXcZA7IzWJxVZ7EcRH@w32EscqumK1f9hY18/urtIVCkl@JzfnnNivz3HcXbr3c3PooBa9HPB6/Dhfjh0MWS0G2b8MmPS3h2cvTrLFq6VTujscRUMqbXx/s03RkoVTWpGlNrPur5v8PDnaFCuqwKb3@upW@iRKEjl5Gl9FQV6Ei1rkskAkHm@KrEhyzMoklF5I3LgX7rcrPSW3VC7yQCEPAlfmgafQfeseBjMbioehCDyD46hAwxJWTggKeN@pHQWG1UTNNDM1RHdqx8zva@YSIogdvQLDuTWfTgx801yqIJ7i5l9EU304/aM4yCqalJqHSvH6Aw "AWK ‚Äì Try It Online")
* -9 bytes thanks to [@ceilingcat](https://codegolf.stackexchange.com/users/52904/ceilingcat)
* -9 bytes:
	+ -1 replaced `""` with `z`
	+ -8 replaced last structure by implicit assignation
---
This use POSIX awk, and not gawk.  
In gawk you can use the abbreviation `func` for `function`.   
[GAWK function](https://www.gnu.org/software/gawk/manual/html_node/Definition-Syntax.html) :
> 
> In many awk implementations, including gawk, the keyword function may be abbreviated func. (c.e.) However, POSIX only specifies the use of the keyword function. This actually has some practical implications. If gawk is in POSIX-compatibility mode (see Command-Line Options), then the following statement does not define a function:
> 
> 
> 
> ```
> func foo() { a = sqrt($1) ; print a }
> 
> ```
> 
> 
[Answer]
# [Julia](https://julialang.org), 77 bytes
```
n|d=(l=lcm(d...);x=l*2^(l‚ààd).√∑d.-1;p='|';@. p*('x'^x*p)^n*('-'^x*p)^(d-n))
```
[Attempt This Online!](https://ato.pxeger.com/run?1=TZBBbsMgEEXVrW_Q3ewMVo0MODIRQuoFegIrliLjqKkosRIieeED5A7dZJMz9AA9RbvsSQrGqbyB9zV_PsN83N7OZr-9Xm9nt8vF94sdtUJGmfYdaUIIloMyGWuQ-b1cNCZfn5rkVPYqHVP5TKDPUDqkzZD1uLGe85mRzi3GMfTn4dF1J3dSdVIzWEmgwDdPSU2BSViBCFwAleCPBbPo4cHP_v3LXgblgicPj_51ZP9WCVVgJoAX3rX2V9AVMBGaRAyoAlO-FOU8SjHNRWNgUOWsaCxSGnSySXaHIzg1_RT64946YwkaUbdtX9uDQQ6HdWJ5ryEMndVxQ_f1_wE)
Accepts input as two vectors: numerators `n` and denominators `d`.
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), 45 bytes
```
=GyW}J/*FKeMQiFKKJjmsm?%k/Ged?>cFdckG\x\-\|hG
```
[Try it online!](https://tio.run/##K6gsyfj/39a9MrzWS1/LzTvVNzDTzdvbKyu3ONdeNVvfPTXF3i7ZLSU52z2mIkY3pibD/f//6GhjHdNYnWgTHfPYWAA "Pyth ‚Äì Try It Online")
Takes input as a list of lists `[[a, b], [c, d]]`.
### Explanation
First we compute the length of the lines (minus 1). This is the least common multiple of `b` and `d`, multiplied by 2 if it is exactly `b` or `d`. We save this number in the variable `G`.
```
                      # implicitly assign Q = eval(input())
         KeMQ         # assign K to [b, d]
       *FK            # multiply the elements of K
      /      iFK      # divide by the gcd of K (to obtain lcm)
     J                # assign this to J
  yW             J    # conditional apply doubling to J
    }J          K     # if J is in K
=G                    # assign this to G
```
Next, we loop through the input and `G+1` choosing the correct character for each position through two conditional operators.
```
jmsm?%k/Ged?>cFdckG\x\-\|hGQ    # implicitly add Q
 m                         Q    # map d over Q
   m                     hG     #   map k over G+1
    ?%k/Ged                     #     if (k % (G / d[-1])):
           ?>cFdckG             #       if (d[0] / d[1] > k / G):
                   \x           #         "x"
                                #       else:
                     \-         #         "-"
                                #     else:
                       \|       #       "|"
  s                             #   sum the list of chars into a string
j                               # join on newlines and print
```
[Answer]
# [Arturo](https://arturo-lang.io), ~~113~~ 105 bytes
```
$->a[e:lcm@[a\1a\3]if‚à®e=a\1e=a\3->'e*2map a[x y]->[124]++map
e'z->(0=z%e/y)?->124->(z>x*e/y)?->45->120]
```
[Try it](http://arturo-lang.io/playground?U5lJE0)
```
$->a[                     ; a function taking a list of four integers named a
    e:lcm@[a\1a\3]        ; assign lcm of 2nd and 4th args to e
    if‚à®e=a\1e=a\3->       ; if e is equal to 2nd or 4th arg...
        'e*2              ; double e in place; this ensures no zero-width sections
    map a[x y]->          ; map over input in pairs, assign to x and y
        [124]++           ; prepend pipe character to...
        map e'z->         ; map over [1..e] and assign current elt to z
            (0=z%e/y)?->  ; does e/y divide z? Then...
                124       ; pipe
            ->            ; otherwise
            (z>x*e/y)?->  ; is z greater than x times e/y? Then...
                45        ; x
            ->            ; otherwise
                120       ; hyphen
]                         ; end function
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~98 94~~ 93 bytes
```
->a,b,c,d{[[a,b],[c,d]].map{|x,y|[p,*[?x*~k=b.lcm(d)/y*~1[b%d*(d%b)]]*x,*[?-*~k]*y-=x,p]*?|}}
```
[Try it online!](https://tio.run/##VcpLCoMwFAXQeVfRiaDhxhptoR1YF/J4A2Nw0gqhrZDgZ@tphCJ0dj/nNWof@jrIewuNDmYiiolBMTPnQ2un2cHPZCGocWJ91Dp/dkNqspMXqyKdGJGaRGfMwm1GRsPCy9rBsmjmZQl2/LyPPZW4QKHiw68XuKGAKvYhnij/gNrA3iuco7hy@AI "Ruby ‚Äì Try It Online")
[Answer]
# [Java (JDK)](http://jdk.java.net/), 166 ~~172~~ bytes
> 
> -6 bytes thanks to @KevinCruijssen !
> 
> 
> 
Thank you for the challenge, it was very cool!
```
(a,b,c,d)->{var r="";int i,j=0,p=b,q=d;while(p!=q|p<=b|q<=d)p+=p<q?b:0*(q+=d);for(;j++<2;r+="|\n",b=d,a=c)for(i=0;i++<b;)r+="|"+(i>a?"-":"x").repeat(p/b-1);return r;}
```
[Try it online!](https://tio.run/##tVXNmpowFN3PU6RZQQlW0PmcMWZ8gXbVZaeLAHGKRYSAln6jy@76CNOXmxexAQKCRL9aRwPk797DOffm4pyuqTn3vu@ilRP4LnADmiTgE/VD8HxzA4AfpozPqMvAR7pwPCpWgfh9TrkfPoGZJvYBRbkZcMrOLTtPx8Jym2MkKU0FtAQIyo7sNIoc5CJPNx@e15QDTiDEuauP5qSPIuKgmHj4xzc/YFr0jsSbaEKcTTwhnh4ZJJrEU2fcf6/FhljAsyXX8NwwJjbmBoGbxxAih3iIElfP93zSx77YdrBe7END8x/oFJpwDDOo9ziLGE216INjWjrmLF3xEHC83eFcgoyOVLJe@h5gaxqckI@qGLEsYm7KPL0dOs6SVZACIuPRm9XhwKXZzyRli95ylfYi4ZAGoaZVUD0Wr2iQaCWGPoWvL7@E3jF8/fNb9LohN@oMKOgvRIq1ksuXr4Dyp6QiWAgDNrpFFhoAgACAmyzLL9OU12MopsVCMS9WIJDMS38L5Qh3tX9WO5gSoG5m0ToIffF@cUuEwueolV1ZmdJOyWggbCvLTBpJXUr@Lf0V6yPYtmjDvdpNQ@UJjyYbad2xHBS875uRbD1rVs2mQLlFQzRq5eOgk7lppKjabDz2KVfn3b5DA5GPe/Gstf1fMzcH5@R8gA67ERL87P2x7Lzw35qMzbHQneoUB2GUH7VBu1Ja5dIEuGByAesLhB0WhepuFIo63N2i7@ffBmtf9l3FVxvmH5ju@hVHimIW@od7/Y0jox6@tX7FS5SjK@m3igNgWWdE4E2HZ0TgbUYyAuX/@Xb3Fw "Java (JDK) ‚Äì Try It Online")
---
A little explanation of my answer: first we calculate the  
"**Least Common Multiple strictly greater than the `b` and `d` parameters**"  
using the following:
`p=b,q=d;while(p!=q|p<=b|q<=d)p+=p<q?b:0*(q+=d);`  
which leaves the result in `p`.  
  
Then we draw the 2 lines (using a small loop) with an inner loop that decides using its index wether we should draw a `x` or `-`, and we repeat this character a number of times using:  
the "**greater-LCM**", divided by the `b` or `d` parameter (depending on the current line), minus 1.  
And the `|` and `\n` are put where they should be during the process.
[Answer]
# SAS, 181 (73+108) bytes
1. The code:
Macro (73):
```
%macro m(x,n,k);s=repeat("&k",&n-2);do i=1to &x;put s+(-1)"|"@;end;%mend;
```
Data step (108):
```
data;set;L=LCM(b,d);L=L+(L=b<>d)*L;put"|"@;%m(a,L/b,*)%m(b-a,L/b,-)put/"|"@;%m(c,L/d,*)%m(d-c,L/d,-)put;run;
```
*Process:*
Process assumes that input data are passed in a SAS dataset with variables `a`, `b`, `c`, and `d`. Dataset has to be created just before executing the code.
Example data (extending test cases):
```
data i;
  input A B C D;
cards;
2 5 1 3
1 2 1 3
1 2 2 4
1 2 2 2
3 3 1 9
1 3 1 9
1 3 3 9
3 9 5 15
3 5 4 7
28 30 29 30
7 28 2 8
1 7 2 13
1 7 2 14
0 10 0 11
3 10 4 11
10 10 11 11
2 3 11 17
1 10 2 10
10 100 20 100
1 10 10 100
1 10 1 1
1 1 1 10
3 3 1 9
1 1 1 1
0 1 0 1
;
run;
```
2. Human readable code:
Macro:
```
%macro m(x,n,k);
  s = repeat("&k", &n-2);
  do i = 1 to &x;
    put s +(-1) "|" @;
  end;
%mend;
```
Data step:
```
data ;
  set ;
  L = LCM(b, d);
  L = L + (L = b<>d)*L;
  /* put / / a +(-1)"/" b "  " c +(-1)"/" d; */
  put "|" @;
    %m(  a, L/b, *)
    %m(b-a, L/b, -)
  put / "|" @;
    %m(  c, L/d, *)
    %m(d-c, L/d, -)
  put ;
run;
```
Uncoment the `put / / a +(-1)"/" b " " c +(-1)"/" d;` line to have nicer
looking result in the log.
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 50 bytes
```
ÔºÆŒ∏‚äûœÖÔºÆÔºÆŒ∑‚äûœÖÔºÆ‚âîŒ£œÖŒ∂Ôº∑Œ£Ôπ™Œ∂œÖ‚â¶‚äïŒ∂Ôº¶œÖ¬´‚ü¶‚≠Ü‚äïŒ∂‚éáÔπ™Œ∫√∑Œ∂Œπ¬ß-x‚ÄπŒ∫√óŒ∏√∑Œ∂Œπ|‚üß‚âîŒ∑Œ∏
```
[Try it online!](https://tio.run/##fZBPa8JAEMXP@imGnGZgPbTSU0@Cl4AWQW/iISZTdzHZ6P6xmraffd2tCoGCp2Eev/fmMaUsTNkWdQi5Pnj34ZstGzzS@3DhrUQvoK9T1Pu7fMJNrFU7jUvfoCcBXZS@pKoZ/qR5W/m6xU6AJyKYF4c7n@vScMPacXUzfbYGYgJ8DwcLo7TD9dLFuYuWPoxdPLJiowtzeaTvUys3VSdVcTqlKDITl@uKz5iNzpmAGVubuJVq2OLxvyFZsp@MaBO7DO4lpYD0ot8QXuENXmAcRqf6Cg "Charcoal ‚Äì Try It Online") Link is to verbose version of code. Explanation:
```
ÔºÆŒ∏‚äûœÖÔºÆÔºÆŒ∑‚äûœÖÔºÆ
```
Input the four integers, but push the denominators to the predefined empty list.
```
‚âîŒ£œÖŒ∂Ôº∑Œ£Ôπ™Œ∂œÖ‚â¶‚äïŒ∂
```
Calculate the adjusted LCM of the denominators, which is like the LCM execpt that it can't equal either denominator. This is achieved by starting the search with the sum of the denominators.
```
Ôº¶œÖ¬´
```
Loop over the denominators.
```
‚ü¶‚≠Ü‚äïŒ∂‚éáÔπ™Œ∫√∑Œ∂Œπ¬ß-x‚ÄπŒ∫√óŒ∏√∑Œ∂Œπ|‚üß
```
Calculate the display for this denominator.
```
‚âîŒ∑Œ∏
```
Copy the second numerator to the first so that the second loop calculates the display for the second denominator correctly.
43 bytes by taking the inputs in the order B, D, A, C:
```
Ôº¶¬≤‚äûœÖÔºÆ‚âîŒ£œÖŒ∂Ôº∑Œ£Ôπ™Œ∂œÖ‚â¶‚äïŒ∂Ôº¶œÖ¬´ÔºÆŒ∏‚ü¶‚≠Ü‚äïŒ∂‚éáÔπ™Œ∫√∑Œ∂Œπ¬ß-x‚ÄπŒ∫√óŒ∏√∑Œ∂Œπ|
```
[Try it online!](https://tio.run/##ZY49i8JAEIZr/RVDqhmIxXlYWQnXBPQQTCcWuWQ0i8lGd3c0F73fvm78AOGqgZn3mefNy8zkTVZ5v20M4JhgKbZEiSHRB3HfUv@wQaLpcGat2mlcSY1CMXRhdS5VxXBfLZpCqga7GISIYJEdnvlE54Zr1o6LB3T3CMFlOHhXHMNpsDRKO1yvXJi78OOdxi5YUzY6M78v3b6v6b7USRXcuxWFzMwluuAWo1EbxTBna/tcqmq2ePwP9Eh0jYg2ocGf9xP4hDF8@NGpugE "Charcoal ‚Äì Try It Online") Link is to verbose version of code.
[Answer]
# [Thunno 2](https://github.com/Thunno/Thunno2) `N`, 30 [bytes](https://github.com/Thunno/Thunno2/blob/main/docs/codepage.md)
```
z·∫∏√êD≈Ä∆Å∆á‚Å∫√ó_\¬µ¬´L¬©ƒ±`x-si;√óƒ±'|j'|·πõ
```
Requires Thunno 2.2.0+ for stack rotation. ATO is on v2.1.9.
Port of Jacob's Vyxal answer. See that answer for a more detailed explanation.
#### Explanation
```
z·∫∏          # Uninterleave into two pieces
  √êD        # Quadruplicate so four copies are on the stack
    ≈Ä       # Pop one copy and push the LCM
     ∆Å∆á     # Without popping anything, check for containment
       ‚Å∫√ó   # Increment and multiply (i.e. double if true)
         _  # Subtract the list from this number
\           # Divide the two lists
 ¬µ¬´         # Rotate the stack left
   L        # Lowered range of each number
    ¬©       # Less than or equal to
     ƒ±      # Map over this list of lists:
      `x-   #  Push the string "x-"
         s  #  Swap so the list is on top
i           #  Index into the string
 ;          # End map
  √ó         # Multiply each string by each number
   ƒ±        # Map over this list of lists:
    '|j     #  Join the list by the character "|"
       '|·πõ  #  And surround this string by the character "|"
            # N flag joins by newlines
            # Implicit output
```
#### Screenshot
[![Screenshot](https://i.stack.imgur.com/G1D4Hm.png)](https://i.stack.imgur.com/G1D4H.png)
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 30 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
:g/He¬°$$·πö·π¨‚Ç¨·∏∑‚±Æ"∆≤~R}¬¶"·π≠‚Ç¨1·ªã‚Äú|x-‚ÄùY
```
A full program that accepts the denominators, `[B, D]` and the numerators, `[A, C]`, and prints the result.
**[Try it online!](https://tio.run/##AU4Asf9qZWxsef//OmcvSGXCoSQk4bma4bms4oKs4bi34rGuIsayflJ9wqYi4bmt4oKsMeG7i@KAnHx4LeKAnVn///9bMTAsIDExXf9bMywgNF0 "Jelly ‚Äì Try It Online")** Or see the [test-suite](https://tio.run/##y0rNyan8/98qXd8j9dBCFZWHO2c93LnmUdOahzu2P9q4TunYprqg2kPLlB7uXAsUNHy4u/tRw5yaCt1HDXMj/xcbhUYdXq4fruPgHamZ9ahx36Fth7b9/x8dbaSjYKqjYKijYByroxANpCECFiCeAVgCRKLwjKAqjcECRgh9qKYAkQkKD6zSGKbPEsoDWmaio2AO4hlZACVBFliCaJCIOZBjAdZsATXKHGKTMSrXBOZAA4h7DaGGg/gmML4hVIGhIVgkFgA "Jelly ‚Äì Try It Online").
### How?
```
:g/He¬°$$·πö·π¨‚Ç¨·∏∑‚±Æ"∆≤~R}¬¶"·π≠‚Ç¨1·ªã‚Äú|x-‚ÄùY - Main Link: [B, D]; [A, C]
              ∆≤                - last four links as a monad - f([B, D]):
       $                       -   last two links as a monad - f([B, D]):
      $                        -     last two links as a monad - f([B, D]):
  /                            -       reduce by:
 g                             -         greatest common divisor (GCD)
     ¬°                         -       repeat...
    e                          -       ...number of times: exists in?
                                              - i.e. if the GCD is one B or D:
   H                           -       ...action: halve (the GCD)
:                              -     ([B, D]) integer divide (that) (vectorises)
        ·πö                      -   reverse
         ·π¨‚Ç¨                    -   untruth each - e.g. 4 -> Patten = [0,0,0,1]
             "                 -   zip with ([B, D]) applying:
            ‚±Æ                  -     map (across implicit range [1..x]):
           ·∏∑                   -       left argument
                                   - i.e. B and D copies of the respective Patterns
                   "           - zip with ([A, C]) applying:
                  ¬¶            -   sparse application...
                R}             -   ...to indices: range of right -> [1..A] or [1..C]
               ~               -   ...action: bitwise NOT -> 0:-1 and 1:-2
                    ·π≠‚Ç¨1        - tack each to a one - handles the leading "|"
                        ‚Äú|x-‚Äù  - list of characters = "|x-"
                       ·ªã       - (repeated, augmented Patterns) index into (those)
                                   - 1-based and modular so -2 & 1 are '|',
                                     0 is '-', and -1 is 'x'.
                             Y - join with a newline
                               - implicit, smashing print
```
[Answer]
# [J](http://jsoftware.com/), 55 52 51 bytes
```
'-x|'{~(*.(%*1+e.),)&{:(2,~&,2,.}.@#"+)&>;&((>i.)/)
```
[Try it online!](https://tio.run/##lZExb4MwEIV3fsXFFLDBGNsoLTgNQq3UqerQlXiqEjVdulZK8F@nB2WAELXqYFv@7t57Z/mjK1dG2duVKaPIIyI6wNZABBwkGFypgMfX56cuSr/O0cnRWNAgVsleMM7Ck6Gau5BrLlpR@yRhYbUJKa2OgmWsY97Lg4BflbJ1oV4o/9ANga41/9VhXlo3Q@TOXwopxfZKZEQxOpr0ORZRzU1zQxJlmI7l1jJLA3fOjqK2LBYZbX5y7DS/MRxftiGqH8QGrpnOgmPc11Qb2Vq2IxKUH1ZsMs7@7f0TFKzhABry4Yq/M1KNdA3FjKIFUtyvUn3hkCNVC6oHei1NX/Tmo0M5o7qAXPbdJZ6zyl1f620Kz@u@AQ "J ‚Äì Try It Online")
Great challenge, surprisingly difficult to golf, and tried a few different approaches just to get this:
The basic idea is:
1. First create each fraction with no dividing bars, using 0 for "empty" and 1 for "full". Eg, \$ \frac{2}{3}\$ is `1 1 0` and \$\frac{1}{5}\$ is `1 0 0 0 0`.
2. Next we compute the amount each number needs to "puff up", so that the final length is the modified LCM -- 15 in this case. The modification, described in many other answers, is to double the LCM when one of the denominators *is* the LCM.
3. "Puff up" each number as needed -- 5x for \$ \frac{2}{3}\$ and 3x for \$\frac{1}{5}\$ (extra spaces for clarity):
```
1 1 1 1 1   1 1 1 1 1   0 0 0 0 0 
1 1 1  0 0 0  0 0 0  0 0 0  0 0 0
```
4. Change the first element in each group to a 2, to represent the divider, and append and extra 2 at the end:
```
2 1 1 1 1   2 1 1 1 1   2 0 0 0 0  2
2 1 1  2 0 0  2 0 0  2 0 0  2 0 0  2
```
5. Convert to ascii:
```
|xx|--|--|--|--|
|xxxx|xxxx|----|
```
[Answer]
# [Perl 5](https://www.perl.org/) `-MList::Util=pairmap -pa`, 97 bytes
```
($_,$\)=pairmap{"|x"x$a."|-"x($b-$a)."|
"}@F;($c>0?$_:$\)=~s/\|\K./$&$&/g while$c=$\=~y///c-y///c
```
[Try it online!](https://tio.run/##K0gtyjH9/19DJV5HJUbTtiAxsyg3saBaqaZCqUIlUU@pRlepQkMlSVclURPI4VKqdXCz1lBJtjOwV4m3AumoK9aPqYnx1tNXUVNR009XKM/IzElVSbZVibGtq9TX10/WBZP//xsqGCkYK1j8yy8oyczPK/6v6@uTWVxiZRVakpkDsxcoaKpnYGjwX7cgEQA "Perl 5 ‚Äì Try It Online")
Brute force method. Creates each fraction with only one character between the lines. Then it extends the length of the shorter by one more character between the lines, repeatedly, until the two lengths are the same.
]