Directi Interview Question for Software Engineer / Developers


Country: India
Interview Type: Written Test




Comment hidden because of low score. Click to expand.
1
of 1 vote

Run through the list and do a bitwise 'and', and maintain a list of the non-intersecting results. If the bit-and intersects any of the previously non-intersecting items , update the item with the new bit-and result. If it doesn't, add that fan to the non-intersecting list. At the end you'll have a list of all combinations of players which don't intersect with each other. Choose one player from each item, and you're done.

You have to run through the raw fan list once at O(K). The largest the non-intersecting list can possibly get is N. In the worst case the first n-1 fans individually only like the first N-1 players, and the rest of the fans only like the Nth player -- O(N) for each fan for the non-intersecting checks. Making this O(KN).

Here is working PHP code:

<?php

$test = array(
    '11111', 
    '01000',
    '00100', 
    '11110',
    '00001'

    /*
    '10101', 
    '01010',
    '00001', 
    '10000',
    '01110'
    */
);

function compactAnswer(&$arr) {
  $disparates = array();
  
  foreach ($arr as $i) {
    $i = bindec($i);
  
    $match = false;
    foreach ($disparates as $dNum => $dItem) {
      $matchNum = $i & $dItem;

      if ($matchNum) {
      	$disparates[$dNum] = $matchNum;
        $match = true;
        break;
      }
      
    }
    
    if (! $match) {
      $disparates[] = $i;
    }
  }
  
  return $disparates;
}

echo "\n\n\n";

echo 'Original: ';
foreach ($test as $i) echo $i, ', ';
echo "\n";

$test = compactAnswer($test);

echo 'Compacted: ';
foreach ($test as $i) echo decbin($i), ', ';
echo "\n", 'need ', count($test), ' players', "\n\n\n";

?>

- jvermette October 24, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Can you please explain with example.

- arpitbaheti7 October 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 votes

Sure. In the test case above with
'11111',
'01000',
'00100',
'11110',
'00001'

we are running through this fan list item by item and doing bitwise-and.

With the first item 11111 there is nothing to compare it to -- just put it in $disparates

Second item 01000 we run through disparates until we get a bitwise-and match or get to the end "11111" is the only thing in disparates. bitwise-and yields 01000. We replace that spot in $disparates with 01000.

Third item 00100 we compare in $disparates in the same way. The only item is 01000. Bitwise-and yields 00000 -- no match. Add 01000 as a second item.

Fourth item 11110 yields a match with the first item 01000 in $disparates. It yields 01000, we "replace" again but it's a no-op since they're the same.

Fifth item 00001 yields 00000 bitwise-and match with both items in $disparates. Add it as a third item.

We're now done with the fan list. We have three items in $disparates (01000, 00100, 00001). These represent the groups of fans who like non-intersecting ("disparate") groups of players. In this case that represents players 2, 3, 5. So that's our answer -- players 2, 3, 5.

If we run this with the second, commented out test case, it yields $disparates having "10000", "00001", and "01010". The answer would be players (1, 2, 5), or (1, 4, 5).

The biggest that $disparates can get is 5 items, since if it's 5 items then they're 10000, 01000, 00100, 00010, and 00001. All other bitwise-and's will match one of those. In fact if it ever gets to 5 items we can stop since all players are needed.

So we're doing one pass of the fan list, O(N), and for each one we're checking at worse K items in $disparates, O(K). Total O(KN).

- jvermette October 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

what about :
101
110
001

- arpitbaheti7 October 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

First I must apologize, in that last comment I kept saying "bitwise-or" but as you can see from the original post and code it's "bitwise-and". I just fixed the comment.

Then to your question -- 101,110,001 would yield disparates of 100,001 since the first two combine to 100 and the third is non-intersecting at 001. So the answer is players 1 and 3. And this is the correct answer since all fans like either player 1 or player 3.

- jvermette October 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@jvermette your algorithm gives correct results for the test cases.. but can you please explain the logic behind your algorithm. Actually this problem reduces to finding minimum vertex cover in bipartite graph....

- vijay40 November 07, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yeah... I tried to explain above in my previous comment, is there something specific missing there? I'm not sure how it translates to the NP-complete vertex cover problem, and the only two options there are that either it doesn't or my solution is incomplete. Either that or I just changed the face of computer science ;). My guess is that (assuming my solution works) this translates at most to a limited subset of that problem, which has an easier solution.

The basic idea here is that in $disparates we're keeping a list of the non-intersecting sets. With each fan bitstring we "and" it to each item already in $disparates. If at any time we get a non-zero answer, there's at least one bit in the new bit string which intersects with that group. We replace that spot in $disparates with the and-result.

If we reach the end of the current list of $disparates, it means this fan likes players which don't intersect any encountered set. It's a disparate set of players.

At the end, we have in $disparates a list of non-intersecting sets of players. With max possible length of the number of players. Select one from each, that's the answer.

This works because for each bit string if they fit into a group (an item in $disparates) then they share a common bit. And by fitting in, that bit string shrinks the group if they represent a subset of that group.

