Open In App

Determining the inconsistently weighted object

Last Updated : 07 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given N objects numbered from 1 to N out of which all are of the same weights except only one object which is not known beforehand. We are also given Q comparisons, in each of which an equal number of objects are placed on both sides of a balance scale, and we are told the heavier side. 
The task is to find the inconsistently weighted object or determine if the data is not sufficient enough.
Examples
 

Input : N = 6
Q = 3
1 2 = 5 6
1 2 3 > 4 5 6
3 4 < 5 6
Output : 4
Explanation: Object 4 is lighter than all other objects.
Input : N = 10
Q = 4
1 2 3 4 < 7 8 9 10
1 = 9
2 3 4 > 1 5 10
6 = 2
Output : Insufficient data

 

It is told that except only one element, the rest of the elements are of the same weights. So, if we observe carefully, it can be said that: 
 

  1. In a ‘=’ comparison, none of the objects on both sides is the inconsistently weighted one. 
     
  2. If an object appears on the heavier side in one comparison and on the lighter side in another, then it is not the inconsistently weighted object. This is because, if an object appears on the heavier side then it is of the maximum weight and if it appears on the lighter side then it is of the minimum weight. Since a single element can’t be both maximum and minimum at the same time. So, this case will never occur. 
     
  3. The inconsistently weighted object must appear in all of the non-balanced (‘>’ or ‘<‘) comparisons. 
     

We can use the above three observations to narrow down the potential candidates for the inconsistently weighted object. We will consider only those objects which are either on the heavier side or the lighter side; if there is only one such object then it is the required one. If there is no such object, then we will consider all those objects which do not appear in any comparison. If there is only one such object then it is the inconsistently weighted object. If none of these scenarios arises, the data is insufficient.
Below is the implementation of the above approach: 
 

C++




#include <iostream>
#include <vector>
#include <algorithm>
 
// Function to get the difference of two vectors
std::vector<int> subtract(const std::vector<int>& A, const std::vector<int>& B) {
    std::vector<int> result;
    std::set_difference(A.begin(), A.end(), B.begin(), B.end(), std::back_inserter(result));
    return result;
}
 
// Function to get the intersection of two vectors
std::vector<int> intersect(const std::vector<int>& A, const std::vector<int>& B) {
    std::vector<int> result;
    std::set_intersection(A.begin(), A.end(), B.begin(), B.end(), std::back_inserter(result));
    return result;
}
 
// Function to get the union of two vectors
std::vector<int> unite(const std::vector<int>& A, const std::vector<int>& B) {
    std::vector<int> result;
    std::set_union(A.begin(), A.end(), B.begin(), B.end(), std::back_inserter(result));
    return result;
}
 
// Function to find the inconsistently weighted object
std::string inconsistentlyWeightedObject(int N, int Q,
                                         const std::vector<std::vector<std::vector<int>>>& comparisons) {
    std::vector<int> potentialCandidates(N, 0);
    std::vector<int> objectNotCompared(N, 0);
 
    for (int i = 0; i < N; ++i) {
        potentialCandidates[i] = i + 1;
        objectNotCompared[i] = i + 1;
    }
 
    for (const auto& c : comparisons) {
        if (c[1][0] == '=') {
            // Observation 1: '=' comparison, remove objects from potential candidates
            potentialCandidates = subtract(potentialCandidates, unite(c[0], c[2]));
        } else {
            // Observation 2: Non-balanced ('>' or '<') comparison, retain only those on the heavier side
            potentialCandidates = intersect(potentialCandidates, (c[1][0] == '>') ? c[2] : c[0]);
        }
 
        // Observation 3: Remove objects that appear in any comparison from objectNotCompared
        objectNotCompared = subtract(objectNotCompared, unite(c[0], c[2]));
    }
 
    if (potentialCandidates.size() == 1) {
        return std::to_string(potentialCandidates[0]);
    } else if (potentialCandidates.empty()) {
        if (objectNotCompared.size() == 1) {
            return std::to_string(objectNotCompared[0]);
        } else {
            return "Insufficient data";
        }
    } else {
        return "Insufficient data";
    }
}
 
