Open In App

Equation satisfiability check

Last Updated : 18 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of size N where each arr[i] is a string denoting an equation, the task is to return true if all the statements are satisfactory otherwise return false if any two equations contradict each other. An equation can be one of the two types below:

  • Type 1: “a != b”, which denotes that a is not equal to b
  • Type 2: “a == b”, which denotes that both a and b are equal

Note: The provided equations are transitive in nature (i.e. if “a==b” and “b==c“, then “a==c“). 

Examples:

Input: N = 3, arr[] = [“a==b”, “a==c”, “b != c”]
Output: False
Explanation: Given “a == b” and “a == c”, using the transitive property we get “b == c “, but arr[2] i.e. “b != c” contradicts that, so we print False.

Input: N = 2, arr = [“a == b”, “b == a”]
Output: True
Explanation: Clearly arr[0] and arr[1] are same equations and there does not exists any contradicting equation, hence we print True.

Efficient Approach: Using Disjoint Set Union (DSU) to solve the equations efficiently.

Since the Equations follow the transitive property, we can use Union operation of DSU to put together all the equal equations in a single set, for example if we have {a==b, b==c, d==e} then we will have two sets i.e. {a,b,c} and {d,e} . We can process all the equations of type 2 first using DSU and finally check all the equation of type 1 and retrieve our answer as per the below two cases:

  • Case 1: if both the variables of type 1 equation belong to same set
    • return False
  • Case 2: if all the type1 equation does not follow Case1
    • return True

Follow the steps to solve the problem:

  • Firstly, initialize the DSU data structure, i.e. Find(), Union(), and parent[] array.
  • Make the parent of each character itself.
  • For each equation of type 2, merge the variables using the Union operation
  • Now for each equation of type 1, if the variables belong to the same disjoint set then return “False” else return “True“.

Below is the implementation of the above algorithm:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
// parent array to store the parent of
// each set of equations
int parent[26];
 
// This function finds the parent of
// each disjoint set
int find(int v)
{
    if (v == parent[v])
        return v;
    return parent[v] = find(parent[v]);
}
 
// This function is used to merge two
// disjoint sets into a single set
void Union(int a, int b)
{
    a = find(a);
    b = find(b);
    if (a != b) {
        parent[b] = a;
    }
}
 
string satisfactoryEquation(vector<string>& arr)
{
 
    // Loop to initialize the
    // parent array
    for (int i = 0; i < 26; i++)
        parent[i] = i;
 
    // Iterating on equations of type 2
    for (auto e : arr) {
        int a = e[0] - 'a';
        int b = e[3] - 'a';
        char c = e[1];
 
        // Equation to find type 2 equation
        if (c == '=') {
 
            // Merging the variables of
            // type 2 equations
            Union(a, b);
        }
    }
 
    // Iterating on equations of type 1
    for (auto e : arr) {
 
        // Condition to check type 1 equation
        if (e[1] == '!') {
            int a = e[0] - 'a';
            int b = e[3] - 'a';
 
            // If parents of both variables
            // are same we got
            // a contradiction
            if (find(a) == find(b))
                return "False";
        }
    }
    return "True";
}
 
// Driver code
int main()
{
    int N = 3;
    vector<string> arr = { "a==b", "a==c", "b!=c" };
 
    // Function Call
    cout << satisfactoryEquation(arr);
}


Java




// Java code for the above approach:
import java.util.*;
 
public class Main {
 
    // Parent array to store the parent of
    // each set of equations
    static int[] parent = new int[26];
 
    // This function finds the parent of
    // each disjoint set
    static int find(int v)
    {
        if (v == parent[v])
            return v;
        return parent[v] = find(parent[v]);
    }
 
    // This function is used to merge two
    // disjoint sets into a single set
    static void union(int a, int b)
    {
        a = find(a);
        b = find(b);
        if (a != b) {
            parent[b] = a;
        }
    }
 
    static String
    satisfactoryEquation(ArrayList<String> arr)
    {
 
        // Loop to initialize the
        // parent array
        for (int i = 0; i < 26; i++)
            parent[i] = i;
 
        // Iterating on equations of type 2
        for (String e : arr) {
            int a = e.charAt(0) - 'a';
            int b = e.charAt(3) - 'a';
            char c = e.charAt(1);
 
            // Equation to find type 2 equation
            if (c == '=') {
 
                // Merging the variables of
                // type 2 equations
                union(a, b);
            }
        }
 
        // Iterating on equations of type 1
        for (String e : arr) {
 
            // Condition to check type 1 equation
            if (e.charAt(1) == '!') {
                int a = e.charAt(0) - 'a';
                int b = e.charAt(3) - 'a';
 
                // If parents of both variables
                // are the same, we got a
                // contradiction
                if (find(a) == find(b))
                    return "False";
            }
        }
        return "True";
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int N = 3;
        ArrayList<String> arr = new ArrayList<String>(
            Arrays.asList("a==b", "a==c", "b!=c"));
 
        // Function Call
        System.out.println(satisfactoryEquation(arr));
    }
}
// This code is contributed by Prasad264


