              There is a fine line between numerator and denominator.       ─── anonymous



A method to   "reduce"   some reducible fractions is to   cross out   a digit from the
numerator and the denominator.   An example is:

       16                                                  16
      ────     and then (simply) cross─out the sixes:      ────
       64                                                  64

resulting in:

        1
       ───    
        4



Naturally,   this "method" of reduction must reduce to the proper value   (shown as a fraction).

This "method" is also known as   anomalous cancellation   and also   accidental cancellation.



(Of course,   this "method" shouldn't be taught to impressionable or gullible minds.)        😇 



Task

Find and show some fractions that can be reduced by the above "method".

   show 2-digit fractions found   (like the example shown above)
   show 3-digit fractions
   show 4-digit fractions
   show 5-digit fractions   (and higher)       (optional)
   show each (above) n-digit fractions separately from other different n-sized fractions, don't mix different "sizes" together
   for each "size" fraction,   only show a dozen examples   (the 1st twelve found)
   (it's recognized that not every programming solution will have the same generation algorithm)
   for each "size" fraction:
   show a count of how many reducible fractions were found.   The example (above) is size 2
   show a count of which digits were crossed out   (one line for each different digit)
   for each "size" fraction,   show a count of how many were found.   The example (above) is size 2
   show each n-digit example   (to be shown on one line):
   show each n-digit fraction
   show each reduced n-digit fraction
   show what digit was crossed out for the numerator and the denominator


Task requirements/restrictions

   only proper fractions and their reductions   (the result)   are to be used   (no vulgar fractions)
   only positive fractions are to be used   (no negative signs anywhere)
   only base ten integers are to be used for the numerator and denominator
   no zeros   (decimal digit)   can be used within the numerator or the denominator
   the numerator and denominator should be composed of the same number of digits
   no digit can be repeated in the numerator
   no digit can be repeated in the denominator
   (naturally)   there should be a shared decimal digit in the numerator   and   the denominator
   fractions can be shown as   16/64   (for example)


Show all output here, on this page.



Somewhat related task

   Farey sequence       (It concerns fractions.) 


References

   Wikipedia entry:   proper and improper fractions.
   Wikipedia entry:   anomalous cancellation and/or accidental cancellation.


import "/dynamic" for Struct
import "/fmt" for Fmt
 
var Result = Struct.create("Result", ["n", "nine"])
 
var toNumber = Fn.new { |digits, removeDigit|
    var digits2 = digits.toList
    if (removeDigit != 0) {
        var d = digits2.indexOf(removeDigit)
        digits2.removeAt(d)
    }
    var res = digits2[0]
    var i = 1
    while (i < digits2.count) {
        res = res * 10 + digits2[i]
        i = i + 1
    }
    return res
}
 
var nDigits = Fn.new { |n|
    var res = []
    var digits = List.filled(n, 0)
    var used = List.filled(9, false)
    for (i in 0...n) {
        digits[i] = i + 1
        used[i] = true
    }
    while (true) {
        var nine = List.filled(9, 0)
        for (i in 0...used.count) {
            if (used[i]) nine[i] = toNumber.call(digits, i+1)
        }
        res.add(Result.new(toNumber.call(digits, 0), nine))
        var found = false
        for (i in n-1..0) {
            var d = digits[i]
            if (!used[d-1]) {
                Fiber.abort("something went wrong with 'used' array")
            }
            used[d-1] = false
            var j = d
            while (j < 9) {
                if (!used[j]) {
                    used[j] = true
                    digits[i] = j + 1
                    for (k in i + 1...n) {
                        digits[k] = used.indexOf(false) + 1
                        used[digits[k]-1] = true
                    }
                    found = true
                    break
                }
                j = j + 1
            }
            if (found) break
        }
        if (!found) break
    }
    return res
}
 
for (n in 2..5) {
    var rs = nDigits.call(n)
    var count = 0
    var omitted = List.filled(9, 0)
    for (i in 0...rs.count-1) {
        var xn = rs[i].n
        var rn = rs[i].nine
        for (j in i + 1...rs.count) {
            var xd = rs[j].n
            var rd = rs[j].nine
            for (k in 0..8) {
                var yn = rn[k]
                var yd = rd[k]
                if (yn != 0 && yd != 0 && xn/xd == yn/yd) {
                    count = count + 1
                    omitted[k] = omitted[k] + 1
                    if (count <= 12) {
                        Fmt.print("$d/$d => $d/$d (removed $d)", xn, xd, yn, yd, k+1)
                    }
                }
            }
        }
    }
    Fmt.print("$d-digit fractions found:$d, omitted $s\n", n, count, omitted)
}