[Question]
  [
Given two non-negative integers e.g. `27, 96` their multiplication expression would be `27 x 96 = 2592`.  
If now each digits is replaced with a symbol, such that
* *two digits are replaced with the same symbol if and only if they are equal*
we could get something like `AB x CD = AECA` or `0Q x 17 = 0Z10` or `!> x @^ = !x@!`.  
(following this rule we can also get the original expression itself but we'd lose the meaning of the digits being numbers since they will become just placeholders).  
We call such an expression a ***cryptic multiplication*** of `{27, 96}`.
Is clear that some information is lost and the process is not always reversible, indeed an `AB x CD = AECA` ***cryptic multiplication*** can be obtained from each of the following pairs
* `{27, 96}` `27 x 96 = 2592`
* `{28, 74}` `28 x 74 = 2072`
* `{68, 97}` `68 x 97 = 6596`
There is no other pair of numbers that yields `AB x CD = AECA`.  
Hence ***3*** is the ***cryptic multiplication ambiguity*** of `{27, 96}`
Write a function or a program that given two non-negative integers prints their ***cryptic multiplication ambiguity***.
## Test cases
```
{0, 0} -> 2
{5, 1} -> 17
{11, 11} -> 1
{54, 17} -> 18
{10, 49} -> 56
{7, 173} -> 1
{245, 15} -> 27
{216, 999} -> 48
{1173, 72} -> 3
```
*[Mathematica reference program](https://tio.run/##fY/LasNADEX3/ooBgUmK0sm4i1DyQBATCBRaSneDA0MqP8CZBEcGg/G3uxPidRdC4iLOkS5OSr44qc5uHG9OhBuvturQ@rNUV2877PTrT9mw@7VgFjtIYgv47XzB9MG@kJIgy2JKuWbhtL3VgSR8p0P9gHnqsnWUB@L@2nqxk0HTPiz5UPazDYE9euGCm7QqKrlr6sEgJAjmBZIhRoBgoNnTSsfcwmZrsF/i@4C9WZ5msDBzDEPoQxZrmnDPAx84GOYZqsn@ry08s46inKhfJaiMWb0NSmv11VRexvEP)*
  
[Answer]
# [K (ngn/k)](https://codeberg.org/ngn/k), ~~41~~ 36 bytes
-5 bytes inspired by [Jonathan Allan's answer](https://codegolf.stackexchange.com/a/250748/64121).
```
{#*={.(=`k@x,*/x)_" "}'?+x,'!10*1+x}
```
[Try it online!](https://ngn.codeberg.page/k#eJw1jEsOwjAMRPc+xVAWhbQisZPUBKmCm8CqGy4QqWrPToRBmsVoPm+5rUc3r5fT/Ho/6uh8PT87dFt/H+rYHzg4HupGJMCOBQGBWL82g4ktZW4ivlqewEp5siYgFfK/nbYmkhcDSGqITD7ZT3hCKW0c/1CNUPkAaV4iZw==) The last 4 cases are too slow to run online.
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal) `s`, 17 bytes
```
vL↵ʀΠƛ?"ƛΠJṄ:vḟ;≈
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJUcyIsIiIsInZM4oa1yoDOoMabP1wixpvOoErhuYQ6duG4nzviiYgiLCIiLCJbNSwxXSJd)
This would flaglessly be 19 bytes. It can be shorter flagless, though:
# [Vyxal](https://github.com/Vyxal/Vyxal), 18 bytes
```
vL↵ʀΠ?wJƛΠJṄ:vḟ;ṫO
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyJUIiwiIiwidkzihrXKgM6gP3dKxpvOoErhuYQ6duG4nzvhuatPIiwiIiwiWzUsMV0iXQ==)
```
vL↵ʀΠ?wJƛΠJṄ:vḟ;ṫO
vL                  # For each number in the input, get its length
  ↵                 # Take 10 to the power of each
   ʀ                # For each, generate an inclusive zero range [0, n]
    Π               # Get the cartesian product of these two lists
     ?wJ            # Append the input to this
        ƛ           # For each:
         Π          #  Get the product of the two
          J         #  Append that onto the list
           Ṅ        #  Join by spaces
            :       #  Duplicate
             vḟ     #  For each in the duplicate, get the first index that it occurs in the other identical copy
               ;    # Close map
                ṫ   # Tail extract - push a[:-1] and a[-1]
                 O  # Count the number of times this a[-1] appears in this a[:-1]