// Driver code
int main() {
    int N = 6;
    int Q = 3;
    std::vector<std::vector<std::vector<int>>> comparisons = {
        {{1, 2}, {'='}, {5, 6}},
        {{1, 2, 3}, {'>'}, {4, 5, 6}},
        {{3, 4}, {'<'}, {5, 6}}
    };
 
    std::cout << inconsistentlyWeightedObject(N, Q, comparisons) << std::endl;
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
public class Main {
 
    // Function to get the difference of two lists
    public static List<Integer> subtract(List<Integer> A, List<Integer> B) {
        List<Integer> result = new ArrayList<>(A);
        result.removeAll(B);
        return result;
    }
 
    // Function to get the intersection of two lists
    public static List<Integer> intersect(List<Integer> A, List<Integer> B) {
        List<Integer> result = new ArrayList<>(A);
        result.retainAll(B);
        return result;
    }
 
    // Function to get the union of two lists
    public static List<Integer> unite(List<Integer> A, List<Integer> B) {
        Set<Integer> unionSet = new HashSet<>(A);
        unionSet.addAll(B);
        return new ArrayList<>(unionSet);
    }
 
    // Function to find the inconsistently weighted object
    public static String inconsistentlyWeightedObject(int N, int Q, List<List<List<Integer>>> comparisons) {
        List<Integer> potentialCandidates = new ArrayList<>();
        List<Integer> objectNotCompared = new ArrayList<>();
 
        for (int i = 0; i < N; ++i) {
            potentialCandidates.add(i + 1);
            objectNotCompared.add(i + 1);
        }
 
        for (List<List<Integer>> c : comparisons) {
            if (c.get(1).get(0) == '=') {
                // Observation 1: '=' comparison, remove objects from potential candidates
                potentialCandidates = subtract(potentialCandidates, unite(c.get(0), c.get(2)));
            } else {
                // Observation 2: Non-balanced ('>' or '<') comparison, retain only those on the heavier side
                potentialCandidates = intersect(potentialCandidates, (c.get(1).get(0) == '>') ? c.get(2) : c.get(0));
            }
 
            // Observation 3: Remove objects that appear in any comparison from objectNotCompared
            objectNotCompared = subtract(objectNotCompared, unite(c.get(0), c.get(2)));
        }
 
        if (potentialCandidates.size() == 1) {
            return Integer.toString(potentialCandidates.get(0));
        } else if (potentialCandidates.isEmpty()) {
            if (objectNotCompared.size() == 1) {
                return Integer.toString(objectNotCompared.get(0));
            } else {
                return "Insufficient data";
            }
        } else {
            return "Insufficient data";
        }
    }
 
    // Driver code
    public static void main(String[] args) {
        int N = 6;
        int Q = 3;
        List<List<List<Integer>>> comparisons = new ArrayList<>();
        comparisons.add(List.of(List.of(1, 2), List.of((int) '='), List.of(5, 6)));
        comparisons.add(List.of(List.of(1, 2, 3), List.of((int) '>'), List.of(4, 5, 6)));
        comparisons.add(List.of(List.of(3, 4), List.of((int) '<'), List.of(5, 6)));
 
        System.out.println(inconsistentlyWeightedObject(N, Q, comparisons));
    }
}


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class Program {
    // Function to get the difference of two lists
    static List<int> Subtract(List<int> A, List<int> B)
    {
        return A.Except(B).ToList();
    }
 
    // Function to get the intersection of two lists
    static List<int> Intersect(List<int> A, List<int> B)
    {
        return A.Intersect(B).ToList();
    }
 
    // Function to get the union of two lists
    static List<int> Unite(List<int> A, List<int> B)
    {
        return A.Union(B).ToList();
    }
 
    // Function to find the inconsistently weighted object
    static string InconsistentlyWeightedObject(
        int N, int Q, List<List<List<int> > > comparisons)
    {
        List<int> potentialCandidates
            = new List<int>(Enumerable.Range(1, N));
        List<int> objectNotCompared
            = new List<int>(Enumerable.Range(1, N));
 
        foreach(var c in comparisons)
        {
            if (c[1][0] == '=') {
                // Observation 1: '=' comparison, remove
                // objects from potential candidates
                potentialCandidates = Subtract(
                    potentialCandidates, Unite(c[0], c[2]));
            }
            else {
                // Observation 2: Non-balanced ('>' or '<')
                // comparison, retain only those on the
                // heavier side
                potentialCandidates = Intersect(
                    potentialCandidates,
                    (c[1][0] == '>') ? c[2] : c[0]);
            }
 
            // Observation 3: Remove objects that appear in
            // any comparison from objectNotCompared
            objectNotCompared = Subtract(objectNotCompared,
                                         Unite(c[0], c[2]));
        }
 
        if (potentialCandidates.Count == 1) {
            return potentialCandidates[0].ToString();
        }
        else if (!potentialCandidates.Any()) {
            if (objectNotCompared.Count == 1) {
                return objectNotCompared[0].ToString();
            }
            else {
                return "Insufficient data";
            }
        }
        else {
            return "Insufficient data";
        }
    }
 
    // Driver code
    static void Main(string[] args)
    {
        int N = 6;
        int Q = 3;
        List<List<List<int> > > comparisons
            = new List<List<List<int> > >{
                  new List<List<int> >{
                      new List<int>{ 1, 2 },
                      new List<int>{ '=' },
                      new List<int>{ 5, 6 } },
                  new List<List<int> >{
                      new List<int>{ 1, 2, 3 },
                      new List<int>{ '>' },
                      new List<int>{ 4, 5, 6 } },
                  new List<List<int> >{
                      new List<int>{ 3, 4 },
                      new List<int>{ '<' },
                      new List<int>{ 5, 6 } }
              };
 
        Console.WriteLine(InconsistentlyWeightedObject(
            N, Q, comparisons));
    }
}


Javascript




// JavaScript program to determine the
// inconsistently weighted object
 
// Function to get the difference of two lists
function subt(A, B)
{
    return A.filter(x => !B.includes(x))
}
 
 
// Function to get the intersection of two lists
function intersection(A, B)
{
    return A.filter(x => B.includes(x));
}
 
// Function to get the intersection of two lists
function union(A, B)
{
    return [...A, ...B];
}
 
// Function to find the inconsistently weighted object
function inconsistentlyWeightedObject(N, Q, comparisons)
{
    // Objects which appear on the heavier side
    let heavierObj =  [];
    for (i = 1; i <= N; i++)
        heavierObj.push(i);
     
    // Objects which appear on the lighter side
    let lighterObj = [];
    for (i = 1; i <= N; i++)
        lighterObj.push(i);
         
    let equalObj = [];  // Objects which appear in '=' comparisons
     
    // Objects which don't appear in any comparison
    objectNotCompared = [];
    for (i = 1; i <= N; i++)
        objectNotCompared.push(i);
     
    for (var c of comparisons)
    {
        objectNotCompared = subt(objectNotCompared, union(c[0], c[2])) ;
         
        if (c[1] == '=')
            equalObj = union(equalObj, union(c[0], c[2]))
        else if (c[1] == '<')
        {
            // Removing those objects which do
            // not appear on the lighter side
            lighterObj = intersection(lighterObj, c[0])
             
            // Removing those objects which do
            // not appear on the heavier side
            heavierObj = intersection(heavierObj, c[2])
        }
        else
        {
            // Removing those objects which do
            // not appear on the lighter side
            lighterObj = intersection(lighterObj, c[2])
             
            // Removing those objects which do
            // not appear on the heavier side
            heavierObj = intersection(heavierObj, c[0])
        }
    }
     
    let L_iwo = subt(union(heavierObj, lighterObj), equalObj)   // Potential candidates
 
    if ((L_iwo).length == 1)
        return L_iwo[0]
    else if ((L_iwo).length == 0)
    {
        if (objectNotCompared.length == 1)
            return objectNotCompared[0]
        else
            return 'Insufficient data'
    }
    else
        return 'Insufficient data'
}
 
 
// Driver code
let N = 6
let Q = 3
let comparisons = [ [[1, 2], '=', [5, 6]], [[1, 2, 3], '>', [4, 5, 6]],
                                        [[3, 4], '<', [5, 6]] ]
console.log(inconsistentlyWeightedObject(N, Q, comparisons))
 
 
 
// This code is contributed by phasing17


Python3




# Python program to determine the
# inconsistently weighted object
 
# Function to get the difference of two lists
def subt(A, B):
    return list(set(A) - set(B))
 
# Function to get the intersection of two lists
def intersection(A, B):
    return list(set(A).intersection(set(B)))
 
# Function to get the intersection of two lists
def union(A, B):
    return list(set(A).union(set(B)))
 
# Function to find the inconsistently weighted object
def inconsistentlyWeightedObject(N, Q, comparisons):
    # Objects which appear on the heavier side
    heavierObj = [i for i in range(1, N + 1)]
     
    # Objects which appear on the lighter side
    lighterObj = [i for i in range(1, N + 1)]
    equalObj = [] # Objects which appear in '=' comparisons
     
    # Objects which don't appear in any comparison
    objectNotCompared = [i for i in range(1, N + 1)]
     
    for c in comparisons:
        objectNotCompared = subt(objectNotCompared, union(c[0], c[2]))
         
        if c[1] == '=':
            equalObj = union(equalObj, union(c[0], c[2]))
        elif c[1] == '<':
            # Removing those objects which do
            # not appear on the lighter side
            lighterObj = intersection(lighterObj, c[0])
             
            # Removing those objects which do
            # not appear on the heavier side
            heavierObj = intersection(heavierObj, c[2])
        else:
            # Removing those objects which do
            # not appear on the lighter side
            lighterObj = intersection(lighterObj, c[2])
             
            # Removing those objects which do
            # not appear on the heavier side
            heavierObj = intersection(heavierObj, c[0])
     
    L_iwo = subt(union(heavierObj, lighterObj), equalObj) # Potential candidates
 
    if len(L_iwo) == 1:
        return L_iwo[0]
    elif not len(L_iwo):
        if len(objectNotCompared) == 1:
            return objectNotCompared[0]
        else:
            return 'Insufficient data'
    else:
        return 'Insufficient data'
 
 
# Driver code
N = 6
Q = 3
comparisons = [ [[1, 2], '=', [5, 6]], [[1, 2, 3], '>', [4, 5, 6]],
                                        [[3, 4], '<', [5, 6]] ]
print(inconsistentlyWeightedObject(N, Q, comparisons))


Output

4



Time Complexity: O(nlogn)

Auxiliary Space: O(n)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads