I have to develop a C program for a given set of input values, where we describe the rectanged figure by its boundary by specifying a starting point and a series of movements in four basic directions – as if we were going around the formation along its boundary.
We enter each movement in the direction (WESN) and length – "W 3" means moving from the current position three steps west (left).
The figure in Figure 1 could be described — starting from the upper-right corner — as:
"W 6, S 2, W 3, S 2, E 1, S 2, E 2, N 1, E 2, N 1, E 2, N 1, W 2, N 1,
E 3, S 3, E 1, N 5".
My problem is:
What is such a shape called in geometry?
How can I calculate the area of such a shape? I have lengths of all the sides as W6, S4 etc.
Thanks.
This can be called a rectilinear polygon.
A general algorithm for calculating the area of any polygon is:
Let (xo, yo) be the starting point (“o” for old).
Initialize a sum S to zero.
For each movement:
Calculate the new point (xn, yn) (“n” for new) from the movement and the old point.
Add xn•yo−xo•yn to S.
Set xo=xn and yo=yn.
The area inside the polygon is |S|/2.
The above presumes the last movement closes the polygon, so the last point is the starting point. If it does not, a copy of the starting point should be saved and used to finish the sum with the last point.
This uses the sum/algorithm chux pointed out.
The shape is called polyomino. It's special case of polygon.
The problem of finding the area can be solved by starting at point (0,0) with a polygon of area 0. Next, extending the area by rectangle while moving horizontally.
Assume that the current point is (x,y). Moving to east by d unit means adding a rectangle at points (x,0) -> (x,y) -> (x + d, y) -> (x + d, 0). Rectangle's area is d * y.
When moving west one needs to subtract the rectangle.
The final area is positive if the walk is clockwise or negative if the path was counter-clockwise.
This approach results in a very simple program:
#include <stdio.h>
int main() {
int x = 0, y = 0, A = 0, d;
int c;
while ((c = getchar()) != EOF) {
if (c == 'W' && scanf(" %d", &d) == 1) {
x += d;
A += d * y;
} else if (c == 'E' && scanf(" %d", &d) == 1) {
x -= d;
A -= d * y;
} else if (c == 'N' && scanf(" %d", &d) == 1) {
y += d;
} else if (c == 'S' && scanf(" %d", &d) == 1) {
y -= d;
}
}
if (A < 0) A = -A;
printf("%d\n", A);
return 0;
}
For input from the question is gives the expected answer of 33.
Related
#include <stdio.h>
int main()
{
signed int x;
int x1 = 0, x2 = 10, final, loop = 1, y = 10, c;
printf("Enter the value of X.\n");
scanf("%d", &x);
printf("Value Scanned:%d\n", x);
again:
if (loop <= 32)
{
if (x >= x1 && x < x2)
{
final = x - x1;
printf("%d", final);
y = y * 10;
x1 = 0;
x2 = 0;
++loop;
goto again;
}
else
{
c = x2 - x1;
if (x1 == x2)
{
x2 += y;
goto again;
}
else if (c == y)
{
x1 += y;
x2 += y;
goto again;
}
else
{
printf("Error in Process");
goto ending;
}
}
}
else
{
printf("0+error, extra long input");
}
ending:
return 0;
}
Flowchart:
I am a beginner in C-language and only know how to use If-else, Switch, Goto statements, with basic knowledge of how to integrate basic level loops. So please tell me what/where I am wrong instead of telling me how to use arrays because I don't know them, etc. This is my most complex code until now.
Now for Explanation of Coding,
I wrote X1 as the lower value and X2 as the upper value while first keeping a difference = Y(initially 10) between them.
Continuously increasing the value of X1 and X2 by Y(10) together simultaneously, I will arrive in between an intersection where my x(input) lies.
Eg-
x=568
then X1 and X2 will keep on increasing until they reach X1 = 560 and X2 = 570, then they will do Final = X(568) - X1(560) and print it.
since it can only happen for 32-digits long, so I wrote loop = 0 and only processing my main statement till loop is smaller than or equal to 32, otherwise printing "0+error".
then I put Y = Y * 10 every time the value was within my specified range.
It should give me the values like Last digit, then last 2 digits, then last 3 digits,etc. but after scanning the value, it isn't exciting at all.
Evaluating what you are attempting to do, I reworked your code to make it a bit more structured without utilizing arrays at that seemed to be something you wanted to avoid at this time. However, these days, the use of the goto statement is usually avoided since functionality such as for loops, do/while loops, and while loops offer better clarity to coding. With that in mind, following is a snippet of code that provides the functionality it looks like you want.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int x, x1, x2, y = 10, counter = 0, last_digit;
printf("Please enter a number: ");
scanf("%d", &x);
if (x < 0) /* Just in case a negative integer is entered */
{
x = x * -1;
}
while (1) /* Use a while loop with associated break statements to avoid goto and label statements */
{
x1 = 0;
x2 = 10;
counter += 1;
while (1)
{
if (x >= x1 && x <= x2)
{
last_digit = x - x1;
if (counter == 1)
{
printf("The last digit is: %d\n", last_digit);
}
else
{
printf("The next digit is: %d\n", last_digit);
}
break;
}
x1 += y;
x2 += y;
}
x = x / 10; /* Perform integer division by ten to get to the next digit in the entered number */
if (x == 0) /* Once all digits have been processed the outer while loop can be exited */
{
break;
}
}
return 0;
}
Following are some key points.
As noted, the loop process using goto statements is replaced by two while loops; one while loop nested inside another while loop.
Utilizing integer division by ten, each digit can be ascertained and printed.
Utilizing the nested while loops with break statements allows for a more compact program.
Utilizing this code snippet, following is a sample test from the terminal.
#Dev:~/C_Programs/Console/LastDigit/bin/Release$ ./LastDigit
Please enter a number: 479824385
The last digit is: 5
The next digit is: 8
The next digit is: 3
The next digit is: 4
The next digit is: 2
The next digit is: 8
The next digit is: 9
The next digit is: 7
The next digit is: 4
Back in the day, the goto statement had its place in coding, but today it is pretty much an artifact.
Give that a try and see if it meets the spirit of your project.
I'm new in C, so I try to create a program that calculate the area of triangle as a start.
Calculating the area is easy when the triangle exists, however the validation of straight line is working partially.
Example:
A(0,-4) B(1,0) C(4,12) does not produce straight line error.
but
A(4,12) B(1,0) C(0,-4) produce straight line error.
#include <stdio.h>
#include <math.h>
double square(double num){
return (num*num);
}
int main()
{
double x[5],y[5],a,b,c,angle,area;
printf("Hello there! Calculating the area of triangle.\n");
printf("Enter a coordinate A :\n");
scanf("%lf,%lf",&x[0],&y[0]);
printf("Enter another coordinate B :\n");
scanf("%lf,%lf",&x[1],&y[1]);
printf("Enter another coordinate C :\n");
scanf("%lf,%lf",&x[2],&y[2]);
// AB as base (a) , c is opposite side
a = sqrt( square((x[0]-x[1])) + square((y[0]-y[1])) );
b = sqrt( square((x[0]-x[2])) + square((y[0]-y[2])) );
c = sqrt( square(x[1]-x[2]) + square((y[1]-y[2])) );
double num = (square(a)+square(b)-square(c))/(2*a*b);
angle = acos(num);
area = .5*a*b*sin(angle);
//printf("%lf %lf %lf %lf %lf \n",a,b,c,num,angle);
if (num == 1 || num ==-1){
printf("That's a straight line.");
}else{
printf("Area of triangle is %lf\n",area);
}
return 0;
}
You can use a different test, and perhaps a different area formula. If you use Heron's formula, then once you have the lengths of the sides a, b, and c, you can compute:
double p = (a + b + c)/2;
double area = sqrt(p*(p-a)*(p-b)*(p-c));
You can detect if the triangle is valid by checking that p is greater than each of the sides.
double p = (a + b + c)/2;
if ((p > a) && (p > b) && (p > c)) {
double area = sqrt(p*(p-a)*(p-b)*(p-c));
printf("Area of triangle is %lf\n", area);
} else {
printf("I don't consider that a triangle.\n");
}
Try it online!
The problem in your code is double num = (square(a)+square(b)-square(c))/(2*a*b); gets evaluated to a number slightly larger than 1 in some cases. This can happen with floating point computations. In your case you can safely add if (num > 1) num = 1; after that line since cosine equation always will give you a value larger than 0 and less than 1 for triangles.
However there's a problem if two points overlap and a or b becomes zero. You will have to check for that and handle it as a special case if such input is expected by your code. (If two points overlap then they are collinear anyways. You can check the overlap by checking if any of a,b,c are zero)
I have encountered the following problem that I am attempting to solve:
In a N x N grid representing a field of cherries, each cell is one of three possible integers.
0 means the cell is empty, so you can pass through;
1 means the cell contains a cherry, that you can pick up and pass through;
-1 means the cell contains a thorn that blocks your way.
Your task is to collect maximum number of cherries possible by following the rules below:
Starting at the position (0, 0) and reaching (N-1, N-1) by moving right or down through valid path cells (cells with > value 0 or 1);
After reaching (N-1, N-1), returning to (0, 0) by moving left or up through valid path cells;
When passing through a path cell containing a cherry, you pick it up and the cell becomes an empty cell (0);
If there is no valid path between (0, 0) and (N-1, N-1), then no cherries can be collected.
Example 1:
Input: grid =
[[0, 1, -1],
[1, 0, -1],
[1, 1, 1]]
Output: 5
Explanation:
The player started at (0, 0) and went down, down, right right to reach (2, 2).
4 cherries were picked up during this single trip, and the matrix becomes [[0,1,-1],[0,0,-1],[0,0,0]].
Then, the player went left, up, up, left to return home, picking up one more cherry.
The total number of cherries picked up is 5, and this is the maximum possible.
Note:
grid is an N by N 2D array, with 1 <= N <= 50.
Each grid[i][j] is an integer in the set {-1, 0, 1}.
It is guaranteed that grid[0][0] and grid[N-1][N-1] are not -1.
So I need to write a function cherryPickup that takes a grid and returns the maximum score.
My first suboptimal attempt (written in Go) is the following, which supposedly would try to walk every possible path, storing the score in a slice upon round-trip path completion, and then return the greatest score present in the slice:
func cherryPickup(grid [][]int) int {
values := []int{}
pVals := &values
finalPoints := 0
// Begin top-down path
traverseAndCollectTopDown(grid, 0, 0, 0, pVals)
// Find max value in slice
for i, pathPoints := range values {
if i == 0 || pathPoints > finalPoints {
finalPoints = pathPoints
}
}
return finalPoints
}
func isTraversable(grid [][]int, x, y int) bool {
return (grid[x][y] != -1)
}
func isOnBounds(grid [][]int, x, y int) bool {
return (x < len(grid) && y < len(grid[0]) && x >= 0 && y >= 0)
}
func traverseAndCollectTopDown(grid [][]int, x, y, points int, vals *[]int) {
// Collect point before continuing
if grid[x][y] == 1 {
grid[x][y] = 0
points++
}
// If reached bottom, begin bottom-up path
if (x == len(grid)-1) && (y == len(grid[0])-1) {
traverseAndCollectBottomUp(grid, x, y, points, vals)
return
}
// Go Down
if isOnBounds(grid, x+1, y) && isTraversable(grid, x+1, y) {
traverseAndCollectTopDown(grid, x+1, y, points, vals)
}
// Go Right
if isOnBounds(grid, x, y+1) && isTraversable(grid, x, y+1) {
traverseAndCollectTopDown(grid, x, y+1, points, vals)
}
}
func traverseAndCollectBottomUp(grid [][]int, x, y, points int, vals *[]int) {
if grid[x][y] == 1 {
grid[x][y] = 0
points++
}
if x == 0 && y == 0 {
*vals = append(*vals, points)
return
}
// Go Up
if isOnBounds(grid, x-1, y) && isTraversable(grid, x-1, y) {
traverseAndCollectBottomUp(grid, x-1, y, points, vals)
}
// Go Left
if isOnBounds(grid, x, y-1) && isTraversable(grid, x, y-1) {
traverseAndCollectBottomUp(grid, x, y-1, points, vals)
}
}
Currently it passes a bunch of tests, but this one is failing and I don't know why.
Input: [[1,1,1,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,1],[1,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,1,1,1]]
Output: 10
Expected: 15
I get the way this grid must score the 15 points, however, why does my code fail to travel the winning path and only scores 10? Also, do you recommend any terminal utilities, programs or strategies to help visualize better what is happening on every run?
Thanks in advance!
The parameter you are using to traverseAndCollectTopDown / traverseAndCollectBottomUp is a grid [][]int. You are modifying that and then passing it directly into other functions (recursively). In go a slice is effectively passed by reference meaning that when one of your routines edits the slice this impacts the slice held by all of the other routines too (so as soon as one path finds a '1' it gets removed and another path going through the same cell will find a '0' there).
To fix this take a copy of grid before making a recursive call e.g. call grid = copyGrid(grid) in traverseAndCollectTopDown / traverseAndCollectBottomUp before modifying grid.
func copyGrid(in [][]int) [][]int {
duplicate := make([][]int, len(in))
for i := range in {
duplicate[i] = make([]int, len(in[i]))
copy(duplicate[i], in[i])
}
return duplicate
}
Suppose one wanted to search for pairs of integers x and y a that satisfy some equation, such as (off the top of my head) 7 x^2 + x y - 3 y^2 = 5
(I know there are quite efficient methods for finding integer solutions to quadratics like that; but this is irrelevant for the purpose of the present question.)
The obvious approach is to use a simple double loop "for x = -max to max; for y = -max to max { blah}" But to allow the search to be stopped and resumed, a more convenient approach, picturing the possible integers of x and y as a square lattice of points in the plane, is to work round a "square spiral" outward from the origin, starting and stopping at (say) the top right corner.
So basically, I am asking for a simple and sound "pseudo-code" for the loops to start and stop this process at points (m, m) and (n, n) respectively.
For extra kudos, if the reader is inclined, I suggest also providing the loops if one of x can be assumed non-negative, or if both can be assumed non-negative. This is probably somewhat easier, especially the second.
I could whump this up myself without much difficulty, but am interested in seeing neat ideas of others.
This would make quite a good "constructive" interview challenge for those dreaded interviewers who like to torture candidates with white boards ;-)
def enumerateIntegerPairs(fromRadius, toRadius):
for radius in range(fromRadius, toRadius + 1):
if radius == 0: yield (0, 0)
for x in range(-radius, radius): yield (x, radius)
for y in range(-radius, radius): yield (radius, -y)
for x in range(-radius, radius): yield (-x, -radius)
for y in range(-radius, radius): yield (-radius, y)
Here is a straightforward implementation (also on ideone):
void turn(int *dr, int *dc) {
int tmp = *dc;
*dc = -*dr;
*dr = tmp;
}
int main(void) {
int N = 3;
int r = 0, c = 0;
int sz = 0;
int dr = 1, dc = 0, cnt = 0;
while (r != N+1 && c != N+1) {
printf("%d %d\n", r, c);
if (cnt == sz) {
turn(&dr, &dc);
cnt = 0;
if (dr == 0 && dc == -1) {
r++;
c++;
sz += 2;
}
}
cnt++;
r += dr;
c += dc;
}
return 0;
}
The key in the implementation is the turn function, that performs the right turn given a pair of {delta-Row, delta-Col}. The rest is straightforward arithmetic.
i need to draw a polygon of "n" sides given 2 points (the center and 1 of his vertex) just that i suck in math. I have been reading a lot and all this is what i have been able to figure it (i dont know if it is correct):
Ok, i take the distance between the 2 points (radius) with the theorem of Pythagoras:
sqrt(pow(abs(x - xc), 2) + pow(abs(y - yc), 2));
And the angle between this 2 points with atan2, like this:
atan2(abs(y - yc), abs(x - xc));
Where xc, yc is the center point and x, y is the only vertex know.
And with that data i do:
void polygon(int xc, int yc, int radius, double angle, int sides)
{
int i;
double ang = 360/sides; //Every vertex is about "ang" degrees from each other
radian = 180/M_PI;
int points_x[7]; //Here i store the calculated vertexs
int points_y[7]; //Here i store the calculated vertexs
/*Here i calculate the vertexs of the polygon*/
for(i=0; i<sides; i++)
{
points_x[i] = xc + ceil(radius * cos(angle/radian));
points_y[i] = yc + ceil(radius * sin(angle/radian));
angle = angle+ang;
}
/*Here i draw the polygon with the know vertexs just calculated*/
for(i=0; i<sides-1; i++)
line(points_x[i], points_y[i], points_x[i+1], points_y[i+1]);
line(points_y[i], points_x[i], points_x[0], points_y[0]);
}
The problem is that the program dont work correctly because it draw the lines not like a polygon.
Someone how know enough of math to give a hand? im working in this graphics primitives with C and turbo C.
Edit: i dont want to fill the polygon, just draw it.
Consider what 360/sides actually returns if sides is not a factor of 360 (this is integer division - see what 360/7 actually returns).
There is no need to use degrees at all - use 2*Math_PI/(double)nsides and work throughout in radians.
also you can omit the final line by using the modulus function (module nsides).
If you have more than 7 sides you will not be able to store all the points. You don't need to store all the points if you are simply drawing the polygon rather than storing it - just the last point and the current one.
You should be using radians in all your calculations. Here's a complete program that illustrates how best to do this:
#include <stdio.h>
#define PI 3.141592653589
static void line (int x1, int y1, int x2, int y2) {
printf ("Line from (%3d,%3d) - (%3d,%3d)\n", x1, y1, x2, y2);
}
static void polygon (int xc, int yc, int x, int y, int n) {
int lastx, lasty;
double r = sqrt ((x - xc) * (x - xc) + (y - yc) * (y - yc));
double a = atan2 (y - yc, x - xc);
int i;
for (i = 1; i <= n; i++) {
lastx = x; lasty = y;
a = a + PI * 2 / n;
x = round ((double)xc + (double)r * cos(a));
y = round ((double)yc + (double)r * sin(a));
line (lastx, lasty, x, y);
}
}
int main(int argc, char* argv[]) {
polygon (0,0,0,10,4); // A diamond.
polygon (0,0,10,10,4); // A square.
polygon (0,0,0,10,8); // An octagon.
return 0;
}
which outputs (no fancy graphics here, but you should get the idea):
===
Line from ( 0, 10) - (-10, 0)
Line from (-10, 0) - ( 0,-10)
Line from ( 0,-10) - ( 10, 0)
Line from ( 10, 0) - ( 0, 10)
===
Line from ( 10, 10) - (-10, 10)
Line from (-10, 10) - (-10,-10)
Line from (-10,-10) - ( 10,-10)
Line from ( 10,-10) - ( 10, 10)
===
Line from ( 0, 10) - ( -7, 7)
Line from ( -7, 7) - (-10, 0)
Line from (-10, 0) - ( -7, -7)
Line from ( -7, -7) - ( 0,-10)
Line from ( 0,-10) - ( 7, -7)
Line from ( 7, -7) - ( 10, 0)
Line from ( 10, 0) - ( 7, 7)
Line from ( 7, 7) - ( 0, 10)
I've written the polygon function as per your original specification, passing in just the two co-ordinates. As an aside, you don't want those abs calls in your calculations for radius and angle because:
they're useless for radius (since -n2 = n2 for all n).
they're bad for angle since that will force you into a specific quadrant (wrong starting point).
I'm not going to just give you the answer, but I have some advice. First, learn how line drawing works INSIDE AND OUT. When you have this down, try to write a filled triangle renderer.
Generally, filled polygons are drawn 1 horizontal scan line at a time, top to bottom. You're job is to determine the starting and stopping x coordinate for every scan line. Note that the edge of a polygon follows a straight line (hint, hint)... :)
You're trying to draw a filled poly I guess?
If you're going to try to draw the polys using a line primitive, you're going to have a lot of pain coming to you. dicroce actually gave you some very good advice on that front.
Your best bet is to find a primitive that fills for you and supply it a coordinates list. It's up to you to determine the coordinates to give it.
I think the main trouble is: atan2(abs(y - yc), abs(x - xc)); is giving you radians, not degrees, just convert it to degrees and try.
/* all angles in radians */
double ainc = PI*2 / sides;
int x1, y1;
for (i = 0; i <= sides; i++){
double a = angle + ainc * i;
int x = xc + radius * cos(a);
int y = yc + radius * sin(a);
if (i > 0) line(x1, y1, x, y);
x1 = x; y1 = y;
}
Or, you could save the points in an array and call the DrawPoly routine if you've got one.
If you want a filled polygon, call FillPoly if you've got one.