Python3




# parent array to store the parent of
# each set of equations
parent = list(range(26))
 
# This function finds the parent of
# each disjoint set
def find(v):
    if v == parent[v]:
        return v
    parent[v] = find(parent[v])
    return parent[v]
 
# This function is used to merge two
# disjoint sets into a single set
def Union(a, b):
    a = find(a)
    b = find(b)
    if a != b:
        parent[b] = a
 
def satisfactoryEquation(arr):
    # Loop to initialize the parent array
    for i in range(26):
        parent[i] = i
 
    # Iterating on equations of type 2
    for e in arr:
        a = ord(e[0]) - ord('a')
        b = ord(e[3]) - ord('a')
        c = e[1]
 
        # Equation to find type 2 equation
        if c == '=':
            # Merging the variables of type 2 equations
            Union(a, b)
 
    # Iterating on equations of type 1
    for e in arr:
        # Condition to check type 1 equation
        if e[1] == '!':
            a = ord(e[0]) - ord('a')
            b = ord(e[3]) - ord('a')
 
            # If parents of both variables are same, we got a contradiction
            if find(a) == find(b):
                return "False"
 
    return "True"
 
# Driver code
if __name__ == "__main__":
    N = 3
    arr = ["a==b", "a==c", "b!=c"]
 
    # Function Call
    print(satisfactoryEquation(arr))


C#




// C# code for the above approach
using System;
 
public class GFG
{
    // Parent array to store the parent
    // of each set of equations
    static int[] parent = new int[26];
 
    // This function finds the parent of
    // each disjoint set
    static int Find(int v)
    {
        if (v == parent[v])
            return v;
        return parent[v] = Find(parent[v]);
    }
 
    // This function is used to merge two
    // disjoint sets into a single set
    static void Union(int a, int b)
    {
        a = Find(a);
        b = Find(b);
        if (a != b)
        {
            parent[b] = a;
        }
    }
 
    static string SatisfactoryEquation(string[] arr)
    {
        // Loop to initialize the parent array
        for (int i = 0; i < 26; i++)
        {
            parent[i] = i;
        }
 
        // Iterating on equations of type 2
        foreach (string e in arr)
        {
            int a = e[0] - 'a';
            int b = e[3] - 'a';
            char c = e[1];
 
            // Equation to find type 2 equation
            if (c == '=')
            {
                // Merging the variables of type 2 equations
                Union(a, b);
            }
        }
 
        // Iterating on equations of type 1
        foreach (string e in arr)
        {
            // Condition to check type 1 equation
            if (e[1] == '!')
            {
                int a = e[0] - 'a';
                int b = e[3] - 'a';
 
                // If parents of both variables are
                // the same, we have a contradiction
                if (Find(a) == Find(b))
                {
                    return "False";
                }
            }
        }
 
        return "True";
    }
     
    // Driver code
    public static void Main()
    {
        string[] arr = { "a==b", "a==c", "b!=c" };
 
        // Function Call
        Console.WriteLine(SatisfactoryEquation(arr));
    }
}


Javascript




const parent = {};
function GFG(v) {
    if (v === parent[v]) {
        return v;
    }
    return parent[v] = GFG(parent[v]);
}
// Function to merge two variables into
// single set
function union(a, b) {
    a = GFG(a);
    b = GFG(b);
    if (a !== b) {
        parent[b] = a;
    }
}
// Function to determine if the given
// equations are satisfactory
function satisfactoryEquation(arr) {
    // Initialize the parent object
    for (let i = 0; i < 26; i++) {
        parent[String.fromCharCode('a'.charCodeAt(0) + i)] = String.fromCharCode('a'.charCodeAt(0) + i);
    }
    // Iterate through equations of type 2
    for (const e of arr) {
        const a = e.charCodeAt(0) - 'a'.charCodeAt(0);
        const b = e.charCodeAt(3) - 'a'.charCodeAt(0);
        const c = e[1];
        // Check for type 2 equation
        if (c === '=') {
            // Merge the variables of type 2 equations
            union(String.fromCharCode('a'.charCodeAt(0) + a), String.fromCharCode('a'.charCodeAt(0) + b));
        }
    }
    // Iterate through equations of type 1
    for (const e of arr) {
        // Check for type 1 equation
        if (e[1] === '!') {
            const a = e.charCodeAt(0) - 'a'.charCodeAt(0);
            const b = e.charCodeAt(3) - 'a'.charCodeAt(0);
            // If parents of both variables are the same
            // we have a contradiction
            if (GFG(String.fromCharCode('a'.charCodeAt(0) + a)) === GFG(String.fromCharCode('a'.charCodeAt(0) + b))) {
                return "False";
            }
        }
    }
    return "True";
}
// Driver code
function main() {
    const arr = ["a==b", "a==c", "b!=c"];
    // Function call
    console.log(satisfactoryEquation(arr));
}
main();


Output

False

Time Complexity: O(N), where N is the number of equations
Auxiliary Space: O(26), for the parent array



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads