# Help! My calculator malfunctions!

## Introduction

My calculator is behaving weird. Sometimes when I type in an 8 it displays a 2. And sometimes when I type in a 6 it displays a +. Some buttons are mixed up!
Could anyone help me determine which?

## Challenge:

Input: List of incorrect equations, with correct results.

Output: The two buttons that are swapped.

For example:
An input could be:

123    = 3
8423   = 252
4+4    = 8
4*7-10 = 417
9/3    = 3
42-9   = -36


For which the expected outputs are: 2 and *.

Why? Because ALL the equations would be correct if we swap the 2's and *'s:

1*3    = 3
84*3   = 252
4+4    = 8
427-10 = 417
9/3    = 3
4*-9   = -36


## Challenge rules:

• Input can be in any reasonable format. Can be a single string with space delimited; a string-list or -array; a list with equations and another list with the correct results. Your call. Please state which input format you've used!
NOTE: This also means you are allowed to input the test case -5--15 as -5- -15 or -5 - -15. However, a number resulting in -- should either be inputted without spaces or with a space between every digit. So test case 9119 can be inputted like 9119 or 9 1 1 9 (reason 91 19 isn't allowed is because you can then be guided by the space for finding - -). So spaces are (somewhat) optional and allowed.
• Output format can be in any reasonable format as well. Can be two characters; a single two-character string; a string-list containing the two characters. Your call. Again, please state which output format you've used!
• You are allowed to use any distinct 14 outputs that map to 0123456789+-*/. So you are even allowed to output two distinct integers if you want to (again, please specify the mapping you've used, if any).
• You only have to support integers. So there won't be any test cases like 1/8=0.125 or 1/8=0.
• Arithmetic operands you'll have to support: addition (+); subtraction (-); multiplication (* or × or ·); division (/ or ÷). (NOTE: Characters between parenthesis are only added as clarification.)
• You'll have to support negative numbers. This means - can be interpreted in the equation as both a mathematical operand or a negative indicator.
• You can assume the given incorrect equations and supposed correct equations are always valid (so there won't be things like 4-/2 or 9+-+8 for example).
• The incorrect input-equations can contain a division by 0, but the corrected and expected equations will never contain division by 0.
• The incorrect input-equations can already be correct even if you swap the intended buttons back.
• A given input equation can be irrelevant for the buttons to swap (like the 4+4=8 and 9/3=3 equations, with the swapped buttons 2 and *).
• You can assume there will always be only one possible swap that can be made with the given test cases.
• Both buttons to swap will always be present in at least one of the incorrect equations.

## General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.

## Test cases:

Input:
123    = 3
8423   = 252
4+4    = 8
4*7-10 = 417
9/3    = 3
42-9   = -36

Output: 2 *

Input:
4/2   = 6
3/0   = 3
0/8+2 = 4
95-5  = 90
4+2   = 2

Output: + /

Input:
7+4    = 11
5-15   = 46
212-23 = -2121

Output: 1 -

Input:
4+8/2-9*1 = -5
99/3-13   = 20
1+2+3+4   = 10
4-3-2-1   = -6

Output: 2 4

Input:
18/18  = 1
98-8   = 90
55*88  = 4840
-5--15 = 10

Ouput: 5 8

Input:
9119    = 18
5-3     = 513
8*-9    = 152
13116/3 = -1

Output: 1 -

• "real division" means we have to support floats? Sep 4 '17 at 9:30
• @EriktheOutgolfer Oops.. Copied that from a previous arithmetic challenge of mine. Removed, and as answer to your question, no you only have to deal with integers. Sep 4 '17 at 10:35
• I'd suggest a test case where a correct equation contains --. For example 1991 = 2, -/3 = 3. (Many languages confuse this with the decrement operator.) Sep 4 '17 at 15:17
• The problem is that adding a space in 91 19 if the solution is 9--9 and no space in 9119 if the solution is 9229 requires knowledge about the solution when creating the test cases. If this were allowed, I could simply add a space only before the swapped characters and the solution could be immediately derived from the test case. Sep 4 '17 at 19:58
• Is evaluation left-to-right, or * and / before + and binary -? Sep 4 '17 at 22:03

# Perl 6, 132 113 bytes

Thanks to Jo King for -19 bytes.

->\e,$r {first {($!=e.trans($_=>.flip))ne e&&try "all {$!.&{S:g/\-/- /}} Z==$r".EVAL},[X~] (|^10,|<+ - * />)xx 2}  Try it online! Input is a comma-separated string of equations and a comma-separated string of results (hope this is OK). Output is a string containing the two swapped buttons. Correctly handles --. Might product false positives for ---, ++, **, or //, but I couldn't come up with a test case. • You don't have to handle ---;++;**;//; or other things like *+ etc. The only double adjacent non-digit you'll have to support is --. Also, if I understand your code correctly, you won't need .subst('-','- ', since inputting the test case -5--15 with a space is allowed. You aren't the first to add code to add this space programmatically, so I'll specify this more clearly in the challenge description. Sep 4 '17 at 16:06 • @KevinCruijssen I might have to handle things like ** because they have a meaning as Perl 6 expressions and might cause false positives. 1992 = 1 could be 1**2 = 1 or 1//2 = 1, for example. The subst is for cases where the correct equation contains --, for example the new test case you added. Sep 4 '17 at 16:33 • Your answer is currently the one with the least amount of bytes, so I'll accept it for now. If someone comes up with something shorter, the check might shift again. Dec 15 '17 at 8:10 • 113 bytes – Jo King Sep 11 '18 at 14:57 # JavaScript (ES7), 159 158 bytes Edit: new version to comply with the updated rules regarding -- Saved 1 byte thanks to @Shaggy Takes input in currying syntax (e)(r) where e is the array of equations and r is the array of expected results. Returns an array of characters. e=>r=>(l=[...2**29+'4+-*/']).filter(x=>l.some(y=>eval("try{eval((S=(s=[${e}]).replace(/./g,c=>c==x?y:c==y?x:c)).split--.join+)+''==r&S!=s}catch(e){}")))


### Test cases

let f =

e=>r=>(l=[...2**29+'4+-*/']).filter(x=>l.some(y=>eval("try{eval((S=(s=[${e}]).replace(/./g,c=>c==x?y:c==y?x:c)).split--.join+)+''==r&S!=s}catch(e){}"))) console.log(JSON.stringify(f ([ '123', '8423', '4+4', '4*7-10', '9/3', '42-9' ]) ([ 3, 252, 8, 417, 3, -36 ]) )); console.log(JSON.stringify(f ([ '4/2', '3/0', '0/8+2', '95-5', '4+2' ]) ([ 6, 3, 4, 90, 2 ]) )); console.log(JSON.stringify(f ([ '7+4', '5-15', '212-23' ]) ([ 11, 46, -2121 ]) )); console.log(JSON.stringify(f ([ '4+8/2-9*1', '99/3-13', '1+2+3+4', '4-3-2-1' ]) ([ -5, 20, 10, -6 ]) )); console.log(JSON.stringify(f ([ '18/18', '98-8', '55*88', '-5--15' ]) ([ 1, 90, 4840, 10 ]) )); console.log(JSON.stringify(f ([ '9119', '5-3', '8*-9', '13116/3' ]) ([ 18, 513, 152, -1 ]) )); ### Formatted and commented e => r => // given e and r (l = [...2 ** 29 + '4+-*/']) // generate l = [...'5368709124+-*/'] .filter(x => // for each character x of l l.some(y => // for each character y of l eval("try { // we need to 'try', because we don't know eval( // whether the following expression is valid (S = (s = [${e}]).             // s = list of equations coerced to a string
replace(/./g, c =>             // S =
c == x ? y : c == y ? x : c  //   s with x and y exchanged
)                              // end of replace()
).split--.join+              // replace '--' with '+'
) + '' == r                        // does the resulting list match r?
& S != s                           // and was at least one character modified?
} catch(e){}")                       // if we try, we oughta catch
)                                      // end of some()
)                                        // end of filter()

