14
\$\begingroup\$

Challenge

Giving a valid arithmetic sum with some missing numbers, output the full expression.

Example:

    1#3                 123
+   45#     =>     +    456
--------            --------
    579                 579

Input

  • Expression format can be an array ["1#3", "45#", "579"], a string "1#3+45#=579", or 3 inputs f("1#3","45#","579")

Output

  • Same as input
  • You don't need to output the result

Notes

  • The missing numbers are going to be represented using # or any other constant non-numeric character you want
  • Assume result wont have a missing number
  • Assume Input/Output consist in 2 terms and a final result
  • Assume both term > 0 and result >= 2
  • There might be multiple solutions. You can output anyone as long as the sum result match

Test Cases with possibly outputs (pretty format)

    #79                     879
+   44#         =>      +   444
--------                --------
    1323                   1323

    5#5                     555
+   3#3         =>      +   343
--------                --------
    898                     898

      #                       1
+     #         =>      +     1
--------                --------
      2                       2

    ###                     998
+   ###         =>      +     1     PD: there are a lot of possible outputs for this one
--------                --------
    999                     999


    123                     123
+     #         =>      +     1
--------                --------
    124                     124


      9                       9
+    #6         =>      +    46
--------                --------
     55                      55


    #123651                     1123651
+      #98#         =>      +      7981
------------                -----------
    1131632                     1131632

Standard rules apply

\$\endgroup\$
9
  • \$\begingroup\$ Do we need to strip leading zeros? \$\endgroup\$
    – user48543
    Aug 30, 2018 at 14:55
  • \$\begingroup\$ @Mnemonic not necessarily \$\endgroup\$ Aug 30, 2018 at 14:58
  • \$\begingroup\$ can I take the input with the sides around = swapped? e.g. 579=1#3+45# \$\endgroup\$
    – dzaima
    Aug 30, 2018 at 15:25
  • 2
    \$\begingroup\$ "Assume both term > 0" does "assume" mean that I have to output both terms > 0 or that I can assume that there's always a solution with both > 0 but output whatever? \$\endgroup\$
    – dzaima
    Aug 30, 2018 at 15:48
  • 1
    \$\begingroup\$ also your added test-case avoids exactly what I was asking for - the leading zeroes \$\endgroup\$
    – dzaima
    Aug 30, 2018 at 15:48

15 Answers 15

9
\$\begingroup\$

Brachylog, 22 16 bytes

{Ṣ∧Ị∋|}ᵐ²ịᵐ.k+~t

Try it online!

-6 bytes thanks to @Fatelize

Explanation

{Ṣ∧Ị∋|}ᵐ²ịᵐ.k+~t
{     }ᵐ²                   #   for each letter in each string
 Ṣ∧Ị∋                       #       if " " return a digit; else input
     |                      #
         ịᵐ                 #   cast each string to number
            k+              #   the sum of all but the last one
              ~t            #       is equal to the last one
           .                #   output that list
\$\endgroup\$
2
  • 1
    \$\begingroup\$ {"#"∧Ị∋|}ᵐ²ịᵐ.k+~t is 4 bytes shorter. I'm not sure why you did something this convoluted in your map. \$\endgroup\$
    – Fatalize
    Aug 31, 2018 at 6:57
  • \$\begingroup\$ Since we can use any non-numeric character, you should use e.g. space with instead of "#" which will save two more bytes. \$\endgroup\$
    – Fatalize
    Aug 31, 2018 at 6:59
8
\$\begingroup\$

JavaScript (ES6), 74 57 bytes

Takes input as (a)(b)(result), where a and b are strings with . for unknown digits and result is an integer. Returns an array of 2 integers.

a=>b=>F=(c,n)=>`${r=[c,n]}`.match(`^`+[a,b])?r:F(c-1,-~n)

Try it online!

Commented

a => b =>                // a, b = term patterns (e.g. a = ".79", b = "44.")
  F = (c,                // c = expected result (e.g. 1323)
          n) =>          // n = guessed value of b, initially undefined
    `${r = [c, n]}`      // we coerce r = [c, n] to a string (e.g. "879,444")
                         // if n is still undefined, this gives just c followed by a comma
    .match(`^` + [a, b]) // we coerce [a, b] to a string, prefixed with "^" (e.g. "^.79,44.")
    ?                    // this is implicitly turned into a regular expression; if matching:
      r                  //   return r
    :                    // else:
      F(c - 1, -~n)      //   decrement c, increment n and do a recursive call
\$\endgroup\$
4
  • \$\begingroup\$ Ah, so that's what's happening. I tried to understand your code without explanation yesterday (and I'm bad at JS), but didn't understand why -~n couldn't be just n+1 and how F=(c,n)=> was used. Now that you added an explanation it all makes sense. c is the third input, n is undefined (and ~undefined becomes -1 unlike undefined+1). All clear now (and not something I can port to Java unfortunately, which was mainly why I tried to understand it xD). PS: Already upvoted yesterday, so I just upvoted one of your other answers (which I didn't upvote already, not a lot available..) ;p \$\endgroup\$ Aug 31, 2018 at 15:59
  • \$\begingroup\$ @KevinCruijssen FWIW, I wrote a tip about this some times ago. But yeah ... that's a JS thing and is probably not portable to many other languages. \$\endgroup\$
    – Arnauld
    Aug 31, 2018 at 16:08
  • \$\begingroup\$ Well, I might be able to semi-port it but just creating a recursive second method, and using a ternary-if to check for null, manually converting it to -1. However, Java has a (very) limited recursive StackOverflow limit, so using a recursive method with randomness hoping it would end up correct within about 1024 recursive calls isn't going to work anyway in Java. Ah well. I've upvoted your tip. Have a nice weekend! :) \$\endgroup\$ Aug 31, 2018 at 16:38
  • \$\begingroup\$ @KevinCruijssen My first JS attempt was doing exactly that: trying random values with a recursive function. And it was usually doing significantly less iterations than the one using a counter. Fun fact: even for ###+###=999, your odds are 1 in 1000. So with 1024 iterations, you should succeed slightly more often than you fail. :) \$\endgroup\$
    – Arnauld
    Aug 31, 2018 at 17:05
7
\$\begingroup\$

Matlab, 143 134 132 119 115 bytes

function[m]=f(x,y,r),p=@(v)str2num(strrep(v,'#',char(randi([48,57]))));m=[1,1];while sum(m)-r,m=[p(x),p(y)];end;end

-4 bytes thanks to @Luismendo

Try it Online


Pretty big and pretty stupid. It simply replaces all # with random digits until it finds the correct ones.

\$\endgroup\$
0
5
\$\begingroup\$

R, 67 51 bytes

Rock simple and scales horribly, just grep all the sum combinations. Use "." for unknown digits. It won't find the same answer as test case number 4, but it will give a possible answer, which follows the letter of the rules as given.

-16 bytes by grepping after forming the output and replacing paste with the ? operator.

function(x,y,z,`?`=paste)grep(x?y,1:z?z:1-1,v=T)[1]

Try it online!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Awesome idea, I would never have thought of that. You can save a few bytes by using * in place of grepl : tio.run/##PYzLCoMwEEX3/… \$\endgroup\$
    – JayCe
    Aug 31, 2018 at 0:44
  • 1
    \$\begingroup\$ I was looking for various operators and you come up with ?... I think this is a first. by the way, I forgot if I already told you but we're trying to get R nominated for september language of the month - you can upvote if not done already. \$\endgroup\$
    – JayCe
    Aug 31, 2018 at 14:26
  • \$\begingroup\$ I could've chosen anything with low precedence. Feels like there should be a better way to get the match... \$\endgroup\$
    – J.Doe
    Aug 31, 2018 at 14:31
3
\$\begingroup\$

Charcoal, 32 bytes

F²⊞υ0W⁻ζΣIυ≔E⟦θη⟧⭆κ⎇⁼μ#‽χμυ←Eυ⮌ι

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

F²⊞υ0

Push two string 0s to the predefined empty list u to get the while loop going.

W⁻ζΣIυ

Repeat while the sum of casting the values in u to integer is not equal to the desired result.

≔E⟦θη⟧

Create an array of the two inputs and map over it.

⭆κ⎇⁼μ#‽χμυ

Replace each # with a random digit and assign the result back to u.

←Eυ⮌ι

Print the result right justified. (Left justified would be just υ for a 4-byte saving.)

\$\endgroup\$
3
\$\begingroup\$

Jelly, 20 bytes

ØDṛċ¡V€)ŒpḌð€ŒpS⁼¥ƇḢ

Try it online!

\$\endgroup\$
3
\$\begingroup\$

05AB1E (legacy), 23 20 bytes

[²³«εð9ÝΩ:}²gôJDO¹Q#

-3 bytes thanks to @Emigna.

Unknown digits are spaces ( ). Input order should be: expected result; longest string; shortest string.

Try it online.

Explanation:

[                 # Start an infinite loop
 ²³«              #  Take the second and third inputs, and merge them together
               #   i.e. " 79" and " 4 " → " 79 4 "
    ε     }    #  Map each character to:
     ð   :     #   Replace a space with:
      9ÝΩ      #   A random digit in the range [0,9]
               #    i.e. " 79 4 " → ['3','7','9','2','4','3']
               #    i.e. " 79 4 " → ['5','7','9','7','4','4']
²g             #  Get the length of the second input
               #   i.e. " 79" → 3
  ô            #  And split it into two numbers again
               #   i.e. ['3','7','9','2','4','3'] and 3 → [['3','7','9'],['2','4','3']]
               #   i.e. ['5','7','9','7','4','4'] and 3 → [['5','7','9'],['7','4','4']]
   J           #  Join each list together to a single number
               #   i.e. [['3','7','9'],['2','4','3']] → [379,243]
               #   i.e. [['5','7','9'],['7','4','4']] → [579,744]
    D          #  Duplicate this list
     O         #  Sum the list
               #   i.e. [379,243] → 622
               #   i.e. [579,744] → 1323
      ¹Q#      #  If it's equal to the first input: stop the infinite loop
               #  (and output the duplicate list implicitly)
               #   i.e. 1323 and 622 → 0 (falsey) → continue the loop
               #   i.e. 1323 and 1323 → 1 (truthy) → stop the loop and output [579,744]
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Replace saves 3 over the if. \$\endgroup\$
    – Emigna
    Aug 31, 2018 at 6:10
  • \$\begingroup\$ @Emigna Ah, of course. Thanks! \$\endgroup\$ Aug 31, 2018 at 6:52
3
\$\begingroup\$

Perl 6, 81 74 bytes

-7 bytes thanks to nwellnhof!

