Bresenham line drawing fails for a particular co-ordinate? - c++

The code works fine first call of positionGenerator(1046,1623,750,1290); but runs into an infinite loop in the second call positionGenerator(1046,1623,375,810); .
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
void positionGenerator(int xa,int ya, int xb,int yb)
{
int dx=0,dy=0,x_inc=0,y_inc=0,m=0,p=0,i=0;
dx=xb-xa;
dy=yb-ya;
m=dy/dx;
x_inc=dx>0?2:-2;
y_inc=dy>0?2:-2;
cout<<"x_incr"<<x_inc<<"y_incr"<<y_inc<<endl;
cout<<"dx"<<dx<<"dy"<<dy<<endl;
dx=abs(dx);
dy=abs(dy);
cout<<"dx"<<dx<<"dy"<<dy<<endl;
p=(2*dy)-(dx);
for(i=1;((xa!=xb) && (ya!=yb));i++)
{
if(p>0)
{
xa=xa+x_inc;
ya=ya+y_inc;
p=p+(2*dy)-(2*dx);
}
else
{
if(m<1)
{
xa=xa+x_inc;
p=p+(2*dy);
}
else
{
ya=ya+y_inc;
p=p-(2*dx);
}
}
cout<<"x"<<xa<<"y"<<ya<<endl;
}
}
int main()
{
//first_call
positionGenerator(1046,1623,750,1290);
//second_call
positionGenerator(1046,1623,375,810);
return 0;
}
I believe the algorithm works for both positive and negative slope .

You should count the number of pixels along the axis with the longest line projection instead of relying on (xa!=xb) && (ya!=yb). And then there may be some other bugs to fix.

You have problem in condition ((xa!=xb) && (ya!=yb))
Increment value is equal 2 for both x and y.
Therefore you should have at least one value from (xb-xa) and (yb-ya) will be even.
However you have two odd differences for the second call.

Your current loop termination condition will never be true when the distances |xa-xb| and |ya-yb| are both odd.
You need to find a better termination condition.

Related

How to memoize or make recursive function with no apparent pattern?

Consider the following code, it was done for the Codeforces Round #731 (Div. 3), problem B https://codeforces.com/contest/1547/problem/B
In short, you are given a string and you are supposed to check if it's possible to create that string by sequentially adding letters in alphabetical order in either the front to the back of a string that starts empty.
Ex. the string "bac", you would first make the empty string be "a", then it can be either "ba" or "ab", then we try again and we get that based on the last result it now can be "bac", "cba", "abc", "cab". We get that is possible so we return true.
We can only do this procedure up to 26 times.
My code would make a tree, grabbing a base string as the head, and two children nodes, one with the letter added to the front and one with the letter added to the back, if neither worked out, then I would repeat it again with the children nodes.
I rewrote my solution and sent a completely different one, but I still wanted to know if there was a way to optimize so it could actually be executed. The code works if n is around 14 or 15, it stutters a little bit but can finish; but once it goes to 20 it will not even finish.
#include <iostream>
#include <string>
using namespace std;
bool solve(string fs,string s = "", int n = 0){
if(s == fs){
return true;
}
if(n > 26 || s.size() > fs.size()){
return false;
}
if(solve(fs,s+(char)(96+n+1),n+1) ||solve(fs,(char)(96+n+1)+s,n+1)){
return true;
}
return false;
}
int main(){
int t;cin>>t;
for(int i = 0; i < t; i++){
string p;
cin>>p;
if(solve(p)){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
}```
You are doing brute force approach which is time complexity of n * 2^n. And it looks pretty reasonable to fail(TLE) when n is around 20 (taking into account that t is up to 10000)
I cannot come up with a way for efficient memoization, however this problem can easily be solved with greedy approach. You don't have to check all the combinations. Check out the official editorial

My program doesn't end

I'm new too c++ and I had to design a program that determines the first four triangular square numbers and the output is exactly how I want it to be, but it wont quit after its printed the first four. I can't figure out what it could be. I can't CTRL C because I will get points taken off. What is the issue here?
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
//Prints name line
cout<<"*********** BY: ********"<<endl;
//Initializing
const int HOW_MANY=4;
int num=1;
int tsn=0;
int z=1;
int x=0;
//How many TSN it will find and be printed
while (x<=HOW_MANY)
{
//
int sum=0;
for (int y=0;y<512;y++)
{
sum+=y;
tsn=pow(num,2);
//Tests if the numbers are TSN
if ((sum==tsn) || (num+1)/sqrt(num)==sqrt(num))
{
//Prints 1-HOW_MANY TSN and what they are
cout<<"Square Triangular Number "<< z <<" is: "<< tsn <<endl;
z++;
x++;
}
}
num++;
}
return 0;
}
If x = 0 then instead of while (x<=HOW_MANY) you need write while (x<HOW_MANY).
x begins at 0. Every time you find and print a number it gets incremented. You'll continue this, so long as x<=HOW_MANY.
You say your program finds 4 numbers but keeps running. After 4 hits, x will be 4. Is 4 <= 4? The answer is yes, so your program keeps running.
Either change the condition to x < HOW_MANY, or initialize x to 1.
EDIT
Did a little leg work, it turns out the sum of all the numbers in the range [1,512] is 131328. The 5th square triangle number is 1413721.
This means after you find the fourth triangle number, you will never sum high enough to find the next one. This will result in the infinite loop you're seeing.
The answer above is still the correct fix, but this is the reason you end up with an infinite loop.
for should be used for iteration and while should be used for condition testing.
The problem, as has been noted, is that your x condition variable is never being incremented to get you out of the outer loop. That's a logic error that can be avoided by using the appropriate control structure for the job.

using while loop for determining square roots of numbers c++

I am running a c++ program, using while loop for determining square roots of numbers, here i have defined variables, tried but nothings seems to work for me, any hand would be great to assist me.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n=10, N=0, i=0;
while(i<5)
N=i*n;
cout<<"numbers ="<<"\t Square root="<<sqrt(N)<<endl;
return 0;
}
The program execute successfully but nothing display (emptyb line). thanks.
while(i<5)
N=i*n;
Because you didn't indent or use brackets, you may have missed this and is equal to:
while (i < 5) {
N = i * n;
}
because the language specifies that no brackets means you just apply it to the next statement only and keep looping on that.
So this just loops forever as i never grows beyond 5 to exit the loop.
Just add fancy brackets to your loop and check where you want to change i and n.

C++ program to compute lcm of numbers between 1 to 20 (project euler )

as the title explains this is a program to find lcm of numbers between 1 to 20. i found an algorithm to do this, here's the link
http://www.cut-the-knot.org/Curriculum/Arithmetic/LCM.shtml
there is a java applet on the webpage that might explain the algorithm better
Problem: i wrote the code compiler shows no error but when i run the code the program goes berserk, i guess may be some infinite loopig but i can't figure it out for the life of me. i use turbo c++ 4.5 so basically if anyone can look at the code and help me out it would be great . thanks in advance
Algorithm:
say we need to find lcm of 2,6,8
first we find the least of the series and add to it the number above it, i.e the series become
4,6,8
now we find the least value again and add to it the intitial value in the column i.e 2
6,6,8
so the next iteration becomes
8,6,8
8,12,8
10,12,8
10,12,16
12,12,16
14,12,16
14,18,16
16,18,16
18,18,16
18,18,24
20,18,24
20,24,24
22,24,24
24,24,24
as you can see at one point all numbers become equal which is our lcm
#include<iostream.h>
/*function to check if all the elements of an array are equal*/
int equl(int a[20], int n)
{
int i=0;
while(n==1&&i<20)
{
if (a[i]==a[i+1])
n=1;
else
n=0;
i++;
}
return n;
}
/*function to calculate lcm and return that value to main function*/
int lcm()
{
int i,k,j,check=1,a[20],b[20];
/*loading both arrays with numbers from 1 to 20*/
for(i=0;i<20;i++)
{
a[i]=i+1;
b[i]=i+1;
}
check= equl(a,1);
/*actual implementation of the algorith*/
while(check==0)
{
k=a[0]; /*looks for the least value in the array*/
for(i=0;i<20;i++)
{
if(a[i+1]<k)
{
k=a[i+1]; /*find the least value*/
j=i+1; /*mark the position in array */
}
else
continue;
}
a[j]=k+b[j]; /*adding the least value with its corresponding number*/
check= equl(a,1);
}
return (a[0]);
/*at this point all numbers in the array must be same thus any value gives us the lcm*/
}
void main()
{
int l;
l=lcm();
cout<<l;
}
In this line:
a[j]=k+b[j];
You use j but it is unitialized so it's some huge value and you are outside of the array bounds and thus you get a segmentation fault.
You also have some weird things going on in your code. void main() and you use cout without either saying std::cout or using namespace std; or something similar. An odd practice.
Also don't you think you should pass the arrays as arguments if you're going to make lcm() a function? That is int lcm(int a[], int b[]);.
You might look into using a debugger also and improving your coding practices. I found this error within 30 seconds of pasting your code into the compiler with the help of the debugger.
Your loop condition is:
while(n==1&&i<20)
So your equl function will never return 1 because if n happens to be 1 then the loop will just keep going and never return a 1.
However, your program still does not appear to return the correct result. You can split the piece of your code that finds the minimum element and replace it with this for cleanliness:
int least(int a[], int size){
int minPos = 0;
for(int i=0; i<size ;i++){
if (a[i] < a[minPos] ){
minPos = i;
}
}
return minPos;
}
Then you can call it by saying j = least(a, 20);. I will leave further work on your program to you. Consider calling your variables something meaningful instead of i,j,k,a,b.
Your equl function is using array indices from 0-20, but the arrays only have 1-19
j in lcm() is uninitialized if the first element is the smallest. It should be set to 0 at the top of the while loop
In the following code, when i=19, you are accessing a[20], which is out of the bounds of the array. Should be for(i=0;i<19;i++)
for(i=0;i<20;i++) {
if(a[i+1]<k)
You are not actually using the std namespace for the cout. this should be std::cout<<l
Your are including iostream.h. The standard is iostream without the .h, this may not work on such an old compiler tho
instead of hard-coding 20 everywhere, you should use a #define. This is not an error, just a style thing.
The following code does nothing. This is the default behavior
else
continue;

Bipartite matching in graph

I have the following code which is an implementation of BPM (bipartite matching, from graph theory)
#include <iostream>
#include <cstring>
using namespace std;
#define M 128
#define N 128
bool graph[M][N];
bool seen[N];
int matchL[M],matchR[N];
int n=4;
int m=4;
bool bpm(int u){
for(int v=0;v<n;v++) if(graph[u][u])
{
if (seen[v]) continue;
seen[v]=true;
if(matchR[v] <0 || bpm(matchR[v])){
matchL[u]=v;
matchR[v]=u;
return true;
}
}
return false;
}
int main(){
graph[0][1]=1;
graph[0][3]=1;
graph[1][3]=1;
graph[0][2]=1;
memset(matchL,-1,sizeof(matchL));
memset(matchR,-1,sizeof(matchR));
int cnt=0;
// memset(seen,0,sizeof(seen));
for(int i=0;i<m;i++){
memset(seen,0,sizeof(seen));
if(bpm(i)) cnt++;
}
cout<<cnt<<endl;
return 0;
}
The definition of cnt and the purpose of this code are given below.
Given a bipartite graph represented as an m-by-n matrix, where graph[i][j] is true iff there is an edge from pigeon i to hole j, computes the maximum number of pigeons that can find a hole (one per pigeon) and an optimal assignment.
graph[m][n], matchL[n], matchR[m] and seen[m] are global arrays.
main() initializes matchL[] and matchR[] to -1 in all components.
main() does a loop over all pigeons i and in each iteration
clears seen[] to 0 in all components
calls bpm(i) and increments the maxflow counter
bpm(i) returns true iff pigeon i can be assigned a hole
cnt contains the number of happy pigeons.
In my case, cnt's value is output as 0. Does this graph algorithm work correctly or have I made some error?
Either your initialization is faulty or this condition in bpm() is faulty:
if (graph[u][u])
There is no element of graph on the diagonal which is set true, so bpm() always fails completely. It is also not clear why you'd be needing to test the diagonal alone. Maybe it should be if (graph[u][v]), or maybe something else.
(Your indentation leaves somewhat to be desired; it is extremely aconventional to put an if condition such as this on the same line as a for loop control. Incidentally, the initialization of matchL and matchR only works on 2's-complement machines.)