• I think you can save a byte by evaling the try / catch: codepen.io/anon/pen/rzRrLp. Sep 4 '17 at 10:35
• @Shaggy Ah yes, nice one. Thanks! Sep 4 '17 at 10:55
• It looks like this might work for 139 bytes. Sep 4 '17 at 11:01
• Yeah, I just ran a full test suite and spotted that. Sep 4 '17 at 11:06
• Doesn't work for 1991 = 2. The solution should be 1--1 = 2 with 9 and - swapped. Sep 4 '17 at 15:14

# Python 2, 204, 199, 193, 173, 165 bytes

• From 199 bytes to 193 bytes thanks to Mr. Xcode
• From 193 bytes to 173 bytes thanks to Halvard Hummel
s=input()
r=str.replace
t=set(''.join(zip(*s)))
for i in t:
for j in t:
try:
if all(eval(r(r(r(e,i,'$'),j,i),'$',j))==v*(i<j)for e,v in s):print i,j
except:0


Try it online!

• Sep 4 '17 at 15:20
• @Mr.Xcoder thanx for the remark, I'm fixing it.. Sep 4 '17 at 16:11
• @Mr.Xcoder here is the corrected version Sep 4 '17 at 18:58
• 193 bytes Sep 4 '17 at 18:59
• 173 bytes Sep 4 '17 at 21:04