{first {try S/\=/==/.EVAL},map {$^a;S:g[\#]=$a[$++]},[X] ^10 xx.comb('#')}

Try it online!

Anonymous code block that takes input as a string containing an arithmetical expression e.g. "12#+45#=579". Substitutes each # with possible permutations of digits, substitutes the= with == and finds the first valid result.

Explanation:

{  # Anonymous code block                                                      }
 first   # Find the first of:
                                                               ^10  # The range of 0 to 9
                                                                   xx.comb('#') # Multiplied by the number #s in the code
                                                          ,[X]  # The cross-product of these lists
                          map   # Map each crossproduct to:
                              {$^a;.trans: "#"=>{$a[$++]}}  # The given string with each # translated to each element in the list
      {try S/\=/==/.EVAL}, # Find which of these is true when = are changed to == and it is eval'd
\$\endgroup\$
2
  • \$\begingroup\$ You can use S:g[\#]=$a[$++] instead of trans for 74 bytes. \$\endgroup\$
    – nwellnhof
    Sep 1, 2018 at 13:05
  • \$\begingroup\$ @nwellnhof I didn't realise you could use S/// in that sort of syntax! Thanks! \$\endgroup\$
    – Jo King
    Sep 1, 2018 at 13:13
2
\$\begingroup\$

APL (Dyalog Unicode), 22 bytes

{'#'⎕R{⍕?10}t}⍣{⍎⍺}t∘←

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Java 10, 203 198 193 bytes

(a,b,c)->{int A=0,B=0,l=a.length();for(a+=b,b="";A+B!=c;A=c.valueOf(b.substring(0,l)),B=c.valueOf(b.substring(l)),b="")for(var t:a.getBytes())b+=t<36?(t*=Math.random())%10:t-48;return A+"+"+B;}

Try it online.

Explanation:

(a,b,c)->{           // Method with 2 Strings & integer parameters and String return-type
  int A=0,B=0,       //  Result-integers, starting both at 0
      l=a.length();  //  Length of the first String-input
  for(a+=b,          //  Concat the second String-input to the first
      b="";          //  Reuse `b`, and start it as an empty String
      A+B!=c         //  Loop as long as `A+B` isn't equal to the integer-input
      ;              //    After every iteration:
       A=c.valueOf(b.substring(0,l)),
                     //     Set `A` to the first String-part as integer
       B=c.valueOf(n.substring(l)),
                     //     Set `B` to the second String-part as integer
       b="")         //     Reset `b` to an empty String
    for(var t:a.getBytes())
                     //   Inner loop over the characters of the concatted String inputs
      b+=t<36?       //    If the current character is a '#':
          (t*=Math.random())%10
                     //     Append a random digit to `b`
         :           //    Else (it already is a digit):
          t-48;      //     Append this digit to `b`
  return A+"+"+B;}   //  After the loop, return `A` and `B` as result
\$\endgroup\$
1
\$\begingroup\$

C# .NET, 225 220 196 bytes

(a,b,c)=>{int A=0,B=0,l=a.Length;for(a+=b,b="";A+B!=c;A=int.Parse(b.Substring(0,l)),B=int.Parse(b.Substring(l)),b="")foreach(var t in a)b+=(t<36?new System.Random().Next(10):t-48)+"";return(A,B);}

Port of my Java 10 answer.
(I'm very rusty in C# .NET golfing, so can defintely be golfed..)

-3 bytes implicitly thanks to @user82593 and this new C# tip he added.
-29 bytes thanks to @hvd.

Try it online.

Explanation:

(a,b,c)=>{        // Method with 2 string & int parameters and int-tuple return-type
  int A=0,B=0,    //  Result-integers, starting both at 0
      l=a.Length; //  Length of the first string-input
  for(a+=b,       //  Concat the second string-input to the first
      b="";       //  Reuse `b`, and start it as an empty string
      A+B!=c      //  Loop as long as `A+B` isn't equal to the integer-input
      ;           //    After every iteration:
       A=int.Parse(b.Substring(0,l)),
                  //     Set `A` to the first string-part as integer
       B=int.Parse(b.Substring(l)),
                  //     Set `B` to the second string-part as integer
       b="")      //     Reset `b` to an empty string
    foreach(var t in a)
                  //   Inner loop over the characters of the concatted string inputs
      b+=(t<36?   //    If the current character is a '#':
           new System.Random().Next(10)
                  //     Use a random digit
          :       //    Else (it already is a digit):
           t-48)  //     Use this digit as is
         +"";     //    And convert it to a string so it can be appended to the string
  return(A,B);}   //  After the loop, return `A` and `B` in a tuple as result
\$\endgroup\$
4
  • \$\begingroup\$ You can use the regular using System; instead, it is shorter than namespace System{}. \$\endgroup\$
    – hvd
    Sep 1, 2018 at 8:01
  • \$\begingroup\$ @hvd That was it!.. I haven't done C# in years, lol.. I tried using System.*; similar as imports in Java, but that didn't work. Forgot I had to remove the .* part.. Thanks for the -5 bytes. \$\endgroup\$ Sep 1, 2018 at 11:01
  • 1
    \$\begingroup\$ Re-reading it now, that was actually a sub-optimal suggestion. You can write int.Parse (-4), use new System.Random() (+7) and drop using System; (-13) to save another 10 bytes. :) Also, you do not need .ToCharArray(), that takes off 14 more bytes. \$\endgroup\$
    – hvd
    Sep 1, 2018 at 11:05
  • \$\begingroup\$ @hvd Thanks! Not sure how I forgot about int.Parse vs System.Int32.Parse... It's basically the same as System.String and string.. And didn't knew it was possible to loop over the characters without the .ToCharArray(). Thanks for another -24 bytes. :D \$\endgroup\$ Sep 1, 2018 at 11:49
1
\$\begingroup\$

Python 3, 121 155 152 149 bytes

import re
def f(i,k=0,S=re.sub):s=S('#','%s',i)%(*list('%0*d'%(i.count('#'),k)),);print(s)if eval(S('=','==',S('\\b0*([1-9])','\\1',s)))else f(i,k+1)

Try it online!

+34 New solution with regex to circumvent the fact that python doesn't support numbers with leading zeroes.

-3 thanks to @Jonathan Frech


The old solution doesn't work if # is the first character in any number (because eval doesn't accept leading zeroes) and is therefore invalid :(

def f(i,k=0):
 s=i.replace('#','%s')%(*list('%0*d'%(i.count('#'),k)),)
 print(s)if eval(s.replace('=','=='))else f(i,k+1)

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I'm afraid this submission is invalid for the reason stated in the post. \$\endgroup\$ Aug 30, 2018 at 17:10
  • 2
    \$\begingroup\$ Since your function does not contain any compound statements you can condense it to only one line. \$\endgroup\$ Aug 30, 2018 at 23:21
1
\$\begingroup\$

C (gcc), 228 213 203 172 170 bytes

-15 Bytes thanks to @ceilingcat. I've never used index before.

-10 Bytes thanks to @Logem. Preprocessor magic

refactored call to exit(0) with puts as parameter.

char*c,*p[9],k;main(i,v)int**v;{for(i=X[1],35))||X[2],35))?p[k++]=c,main(*c=57,v):k;!c*i--;)47==--*p[i]?*p[i]=57:Y[1])+Y[2])^Y[3])?main(i,v):exit(puts(v[2],puts(v[1])));}

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ 194 bytes - Try it online! \$\endgroup\$
    – user36046
    Sep 25, 2018 at 13:07
  • \$\begingroup\$ You can save two bytes replacing the macro -DX=c=index(v, with -DX=(c=index(v, TIO link in my last comment. \$\endgroup\$
    – user36046
    Sep 25, 2018 at 13:24
  • \$\begingroup\$ Thanks guys. Doesn't look like I even tried to golf this before... \$\endgroup\$
    – cleblanc
    Sep 25, 2018 at 13:33
0
\$\begingroup\$

PHP, 112 bytes

lame brute force solution

for(;$s=$argn;eval(strtr($s,['='=>'==','#'=>0]).'&&die($s);'))for($k=$n++;$k;$k=$k/10|0)$s[strpos($s,35)]=$k%10;

takes string as input, stops at first solution. Run as pipe with -nR or try it online.

\$\endgroup\$
0
\$\begingroup\$

Powershell, 91 byte

The script finds all solutions. The total number of iterations is 10 power the number of characters #. The recursion depth is equal to the number of characters #.

filter f{$h,$t=$_-split'#',2
if($t){0..9|%{"$h$_$t"}|f}elseif($h-replace'=','-eq'|iex){$h}}

Test script:

filter f{$h,$t=$_-split'#',2
if($t){0..9|%{"$h$_$t"}|f}elseif($h-replace'=','-eq'|iex){$h}}

@(
    ,('1#3+45#=579','123+456=579')
    ,('#79+44#=1323','879+444=1323')
    ,('5#5+3#3=898','505+393=898 515+383=898 525+373=898 535+363=898 545+353=898 555+343=898 565+333=898 575+323=898 585+313=898 595+303=898')
    ,('#+#=2','0+2=2 1+1=2 2+0=2')
    ,('9+#6=55','9+46=55')
    ,('123+##=124','123+01=124')
    ,('#123651+#98#=1131632','1123651+7981=1131632')
    ,('##+##=2','00+02=2 01+01=2 02+00=2')
    ,('##+##=99','00+99=99 01+98=99 02+97=99 03+96=99 04+95=99 05+94=99 06+93=99 07+92=99 08+91=99 09+90=99 10+89=99 11+88=99 12+87=99 13+86=99 14+85=99 15+84=99 16+83=99 17+82=99 18+81=99 19+80=99 20+79=99 21+78=99 22+77=99 23+76=99 24+75=99 25+74=99 26+73=99 27+72=99 28+71=99 29+70=99 30+69=99 31+68=99 32+67=99 33+66=99 34+65=99 35+64=99 36+63=99 37+62=99 38+61=99 39+60=99 40+59=99 41+58=99 42+57=99 43+56=99 44+55=99 45+54=99 46+53=99 47+52=99 48+51=99 49+50=99 50+49=99 51+48=99 52+47=99 53+46=99 54+45=99 55+44=99 56+43=99 57+42=99 58+41=99 59+40=99 60+39=99 61+38=99 62+37=99 63+36=99 64+35=99 65+34=99 66+33=99 67+32=99 68+31=99 69+30=99 70+29=99 71+28=99 72+27=99 73+26=99 74+25=99 75+24=99 76+23=99 77+22=99 78+21=99 79+20=99 80+19=99 81+18=99 82+17=99 83+16=99 84+15=99 85+14=99 86+13=99 87+12=99 88+11=99 89+10=99 90+09=99 91+08=99 92+07=99 93+06=99 94+05=99 95+04=99 96+03=99 97+02=99 98+01=99 99+00=99')
) | % {
    $s,$e = $_
    $r = $s|f
    "$($e-eq$r): $r"
}

Powershell, 'Assume both term > 0' is mandatory, 110 bytes

filter f{$h,$t=$_-split'#',2
if($t){0..9|%{"$h$_$t"}|f}else{$a,$b,$c=$_-split'\D'
$_|?{+$a*+$b*!(+$a+$b-$c)}}}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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