finding the number of integer points under a triangle, square and circle - math

for circle i have tried to check for all points within radius distance from center.For square, i test for all points from bottom-left-corner to upper-right-corner and for triangle i test the signs of determinants as suggested here. I get correct answer while i enter individual values i.e either 1 cirlce or 1 square or 1 triangle , but not when there are >1 of them. E.g for the case:
C 10 10 3
S 9 8 4
T 7 9 10 8 8 10
where C is circle, S is square and T is triangle,and (10,10) is center of circle with radius 3. (9,8) is the left-most corner of square of side 4 and (7,9),(10,8) and (8,10) are the three vertices of the triangle , the total distinct points covered by them is 34 but i am getting 37.
Here's what i've tried:
typedef pair<int,int> point;
set<point>myset;
set<point>::iterator it;
int findDeter(int x1,int y1,int x2,int y2,int x0,int y0)
{
int ret = x1*(y2-y0)-y1*(x2-x0)+(x2*y0-x0*y2)
-x2*(y1-y0)+y2*(x1-x0)-(x1*y0-x0*y1)
+x0*(y1-y2)-y0*(x1-x2)+(x1*y2-x2*y1);
return ret;
}
bool sameSign(int x, int y)
{
if(x==0||y==0)
return true;
return (x >= 0) ^ (y < 0);
}
int main()
{
int t,i,j,k,n;
int x,y,r,x1,y1,len;
int xmax,ymax,xmin,ymin;
int D1,D2,D3;
int ax,ay,bx,by,cx,cy;
char shape,dump;
scanf("%d",&t);
while(t--)
{
myset.clear();
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%c",&dump);
scanf("%c",&shape);
if(shape=='C')
{
scanf("%d %d %d",&x,&y,&r);
for(j=x;j<=x+r;j++)
{
for(k=y;k<=y+r;k++)
{
point p(j,k);
myset.insert(p);
}
}
for(j=x-r;j<x;j++)
{
for(k=y-r;k<y;k++)
{
point p(j,k);
myset.insert(p);
}
}
}
else if(shape=='S')
{
scanf("%d %d %d",&x1,&y1,&len);
for(j=x1;j<=x1+len;j++)
{
for(k=y1;k<=y1+len;k++)
{
point p(j,k);
myset.insert(p);
}
}
}
else
{
//printf("here\n");
scanf("%d %d %d %d %d %d",&ax,&ay,&bx,&by,&cx,&cy);
/*a1=ax;a2=ay;
b1=bx;b2=by;
c1=cx;c2=cy;*/
xmax = max(ax,max(bx,cx));
ymax = max(ay,max(by,cy));
xmin = min(ax,min(bx,cx));
ymin = min(ay,min(by,cy));
/*for each point P check if sum(the determinants PAB,PAC and PBC have the same signs)*/
for(j=xmin;j<=xmax;j++)
{
for(k=ymin;k<=ymax;k++)
{
D1 = findDeter(ax,ay,bx,by,j,k);
//printf("D1 : %d\n",D1);
D2 = findDeter(bx,by,cx,cy,j,k);
//printf("D2 : %d\n",D2);
D3 = findDeter(cx,cy,ax,ay,j,k);
//printf("D3 : %d\n",D3);
if(sameSign(D1,D2)&&sameSign(D2,D3)&&sameSign(D1,D3))
{
//printf("here\n");
point p(j,k);
myset.insert(p);
}
}
}
}
}
printf("%d\n",myset.size());
}
return 0;
}

After refactoring your code heavily so that it was clearer to me what is going on - I'd say the error is in the circle code. I've included the complete refactored code below but the troublesome section amount s to this:
struct Circle
{
int x;
int y;
int r;
void add_covered_points( set<points> & pts ) const
{
for(int j=x;j<=x+r;j++)
{
for(int k=y;k<=y+r;k++)
{
pts.insert(point(j,k));
}
}
for(int j=x-r;j<x;j++)
{
for(int k=y-r;k<y;k++)
{
pts.insert(point(j,k));
}
}
}
};
This seems to add points from two rectangular sections, one above and the other below the center of the circle. I'd expect the code to look more like this:
void add_covered_points( set<points> & pts ) const
{
for(int j=-r;j<=+r;j++)
{
for(int k=-r;k<=+r;k++)
{
if (j*j + k*k < r*r )
{
pts.insert(point(x+j,x+k));
}
}
}
}
Heres the complete refactored case for your reference
typedef pair<int,int> point;
int findDeter(int x1,int y1,int x2,int y2,int x0,int y0)
{
int ret = x1*(y2-y0)-y1*(x2-x0)+(x2*y0-x0*y2)
-x2*(y1-y0)+y2*(x1-x0)-(x1*y0-x0*y1)
+x0*(y1-y2)-y0*(x1-x2)+(x1*y2-x2*y1);
return ret;
}
bool sameSign(int x, int y)
{
if(x==0||y==0)
return true;
return (x >= 0) ^ (y < 0);
}
struct Circle
{
int x;
int y;
int r;
void add_covered_points( set<points> & pts ) const
{
for(int j=x;j<=x+r;j++)
{
for(int k=y;k<=y+r;k++)
{
pts.insert(point(j,k));
}
}
for(int j=x-r;j<x;j++)
{
for(int k=y-r;k<y;k++)
{
pts.insert(point(j,k));
}
}
}
};
struct Square
{
int x1,y1,len;
void add_covered_points( set<points> & pts ) const
{
for(int j=x1;j<=x1+len;j++)
{
for(int k=y1;k<=y1+len;k++)
{
myset.insert(point(j,k));
}
}
}
};
struct Triangle
{
int ax,ay,bx,by,cx,cy;
void add_covered_points( set<points> & pts ) const
{
int xmax = max(ax,max(bx,cx));
int ymax = max(ay,max(by,cy));
int xmin = min(ax,min(bx,cx));
int ymin = min(ay,min(by,cy));
/*for each point P check if sum(the determinants PAB,PAC and PBC have the same signs)*/
for(int j=xmin;j<=xmax;j++)
{
for(int k=ymin;k<=ymax;k++)
{
int D1 = findDeter(ax,ay,bx,by,j,k);
int D2 = findDeter(bx,by,cx,cy,j,k);
int D3 = findDeter(cx,cy,ax,ay,j,k);
if(sameSign(D1,D2)&&sameSign(D2,D3)&&sameSign(D1,D3))
{
pts.insert(point(j,k));
}
}
}
}
};
int main()
{
set<point>myset;
int t;
scanf("%d",&t);
while(t--)
{
myset.clear();
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
char dump;
char shape;
scanf("%c",&dump);
scanf("%c",&shape);
if(shape=='C')
{
Circle c;
scanf("%d %d %d",&c.x,&c.y,&c.r);
c.add_covered_points( myset );
}
else if(shape=='S')
{
Square s;
scanf("%d %d %d",&s.x1,&s.y1,&s.len);
s.add_covered_points( myset );
}
else
{
Triangle t;
int ax,ay,bx,by,cx,cy;
scanf("%d %d %d %d %d %d",&t.ax,&t.ay,&t.bx,&t.by,&t.cx,&t.cy);
t.add_covered_points( myset );
}
}
}
return 0;
}

Pick's theorem is suitable for counting integer points in the interior of simple polygons with integer vertices.
Here we can see solution for circles.

Related

Stuck at solving leetcode Q5 using C [=34==ERROR: AddressSanitizer]