take A:10101, B:10100, C:00001. In three passes $disparates is {10101} (A), then {10100} (A&B), then {10100, 00001} (A&B, C).

You see from this that the possible answers are 10001 and 00101 (take one bit from each ending item in $disparates). Note that in step 2 {10100} we lose bit 5 because the algorithm found that A and B intersect only in bits 1 and 3. C happens to contain bit 5 so it's then added back in as a disparate intersection. At that point $disparates contains an entry with just one bit (00001) which means that that bit (bit 5 here) is required to be in the answer. That's why the total size of $disparates is max at the total number of bits -- if we ever get to that size, each entry contains just one bit and any new bit string will match at least one... and for that matter we can stop since we'd know that all bits need to be in the answer.

So... could you explain how this problem converts to vertex cover? That would be an interesting thing to hear, since there has to be something wrong on one side or the other.

- jvermette November 07, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

"00001
00010
10001
00011
10001
01001"

your solution will fail for this test case. your algo gives 3 answer but actual answer is 2. please correct if i am wrong.

- vinit November 14, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Vinit -- naw, it gives 00011. After the second item $disparates contains {00001, 00010} and every item after that matches one of them via bitwise-and. So it gives the right answer.

- jvermette November 14, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

You can use an algorithm similar to the quine-mccluskey algorithm for finding prime implicants.
Consider the likematrix above:

players_needed=0
likematrix=
10101
00001
01011

-player 5 is essential so increment the players_needed counter and remove the player column as well as all rows containing that player

players_needed =1
likematrix= empty

-likematrix is empty, therefore we are done. players_needed is 1

- mohd.husn001 October 24, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

how do you get to know which player is essential.

- arpitbaheti7 October 24, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

adding some details to @mohd.husn001's answer

we got to create a sum array that contains sum of likes per player (i.e. per column). At each step, the player with the max number of likes will be selected.

10101
00001
01011

sum array - 11113

at first step player 5 will be selected. now the 5th column and the rows for which 5th element is 1 (in this case all of them) are removed.

- sukheshmg October 24, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

for
101
001
010
110
it give 2 2 2 now we need to decide which one to select hear it must second or third column.
for
101
100
010
011

and here must be first or second column so.

- arpitbaheti7 October 24, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

What about a greedy approach? We have a set of fans and an array of players, sorted according to numbers of fans they have. Till the set is not empty, we choose a player that is liked by the biggest amount of fans (first in the sorted array). Now we remove those fans from the set, update the table (if fan F was removed, then decrease the counter of fans number, for a player, that had F as a fan) and resort. Repeat. The number of iterations, would be the searched minimum. I dind't look for a counter example, but still can't prove it works.

- joe kidd October 24, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

same solution i had already try but doesn't work for input:
101
001
010
110

- arpitbaheti7 October 24, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Why? Every players is liked by two fans. So if we choose a random player, we remove it and its fans, we have 2 players and 1 fan remaining. So now choose again a random player, and we remove the last fan. Fan set is empty. Answer=2. Please tell me if I am wrong as I had a tough day and may have some problems with thinking.

- joe kidd October 24, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

we need to find out which player to be choose..suppose if we choose 1st player then it will give ans 3 and if we choose 2nd or 3rd player it will give ans 2.now for an another ex:
101
100
010
011
if we choose 1st or 2nd player it will give ans 2 but for 3rd it is 3.

- arpitbaheti7 October 24, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Ok, maybe I don't understand the question: we have an array, of size K, where every element is a string of size N? So in this case we have K=4, N=3?

Player1 is liked by {1,2 }
Player2 is liked by {3, 4 }
Player3 is liked by {1,4}

Fans = {1,2,3,4}

Choose player1: Remainig Fans: {3,4}, Remaining players: Player2 = {3,4}, Player3 {4}
Choose player2: Remainig Fans {}

When we remove a player, we remove a fan related to that player, but also the players that are liked by this fan.

- joe kidd October 24, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

this is a fairly difficult problem :)

i came up with another idea but didn't test it because of time constraints. i tried a couple of simple examples though.

i guess the approach of selecting the player with most number of likes should still work. But in case of a tie, we have to chose the player whose fans are most 'loyal' to him i.e. we have to chose the player whose fans like least number of players other than him.

for this purpose, we will calculate a "loyalty index" for each player

loyalty index = number of other players liked by a fan of this player

and the player with least loyalty index is favored. in case of tie in loyalty index, any player ca be chosen among them.

For example, player 1 is liked by fan 1. fan 1 likes player 3 also. similarly, player 1 is liked by fan 2 and fan2 likes 0 other players. So,

loyalty index for player 1 = 1
for player 2 = 1
for player 3 = 2

so, we can chose either player 1 or player 2

101
100
010
011

sum array = 2 2 2
loyalty index array = 1 1 2

- sukheshmg October 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

how about treat this question as looking for min dist from node 00000 to node 11111 using BFS? each node is accessed once so i guess its O(n)?

- Anonymous October 25, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Can you explain?

- jvermette October 26, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is the java implementation of the solution. Logic used has been as suggested by jvermette:

int[][] likeMatrix = { {1, 1, 1, 1, 1},  
			        {0, 1, 0, 0, 0}, 
				{0, 0, 1, 0, 0},
				{1, 1, 1, 1, 0},
				{0, 0, 0, 0, 1}}; 
int[] rating = converter(likeMatrix);
ArrayList<Integer> result = finalizePlayers(rating);
print(result, likeMatrix[0].length);
}



public static int[] converter(int[][] likeMatrix){
		int result [] = new int[likeMatrix.length];
		int rating;
		for (int i = 0; i < likeMatrix.length; i++) {
			rating = 0;
			for (int j = 0; j < likeMatrix[0].length; j++) {
				if (likeMatrix[i][j] == 1) {
					rating += Math.pow(2, (likeMatrix[0].length - 1 - j));
				}
			}
			result[i] = rating;
		}
		return result;
	}

public static ArrayList<Integer> finalizePlayers(int[] rating){
		ArrayList<Integer> result = new ArrayList<Integer>();
		boolean match;
		int item;
		for (int i = 0; i < rating.length; i++) {
			match = false;
			for (int j = 0; j < result.size(); j++) {
				item = rating[i] & result.get(j);
				if(item > 0){
					result.remove(j);
					result.add(j, item);
					match = true;
					break;
				}
			}
			if(!match){
				result.add(rating[i]);
			}
		}
		return result;
	}

public static void print(ArrayList<Integer> result, int totalPlayers){
		int index = 0;
		System.out.println("Minimum players required are: ");
		for (Integer integer : result) {
			index = 0;
			while(integer>0){
				if((integer & 1) >0){
					index = totalPlayers - index;
					break;
				}else{
					integer = integer>>1;
					index++;
				}
			}
			System.out.print("Player# " + index + " ");
		}
	}

- Rakesh Roy October 26, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is the logic I followed for the code below
for each player i from 0 to (n-1), do the following steps
1) Check whether any fan contains only player i in its list. If so, this player has to be in the output. Add this player to output list.
2) Remove all fans liking player i (since this player is in the output list).
3) Also remove the player i (i.e. set bit i = 0) for all remaining rows (This is done irrespective of whether player i is in output list or not. Player i wont matter in further decision making)
4) If during this process, the number of rows (fans) becomes 0, we will stop and print the output list. This is the minimum set.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;


public class FansAndPlayers {

	public static List<List<Integer>> checkArrayList(List<List<Integer>> list, int playerNo)
	{
		List<List<Integer>> fanList = new ArrayList<List<Integer>>();
		boolean isPlayerNecessary = false;
		for(int i=0;i<list.size();i++)
		{
			List<Integer> temp = list.get(i);
			if(temp.contains(playerNo))
			{
				fanList.add(temp);	//These fans will be removed from the List if this player is necessary
				if(!isPlayerNecessary && temp.size()==1)
				{
					isPlayerNecessary = true;
				}
			}
		}
		
		
		if(isPlayerNecessary)
		{
			for(int i=0;i<fanList.size();i++)
			{
				list.remove(fanList.get(i));
			}
		}
                for(int i=0;i<list.size();i++)
		{
			List<Integer> temp = list.get(i);
			if(temp.get(0) == playerNo)
				temp.remove(0);
		}
		return list;
	}
	
	public static List<Integer> minimumFanList(List<List<Integer>> list, int noOfPlayers, int noOfFans)
	{
		List<Integer> playersNecessary = new ArrayList<Integer>();
		for(int i=0; i<noOfPlayers; i++)
		{
			int oldSize = list.size();		//No need this if you can return a tuple of list,boolean. I was feeling bored
			list = checkArrayList(list, i);
			int newSize = list.size();
			if(newSize!=oldSize)
			{
				//Player is necessary
				playersNecessary.add(i);
			}
			if(newSize == 0)	//All fans satisfied
				break;
		}
		return playersNecessary;
	}
	
	public static void main(String args[])
	{
		BufferedReader br = null;
		try
		{
			br = new BufferedReader(new InputStreamReader(System.in));
			int testCases = Integer.parseInt(br.readLine());
			for(int t = 0;t<testCases;t++)
			{
				int noOfPlayers = Integer.parseInt(br.readLine());
				int noOfFans = Integer.parseInt(br.readLine());
				List<List<Integer>> playersFansList = new ArrayList<List<Integer>>();
				for(int i=0;i<noOfFans;i++)
				{
					List<Integer> temp = new ArrayList<Integer>();
					String str = br.readLine();
					for(int j=0;j<noOfPlayers;j++)
					{
						if(str.charAt(j)=='1')
							temp.add(j);
					}
					playersFansList.add(temp);
				}
				List<Integer> finalList = minimumFanList(playersFansList, noOfPlayers, noOfFans);
				for(int i=0;i<finalList.size();i++)
				{
					System.out.print(finalList.get(i) + " ");
				}
				System.out.println();
			}
		}
		catch(Exception e)
		{
			System.out.println(e.getMessage());
		}
	}
}

- Ajay November 26, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Oh,it seems like NP-complete minimal vertex cover problem

- gstepanov@griddynamics.com October 24, 2013 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More