Google Interview Question for Software Engineer / Developers


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
14
of 16 vote

One idea, not sure whether this is correct.

Construct two graphs, one for x-coordinate--Gx, one for y-coordinate--Gy.

For Gx, If x1 < x2, then we have an edge from x1->x2, if x1 > x2, one edge x1<-x2. If x1 == x2, combine x1 and x2 together.

Similarly for Gy.

In the end, we check whether there exists a cycle in Gx or Gy. If this is true, then the answer is impossible.

For example, p1 SE p2, we have x1 > x2 and y1 < y2.
Gx: x1 <-- x2 Gy: y1 -->y2

p2 SE p3, we have x2 > x3 and y2 < y3.
Gx: x1 <-- x2 <-- x3 Gy: y1 -->y2 -->y3

p3 SE p1, we have x3 > x1 and y3 < y1
In Gx, we have a cycle from x1 <-- x2 <-- x3 <-- x1. So it is impossible.


Any comment/correction/improvement is welcome...

- wwu November 02, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
Comment hidden because of low score. Click to expand.
0
of 0 votes

Hi ninhnnsoc, I don't understand why p1 SE p2; p3 NE p2; p3 NE p1 is impossible? It looks like possible

- Anonymous November 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I agree, p1 SE p2; p3 NE p2; p3 NE p1 looks like possible

- Mike November 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 votes

Great approach to decompose the problem to a smaller set. But your solution misses a corner case:

This is a "possible" state: p1 SE p2, p2 SE p3, p3 NW p1
This is an "impossible" state: p1 SE p2, p2 SE p3, p3 W p1 (based on the assumption that NW != W)

Your solution above will miss this case and deem p1 SE p2, p2 SE p3, p3 W p1 as a "possible" scenario.

- lunatic November 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

@lunatic, you are right, thanks for pointing it out. One way I think to fix it is that every time we want to combine two existing different vertexs in the graph, we should output impossible.. Do you agree?

- wwu November 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
3
of 3 votes

@lunatic: The solution would not miss that case. For the y-dimension the graph will be p1 -> p2, p2 -> p3, merge(p3, p1), which would yield the graph p1 -> p2, p2 -> p1, which is a cycle.

- Anonymous November 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

The original solution is entirely correct as far as I can tell.

- Anonymous November 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

p0 W p1, p1 SW p2, p2 SE p3, p3 NE p0
Gx: p0->p1->p2<-p3<-p0
Gy: p0=p1->p2->p3<-p0
It seems there is no circle in Gx and Gy, but the answer is impossible.

- Zhangwen November 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Hi all,
Seems like we don't have a consensus definition on the "relative position".
For example, is NE exactly northeast or "approximately" northeast?

So, what is your opinion on this example: Is it possible or impossible?:

p1 SE p2; p3 NE p2; p3 NE p1; p4 SW p1; p5 SE p4; p5 SE p1;  p3 NE p5.

(First 3 points are in my previous example).
This example is a W-shape, where p3 and p5 run to infinity. But the last pair "p3 NE p5" may or may not be possible, depends on how NE direction is defined.

Thanks!

- ninhnnsoc November 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

@Zhangwen:
Again, I don't see how your example should be impossible. It looks perfectly possible to me

@ninhnnsoc:
I think it's quite clear that if it says p1 NE p2, it means any point in the plane with strictly Xp1 > Xp2 and Yp1 > Yp2. Which means that anything is good as p1 long as it's not exactly East or North of p2

- Mike November 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Mike: Ok. So NE means approximately northeast.
Then we can transform "relative position" into coordinate relation.
And the OP is correct.

- ninhnnsoc November 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I though for a moment that my solution is so different. But when I realized that my solution has elements of Floyd Warshall, therefore it does have a graph implied :)

- CT November 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@wws: i think your original solution is correct. Perhaps i misunderstood your improvement, but if you output "impossible" when you're are trying to merge two different existing vertices, what about { p1 S p2, p2 S p3, p3 N p1 } ? I think in this case, all three vertices have the same x coordinate, but it is "possible".

- Cloud_cal November 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Cloud_cal, In that case, you only have one x vertex...

- wwu November 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

It is entirely correct. If it's possible in each coordinate, that means a feasible coordinate, x[0], ... x[n-1], and y[0], ..., y[n-1], then (x[0], y[0]), ..., (y[n-1], y[n-1]) is a solution to the original 2D question.

- Chenliang Xu November 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 votes

p1 S p2
p2 S p3
p3 N p4
p4 S p2

There is a circle, but it is possible.

- czhao86 November 13, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

czhao86 there is no cycle

- Demo April 28, 2015 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

quick solution in python

#Given the relative positions (S, W, N, E, SW, NW, SE, NE) of some pairs of points on a 2D plane, 
#determine whether it is possible. No two points have the same coordinates. 

# INPUT
# p12is SouthEast of p1
c1 = ("p1","p2","SE")
# p3 is SouthEast of p2
c2 = ("p2","p3","SE")
# p1 is SouthEast of p3
c3 = ("p3","p1","SE")
cs = [c1,c2,c3]

# Mappings
translations = {
	"S":{"S"},
	"W":{"W"},
	"N":{"N"},
	"E":{"E"},
	"SW":{"S","W"},
	"SE":{"S","E"},
	"NW":{"N","W"},
	"NE":{"N","E"},
}

opposites = {
	"S":"N",
	"W":"E",
	"N":"S",
	"E":"W"
}



# returns true if isuch nformation regarding the direction exists
def isInDirection(src,dst,graph,dr):
	if dst in graph[src][dr]:
		return True
	for meta_dst in graph[src][dr]:
		if isInDirection(meta_dst,dst,graph,dr):
			return True
	return False


emptyNode = lambda : {"S":[],"W":[],"N":[],"E":[]}

graph = {}
for c in cs:
	src,dst,directions = c[0],c[1],c[2]
	if not(src in graph):
		graph[src] = emptyNode()
	if not(dst in graph):
		graph[dst] = emptyNode()
	# c0 is c2 of c1
	for direction in translations[directions]:
		if isInDirection(src,dst,graph,opposites[direction]):
			print "Impossible for " + dst + " to be " + directions + " of " + src +\
			 " because " + dst  + " is " + opposites[direction] + " of it"
			break
		graph[src][direction].append(dst)
		graph[dst][opposites[direction]].append(src)
#print graph

- mcfly November 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

{{ if we have input p1 SE p2, p2 SE p3, p3 SE p4, p4 NW p5 and p5 SE p1, output depends upon p5, if p5 > p1 - this path invalid.
if p1 < p5 this path is valid

How we identify weather p5 > p1? }}

- Yogesh November 03, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

You don't. You output "Possible" because depending on the values of p5 and p1 it could be possible.

- Anonymous November 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

For each x and y, fill two matrices. We only want one triangle so it can be optimized into one.
size of matrix side is the amount of points. Enter only what is given. If p1 and p2 p1.x > p2.x enter 1 at position 1,2. less, enter -1. equal 0.

For every filled point, see that if all filled elements on the same row and column >= 1 and current is -1: impossible. Similarly, all are <= 1 and current one 1: impossible

- CT November 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Ithink this question maybe can be sloved with bit manipulation.

- byrlhb November 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

import java.util.*;
class RelativePositioning {
	
	Set<String> getValue(String key, HashMap<String, Set<String>> hashMap) {
		Set<String> value = hashMap.get(key);
		if(value == null) {
			value = new HashSet<String>();
		}
		return value;
	}
	
	boolean isValueRepeated(String key, ArrayList<String> keyList, HashSet<String> visitedKeys, HashMap<String, Set<String>> hashMap) {
		if(visitedKeys.contains(key)) return false;
		keyList.add(key);
		Set<String> valuesSet = hashMap.get(key);
		for(String value : valuesSet) {
			if(keyList.contains(value)) return true;
			@SuppressWarnings("unchecked")
			ArrayList<String> keyListClone = (ArrayList<String>)keyList.clone();
			if(isValueRepeated(value, keyListClone, visitedKeys, hashMap)) return true;
		}
		visitedKeys.add(key);
		return false;
	}
	
	boolean checkForLoops(HashMap<String, Set<String>> hashMap) {
		Set<String> keys = hashMap.keySet();
		HashSet<String> visitedKeys = new HashSet<String>();
		for(String key: keys) {
			ArrayList<String> keyList = new ArrayList<String>();
			if(isValueRepeated(key, keyList, visitedKeys, hashMap)) return true;
		}
		return false;
	}
	
	boolean fitInAGraph(String[] positions) {
		HashMap<String, Set<String>> xHashMap = new HashMap<String, Set<String>>();
		HashMap<String, Set<String>> yHashMap = new HashMap<String, Set<String>>();
		for(String position: positions) {
			String[] positionParts = position.split(" ");
			String val1 = positionParts[0];
			String val2 = positionParts[2];
			String relation = positionParts[1];
			
			Set<String> val1ArrayX = getValue(val1, xHashMap);
			Set<String> val2ArrayX = getValue(val2, xHashMap);
			Set<String> val1ArrayY = getValue(val1, yHashMap);
			Set<String> val2ArrayY = getValue(val2, yHashMap);
			
			if(relation.equals("S")) {
				val1ArrayX.addAll(val2ArrayX);
				val2ArrayX = val1ArrayX;
				val2ArrayY.add(val1);
			} else if(relation.equals("W")) {
				val1ArrayY.addAll(val2ArrayY);
				val2ArrayY = val1ArrayY;
				val2ArrayX.add(val1);
			} else if(relation.equals("N")) {
				val1ArrayX.addAll(val2ArrayX);
				val2ArrayX = val1ArrayX;
				val1ArrayY.add(val2);
			} else if(relation.equals("E")) {
				val1ArrayY.addAll(val2ArrayY);
				val2ArrayY = val1ArrayY;
				val1ArrayX.add(val2);
			} else if(relation.equals("SW")) {
				val2ArrayX.add(val1);
				val2ArrayY.add(val1);
			} else if(relation.equals("NW")) {
				val1ArrayY.add(val2);
				val2ArrayX.add(val1);
			} else if(relation.equals("SE")) {
				val2ArrayY.add(val1);
				val1ArrayX.add(val2);
			} else if(relation.equals("NE")) {
				val1ArrayX.add(val2);
				val1ArrayY.add(val2);
			}
			xHashMap.put(val1, val1ArrayX);
			xHashMap.put(val2, val2ArrayX);
			yHashMap.put(val1, val1ArrayY);
			yHashMap.put(val2, val2ArrayY);
			
		}
		return !checkForLoops(xHashMap) && !checkForLoops(yHashMap);
	}

	public static void  main(String[] inputs) {
		RelativePositioning rp = new RelativePositioning();
		String[] positions = new String[10];
		positions[0] = "p1 N p3";
		positions[1] = "p1 NW p5";
		positions[2] = "p1 NW p2";
		positions[3] = "p2 SW p6";
		positions[4] = "p4 SW p6";
		positions[5] = "p3 W p2";
		positions[6] = "p4 S p1";
		positions[7] = "p5 E p4";
		positions[8] = "p1 W p6";
		positions[9] = "p6 NE p5";
		System.out.println(rp.fitInAGraph(positions));
		/*above test: 
		  ________________
		  | p1 |    | p6 |
		  _________________
		  | p3 | p2 |    |
		  ________________
		  | p4 | p5 |    |
		  ________________
		*/
		
	}
}

- Adi November 06, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

same idea as wws, but implemented using hashmap to represent the graph. key in hashmap points to values that should have lower coordinate point than the key.

- Adi November 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

public void solve(String input) {
  HashMap<String, Point> coordinates = new HashMap<>();
  String[] pairs = input.split(",");
  for (String pair : pairs) {
    String[] token = pair.split("\\s+");
    if (!coordinates.contains(token[0])) {
      coordinates.add(token[0], new Point(0, 0));
    }
    Point p1 = coordinates.get(token[0]);
    Point p2 = null;
    if (token[1].equals("S")) {
    p2 = new Point(token[2], new Point(p1.x, p1.y - 1)); 
    } else if (token[1].equals("W")) {
    p2 = new Point(token[2], new Point(p1.x - 1, p1.y));    
    } else if (token[1].equals("N")) {
    p2 = new Point(token[2], new Point(p1.x, p1.y + 1));    
    } else if (token[1].equals("E")) {
    p2 = new Point(token[2], new Point(p1.x + 1, p1.y));    
    } else if (token[1].equals("SW")) {
    p2 = new Point(token[2], new Point(p1.x - 1, p1.y - 1));    
    } else if (token[1].equals("NW")) {
    p2 = new Point(token[2], new Point(p1.x - 1, p1.y + 1));    
    } else if (token[1].equals("SE")) {
    p2 = new Point(token[2], new Point(p1.x + 1, p1.y - 1));    
    } else if (token[1].equals("NE")) {
    p2 = new Point(token[2], new Point(p1.x + 1, p1.y + 1));    
    }
    if (coordinates.contains(token[2]) && p2 != null) {
      if (!p2.equals(coordinates.get(p2))) {
        System.out.println("Impossible");
      }
    }
  }
}

- Nomster November 06, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include <iostream>
#include <assert.h>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>

using namespace std;

typedef struct
{
	string src;
	string dst;
	string angle;
}Relation;

typedef struct RelationNode_{
	string name;
	map<string, set<RelationNode_*> > nodes;
}RelationNode;

RelationNode *findNodeByName(RelationNode * root, const string& name, const string& angle)
{
	queue<RelationNode *> task;
	task.push(root);
	while (!task.empty())
	{
		if (task.front()->name == name)
			return task.front();

		for ( const auto& node : task.front()->nodes )
			if (angle.empty() || node.first == angle)
				for ( const auto& nodeInSet : node.second )
				task.push(nodeInSet);

		task.pop();
	}

	return nullptr;
}

string getOpposite(const string& angle)
{
		 if ("S" == angle) return "N";  else if ("N" == angle)  return "S";
	else if ("W" == angle) return "E";  else if ("E" == angle)  return "W";

	else if ("NE" == angle) return "SW";  else if ("SW" == angle)  return "NE";
	else if ("NW" == angle) return "SE";  else if ("SE" == angle)  return "NW";

	assert(false);
	return string();
}

bool TryAddNode(RelationNode **root, const Relation& relation)
{
	if (!*root)
	{
		*root = new RelationNode();
		(*root)->name = relation.src;
	}

	const auto srcNode = findNodeByName(*root, relation.src, string());
	if ( !srcNode )
		// Sorry, for this task we do not create flat hierarchy. Only root-based
		// It is easy to extend it by vector of roots.
		return false;

	const auto dstNode = findNodeByName(*root, relation.dst, string());
	if ( dstNode )
		// If we have this node already, we just make sure that is is correctly placed and test way back
		return 	findNodeByName(srcNode, relation.dst, relation.angle) 
				|| 
				findNodeByName(dstNode, relation.src, getOpposite(relation.angle));

	const auto dst = new RelationNode();
	dst->name = relation.dst;

	if ( srcNode->nodes.end() == srcNode->nodes.find(relation.angle))
	{
		auto iter = srcNode->nodes.insert(make_pair(relation.angle, set<RelationNode_*>()));
		iter.first->second.insert(dst);
	}
	else
	{
		srcNode->nodes[relation.angle].insert(dst);
	}

	return true;
}

bool isPossible(const vector<Relation>& pairs)
{
	if (pairs.empty())
		return true;

	RelationNode *root = nullptr;
	for (const auto& relation : pairs)
	{
		if (!TryAddNode(&root, relation))
			return false;
	}

	return true;
}

void Google4()
{
	Relation r1 { "p1", "p2", "SE" };
	Relation r2 { "p2", "p3", "SE" };
	Relation r3 { "p3", "p1", "SE" };
	Relation r4 { "p3", "p1", "NW" };

	assert( true == isPossible({ r1, r2 }) );
	assert( false == isPossible({ r1, r2, r3 }) );
	assert( true == isPossible({ r1, r2, r4 }) );
}

- PavPS November 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

class Program
    {
        static void Main(string[] args)
        {
            string test = "p1 SE p2, p2 SE p3, p3 SE p1";
            ThreePoints tp = new ThreePoints(test);
            bool poss = tp.CheckPossible();
            Console.WriteLine("Possible? " + poss);
        }
    }

    public class ThreePoints
    {//Idea: to solve this problem, we assume two points do have the same coordinates and do the evaluation. 
     //These two points all have (0,0) coordinate.Because all points are in relative position, this is fine.
     //Now we only need to enumerate all possible locations for the third point, I call it nonzeropoint. Array nonzeropoints have all values for it.
     //If there is no valid evaluation in any possible value combination of the three points. we output "impossible"
        List<Conditon> conditions = new List<Conditon>();
        Dictionary<string, Point> pointmap = new Dictionary<string, Point>();
        Point[] nonzeropoints = new Point[]{
            new Point(0,1),new Point(0,-1),
            new Point(1,0),new Point(-1,0),
            new Point(1,1),new Point(-1,-1),
            new Point(-1,1),new Point(1,-1),
        };
        public class Point
        {
            public int x;
            public int y;
            public Point(int x, int y){
                this.x=x;
                this.y=y;
            }
        }

        public class Conditon
        {
            public string keyA;
            public string keyB;
            public string Operator;
        }
        public ThreePoints(string formula)
        {
            string[] phrases = formula.Split(',');

            foreach (string phrase in phrases)
            {
                string[] words = phrase.Trim().Split(' ');
                Conditon acondition = new Conditon();
                if (!pointmap.ContainsKey(words[0]))
                {
                    Point apoint = new Point(0,0);
                    pointmap.Add(words[0], apoint);
                }
                acondition.keyA = words[0];
                acondition.Operator = words[1];
                if (!pointmap.ContainsKey(words[2]))
                {
                    Point apoint = new Point(0,0);
                    pointmap.Add(words[2], apoint);
                }
                acondition.keyB = words[2];
                conditions.Add(acondition);
            }
        }

        public bool CheckPossible()
        {
            string[] keys = pointmap.Keys.ToArray();
            foreach (string key in keys)
            {
                if (CheckOneCombination(key))
                {
                    return true;
                }
            }
            return false;
        }

        private bool CheckOneCombination(string NonZeroPoint)
        {
            //non zero point coordinates have the following values:
            // (0,1),(1,1),(1,0), (0,-1), (-1,0),(-1,-1), (1,-1), (-1,1)
            foreach(Point nzpoint in nonzeropoints){
                string[] keys = pointmap.Keys.ToArray();
                foreach (string key in keys)
                {
                    if (key.Equals(NonZeroPoint))
                    {
                        pointmap[key] = nzpoint;
                    }
                    else
                    {
                        pointmap[key]= new Point(0,0);
                    }
                }
                bool conResult = true;
                foreach(Conditon con in conditions){
                    if (!Evaluate(con))
                    {
                        conResult = false;
                        break;
                    }
                }
                if (conResult)
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// Evaluate Point A Operator Point B
        /// </summary>
        /// <param name="a"></param>
        /// <param name="op">N, S, W, E and a combination like NW, NE, SW, SE</param>
        /// <param name="b"></param>
        /// <returns></returns>
        private bool Evaluate(Conditon con)
        {

            Point a = pointmap[con.keyA];
            string op = con.Operator;
            Point b = pointmap[con.keyB];
            if (op.Contains("S")) //point b is on S of point a
            {
                if(a.y <= b.y) return false;
            }
            else if (op.Contains("N")) //point b is on N of point a
            {
                if (a.y >= b.y) return false;
            }
            if (op.Contains("E")) //point b is on E of point a
            {
                if (a.x >= b.x) return false;
            }
            else if (op.Contains("W")) //point b is on W of point a
            {
                if (a.x <= b.x) return false;
            }
            return true;
        }
    }

- C# solution November 10, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

@wws 's idea is intreasting, I just not sure how to merge two nodes. Disjoint set may be a way, we can merge the neighbors of two nodes to their fathors, but other nodes may also point to two nodes who share their father, and I can fingure out an efficient way to merge this condition.
The nearest distance between two nodes cross my mind. If we define a directed graph like this: if x1<x2, then the distance d[x2][x1] = -1, if x1 == x2, d[x1][x2] = d[x2][x1] == 0, y is the same. I use floyd-warshall to get the distance between any two nodes and if there are a circle, the distance of d[i][i] will definite be negative.
I use test cases from @Adi, here is my implementation. Any comment/correction is welcome!

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <sstream>
using namespace std;

const int MAX_V = 102;
const int INF = 100000;

int d[2][MAX_V][MAX_V];

map<string, int> dict;
int mid;
int getId(string &s){
    if(dict.find(s) == dict.end()){
        dict[s] = mid++;
    }
    return dict[s];
}

void handle_input(int a, int b, string &op){
    if(op == "S"){
        d[0][a][b] = d[0][b][a] = 0;
        d[1][b][a] = -1;
    }else if(op == "W"){
        d[1][a][b] = d[1][b][a] = 0;
        d[0][b][a] = -1;
    }else if(op == "N"){
        d[0][a][b] = d[0][b][a] = 0;
        d[1][a][b] = -1;
    }else if(op == "E"){
        d[1][a][b] = d[1][b][a] = 0;
        d[0][a][b] = -1;
    }else if(op == "SW"){
        d[0][b][a] = -1;
        d[1][b][a] = -1;
    }else if(op == "NW"){
        d[0][b][a] = -1;
        d[1][a][b] = -1;
    }else if(op == "SE"){
        d[0][a][b] = -1;
        d[1][b][a] = -1;
    }else if(op == "NE"){
        d[0][a][b] = -1;
        d[1][a][b] = -1;
    }
}

bool floyd_warshall(int G[MAX_V][MAX_V]){ 
    for(int k=0;k<mid;++k)
        for(int i=0;i<mid;++i)
            for(int j=0;j<mid;++j){
                G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
            }
    for(int i=0;i<mid;++i){
        if(G[i][i]<0)   return false;
    }
    return true;
}

void init(){
    for(int i=0;i<MAX_V;++i)  for(int j=0;j<MAX_V;++j){
        d[0][i][j] = d[1][i][j] = i == j?0:INF;
    }
}

void solve(vector<string> &input){
    string p1, p2, op;
    stringstream stream;
    mid = 0;
    init();
    for(int i=0;i<input.size();++i){
        stream.clear();
        //stream.str("");
        stream<<input[i];
        stream>>p1>>op>>p2;
        int a = getId(p1);
        int b = getId(p2);
        handle_input(a, b, op); 
    }
    if(!floyd_warshall(d[0])||!floyd_warshall(d[1])){
        cout<<"impossible"<<endl;
    }else{
        cout<<"possible"<<endl;
    }
}

int main(){
    vector<string> input;
    input.push_back("p1 N p3");
	input.push_back("p1 NW p5");
	input.push_back("p1 NW p2");
	input.push_back("p2 SW p6");
	input.push_back("p4 SW p6");
	input.push_back("p3 W p2");
	input.push_back("p4 S p1");
	input.push_back("p5 E p4");
	input.push_back("p1 W p6");
	input.push_back("p6 NE p5");//possible
    input.push_back("p7 N p2");
    input.push_back("p7 SE p6");//imposible
    solve(input);
}

/*
                p7?
          ________________
          | p1 |    | p6 |
		  _________________
		  | p3 | p2 |    |
		  ________________
		  | p4 | p5 |    |
		  ________________
          */

- Mr.Giraffe November 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include <iostream> 
#include <vector> 
#include <sstream>
#include <unordered_map>
#include <string>
#include <tuple>
using namespace std; 

bool pointsPossible(vector<string> input)
{
vector<tuple<string,string,int,int> > allinone;
for (int i=0;i<input.size();++i)
{
	istringstream ss;
	ss.str(input[i]);
	string p1,dir,p2;
	ss>>p1>>dir>>p2;
	string dirstr[8]={"S","W","N","E","SW","NW","SE","NE"};
	int x[8]={0,-1,0,1,-1,-1,1,1};
	int y[8]={-1,0,1,0,-1,1,-1,1};
	int pos;
	for (pos=0;pos<8 && dirstr[pos]!=dir;++pos) {}
	auto cur=make_tuple(p1,p2,x[pos],y[pos]);
	allinone.push_back(cur);
	for (int i=0;i<allinone.size();++i)
	{
	if (get<2>(allinone[i])==get<2>(cur) && get<3>(allinone[i])==get<3>(cur))
	{
	if (get<1>(allinone[i])==get<0>(cur))
	{allinone.push_back(make_tuple(get<0>(allinone[i]),get<1>(cur),get<2>(cur),get<3>(cur)));}	
	if (get<0>(allinone[i])==get<1>(cur))
	{allinone.push_back(make_tuple(get<0>(cur),get<1>(allinone[i]),get<2>(cur),get<3>(cur)));}	
	}
	}

	for (int i=0;i<allinone.size();++i)
	{
	cout<<get<0>(allinone[i])<<" "<<get<1>(allinone[i])<<" "<<get<2>(allinone[i])<<" "<<get<3>(allinone[i])<<" "<<endl;
	}

	for (int i=0;i<allinone.size();++i)
	{
	if (get<0>(allinone[i])==get<0>(cur) && get<1>(allinone[i])==get<1>(cur) && (get<2>(allinone[i])!=get<2>(cur) || get<3>(allinone[i])!=get<3>(cur))) return false;
	if (get<0>(allinone[i])==get<1>(cur) && get<1>(allinone[i])==get<0>(cur) && (get<2>(allinone[i])!=-get<2>(cur) || get<3>(allinone[i])!=-get<3>(cur))) return false;
	}
	cout<<endl;
}
return true;
}

int main()
{
string s1="p1 S p2";
string s2="p2 S p3";
string s5="p3 S p1";
string s3="p3 N p4";
string s4="p4 S p2";
vector<string> input;
input.push_back(s1);
input.push_back(s2);
input.push_back(s3);
input.push_back(s4);
input.push_back(s5);
cout<<pointsPossible(input)<<endl;
return 0;

}

- czhao86 November 13, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

First solution is right. The problem can be represented as a topologycal sorting where nodes represents coordinates.

- Andy November 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

enum DIRECTS{S=4, W=3, N=2, E=1, SW=12, NW=6, SE=9, NE=3};
typedef unsigned char Byte;
struct Data{
    int i;
    DIRECTS op;
    int j;
    Data(int ii, DIRECTS oop, int jj):i(ii), op(oop), j(jj){}
};

bool validPoints(vector<Data> &dset){
    if(dset.empty()) return true;
    unordered_map<int, Byte> hmap;
    for(auto &e:dset){
        if(hmap.find(e.i)==hmap.end())
            hmap[e.i] = 0;
        Byte j = hmap[e.i] ^ e.op;
        if(hmap.find(e.j)!=hmap.end() && hmap[e.j]&j!=0)
            return false;
        hmap[e.j] = j;
    }
    return true;
}

- simon.zhangsm December 21, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Here is an O(nlogn). Basically, do a merge sort but count inversions while merging.

package com.algo;

public class CountInversions {

	public static void main(String[] args) {

		int[] values = { 11, 4, 5, 8, 1, 3, 25 };

		int inversions = countInversions(values);
		System.out.println(inversions);

	}

	private static int countInversions(int[] values) {
		return countInversions(values, 0, values.length);
	}

	private static int countInversions(int[] values, int start, int end) {

		if (start == end || start + 1 == end) {
			return 0;
		} else {
			int mid = start + (end - start) / 2;
			return countInversions(values, start, mid) + countInversions(values, mid, end)
					+ merge(values, start, mid, mid, end);
		}

	}

	// 7, 11, 11, 16
	// 7,8,9,10,11,12,13,14,15
	// 11 - 7 + 16 - 11
	private static int merge(int[] values, int start1, int end1, int start2, int end2) {

		int inversions = 0;

		int length1 = end1 - start1;
		int length2 = end2 - start2;

		int[] mergedValues = new int[length1 + length2];

		int p1 = start1;
		int p2 = start2;

		int m = 0;
		while (p1 < end1 && p2 < end2) {

			if (values[p2] < values[p1]) {
				mergedValues[m] = values[p2];
				inversions += end1 - p1;
				p2++;
			} else {
				mergedValues[m] = values[p1];
				p1++;
			}

			m++;
		}

		while (p1 < end1) {
			mergedValues[m] = values[p1];
			m++;
			p1++;
		}

		while (p2 < end2) {
			mergedValues[m] = values[p2];
			m++;
			p2++;
		}

		m = 0;
		for (int i = start1; i < end2; i++) {
			values[i] = mergedValues[m];
			m++;
		}

		return inversions;
	}

}

- LetMeKnow November 03, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry, I posted to the wrong question. This code is for finding the number of inversions.

- LetMeKnow November 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Based on wws's comment, we can simulate the whole process:

For every maximum connected subgraph:
We random select a point and assign its position (0,0)
For every new point that is connected to this point, calculate their positions.
Select the new point, and for every point that is connected to this, if the point has position, check whether it is right, otherwise, calculate it and keep it.
Do this process until all the edges has been checked.

Example:
p0 W p1, p1 SW p2, p2 SE p3, p3 NE p0,p6 W p7
We can easily judge that (p0,p1,p2,p3) and (p6,p7) are maximum connected subgraph.
For (p0,p1,p2,p3):
We assign p0 (0,0)
p0 W p1 => p1 (1,0)
p1 SW p2 => p2 (2,1)
p2 SE p3 => p3(1,2)
p3 NE p0 => we know p0, so check whether p3 NE p0 => False

Of course sometimes when we select p0 and assign the coordinator, but edges connected to p0 would be mentioned later. So we'd better store all the connected points for every point.

vector<PointRel> v[N]; //store those point relation connect to point i
Point point[N];     // store position of the point i
bool pos[N];        // whether we know the position of point i
bool tag[N];        //whether point i has been checked 
stack<Point> s;
for(i=0;i<N;i++)
{
  if(tag[i])continue; //the related connected subgraph has been checked
  point[i]=(0,0)
  pos[i]=true
  s.push(i)
  while(!s.empty()){
    x = s.pop()
    for(j=0;j<v[x].size();j++)
       if(pos[v[x][j]] and !checkRelation(x,v[x][j]))return false
       else{ point[v[x][j]]=calPos(x,v[x][j]); pos[v[x][j]]=true;s.push(v[x][j]);}
    tag[i]=true
  }
}
return true

- Zhangwen November 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Hi Zhangwen,

I dont think this will work. The problem is that lets say we have this:

p1 SE p2; p2 SE p3; p3 NW p4; p4 SE p1
p1 SE p2; p2 SE p3; p3 NW p4; p4 NW p1

are both possible since we do not know the exact distance between two points as per the question.

Please correct me if I am wrong.

- Rishav November 04, 2014 | Flag


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