Please excuse for my massy code. This was best I could do.
I have been solving leetcode Q5 for a while; however, I couldn't solve it. This is the closest answer I have got.
I think it's acting correctly in terms of showing outputs. But has a runtime error when
let s = "tscvrnsnnwjzkynzxwcltutcvvhdivtmcvwdiwnbmdyfdvdiseyxyiiurpnhuuufarbwalzysetxbaziuuywugfzzmhoessycogxgujmgvnncwacziyybryxjagesgcmqdryfbofwxhikuauulaqyiztkpgmelnoudvlobdsgharsdkzzuxouezcycsafvpmrzanrixubvojyeuhbcpkuuhkxdvldhdtpkdhpiejshrqpgsoslbkfyraqbmrwiykggdlkgvbvrficmiignctsxeqslhzonlfekxexpvnblrfatvetwasewpglimeqemdgdgmemvdsrzpgacpnrbmomngjpiklqgbbalzxiikacwwzbzapqmatqmexxqhssggsyzpnvvpmzngtljlrhrjbnxgpcjuokgxcbzxqhmitcxlzfehwfiwcmwfliedljghrvrahlcoiescsbupitckjfkrfhhfvdlweeeverrwfkujjdwtcwbbbbwctwdjjukfwrreveeewldvfhhfrkfjkctipubscseioclharvrhgjldeilfwmcwifwhefzlxctimhqxzbcxgkoujcpgxnbjrhrljltgnzmpvvnpzysggsshqxxemqtamqpazbzwwcakiixzlabbgqlkipjgnmombrnpcagpzrsdvmemgdgdmeqemilgpwesawtevtafrlbnvpxexkeflnozhlsqexstcngiimcifrvbvgkldggkyiwrmbqaryfkblsosgpqrhsjeiphdkptdhdlvdxkhuukpcbhueyjovbuxirnazrmpvfascyczeuoxuzzkdsrahgsdbolvduonlemgpktziyqaluuaukihxwfobfyrdqmcgsegajxyrbyyizcawcnnvgmjugxgocysseohmzzfguwyuuizabxtesyzlawbrafuuuhnpruiiyxyesidvdfydmbnwidwvcmtvidhvvctutlcwxznykzjwnnsnrvcst"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int is_palindrome(char * s);
void get_substring(const char *str, char *substr, int start, int end);
char * longestPalindrome(char * s){
int strlength = strlen(s);
int end = strlength - 1;
int start = 0;
char substr[1000];
char *longstr = (char *)malloc(1000 * sizeof(char));
strcpy(longstr, "");
while (start <= end)
{
get_substring(s, substr, start, end);
// printf("%s\n", substr);
if (is_palindrome(substr) > strlen(longstr))
{
// printf("UPDATE : %s\n", substr);
strcpy(longstr, substr);
}
if (end == start)
{
start++;
end = strlength - 1;
}
else
{
end--;
}
}
// printf("LONG : %s", longstr);
return longstr;
}
void get_substring(const char *str, char *substr, int start, int end) {
int length = end - start + 1;
strncpy(substr, str + start, length);
substr[length] = '\0';
}
int is_palindrome(char * s){
int length = strlen(s);
int mid = length/2;
if (length % 2 == 0)
{
// printf("EVEN : %d\n", mid);
mid--;
int upperptr = mid+1;
int i = 0;
if (s[mid] != s[upperptr])
{
// printf("Returning FALSE [0]\n");
return 0;
}
while (mid-i >= 0 && upperptr+i <= length)
{
// printf("%c and %c and mid is %c\n", s[mid-i], s[upperptr+i], s[mid]);
if (s[mid-i] != s[upperptr+i])
{
// printf("Returning FALSE [1]\n");
return 0;
}
i++;
}
}
else
{
// printf("ODD: %d\n", mid+1);
int i = 0;
while (mid-i >= 0 && mid+i <= length)
{
// printf("%c and %c and mid is %c\n", s[mid-i], s[mid+i], s[mid]);
if (s[mid-i] != s[mid+i])
{
// printf("Returning FALSE [2]\n");
return 0;
}
i++;
}
}
// printf("Returning TRUE\n");
return length;
}
I had difficulties returning a local string. then found out that local string value can't be returned and has to be dynamically malloced and the pointer has to be returned.
So I fixed it (somehow, if it is right). But I reckon this is causing different - even harder - problems that I can't manage.

TLE on UVA 10776 - Determine The Combination

I tried this problem by backtracking and did some optimization, though I am getting TLE. what further optimization can I do on this code?
Abridged problem statement - Task is to print all different r combinations of a string s (a r combination of a string s is a collection of exactly r letters from different positions in s).There may be different permutations of the same combination; consider only the one that has its r
characters in non-decreasing order. If s = "abaa" and s = 3.Then output should be (aaa,aab).
My code(in c)
int compare_chars(const void* a, const void* b);
char s[50];
int len;
int r ;
char combination[50];
void combinate(int index,int at)
{
if(at == r)
{
combination[at] = '\0';
puts(combination);
return ;
}
int i = index+1;
for ( ; i <= len-r+at ;)
{
char temp = s[I];
combination[at] = temp;
combinate(i,at+1);
while(s[i] == temp and i <= len-r+at)
i++;
}
return ;
}
int solve()
{
while ((scanf("%s %i",s,&r)) == 2)
{
len = strlen(s);
if(len == r)
{
printf("%s\n",s);
continue;
}
qsort(s,len,sizeof(char),compare_chars);
combinate(-1,0);
}
return 0;
}
int main()
{
int a = 1;
int t = 1;
while (a <= t)
{
int kk = solve();
}
return 0;
}
int compare_chars(const void* a, const void* b)
{
char arg1 = *(const char*)a;
char arg2 = *(const char*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}

Next greater element using recursion

I have seen the problem of finding the next greater element for each element in an array and it can be easily solved using monotonic stack. But can it be solved using recursion?
For the input array [4, 5, 2, 25], the next greater elements for each element are as follows.
4 --> 5
5 --> 25
2 --> 25
25 --> -1
Using stack
#include <bits/stdc++.h>
using namespace std;
void printNGE(int arr[], int n)
{
stack<int> s;
int res[n];
for (int i = n - 1; i >= 0; i--) {
if (!s.empty()) {
while (!s.empty() && s.top() <= arr[i]) {
s.pop();
}
}
res[i] = s.empty() ? -1 : s.top();
s.push(arr[i]);
}
for (int i = 0; i < n; i++)
cout << arr[i] << " --> " << res[i] << endl;
}
int main()
{
int arr[] = { 11, 13, 21, 3 };
int n = sizeof(arr) / sizeof(arr[0]);
printNGE(arr, n);
return 0;
}
long long fun(long long i,vector<long long>&v,long long par)
{
if(i==v.size())
return -1;
if(v[i]>v[par])
{
return v[i];
}
return fun(i+1,v,par);
}
void solve(long long i,vector<long long>&v,vector<long long>&ans)
{
if(i==v.size())return ;
solve(i+1,v,ans);
long long temp=fun(i+1,v,i);
ans[i]=temp;
}
vector<long long> nextLargerElement(vector<long long> v, int n)
{
vector<long long>ans(n,-1);
solve(0,v,ans);
return ans;
}

Maximum Xor between Two Arrays | Trie

Given two integer vectors A and B, we have to pick one element from each vector such that their xor is maximum and we need to return this maximum xor value from the function int Solution::solve(vector &A, vector &B).
I found out that the code below is not passing all the test cases when I'm declaring and initializing the head pointer globally right beneath the class Trienode. Why is that?
Code
class Trienode
{
public:
Trienode* left;
Trienode* right;
Trienode()
{
left=0;
right=0;
}
};
// Trienode* head = new Trienode;
int Max_Xor_Pair(Trienode* head, vector<int> B)
{
int n=B.size();
int max_xor=INT_MIN;
for(int i=0; i<n; i++)
{
int pair1 = B[i];
int pair2 = 0;
Trienode* curr=head;
for(int j=31; j>=0; j--)
{
int bit = (pair1>>j)&1;
if(bit)
{
if(curr->left)
curr=curr->left;
else
{
curr=curr->right;
pair2 += pow(2,j);
}
}
else
{
if(curr->right)
{
curr=curr->right;
pair2 += pow(2,j);
}
else
curr=curr->left;
}
}
int curr_xor = pair1 ^ pair2;
max_xor = max(max_xor, curr_xor);
}
return max_xor;
}
void Insert(Trienode* head, int num)
{
Trienode* curr=head;
for(int i=31; i>=0; i--)
{
int x = num;
int bit= (x>>i)&1;
if(bit)
{
if(!curr->right)
{
Trienode* temp = new Trienode;
curr->right=temp;
}
curr=curr->right;
}
else
{
if(!curr->left)
{
Trienode* temp = new Trienode;
curr->left=temp;
}
curr=curr->left;
}
}
}
int Solution::solve(vector<int> &A, vector<int> &B) {
Trienode* head = new Trienode;
for(int x:A)
Insert(head,x);
return Max_Xor_Pair(head,B);
}
Sample Input
A : [ 15891, 6730, 24371, 15351, 15007, 31102, 24394, 3549, 19630, 12624, 24085, 19955, 18757, 11841, 4967, 7377, 13932, 26309, 16945, 32440, 24627, 11324, 5538, 21539, 16119, 2083, 22930, 16542, 4834, 31116, 4640, 29659, 22705, 9931, 13978, 2307, 31674, 22387, 5022, 28746, 26925, 19073, 6271, 5830, 26778, 15574, 5098, 16513, 23987, 13291, 9162 ]
B : [ 18637, 22356, 24768, 23656, 15575, 4032, 12053, 27351, 1151, 16942 ]
When head is a global variable, and you don't have this line in Solution::solve:
Trienode* head = new Trienode;
...then head will retain its value after the first test case has finished, and so the second test case will not start with an empty tree. Each test case will add more nodes to the one tree. Of course this means that, except for the first test case, the tree rooted by head is not the intended tree.
To make the version with the global variable work, reset it in Solution::solve:
head->left = head->right = nullptr;
BTW, you should also initialise these members with nullptr (instead of 0) in your TrieNode constructor. This better reflects the intent.
You can also go with this approach:
Code:
struct Node {
Node* left;
Node* right;
};
class MaxXorHelper{
private : Node* root;
public :
MaxXorHelper() {
root = new Node();
}
void addElements(vector<int> &arr) {
for(int i=0; i<arr.size(); i++) {
Node* node = root;
int val = arr[i];
for(int j=31; j>=0; j--) {
int bit = (val >> j) & 1;
if(bit == 0) {
if(!node->left) {
node->left = new Node();
}
node = node->left;
}
else {
if(!node->right) {
node->right = new Node();
}
node = node->right;
}
}
}
}
int findMaxXor(vector<int> &arr) {
int maxXor = INT_MIN;
for(int i=0; i<arr.size(); i++) {
Node* node = root;
int val2 = 0;
int val1 = arr[i];
for(int j=31; j>=0; j--) {
int bit = (val1 >> j) & 1;
if(bit == 0) {
if(node->right) {
val2 |= (1 << j);
node = node->right;
} else{
node = node->left;
}
}
else {
if(node->left) {
node = node->left;
} else{
val2 |= (1 << j);
node = node->right;
}
}
}
int curXor = val1 ^ val2;
maxXor = max(maxXor, curXor);
}
return maxXor;
}
};
int Solution::solve(vector<int> &A, vector<int> &B) {
MaxXorHelper helper;
helper.addElements(A);
return helper.findMaxXor(B);
}

Why am I getting a run-time error on school server but not on big servers like HackerEarth or HackerRank for this minimum spanning tree code?

I got a homework where I needed to wright a program to find MST of a graph. I tried running it on the school server but I get a run-time error. On big servers like HackerEarth or HackerRank, however, I got correct answers on all test cases. The boundary for the number of edges and vertices is 100000 and for the weight of an edge 10000. Vertices are labeled from 0 to n.
Here is my code:
#include <stdio.h>
#include <algorithm>
using namespace std;
class Edge
{
public:
int x, y;
long long w;
bool operator<(const Edge& next) const;
};
bool Edge::operator<(const Edge& next) const
{
return this->w < next.w;
}
class DisjointSet
{
public:
int parent, rank;
};
DisjointSet set[100100];
Edge edges[100100];
int findWithPathCompression(int x)
{
if(set[x].parent != x)
set[x].parent = findWithPathCompression(set[x].parent);
return set[x].parent;
}
bool unionByRank(int x1, int y1)
{
int x = findWithPathCompression(x1);
int y = findWithPathCompression(y1);
if(x == y)
return false;
if(set[x].rank > set[y].rank)
set[y].parent = x;
else if(set[y].rank > set[x].rank)
set[x].parent = y;
else
{
set[y].parent = x;
set[x].rank++;
}
return true;
}
int main()
{
int n, m, e = 0, c = 0;
long long r = 0;
scanf("%d %d",&n,&m);
for(int i = 0; i <= n; i++)
{
set[i].parent = i;
set[i].rank = 1;
}
for(int i = 0; i < m; i++)
{
scanf("%d %d %lld",&edges[i].x,&edges[i].y,&edges[i].w);
edges[i].x;
edges[i].y;
}
sort(edges,edges + m);
while(e != n - 1)
{
if(unionByRank(edges[c].x,edges[c].y))
{
r += edges[c].w;
e++;
}
c++;
}
printf("%lld\n",r);
}

Resources