# Context

If a0 and b0 are two decimal numbers, with a and b representing the decimal expansion of all digits but the least significant one, then we know that

$$\frac{a0}{b0} = \frac{a{\not\mathrel0}}{b{\not\mathrel0}}= \frac{a}{b}$$

# Phony fraction

A phony fraction is a fraction where the numerator and denominator share a digit (other than a 0 in the units place) and, when that digit is erased from both numerator and denominator, the simplified fraction happens to be equal to the original one.

## Example

$$\16/64\$$ is a phony fraction because if we remove the $$\6\$$, we get $$\16/64 = 1{\not\mathrel6}/{\not\mathrel6}4 = 1/4\$$, even though the intermediate step of removing both sixes is wrong.

Given a fraction, determine if it is phony or not.

## Note

Notice that 10/20 is not a phony fraction. Even though 10/20 = 1/2, the simplification here was mathematically sound, you divided numerator and denominator by 10, which amounts to "crossing out a 0 on the num. and the den.".

On the other hand, 102/204 = 12/24 is a phony fraction, because supposedly we can't cross out the 0s.

Because of this, when the input fraction is such that crossing out 0 gives an equivalent fraction to the original, the behaviour is unspecified.

# Input

The fraction we care about, with positive numerator and denominator, in any sensible format. Some examples of sensible formats include:

• a list [num, den] or [den, num]
• a string of the form "num/den"
• the exact fraction, if your language supports it
• two different arguments to your function

Assume both are greater than 9. You can also assume the denominator is strictly larger than the numerator.

# Output

A Truthy value if the fraction is phony and a Falsy value if it is not.

# Test cases

(Please keep an eye out for the comments, as some people have really nice test case suggestions! I'll edit them in, but sometimes I don't do it immediately.)

## Truthy

69/690 = 9/90
99/396 = 9/36
394/985 = 34/85
176/275 = 16/25
85/850 = 5/50
59/295 = 5/25
76/760 = 6/60
253/550 = 23/50
52/520 = 2/20
796/995 = 76/95
199/796 = 19/76
88/583 = 8/53
306/765 = 30/75
193/965 = 13/65
62/620 = 2/20
363/561 = 33/51
396/891 = 36/81
275/770 = 25/70
591/985 = 51/85
165/264 = 15/24
176/671 = 16/61
385/781 = 35/71
88/484 = 8/44
298/596 = 28/56
737/938 = 77/98
495/594 = 45/54
693/990 = 63/90
363/462 = 33/42
197/985 = 17/85
462/660 = 42/60
154/451 = 14/41
176/374 = 16/34
297/990 = 27/90
187/682 = 17/62
195/975 = 15/75
176/473 = 16/43
77/671 = 7/61
1130/4181 = 130/481


## Falsy

478/674
333/531
309/461
162/882
122/763
536/616
132/570
397/509
579/689
809/912
160/387
190/388
117/980
245/246
54/991
749/892
70/311
344/735
584/790
123/809
227/913
107/295
225/325
345/614
506/994
161/323
530/994
589/863
171/480
74/89
251/732
55/80
439/864
278/293
514/838
47/771
378/627
561/671
43/946
1025/1312


You can check this reference implementation that I used to generate some phony fractions by brute-force.

This is so shortest submission in bytes, wins! If you liked this challenge, consider upvoting it... And happy golfing!

• Possible duplicate of How NOT to reduce fractions Feb 19, 2020 at 14:06
• The linked challenge is about removing a common substring. This is about removing a common digit. I think the difference is significant enough to make it non-dupe Feb 19, 2020 at 15:26
• May we accept lists of digits? Feb 19, 2020 at 15:50
• Is 11/11 a phony fraction? Feb 19, 2020 at 18:10
• @JonathanFrech yes it is. Just not a very interesting one, I would say.
– RGS
Feb 19, 2020 at 19:44

# J, 22 bytes

