18
\$\begingroup\$

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

\$\endgroup\$
5
  • \$\begingroup\$ What's the winning criterion? \$\endgroup\$ Aug 6 at 14:43
  • \$\begingroup\$ @TheFifthMarshal oops, added... I think it would be interesting to see a fastest code version as well, but I don't have a cutting edge computer to benchmark the codes \$\endgroup\$
    – Domenico
    Aug 6 at 14:57
  • \$\begingroup\$ Can inputs or potential solutions we count have leading zeroes? The {0, 0} -> 2 test case technically has leading zeroes, though it's a common convention to notate zero as 0 rather than the empty string. \$\endgroup\$
    – xnor
    Aug 6 at 22:11
  • \$\begingroup\$ @xnor I'm seeing the problem more from the numbers point of view rather than the expression one, so I feel your legit idea like a hurried generalization, also there are a bunch of answers already. \$\endgroup\$
    – Domenico
    Aug 6 at 23:32
  • 2
    \$\begingroup\$ If leading zeroes were allowed, then the first test case would be wrong: 02 * 95 = 0190 04 * 65 = 0260 And so on (4 more) \$\endgroup\$
    – G B
    Aug 7 at 8:50

8 Answers 8

6
\$\begingroup\$

K (ngn/k), 41 36 bytes

-5 bytes inspired by Jonathan Allan's answer.

{#*={.(=`k@x,*/x)_" "}'?+x,'!10*1+x}

Try it online! The last 4 cases are too slow to run online.

\$\endgroup\$
4
\$\begingroup\$

Knight, 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!

-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)
\$\endgroup\$
3
  • \$\begingroup\$ FYI you can chain = - =c=d=e...=N \$\endgroup\$
    – emanresu A
    Aug 6 at 20:23
  • \$\begingroup\$ Also, since N can be coerced into 0, you can save some extra bytes there as well I think: pastebin.com/BmWUGe7N \$\endgroup\$
    – Adam
    Aug 6 at 20:26
  • \$\begingroup\$ Also you can probably name the vars x0, x1, x2... and use eval \$\endgroup\$
    – emanresu A
    Aug 6 at 20:27
4
\$\begingroup\$

Vyxal s, 17 bytes

vL↵ʀΠƛ?"ƛΠJṄ:vḟ;≈

Try it Online!

This would flaglessly be 19 bytes. It can be shorter flagless, though:

Vyxal, 18 bytes

vL↵ʀΠ?wJƛΠJṄ:vḟ;ṫO

Try it Online!

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]
\$\endgroup\$
3
\$\begingroup\$

Jelly,  20 18  17 bytes

Thanks to 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!

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
\$\endgroup\$
3
  • 1
    \$\begingroup\$ replace ‘×⁵ with æċ⁵ to speed things up \$\endgroup\$
    – Steffan
    Aug 6 at 14:23
  • \$\begingroup\$ Tried golfing this, but ended up with another 20-byter: æċ⁵Ż€Œp⁸ṭµ;PDKĠṢ)ċṪ$ \$\endgroup\$
    – Steffan
    Aug 6 at 14:34
  • \$\begingroup\$ Thanks! Counting does save bytes :) \$\endgroup\$ Aug 6 at 17:40
3
\$\begingroup\$

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!

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
}                        //
\$\endgroup\$
3
\$\begingroup\$

05AB1E, 20 bytes

€g°Ý`âIšεDPª»DSk»}ć¢

Port of @Steffan's Vyxal answer, but with less convenient builtins.

Try it online or verify (almost) all test cases (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)
\$\endgroup\$
1
\$\begingroup\$

Ruby, 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!

\$\endgroup\$
1
\$\begingroup\$

Charcoal, 36 bytes

FXχLθFEXχLη⪫⟦ικ×ικ⟧¶⊞υEκ⌕κλI№υ§υI⁺θη

Try it online! Link is to verbose version of code. Explanation:

FXχLθ

Loop through numbers with no more digits than the first number.

FEXχLη

Looping through numbers with no more digits than the second number, ...

⪫⟦ικ×ικ⟧¶

... forming a string of the two numbers and their product, ...

⊞υEκ⌕κλ

... get a list of the first indexes of each character in the string.

I№υ§υI⁺θη

Output the number of entries matching that of the input values.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.