Saturday, November 8, 2014

A C# program Test - Area of Intersection of Rectangles

I had been through a online test with a timer reminding me of the time left, which I think I could not complete the actual test on time, though the demo one was well to be fine within the time given. It was a good school exercise to develop algorithm and flow.

Problem (Demo one): 
A zero-indexed array A consisting of N integers is given. An equilibrium index of this array is any integer P such that 0 ≤ P < N and the sum of elements of lower indices is equal to the sum of elements of higher indices, i.e.
A[0] + A[1] + ... + A[P−1] = A[P+1] + ... + A[N−2] + A[N−1].
Sum of zero elements is assumed to be equal to 0. This can happen if P = 0 or if P = N−1.
For example, consider the following array A consisting of N = 8 elements:
  A[0] = -1
  A[1] =  3
  A[2] = -4
  A[3] =  5
  A[4] =  1
  A[5] = -6
  A[6] =  2
  A[7] =  1
P = 1 is an equilibrium index of this array, because:
•A[0] = −1 = A[2] + A[3] + A[4] + A[5] + A[6] + A[7]
P = 3 is an equilibrium index of this array, because:
•A[0] + A[1] + A[2] = −2 = A[4] + A[5] + A[6] + A[7]
P = 7 is also an equilibrium index, because:
•A[0] + A[1] + A[2] + A[3] + A[4] + A[5] + A[6] = 0
and there are no elements with indices greater than 7.
P = 8 is not an equilibrium index, because it does not fulfill the condition 0 ≤ P < N.
Write a function:
               
class Solution
{
    public int solution(int[] A);
}

that, given a zero-indexed array A consisting of N integers, returns any of its equilibrium indices. The function should return −1 if no equilibrium index exists. For example, given array A shown above, the function may return 1, 3 or 7, as explained above.
Assume that:
•N is an integer within the range [0..100,000];
•each element of array A is an integer within the range [−2,147,483,648..2,147,483,647].
Complexity:
•expected worst-case time complexity is O(N);
•expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.

Solution: 
using System;
using System.Collections.Generic;
using System.Linq;
class Solution
   {
       public static int solution(int[] A)
       {
           // write your code in C# 5.0 with .NET 4.5 (Mono)
           int result = -1;
           var eqIdx = from i in Enumerable.Range(0, A.Length)
                       select new
                       {
                           Index = i,
                           LSum = new Func&lt;int&gt;(() =&gt;
                           {
                               int sum = 0;
                               for (int x = 0; x &lt; i; x++)
                                   sum += A[x];
                               return sum;
                           })(),
                           RSum = new Func&lt;int&gt;(() =&gt;
                           {
                               int sum = 0;
                               for (int x = i + 1; x &lt; A.Length; x++)
                                   sum += A[x];
                               return sum;
                           })()
                       };
           if(eqIdx!=null &amp;&amp; eqIdx.Count()&gt;0 )
               result=(from x in eqIdx
                      where x.LSum == x.RSum
                      select x.Index).ToList()[0];
           return result;
       }
   }

Problem (Actual):
A rectangle is called rectilinear if its edges are all parallel to coordinate axes. Such a rectangle can be described by specifying the coordinates of its lower-left and upper-right corners.
Write a function
class Solution
{
    public int solution(int K, int L, int M, int N, int P, int Q, int R, int S);
}

That, given eight integers representing two rectilinear rectangles ( one with lower-left corner(K,L) and upper-right corner(M, N) and another with Lower-Left corner(P,Q) and upper-right corner(R,S)), returns the area of the sum of the rectangles. If the rectangles interest, the area of their intersection should be counted only once. The function should return -1 if the area of the sum exceeds 2,147, 483,647.
For example, given the integers:
K=-4 L=1 M=2 N=6
P=0 Q=-1 R=4 S=3

The function should return 42.
The area of the first Rectangle is 30, the area of the second is 16 and the area of the intersection is 4.

Assume that
 - K,L,M,N,P,Q,R,S are integers within the range [-2147483648, 2147483647]
 - K < M
 - L < N
 - P < R
 - Q < S

Complexity
 - Expected worst-case time-complexity is O(1).
 - Expected worst-case space-complexity is O(1).

Solution: 
Since there was no way to import other namespaces for  CLR provided classes like System.Drawing.Rectangle or System.Windows.Rect, It is better to write a custom class to handle the rectangular functionality for intersection and calculation of Area.

using System;
class Solution
    {
        public int solution(int K, int L, int M, int N, int P, int Q, int R, int S)
        {
            // write your code in C# 5.0 with .NET 4.5
            int result=0;
            Rect r1 = new Rect(K, L, M, N);
            int AreaR1 = r1.Area;
            Rect r2 = new Rect(P, Q, R, S);
            int AreaR2 = r2.Area;
            Rect r3 = Rect.Intersect(r1, r2);
            int AreaR3 = 0;
            if (r3 != null)
            {
                AreaR3 = r3.Area;
            }
            result = (AreaR1 + AreaR2 - AreaR3);
            return result;
        }
    }
class Rect
    {
        public int Left { getset; }
        public int Top { getset; }
        public int Right { getset; }
        public int Bottom { getset; }
        public int Width { getset; }
        public int Height { getset; }
        public int Area { getset; }
 
        public Rect(int K, int L, int M, int N)
        {
            Left = K;
            Bottom = L;
            Right = M;
            Top = N;
            Width = Right - Left;
            Width=Width < 0 ? (~Width + 1) : Width;
            Height = Top - Bottom;
            Height = Height < 0 ? (~Height + 1) : Height;
            Area = Width * Height;
        }
        public static Rect Intersect(Rect r1, Rect r2)
        {
            bool IsIntersect=true;
            Rect r3=null;
            int P=0, Q=0, R=0, S=0;
            if((r2.Right<r1.Left || r2.Left>r1.Right) ||
                (r2.Bottom>r1.Top || r2.Top<r1.Bottom ))
                    IsIntersect=false;
            if(IsIntersect)
            {
                P = r2.Left > r1.Left ? r2.Left : r1.Left;
                R = r2.Right > r1.Right ? r1.Right : r2.Right;
                Q= r2.Bottom > r1.Bottom ? r2.Bottom:r1.Bottom;
                S= r2.Top >r1.Top ? r1.Top : r2.Top;
                r3=new Rect(P,Q,R,S);
            }
            return r3;
        }
    }

Alternative solution using the class System.Drawing.Rectangle.

using System;
    using System.Drawing;
    class Solution
    {
        public int solution(int K, int L, int M, int N, int P, int Q, int R, int S)
        {
            // write your code in C# 5.0 with .NET 4.5 
            int result=0;
            int width = 0, height = 0;
            width = M - K;
            height = N - L;
            Rectangle rect1 = new Rectangle(K, -N, width, height);
            width = R - P;
            height = S - Q;
            Rectangle rect2 = new Rectangle(P, -S, width, height);
            Rectangle rectInterset = Rectangle.Intersect(rect1, rect2);
            int AreaRect1 = rect1.Width * rect1.Height;
            AreaRect1 = AreaRect1 < 0 ? (~AreaRect1 + 1) : AreaRect1;
            int AreaRect2 = rect2.Width * rect2.Height;
            AreaRect2 = AreaRect2 < 0 ? (~AreaRect2 + 1) : AreaRect2;
 
            int AreaIntersect = 0;
            if (!rectInterset.IsEmpty)
            {
                AreaIntersect = rectInterset.Width * rectInterset.Height;
                AreaIntersect = AreaIntersect < 0 ? (~AreaIntersect + 1) : AreaIntersect;
            }
 
            result = AreaRect1 + AreaRect2 - AreaIntersect;
            return Convert.ToInt32(result);
        }
    }

3 comments:

Anonymous said...

Just geious

Unknown said...

how to check area is exceeding Int.max_value or not and return -1 if exceeds that max integer range limit.

M.Pankaj Arun said...

what if the rectangles don't overlaps .. then we have to return Sum of the areas of two rectangles..