%&".e.=/#&,%/&(1".\.])


Try it online!

quick explanation for now:

1. take the input as strings
2. %/&(1".\.]) creates a function table %/ whose axes are the integer ". lists formed by the 1-outfixes \. (remove 1 digit at a time) of both args, and whose cells are the quotients of those numbers
3. =/ forms a corresponding function table of the same shape, which acts as a boolean mask which is only 1 when corresponding "removed" digits are equal
4. #&, Flattens , both function tables into lists and uses the boolean mask to filter # the quotients, since cancelling is only valid when the digits are equal
5. %&". the true quotient of the inputs after converting to ints
6. e. is that true quotient an element of the filtered list from step 4.
• Really nice! +1 I have no idea what is going on but it is passing all test cases... So it can't be that wrong :p
– RGS
Feb 19, 2020 at 9:37
• They’re added already I believe I noted the new ones in my TIO with comments Feb 19, 2020 at 10:07

# Python 3, 86 bytes

lambda a,b:g(a)&g(b)
g=lambda s:{(int(s[:i]+s[i+1:])/int(s),x)for i,x in enumerate(s)}


Try it online!

-8 bytes thanks to ovs

Making use of the fact that the boolean value for a0/b0==a/b is equivalent to a0/a==b0/b. The helper function g generates all ratios a0/a and keeps track of the removed digit. Then it does the same for b0/b. The main function determines the intersection of the two sets.

Returns a non-empty set (boolean True in Python) if a match is found, and an empty set (boolean False in Python) otherwise.

• Looking good! +1 for your good work :D
– RGS
Feb 19, 2020 at 10:06
• 114 bytes with enumerate.
– ovs
Feb 19, 2020 at 12:15

# 05AB1E, 2623 22 bytes

€æâεR*Ë9ÝºIJySõ.;å*}à


-3 bytes thanks to @Grimmy.

Input as a pair [numerator, denominator].

Explanation:

€æ         # Get the powerset of each number in the (implicit) input-pair
# Push both lists separated to the stack
â       # Create all possible pairs by taking the cartesian product
ε          # Map each pair to:
R         #  Reverse the pair
*        #  Multiply it by the (implicit) input-pair
Ë       #  Check if both values are the same
9Ý        #  Push a list in the range [0,9]
º       #  Mirror each horizontally: [00,11,22,33,44,55,66,77,88,99]
IJ        #  Push the input, joined together
y       #  Push the pair we're mapping again
S      #  Convert it to a flattened list of digits
õ.;   #  Remove the first occurrence of those digits in the joined input,
#  by replacing each first occurrence with an empty string
å         #  Check if what remains is in the list of doubled digits
*  #  And check if both that and the earlier check are truthy
}à         # After the map: check if any where truthy by taking the maximum
# (after which this is output implicitly as result)


The R*Ë checks with input-pair $$\[a,b]\$$ and potentially reduced pair $$\[c,d]\$$ whether $$\a×d=b×c\$$ (source).

• 24 with €æâʒ9Ý2×IJySõ.;å}εR*Ë}à. (Use €æâʒ9Ý2×®JySõ.;å}εR®*Ë}à to "verify all test cases".) Feb 19, 2020 at 13:10
• Down to 23 with €æâεR*Ë9Ý2×IJySõ.;å*}à (€æâεR®*Ë9Ý2×®JySõ.;å*}à to verify all). Feb 19, 2020 at 13:23
• @Grimmy Thanks. And an additional -1 with º instead of 2×, since it apparently vectorizes with lists. :) Feb 19, 2020 at 13:58
• Good catch with º. I had missed the other than a 0 part of the spec, so that 9Ý might need to be changed to 9L (pending confirmation from RGS). Feb 19, 2020 at 14:31
• Really good job! +1 sorry for taking so long, but I have tried to make the 0 rule more clear. 10/20 is not a phony fraction because the simplification 10/20 = 1/2 by crossing out the digits is mathematically sound.
– RGS
Feb 19, 2020 at 19:49