```
[Answer]
# [Knight](https://github.com/knight-lang/knight-lang), ~~416~~ 219 bytes
```
;=mB;=u=s+++++""a" "t" "*a t;=o"";=h 10;WhE++"=x"=h-h 1"N";=w=n 0;Wu;=v+"x"-Au 48;I?32Au=o+o" "E+++++";I"v"N="v"=w+1w=o+o "v=uGu 1Lu o;=a+0P;=b=t+0P;=qCm;=a^10La;=b^10Lb;=z 0;W>a~1;=t b;Wt;=t-t 1;=oCmI?q o=z+1zN=a-a 1Oz
```
[Try it online!](https://tio.run/##lVhrV9s4Gv7eXyG0HbBixyTd7uwWI3IoQ@dwtg3dwgxnN0kb2VYSTx0r@AKUxPPXu698lXOBTs8pJNKj96bnvYg/2B2LnNBbxO1AuPy747MoQv8OvOksPg9DESL@EPPAjVD2bZnmgI8sjHhzXzlToj4lQezNn8ddxSFn86UjgigOEycWocbIMp55kRmJJHQ4ZSnseIubmRfzaMEcrhX7cxY7M@3wszYYjoaDYQTr6dFIX/1t8HkYjFraMFi9JKR1SNIF519hN@RxEgZIET7ojFarIPH9NBdmGw7tkKXPY8SobfIH7mgKnFiFCHmEUsp68sORCqHKZzNKbLBdY6DG9HkwjWfEYANnRNJYgONeMN1qVZpm4UDX//14fkUHIysP1e/MT/gyilnsOWghb0GzydI2N8JjTSCKdywEHzoWO87EFPotpuu5fw7N1gdsZJayLG@iOaSwx0kVX9MwCbKwh@IeBfw@Z0TqcjuZblnf4V0mxKw3AddP5jYPd@DKTcC9FcLnLNgBrHbTglXvIRgh8yvi5aFbI1mULKR0IxP1xWUxA67ljipKtjhTfK/PbfOk@N4EbbhRLqgwfutL8woEQx5YzQKHi0nuteLG/r5iPPAx/1RGQQqvQlCEZIM/JdfrbLp@NyKD0/b/Rq1Do1tRnu3vywuWMjV8jaU2krrJfFE5My6deZnlZ0rGqR/Palf2alv391nj2qYqDqm4vSYwzcm8SKKZJleJlafKef/3i0@X/Q/n/Wu6TIuEuXB5EK9x4Dn3B6z9@GUkf3bab75ACNYDkAkFY9On2ORJELCpGZ/sqDfxAJeHKMfJQIG53jSQchRPBjVmVFEzN3gHSmbwnfBc1NmT91NabtUJqtZlbfxb8DUQ9wHyKsvQQcO0g3Ez5pkLpIyvEt0fpdfQ1TdDCgEt0oWRdVIVGzWnmOsqXCnP15zRmVI6SAo1@El4uwmfJ/6T8FYT7np3qpf1lryJxiWUoj6weGYCbwJHkXoIfu@6JHzGgkDECFTBnSD7G3rkocBgqnD/ou5a4U/sWX0gPvGFom8h7p/WV4tfrfY0dtwhP@R8q/UD3vOHhQgkSVnMM4NQLKA2BnwKfLvjCIzjIRjp76gkx@q97aw3Jw1Ug/g17fvQEJ/mvVK9K@L3i5JKcs5LIY0SUlYQ2W7XcgBLsEbwU50hk1c4/0woHTEHM3l2xMRVMP7iKTU4cq2MDjTHZ4MjKWRTpvQcfDAiMMdFw6tRq0eG3UPjVUYrGQ1glq0SCTTIYSUfYpiZD3cSjA9kW3JWqwN8ID@Q2qV6aJVFD6yaewEwyUW3iQBC8cARiVzm7hF6uWTpeFtLz@xv5pHR7ZDVqrNWs4oB4amaJZ0YF4BC4WbpkaBalxnyBWfQe9QK9Azjq1HrScZXKPVSYbHornCKuVffAueIpTTkt4kXcg1PIkyMpRyRsy1b2XJmnu9@WYTC4ZFEvfutf3Z9cdm/qnvzO6gBT7VmhSX5BcNkXokZ2Eqny25amVUthVe9oyzr9JVJDnPGcDlPy/lYfnFhPnaPnXI2dsvZeEIzi8zSFKlsb7KDTh886N3BFLFwmszlwPFy6erdFIESNJFeQke1ZSO1eB7YCUmVO5aB0BzDNvjaSAFLztpYIcVRln8O2JxTO/8MqiPqbM6u2QHNNM0KVVWWvIpjqT32RKBhvZJahcdG5ciZHWU6xQbCum3mMqouruON2nRp/8Gd2PSijL8GjEvppFCFQj71ophnLpIlhLYre1X5QFp7S2i4DyaheQJDng2J@sCc2P@GoBcgZ8ZC@AYziy@CKdQkqyYIG1Fb0QiBqTqXerVFksELVLOVPCBq7anHqPy9YW2lAe4LdCclQ6FMfFfamqlw96BWKlklA06MKgT4IzY0Qk@KJxnGhk3fJpMJD03m@8LRYAB3hQwS0zrAiA5M5AZQ3oYnJbHB8K@Wo4Or95BxXOtCF852specKXPrxoPEx8MAE@JQx4x8D16IHQO168m@rDQOSVXLPuWWNVr3xBfg6@tXb16/@fmfr9783MpWQxa4Yi7Dpp4/xwajJzJkrBHaGnJweiAhVaLn4S2sstXuBgb0SjNzSeYkFPMzYMCZcGHQLN5O5Kg0V71O0ylwp7Gc2VQj32ZGMnXpLF8qHpfZT3V7nG1Xfajp3A5H8X@yQ0VBNPmDt17FFexepSB7azUfQA3k@wopPVYNKZNJRf8iuXVSjW@NYJeWRbErkti8D6Fxg8A8z4nBGjG7bAqqtRbS8HCYPQ/LP38A1Xo7FBSIjlGmP2DJ0VbwWHbJF2NiVNOTapMOZJXlpL442XILLxthaG8g5QthG7K1gZQdehvycAOZvQu2IH/alCm22/l5A5nN31uQxxWyIk15RM4G1RH1zMnuM9NdZ3q7z8jiv/XMfnVGY2WGN/5i0yuOHTVycPXsMXZkb@ampRzLd41tAaMKrFFl5ON2tQKVykO/mdLMLF7qNq302w3hN5XwpeyjViN9LbKWeFvJfJGLgPZPT9jWYDmbvv@qHMqCVttt2I3nmiEbgfK1rGVVOkohqxXGzahdFQrcTEV56BlVLnU3NVfgMuvlgN9jOsyXdUWwie7otUm6K7ty3Tr@PFBrX/MRDziIzvi7RedvLZrQSJf/MGYY4Rj@txiKLSowtugMdTvWzewctukDprM2LOA@bNzTAMFOYtE7HT/g9mmCXv/Luuj9/dVpQoUuQMx5Lta6wHe4T@EHvde793IT4Tua/Jqg7vsECYsyvfPRojaNs9@3Z3NY@tztvGewKH/bFn2Uyk7Yn12LQi@0bsC@uB0j@CrO5he9WyToo9597FPWZqh7@fh9DM9oT/Zc6/s/XnRf/B8)
-190 bytes thanks to Adam and emanresu A
Ungolfed and explained:
```
; = m BLOCK                          # m = block:
  ; = u = s                          #
    + (+ (+ (+ (+ "" a) " ")         #
    t) " ") (* a t)                  #   u = s = a + " " + t + " " + a * t
  ; = o ""                           #   o = ""
  ; = h 10                           #   h = 10
  ; WHILE h                          #   while h:
      : EVAL + + "=x" = h - h 1 "N"  #     eval("=x" + (h = h - 1) + "N")
  ; = w = n 0                        #   w = n = 0
  ; WHILE u                          #   while u:
      ; = v (+ "x" (- (ASCII u) 48)) #     v = "x" + (ord(u[0]) - 48)
      ; IF ? 32 ASCII u              #     if ord(u[0]) == 32:
          : = o (+ o " "(            #       o = o + " "
                                     #     else: (implicit)
          : EVAL + + + + + ";I" v    #
            "N=" v "=w+1w=o+o " v    #       eval(";I" + v + "N=" + v + "=w+1w=o+o " + v)
      : = u (GET u 1 (LENGTH u))     #     u = u[1:]
  : o                                #   return o
; = a (+ 0 PROMPT)                   # a = int(input())
; = b = t (+ 0 PROMPT)               # b = t = int(input())
; = q (CALL m)                       # q = m()
; = a (^ 10 (LENGTH a))              # a = 10 ** len(a)
; = b (^ 10 (LENGTH b))              # b = 10 ** len(b)
; = z 0                              # z = 0
; WHILE > a ~1                       # while a > -1:
    ; = t b                          #   t = b
    ; WHILE t                        #   while t:
        ; = t - t 1                  #      t = t - 1
        ; = o (CALL m)               #      o = m()
        : IF (? q o)                 #      if q == o:
            : = z + 1 z              #         z = z + 1
            N                        #      else: (do nothing)
    : = a - a 1                      #      a = a - 1
: OUTPUT z                           # print(z)
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~20 18~~ 17 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
Thanks to [Steffan](https://codegolf.stackexchange.com/users/92689/steffan) for a speed up! (`‘×⁵` -> `æċ⁵`) and a byte that ended up saving elsewhere!  
Save of 2 using Steffan's idea of counting >.< - thanks again Steffan!
```
;PDKĠṢ
æċ⁵ḶŒpÇ€ċÇ
```
A monadic Link that accepts a pair of non-negative integers and yields a non-negative integer.
**[Try it online!](https://tio.run/##ATAAz/9qZWxsef//O1BES8Sg4bmiCsOmxIvigbXhuLbFknDDh@KCrMSLw4f///81NCwgMTA "Jelly – Try It Online")**
### How?
```
;PDKĠṢ - Helper Link, cryptic multiplication identifier: pair of integers [a,b]
 P     - product -> a×b
;      - concatenate -> [a, b, a×b]
  D    - to decimal digits -> [[a1, a2, ...],[b1, b2, ...],[P1, P2, ...]]
   K   - join with space characters (representing times and equals)
    Ġ  - group indices by their values -> [indices of spaces, indices of 0s, ...]
     Ṣ - sort
æċ⁵ḶŒpÇ€ċÇ - Link, cryptic multiplication ambiguity: pair of integers [x,y]
  ⁵        - 10
æċ         - next power of (10) of each -> [u, v]  (N.B. 0 -> 10, not 1)
   Ḷ       - lowered range of each -> [[0, 1, ..., u-1], [0, 1, ..., v-1]]
    Œp     - Cartesian product -> [[0, 0], [0, 1], ..., [u-1, v-1]]
      Ç€   - call the helper Link for each
         Ç - call the helper Link with [x, y]
        ċ  - count occurrences
```
[Answer]
# JavaScript (ES6), ~~127~~ 120 bytes
Expects `(p)(q)`, as strings.
```
p=>q=>eval("for(n=0,x=1+p;x--;)for(y=1+q;y--;)n+=(g=(p,q)=>(a=[...p+=[,q,p*q]]).map(c=>a.map(C=>c==C))+0)(p,q)==g(x,y)")
```
[Try it online!](https://tio.run/##dc7BboMwDAbge58C5WSPkAKFphNyLn2MqoeIAerESAITgqdnpdAeqHaynXz5nW/d6y5vb/Y3aMxXMZU0WVKOVNHrGlhpWmgo5ANFvs2GIMhwPhrvo8vGeWx8gorAcoekQNNFCGF9unDH7Ye7XlH8aAs5Kf1ozqRyojOiH@LyiCoY@IgMp9w0nakLUZsKSmAh8zxcC3r7vRfvNiJdRPQSkdyS6H6Ja1nIW0iyCPkSp7eQ8EGSzydJj1si16/IA/tnT5ykbBbpMySW0x8 "JavaScript (Node.js) – Try It Online")
**NB**: This algorithm is rather slow, and made even slower by `eval()`. So the larger test cases time out on TIO.
### Commented
This is a version without `eval()` for readability.
```
p =>                     // p = first integer
q => {                   // q = second integer
  for(                   // outer loop:
    n = 0,               //   start with n = 0
    x = 1 + p;           //   and x = p prefixed with '1'
    x--;                 //   decrement x while it's not 0
  )                      //
    for(                 //   inner loop:
      y = 1 + q;         //     start with y = q prefixed with '1'
      y--;               //     decrement y while it's not 0
    )                    //
      n += (             //     update n:
        g = (p, q) =>    //       g is a helper function taking (p, q)
        ( a =            //       append to p a comma followed by q,
          [...p +=       //       followed by another comma, followed
            [, q, p * q] //       by the product p * q
          ]              //       split the resulting string and save
        )                //       this array in a[]
        .map(c =>        //       for each character c in a[]:
          a.map(C =>     //         for each character C in a[]:
            c == C       //           is c equal to C?
          )              //         end of inner map(); what we get is a
                         //         list of Boolean values telling where
                         //         c can be found in a[]
        )                //       end of outer map()
        + 0              //       coerce to a string with a trailing '0'
      )(p, q)            //       do a 1st call with (p, q)
      == g(x, y);        //       do a 2nd call with (x, y)
                         //     increment n if both results are equal
                         // implicit end of both loops
  return n               // return the final count
}                        //
```
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), 20 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
€g°Ý`âIšεDPª»DSk»}ć¢
```
Port of [*@Steffan*'s Vyxal answer](https://codegolf.stackexchange.com/a/250749/52210), but with less convenient builtins.
[Try it online](https://tio.run/##ATEAzv9vc2FiaWX//@KCrGfCsMOdYMOiScWhzrVEUMKqwrtEU2vCu33Eh8Ki//9bMjcsOTZd) or [verify (almost) all test cases](https://tio.run/##yy9OTMpM/V9Waa@k8KhtkoKSfeX/R01r0g9tODw34fCiyqMLz211CTi06tBul@DsQ7trj7QfWvRf5390tJG5jqVZrE60gY4BkDTVMQSShoY6hiDa1ETH0BzEN9AxsQTS5kCuMZA2MgGqM42NBQA) (the last two are omitted).
**Explanation:**
```
€         # Map over the (implicit) input-pair:
 g        #  Pop and push its length
  °       # Pop and push 10 to the power these lengths
   Ý      # Pop and map both to a [0,n]-ranged list
    `     # Pop and push both lists separated to the stack
     â    # Pop both, and get all possible pairs using the cartasian product
      Iš  # Prepend the input-pair
ε         # Map over each pair:
 D        #  Duplicate the pair
  P       #  Pop the copy, and push its product
   ª      #  Append it to the pair
    »     #  Join it by newlines
     D    #  Duplicate this string
      S   #  Convert it to a list of characters
       k  #  Get the first index of each character in the string
        » #  Join that by newlines again to a string
}ć        # After the map: extract the head
  ¢       # Count how many times this string occurs in the remainder-list
          # (after which it is output implicitly as result)
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), 108 bytes
```
->a,b{[*0..9].permutation.map{|c|"#{a}*#{b}==#{a*b}".tr('0-9',c*'')}.uniq.count{|c|/^0|\*0|=0/!~c&&eval(c)}}
```
[Try it online!](https://tio.run/##bc5NDoIwEIbhPadASKRtYGxcaIip7LwEYFKaEkkUsBQTgXp1xL@F0d1svnkf1WbXMWdjsOV@1seEAoQp1FKdWs11UZVw4nU/iMFxe26I22eGsekkmXFAK@TRIPR8QTwPG2jL4gyiakv9WCz2dEgIHRhdzG5iPpcXfkQCGzO69o43WirLtXP2KiuGUMf@RDCIA1fN83cQR8SPWIqn3OaPFSloik7ij7mbhLZ66t64Rh6l@NIlPzzLqu08Xq79cJWOdw "Ruby – Try It Online")
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 36 bytes
```
ＦＸχＬθＦＥＸχＬη⪫⟦ικ×ικ⟧¶⊞υＥκ⌕κλＩ№υ§υＩ⁺θη
```
[Try it online!](https://tio.run/##ZY2xCsIwEIb3PsXR6QInWFAcOokgKAoZ3NQhtNEEY2KTRn37mHT1hrsPvp//OiV854RJ6eY8IHcf6bGZExykvY8KB8YYTOooXv9aMUawd9riWRM8CE76KQMWZleC@mLrUsBjUBgJSkcObbXtyzXZtRX32o64ESEvFzPm4Hrc2V5@C06CmxhwIMj/yrQpLRdVs0qzt/kB "Charcoal – Try It Online") Link is to verbose version of code. Explanation:
```
ＦＸχＬθ
```
Loop through numbers with no more digits than the first number.
```
ＦＥＸχＬη
```
Looping through numbers with no more digits than the second number, ...
```
⪫⟦ικ×ικ⟧¶
```
... forming a string of the two numbers and their product, ...
```
⊞υＥκ⌕κλ
```
... get a list of the first indexes of each character in the string.
```
Ｉ№υ§υＩ⁺θη
```
Output the number of entries matching that of the input values.
[Answer]
# Python 3, 128 bytes
```
lambda x,y,c=lambda z:list(map(z.find,z)):sum(sum(c(f"{f,g,f*g}")==c(f"{x,y,x*y}")for g in range(1+y<<4))for f in range(1+x<<4))
```
[Try it online!](https://tio.run/##Zc7LDoIwEAXQPV8xwU2rjaE8rBL6J24QLDaBQgATwPjtlacQXcxiTu7cTNHWj1w5OuZXnYbZLQ6hIS2J@Lx0fiqrGmVhgbqjkComHcZ@9czQMBES5kuQhIh98jYx5yMMBc2@7UHkJSQgFZShSu6IHtogcPHIYsvNyLoopapRjCwCFsYAO7CNxTwCdDLKjE3wHyntdeH13u2VzXpew32Fe5nYO32ZDWHnt8N2hy@8@TWmPw)
]