# Oracle SQL & PL/SQL, 458 Bytes

Input can be in any reasonable format. [...] a list with equations and another list with the correct results.

Compile the PL/SQL function (210 bytes):

CREATE FUNCTION f(x CHAR,y CHAR)RETURN NUMBER IS o NUMBER;BEGIN EXECUTE IMMEDIATE 'BEGIN :1:='||REPLACE(x,'--','- -')||';END;'USING OUT o;RETURN CASE o WHEN y THEN 1 END;EXCEPTION WHEN OTHERS THEN RETURN 0;END;


Run the SQL (248 bytes):

WITH r(v)AS(SELECT SUBSTR('1234567890-+*/',LEVEL,1)FROM DUAL CONNECT BY LEVEL<15)SELECT r.v,s.v FROM T,r,r s WHERE r.v<>s.v GROUP BY r.v,s.v HAVING SUM(f(TRANSLATE(x,r.v||s.v,s.v||r.v),y))=(SELECT COUNT(1)FROM T)AND SUM(INSTR(x,r.v)+INSTR(x,s.v))>0


After having create a table T with the test data:

CREATE TABLE T(X,Y) AS
SELECT '123',    3     FROM DUAL UNION ALL
SELECT '8423',   252   FROM DUAL UNION ALL
SELECT '4+4',    8     FROM DUAL UNION ALL
SELECT '4*7-10', 417   FROM DUAL UNION ALL
SELECT '9/3',    3     FROM DUAL UNION ALL
SELECT '42-9',   -36   FROM DUAL


Output:

V V_1
- ---
2 *
* 2


Previous Version:

Assumed a string input like '123 = 3':

Same PL/SQL function and the SQL (322 bytes):