# Jelly,  18  17 bytes

DḌ-Ƥż$€÷þ/Ẏċ÷/,1Ɗ  A monadic Link accepting a list, [numerator, denominator] which yields zero (falsey) if not reducible, or a positive integer (truthy) if reducible. Try it online! Or see the test-suite. ### How? DḌ-Ƥż$€÷þ/Ẏċ÷/,1Ɗ - Link: [n, d]
D                 - decimal digits (vectorises)
$€ - last two links as a monad for each: -Ƥ - for overlapping 1-outfixes (i.e. less 1 digit): Ḍ - un-decimal ż - zip (with digits - these are in the same order) / - reduce by: þ - outer-product with: ÷ - division -> [outfixesDivided, digitsDivided] Ẏ - tighten (to a list of pairs) Ɗ - last three links as a monad: / - reduce ([n, d]) by: ÷ - division 1 - one , - pair -> [n÷d, 1] i.e. digitsDivided must be 1 ċ - count occurrences  Unfortunately enumerate, Ė, given a number, n, yields [[1, n]] not simply the first pair [1, n], which would save a byte with ...ċ÷/Ė$.

• Really short answer! +1 Jelly with some nice submissions here
– RGS
Feb 19, 2020 at 20:01

# JavaScript (ES6),  100  93 bytes

Saved 7 bytes by using @Jitse's method

Takes input as ('numerator')('denominator'). Returns a Boolean value.

n=>d=>(g=n=>[...n].map((x,i)=>x+-(n.slice(0,i)+n.slice(i+1))/n))(n).some(v=>g(d).includes(v))


Try it online!

• Great job! +1 i don't know if you think it helps, but you may want to consider reducing the test case results into a single boolean? Using .reduce((a,b)=>a&&b,true) and .reduce((a,b)=>a||b,false) instead of the .join :) I'm leaving this here for your consideration!
– RGS
Feb 19, 2020 at 19:54

# T-SQL, 192 bytes

Returns -1 for true, 0 for false

WITH x as(SELECT substring(@n,number,1)b,substring(@,number,1)a,number
n FROM spt_values)SELECT~(1/~count(*))FROM x,x y
WHERE x.b=y.a AND x.b>0and 1*stuff(@,x.n,1,'')*@n=@*1*stuff(@n,y.n,1,'')


Try it online

• Uh, really interesting submission! +1 thanks for your work!
– RGS
Feb 19, 2020 at 10:30

# Perl 6, 58 bytes