WITH r(v)AS(SELECT SUBSTR('1234567890-+*/',LEVEL,1)FROM DUAL CONNECT BY LEVEL<15),y(x,y)AS(SELECT REGEXP_SUBSTR(t,'[^=]+'),REGEXP_SUBSTR(t,'-?\d+$')FROM T)SELECT r.v,s.v FROM y,r,r s WHERE r.v<>s.v GROUP BY r.v,s.v HAVING SUM(f(TRANSLATE(x,r.v||s.v,s.v||r.v),y))=(SELECT COUNT(1)FROM T)AND SUM(INSTR(x,r.v)+INSTR(x,s.v))>0  After having create a table T with the test data: CREATE TABLE T(T) AS SELECT '123 = 3' FROM DUAL UNION ALL SELECT '8423 = 252' FROM DUAL UNION ALL SELECT '4+4 = 8' FROM DUAL UNION ALL SELECT '4*7-10 = 417' FROM DUAL UNION ALL SELECT '9/3 = 3' FROM DUAL UNION ALL SELECT '42-9 = -36' FROM DUAL;  Output: V V_1 - --- 2 * * 2  Update - Testing: SQL Fiddle Oracle 11g R2 Schema Setup: CREATE FUNCTION F(x CHAR,y CHAR)RETURN NUMBER IS o NUMBER;BEGIN EXECUTE IMMEDIATE 'BEGIN :1:='||REPLACE(x,'--','- -')||';END;'USING OUT o;RETURN CASE o WHEN y THEN 1 END;EXCEPTION WHEN OTHERS THEN RETURN 0;END; / CREATE TABLE A(X,Y) AS SELECT '123', 3 FROM DUAL UNION ALL SELECT '8423', 252 FROM DUAL UNION ALL SELECT '4+4', 8 FROM DUAL UNION ALL SELECT '4*7-10', 417 FROM DUAL UNION ALL SELECT '9/3', 3 FROM DUAL UNION ALL SELECT '42-9', -36 FROM DUAL / CREATE TABLE B(X,Y) AS SELECT '4/2', 6 FROM DUAL UNION ALL SELECT '3/0', 3 FROM DUAL UNION ALL SELECT '0/8+2', 4 FROM DUAL UNION ALL SELECT '95-5', 90 FROM DUAL UNION ALL SELECT '4+2', 2 FROM DUAL / CREATE TABLE C(X,Y) AS SELECT '7+4', 11 FROM DUAL UNION ALL SELECT '5-15', 46 FROM DUAL UNION ALL SELECT '212-23', -2121 FROM DUAL / CREATE TABLE D(X,Y) AS SELECT '4+8/2-9*1', -5 FROM DUAL UNION ALL SELECT '99/3-13', 20 FROM DUAL UNION ALL SELECT '1+2+3+4', 10 FROM DUAL UNION ALL SELECT '4-3-2-1', -6 FROM DUAL / CREATE TABLE E(X,Y) AS SELECT '18/18', 1 FROM DUAL UNION ALL SELECT '98-8', 90 FROM DUAL UNION ALL SELECT '55*88', 4840 FROM DUAL UNION ALL SELECT '-5--15', 10 FROM DUAL / CREATE TABLE G(X,Y) AS SELECT '9119', 18 FROM DUAL UNION ALL SELECT '5-3', 513 FROM DUAL UNION ALL SELECT '8*-9', 152 FROM DUAL UNION ALL SELECT '13116/3', -1 FROM DUAL /  Query 1: WITH r(v)AS(SELECT SUBSTR('1234567890-+*/',LEVEL,1)FROM DUAL CONNECT BY LEVEL<15)SELECT r.v,s.v FROM A,r,r s WHERE r.v<>s.v GROUP BY r.v,s.v HAVING SUM(f(TRANSLATE(x,r.v||s.v,s.v||r.v),y))=(SELECT COUNT(1)FROM A)AND SUM(INSTR(x,r.v)+INSTR(x,s.v))>0  | V | V | |---|---| | 2 | * | | * | 2 |  Query 2: WITH r(v)AS(SELECT SUBSTR('1234567890-+*/',LEVEL,1)FROM DUAL CONNECT BY LEVEL<15)SELECT r.v,s.v FROM B,r,r s WHERE r.v<>s.v GROUP BY r.v,s.v HAVING SUM(f(TRANSLATE(x,r.v||s.v,s.v||r.v),y))=(SELECT COUNT(1)FROM B)AND SUM(INSTR(x,r.v)+INSTR(x,s.v))>0  | V | V | |---|---| | + | / | | / | + |  Query 3: WITH r(v)AS(SELECT SUBSTR('1234567890-+*/',LEVEL,1)FROM DUAL CONNECT BY LEVEL<15)SELECT r.v,s.v FROM C,r,r s WHERE r.v<>s.v GROUP BY r.v,s.v HAVING SUM(f(TRANSLATE(x,r.v||s.v,s.v||r.v),y))=(SELECT COUNT(1)FROM C)AND SUM(INSTR(x,r.v)+INSTR(x,s.v))>0  | V | V | |---|---| | 1 | - | | - | 1 |  Query 4: WITH r(v)AS(SELECT SUBSTR('1234567890-+*/',LEVEL,1)FROM DUAL CONNECT BY LEVEL<15)SELECT r.v,s.v FROM D,r,r s WHERE r.v<>s.v GROUP BY r.v,s.v HAVING SUM(f(TRANSLATE(x,r.v||s.v,s.v||r.v),y))=(SELECT COUNT(1)FROM D)AND SUM(INSTR(x,r.v)+INSTR(x,s.v))>0  | V | V | |---|---| | 2 | 4 | | 4 | 2 |  Query 5: WITH r(v)AS(SELECT SUBSTR('1234567890-+*/',LEVEL,1)FROM DUAL CONNECT BY LEVEL<15)SELECT r.v,s.v FROM E,r,r s WHERE r.v<>s.v GROUP BY r.v,s.v HAVING SUM(f(TRANSLATE(x,r.v||s.v,s.v||r.v),y))=(SELECT COUNT(1)FROM E)AND SUM(INSTR(x,r.v)+INSTR(x,s.v))>0  | V | V | |---|---| | 5 | 8 | | 8 | 5 |  Query 6: WITH r(v)AS(SELECT SUBSTR('1234567890-+*/',LEVEL,1)FROM DUAL CONNECT BY LEVEL<15)SELECT r.v,s.v FROM G,r,r s WHERE r.v<>s.v GROUP BY r.v,s.v HAVING SUM(f(TRANSLATE(x,r.v||s.v,s.v||r.v),y))=(SELECT COUNT(1)FROM G)AND SUM(INSTR(x,r.v)+INSTR(x,s.v))>0  | V | V | |---|---| | 1 | - | | - | 1 |  • No need for ||REPLACE(x,'--','- -')||, input/output format is flexible, so you are allowed to input -5--15 as -5- -15 if you want to. Also, what would be the easiest way for me to verify all the test cases work, especially the last one? Is a TIO-link somehow possible? Sep 4 '17 at 16:01 • Or is the ||REPLACE(x,'--','- -')|| used for an expected correct equation, like the last test case I've added? Sep 4 '17 at 16:49 • @KevinCruijssen -- starts a comment in SQL, so either the test cases need to be formulated so that -- never occurs in the equation (replacing it with - -) or it needs some defensive coding to militate for that. – MT0 Sep 5 '17 at 9:02 • So for the last test case 13116/3 = -1 would need to be written as 131 16/3 = -1 to remove that call to REPLACE. – MT0 Sep 5 '17 at 9:12 • Ah ok, so the replace is indeed used for the expected correct equations. Thanks for adding the SQL fiddle, +1 from me. Sep 5 '17 at 9:16 # Powershell, 222209 192 bytes param($x)1..13|%{0..(($i=$_)-1)|%{$a,$b='+-*/0123456789'[$i,$_]
$a+$b|?{!($x|%{$e,$r=$_-split'='
try{$r-(-join$(switch($e|% t*y){$a{$b}$b{$a}default{$_}})-replace'-',' -'|iex)}catch{1}}|gu)}}}


Test script and explanation:

$f={ param($x)                               # array of strings with equations
1..13|%{                                #
0..(($i=$_)-1)|%{                   # $i and$_ contains unique couples of different indecies
$a,$b='+-*/0123456789'[$i,$_]  # $a and$b contains buttons to swap
$g=$x|%{                        # for each equation from array
$e,$r=$_-split'=' # split incorrect expression and correct result$e=-join$(switch($e|% t*y){ # swap buttons for each symbol in the expression
$a{$b}
$b{$a}
default{$_} })$e=$e-replace'-',' -' # insert a space before each '-'. # It need to work with negative numbers. # For example, '4--1' throws an exception, '4 - -1' returns '5' try{$r-($e|iex)}catch{1} # Try to calc$e as powershell expression
# return 0 if the expression result equal to the result of the calculation
# return non zero integer otherwise
}|gu                            # Get-unique of calculation for each equation
if(!$g){ # if$g is 0 or $null # then all calculations returns true$a+$b # Ok, return the couple of buttons } } } } @( ,('2*','123=3','8423=252','4+4=8','4*7-10=417','9/3=3','42-9=-36') ,('/+','4/2=6','3/0=3','0/8+2=4','95-5=90','4+2=2') ,('1-','7+4=11','5-15=46','212-23=-2121') ,('42','4+8/2-9*1=-5','99/3-13=20','1+2+3+4=10','4-3-2-1=-6') ,('1-','9119=18','5-3=513','8*-9=152','13116/3=-1') ) | % {$e,$x=$_
$r=&$f $x "$($e-eq$r): $r :$x"
}


Output:

True: 2* : 123=3 8423=252 4+4=8 4*7-10=417 9/3=3 42-9=-36
True: /+ : 4/2=6 3/0=3 0/8+2=4 95-5=90 4+2=2
True: 1- : 7+4=11 5-15=46 212-23=-2121
True: 42 : 4+8/2-9*1=-5 99/3-13=20 1+2+3+4=10 4-3-2-1=-6
True: 1- : 9119=18 5-3=513 8*-9=152 13116/3=-1


# 05AB1E, 21 bytes

SÙãʒË_}ʒ¹sÂ‡„--'+:.EQ