{[(&)] .map:{m:g/./>>.&{(.prematch~.postmatch)/.orig~$_}}}  Try it online! Same approach as in Jitse's Python answer. ### Alternative, 75 bytes {?grep {[==]$_ Z*$^m[(3,4),(0,2)]>>.join},m:ex/^(.*)(.)(.*)\s(.*)$1(.*)$/}  Try it online! Same regex-based approach as in Neil's Retina answer. • Cool submission! Thanks for your work +1 – RGS Feb 19, 2020 at 19:59 # Jelly, 22 bytes DżḌ-Ƥ$€ŒpḢ€E$Ƈ÷/€F=÷/Ẹ  Try it online! A monadic link taking a list of [num, den] and returning 1 for phony and 0 for non-phony. ## Explanation D | Convert to decimal digits$€                | For each list of decimal digits:
ż                     | - Zip with:
Ḍ-Ƥ                  | - A list of lists of digits each one with 1 removed, that has then been converted back to a list of integers
Œp              | Cartesian product
$Ƈ | Keep those where the following is true: Ḣ€ | - The heads of each list (which will be the removed digits) E | - Are equal ÷/€ | Reduce each by dividing F | Flatten (to remove the nested lists) =÷/ | Equal to the original argument reduced by division Ẹ | Any  • Cool submission! I'll be wanting to give this a very good look +1 – RGS Feb 19, 2020 at 19:55 # Ruby, 109 86 81 78 bytes ->n,d{g=->n,d{w=1;n.digits.map{|s|[s,d*(n%w+w*(n/w*=10))]}};g[n,d]&g[d,n]!=[]}  Try it online! Saved some bytes by using multiplication instead of division: if a/b==a0/b0, then a*b0==a0*b. Then stole some ideas from Jitse's excellent Python answer (upvote him!) to trim a couple of bytes off the corners. • Great minds copy, genius minds steal. A friend of mine says this a lot. Haven't figured out if it makes sense, but your paragraph reminded me of it +1 – RGS Feb 19, 2020 at 20:02 # Excel (Ver. 1911), 64 Bytes Fraction entered as a row literal of 2 strings e.x. ={"16","64"} A1 'Input: row literal of 2 strings -> ={num,den} C1:D9 {=SUBSTITUTE(A$1#,ROW(),,1)} 'Array formula (entered with <C-S-Enter>)
E1    =SUM((C1:C9/D1:D9=A1/B1)*(A1#<>C1#)) 'Output (truthy/falsy int)


### Test Sample

• Cool submission! Thanks :D +1
– RGS
Feb 20, 2020 at 11:32

# C (gcc), 128126 124 bytes

P,h,o,n,_=10;i(e,s){for(n=P=1;e/P;P*=_)for(h=1;s/h;h*=_)e/P%_&&e/P%_==s/h%_&&(o=s/h/_*h+s%h,n*=!o|(e/P/_*P+e%P)*s-e*o);e=n;}


Try it online!

• Thanks for your submission! +1 what are the weird numbers next to the Falsy test cases?
– RGS
Feb 19, 2020 at 20:00
• @RGS Those are (not) truthy values; i's output. Feb 19, 2020 at 21:01
• Nice variable naming.
– Neil
Feb 20, 2020 at 10:13
• Phonies........ Feb 21, 2020 at 18:54
• @ceilingcat Thank you. Jun 23, 2020 at 5:00

# Retina, 69 bytes

L$w(.)(.*)/(.*)\1$($$2)*$($3$1$')*_/$($$1$2)*$($3$')* \b(_+)/\1\b  Try it online! Link includes test suite. Outputs the number of phony pairs of digit cancellations. Explanation: L$w(.)(.*)/(.*)\1


List all matching pairs of digits in the numerator and denominator, including overlaps.

$($$2)*$($3$1$')*_/$($$1$2)*$($3$')*


Cross-multiply each value with the digit removed from the other value.

\b(_+)/\1\b


Count how many times this results in the same answer, indicating that this digit cancellation was a phony fraction.

• And here it is, Retina again! +1 keep up the interesting work!
– RGS
Feb 19, 2020 at 19:56

# Charcoal, 27 bytes

⊙θ⊙η∧⁼ιλ⁼×ＩΦη⁻ξμＩθ×ＩΦθ⁻ξκＩη


Try it online! Link is to verbose version of code. Outputs a Charcoal boolean, i.e. - for phony, nothing otherwise. Explanation:

 θ                          First input as a string
⊙                           Any character satisfies
η                        Second input as a string
⊙                         Any character satisfies
ι                     First character
⁼                      Equals
λ                    Second character
∧                       Logical And
η               Second input
Φ                Filtered by
ξ             Inner index
⁻              Minus (i.e. not equal to)
μ            Second index
Ｉ                 Cast to integer
×                  Multiplied by
θ          First input
Ｉ           Cast to integer
⁼                   Equals
θ      First input
Φ       Filtered by
ξ    Inner index
⁻     Minus (i.e. not equal to)
κ   First index
Ｉ        Cast to integer
×         Multiplied by
η Second input
Ｉ  Cast to integer
Implicitly print

• Thanks for your submission! +1
– RGS
Feb 20, 2020 at 11:34