Input as two lists, first being the equations and second being the results. Output as a filtered list of pairs with both rotations (i.e. [["2","*"],["*","2"]]).

Try it online or verify all test cases. (NOTE: Uses the legacy version of 05AB1E in the TIO, because .E is disabled in the newer version on TIO. Because of that, an additional ï (cast to integer) is added, because in the legacy version of 05AB1E 1.0 and 1 inside lists were not equal.)

Explanation:

S              # Convert the (implicit) input-list of equations to a list of characters
# (which implicitly flattens)
#  i.e. ["18/18","98-8","55*88","-5--15"]
#   → ["1","8","/","1","8","9","8","-","8","5","5","*","8","8","-","5","-","-","1","5"]
Ù             # Only leave all unique characters
#  → ["1","8","/","9","-","5","*"]
ã            # Cartesian product with itself; creating each possible pair of characters
#  → [["1","1"],["1","8"],["1","/"],["1","9"],["1","-"],["1","5"],["1","*"],["8","1"],["8","8"],["8","/"],["8","9"],["8","-"],["8","5"],["8","*"],["/","1"],["/","8"],["/","/"],["/","9"],["/","-"],["/","5"],["/","*"],["9","1"],["9","8"],["9","/"],["9","9"],["9","-"],["9","5"],["9","*"],["-","1"],["-","8"],["-","/"],["-","9"],["-","-"],["-","5"],["-","*"],["5","1"],["5","8"],["5","/"],["5","9"],["5","-"],["5","5"],["5","*"],["*","1"],["*","8"],["*","/"],["*","9"],["*","-"],["*","5"],["*","*"]]
ʒ  }       # Filter it by:
Ë_        #  Where both characters are unique
#   i.e. → [["1","8"],["1","/"],["1","9"],["1","-"],["1","5"],["1","*"],["8","1"],["8","/"],["8","9"],["8","-"],["8","5"],["8","*"],["/","1"],["/","8"],["/","9"],["/","-"],["/","5"],["/","*"],["9","1"],["9","8"],["9","/"],["9","-"],["9","5"],["9","*"],["-","1"],["-","8"],["-","/"],["-","9"],["-","5"],["-","*"],["5","1"],["5","8"],["5","/"],["5","9"],["5","-"],["5","*"],["*","1"],["*","8"],["*","/"],["*","9"],["*","-"],["*","5"]]
ʒ          # Then filter the pairs again by:
¹         #  Push the first input-list with equations
s        #  Swap to take the pair we're filtering
Â       #  Bifurcate it (short for Duplicate and Reverse)
‡      #  Transliterate; replacing the characters at the same indices in the input-list
#   i.e. ["18/18","98-8","55*88","-5--15"] and ["8","5"]
#    → ["15/15","95-5","88*55","-8--18"]
#   i.e. ["9119","5-3","8*-9","13116/3"] and ["1","-"]
#    → ["9--9","513","8*19","-3--6/3"]
„--'+:  '#  Then replace all "--" with a "+"
#   → ["15/15","95-5","88*55","-8+18"]
#   → ["9+9","513","8*19","-3+6/3"]
.E       #  And evaluate the strings with Python eval
#   → [1.0,90,4840,10]
#   → [18,513,152,-1.0]
Q      #  And then check if this evaluated list is equal to the (implicit) second input
#   i.e. [1.0,90,4840,10] and [1,90,4840,10] → 1 (truthy)
#   i.e. [18,513,152,-1.0] and [18,513,152,-1] → 1 (truthy)
# (and output the result implicitly)
#   i.e. [["8","5"],["5","8"]
#   i.e. [["1","-"],["-","1"]