Related
This question was migrated from Super User because it can be answered on Stack Overflow.
Migrated last month.
Using C language, I wrote a code that gives me the eight nearest neighbors of a "site" or entry in a 2d array. The problem is that when I select an entry located on edge, I cannot obtain the correct neighbor considering the periodic boundary conditions.
The following code works perfectly when I choose an entry outside the edges:
First the program asks the user to enter the coordinates of the matrix entry, then it finds eight nearest neighbors.
//Code:
#define XMAX 3
#define YMAX 3
#define LOWER 0
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main( )
{
int count = 1;
int number;
int x=0,y=0;
int right, left, up, down, upleft, upright, downleft, downright;
int grid[XMAX][YMAX];
//Printing the matrix
for (int i = 0; i < XMAX ; i++) {
for (int j = 0; j < YMAX; j++) {
grid[i][j] = count++;
printf("%d ", grid[i][j]);
}
printf("\n");
}
//Here I ask the user to enter the coordinates of the entry
printf("\nEnter a X-coordinate :\n");
scanf("%d", &y);
printf("\nEnter a Y-coordinate :\n");
scanf("%d", &x);
printf("(x,y)=(%d,%d)\n",y,x); //print the chosen coordinates
//Locating the entry of te matrix given the prior coordinates
for (int i = 0; i < XMAX; i++)
{
for (int j = 0; j < YMAX; j++ )
{
if(x == i && y == j){ grid[x][y] == count; }
}
}
//Looking up the nearest 8 neighbors (If the chosen entry is not on any edge of the matrix)
right = grid[y][x+1];
left = grid[y][x-1];
up = grid[y-1][x];
down = grid[y+1][x];
upleft = grid[y-1][x-1];
upright = grid[y-1][x+1];
downleft = grid[y+1][x-1];
downright = grid[y+1][x+1];
//Considering periodic boundary conditions for the right neighbor
if (grid[y][x] == grid[YMAX-1][x]){
right = grid[0][x];
}
printf("The coordinates are (%d,%d) and the solicited matrix entry is: %d\n", y, x, grid[y][x]);
//Printing the eight nearest neighbors
printf("Right: %d\nLeft: %d\nUp: %d\nDown: %d\nUpleft: %d\nUpright: %d\nDownleft: %d\nDownright: %d\n",right,left,up,down,upleft,upright,downleft,downright);
return 0;
}
However when the user enters an entry located at the right edge, for example, the problem doesn't give the proper neighbor. The part of the code that should do this is:
if (grid[y][x] == grid[YMAX-1][x]){
right = grid[0][x];
}
But it seems the program never passes through this part of the code. I don't know what to do with this problem. Could you help me with that, please?
A very first change I would suggest is to avoid assigning x given by the user to a variable called y. Better keep the same name. So x is the column coordinate and y is the row coordinate, such as the notation used in math matrices.
After this I think the biggest problem is the part the assigns the neighbor values. For instance, this:
right = grid[y][x+1];
Will go out of bounds of grid matrix when x + 1 >= XMAX
Similarly, when x-1 < 0, this part:
left = grid[y][x-1];
Will try to access a negative index which is invalid.
You can follow the suggestion given in a question comment to address this by using modulo or possibly creating a macro. At first I would suggest writing a simple function to handle this, such:
int get_limited_coord(int coord, int coord_max)
{
if (coord >= 0 && coord < coord_max) {
return coord;
} else if (coord >= coord_max) {
return coord - coord_max;
} else {
return coord + coord_max;
}
}
And then the block that assigns these values becomes:
right = grid[get_limited_coord(y , YMAX)][get_limited_coord(x+1, XMAX)];
left = grid[get_limited_coord(y , YMAX)][get_limited_coord(x-1, XMAX)];
up = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x , XMAX)];
down = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x , XMAX)];
upleft = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x-1, XMAX)];
upright = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x+1, XMAX)];
downleft = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x-1, XMAX)];
downright = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x+1, XMAX)];
Would remove this block which does not seem to do anything now:
//Locating the entry of te matrix given the prior coordinates
for (int i = 0; i < XMAX; i++)
{
for (int j = 0; j < YMAX; j++ )
{
if(x == i && y == j){ grid[x][y] == count; }
}
}
And ensure user input is valid:
if (x >= XMAX || x < 0 || y >= YMAX || y < 0) {
printf ("Invalid coordinates given\n");
return 1;
}
Here's the code with these changes:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define XMAX 3
#define YMAX 3
#define LOWER 0
int get_limited_coord(int coord, int coord_max)
{
if (coord >= 0 && coord < coord_max) {
return coord;
} else if (coord >= coord_max) {
return coord - coord_max;
} else {
return coord + coord_max;
}
}
int main( )
{
int count = 1;
int number;
int x=0,y=0;
int right, left, up, down, upleft, upright, downleft, downright;
int grid[XMAX][YMAX];
//Printing the matrix
for (y = 0; y < XMAX ; y++) {
for (x = 0; x < YMAX; x++) {
grid[y][x] = count++;
printf("%d ", grid[y][x]);
}
printf("\n");
}
//Here I ask the user to enter the coordinates of the entry
printf("\nEnter a X-coordinate :\n");
scanf("%d", &x);
printf("\nEnter a Y-coordinate :\n");
scanf("%d", &y);
printf("(x,y)=(%d,%d)\n",x,y); //print the chosen coordinates
if (x >= XMAX || x < 0 || y >= YMAX || y < 0) {
printf ("Invalid coordinates given\n");
return 1;
}
//Looking up the nearest 8 neighbors (If the chosen entry is not on any edge of the matrix)
right = grid[get_limited_coord(y , YMAX)][get_limited_coord(x+1, XMAX)];
left = grid[get_limited_coord(y , YMAX)][get_limited_coord(x-1, XMAX)];
up = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x , XMAX)];
down = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x , XMAX)];
upleft = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x-1, XMAX)];
upright = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x+1, XMAX)];
downleft = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x-1, XMAX)];
downright = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x+1, XMAX)];
printf("The coordinates are (%d,%d) and the solicited matrix entry is: %d\n", y, x, grid[y][x]);
//Printing the eight nearest neighbors
printf("Right: %d\nLeft: %d\nUp: %d\nDown: %d\nUpleft: %d\nUpright: %d\nDownleft: %d\nDownright: %d\n",right,left,up,down,upleft,upright,downleft,downright);
return 0;
}
And a simple test:
$ ./a.out
1 2 3
4 5 6
7 8 9
Enter a X-coordinate :
0
Enter a Y-coordinate :
2
(x,y)=(0,2)
The coordinates are (2,0) and the solicited matrix entry is: 7
Right: 8
Left: 9
Up: 4
Down: 1
Upleft: 6
Upright: 5
Downleft: 3
Downright: 2
#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 am writing a program to see if a user entered number is Armstrong or not, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int x = 0;
printf("Enter a natural number: ");
scanf("%d", &x);
int ans = x;
// Digit Counter
int counter = 0; //Variable for number of digits in the user entered number
int b = x; //For each time number can be divided by 10 and isnt 0
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
++counter;
//Digit Counter
int sum = 0;
// Digit Finder
int D;
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
if (sum == ans){
printf("%d is a Armstrong number! :)", ans);
}else
printf("%d is not an Armstrong number :(", ans);
//Digit Finder
return 0;
}
My problem is that the program works fine apart from one point, when the program is given a Armstrong number which does not start with 1 then it behaves normally and indicates if it is an Armstrong number or not, but when i input a Armstrong number which start with 1 then it will print out the Armstrong number but -1.
For example: If i input something such as 371 which is an Armstrong number it will show that it is an Armstrong number. However if i input 1634 it will output 1633 which is 1 less than 1634.
How can i fix this problem?, also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
How can I fix this problem.
You know the number of iterations you want to make once you have calculated the digit count. So instead of looping till you reach the value of x:
for (int j = 1; j <= x; j++){
use the digit counter instead:
for (int j = 1; j <= counter; j++) {
also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
There's a number of things you can do to improve your code.
First and foremost, any piece of code should be properly indented and formatted. Right now your code has no indenting, which makes it more difficult to read and it just looks ugly in general. So, always indent your code properly. Use an IDE or a good text editor, it will help you.
Be consistent in your code style. If you are writing
if (some_cond) {
...
}
else
//do this
It is not consistent. Wrap the else in braces as well.
Always check the return value of a function you use, especially for scanf. It will save you from many bugs in the future.
if (scanf("%d", &x) == 1)
//...all OK...
else
// ...EOF or conversion failure...
exit(EXIT_FAILURE);
Your first for loop will iterate x times uselessly. You can stop when you know that you have hit 0:
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b == 0){
break;
}
counter += 1;
}
C has ++ operator. Use that instead of doing counter += 1
int D; you create this, but don't initialize it. Always initialize your variables as soon as possible
C has const qualifier keyword, which makes a value immutable. This makes your code more readable, as the reader can immediately tell that this value will not change. In your code, you can change ans variable and make it a const int because it never changes:
const int ans = x;
Use more descriptive names for your variables. ans, D don't tell me anything. Use proper names, so that the reader of your code can easily understand your code.
These are some of the things that in my opinion you should do and keep doing to improve your code and coding skills. I am sure there can be more things though. Keep your code readable and as simple as possible.
The condition in this loop
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
does not make sense because there will be numerous redundant iterations of the loop.
For example if x is equal to 153 that is contains only 3 digits the loop will iterate exactly 153 times.
Also additional increment of the variable counter after the loop
++counter;
makes the code logically inconsistent.
Instead of the loop you could write at least the following way
int counter = 0;
int b = x;
do
{
++counter;
} while ( b /= 10 );
This loop iterates exactly the number of times equal to the number of digits in a given number.
In this loop
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
it seems you did not take into account that the variable x is decreased inside the body of the loop
x /= 10; // Divides user entered number by 10 to get rid of digit found
So the loop can interrupt its iterations too early. In any case the condition of the loop again does not make great sense the same way as the condition of the first loop and only adds a bug.
The type of used variables that store a given number should be unsigned integer type. Otherwise the user can enter a negative number.
You could write a separate function that checks whether a given number is an Armstrong number.
Here you are.
#include <stdio.h>
int is_armstrong( unsigned int x )
{
const unsigned int Base = 10;
size_t n = 0;
unsigned int tmp = x;
do
{
++n;
} while ( tmp /= Base );
unsigned int sum = 0;
tmp = x;
do
{
unsigned int digit = tmp % Base;
unsigned int power = digit;
for ( size_t i = 1; i < n; i++ ) power *= digit;
sum += power;
} while ( ( tmp /= Base ) != 0 && !( x < sum ) );
return tmp == 0 && x == sum;
}
int main(void)
{
unsigned int a[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407,
1634, 8208, 9474, 54748, 92727, 93084, 548834
};
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%u is %san Armstrong number.\n", a[i], is_armstrong( a[i] ) ? "": "not " );
}
return 0;
}
The program output is
0 is an Armstrong number.
1 is an Armstrong number.
2 is an Armstrong number.
3 is an Armstrong number.
4 is an Armstrong number.
5 is an Armstrong number.
6 is an Armstrong number.
7 is an Armstrong number.
8 is an Armstrong number.
9 is an Armstrong number.
153 is an Armstrong number.
370 is an Armstrong number.
371 is an Armstrong number.
407 is an Armstrong number.
1634 is an Armstrong number.
8208 is an Armstrong number.
9474 is an Armstrong number.
54748 is an Armstrong number.
92727 is an Armstrong number.
93084 is an Armstrong number.
548834 is an Armstrong number.
Please remove j++ from 2nd loop for (int j = 1; j <= x; j++)
I tried this:
void armstrong(int x)
{
// count digits
int counter = 0, temp = x, sum = 0;
while(temp != 0)
{
temp = temp/10;
++counter; // Note: pre increment faster
}
// printf("count %d\n",counter);
temp = x;
while(temp != 0)
{
sum += pow(temp % 10, counter);
temp = temp/10;
}
// printf("sum %d\n",sum);
if(x == sum)
{
printf("Armstrong\n");
}
else
{
printf("No Armstrong\n");
}
}
int main(){
armstrong(371);
armstrong(1634);
return 0;
}
Let's take this and add the ability to handle multiple numeric bases while we're at it. Why? BECAUSE WE CAN!!!! :-)
#include <stdio.h>
#include <math.h>
double log_base(int b, double n)
{
return log(n) / log((double)b);
}
int is_armstrong_number(int b, /* base */
int n)
{
int num_digits = trunc(log_base(b, (double)n)) + 1;
int sum = 0;
int remainder = n;
while(remainder > 0)
{
sum = sum + pow(remainder % b, num_digits);
remainder = (int) (remainder / b);
}
return sum == n;
}
int main()
{
printf("All the following are valid Armstrong numbers\n");
printf(" 407 base 10 - result = %d\n", is_armstrong_number(10, 407));
printf(" 0xEA1 base 16 - result = %d\n", is_armstrong_number(16, 0xEA1));
printf(" 371 base 10 - result = %d\n", is_armstrong_number(10, 371));
printf(" 1634 base 10 - result = %d\n", is_armstrong_number(10, 1634));
printf(" 0463 base 8 - result = %d\n", is_armstrong_number(8, 0463));
printf("All the following are NOT valid Armstrong numbers\n");
printf(" 123 base 10 - result = %d\n", is_armstrong_number(10, 123));
printf(" 0x2446 base 16 - result = %d\n", is_armstrong_number(16, 0x2446));
printf(" 022222 base 8 - result = %d\n", is_armstrong_number(8, 022222));
}
At the start of is_armstrong_number we compute the number of digits directly instead of looping through the number. We then loop through the digits of n in base b, summing up the value of the digit raised to the number of digits in the number, for the given numeric base. Once the remainder hits zero we know there are no more digits to compute and we return a flag indicating if the given number is an Armstrong number in the given base.
I am getting an error when compiling this code. Z is the final count of coins needed to make change with aim being to use minimum number of coins. I defined int Z = 0 near the top. I've tried adding int z again and changing type to f in print statement but no luck.
Here's the error:
error: format specifies type 'int' but the argument has type '<dependent type>' [-Werror,-Wformat]
greedy.c:77:16: error: use of undeclared identifier 'z'
printf("%i\n", z);
Here is my code. I am a beginner so any suggestions or corrections would be welcome.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
//prompt user for amount of change owed
float f;
int num; //amount of change
do
{
printf("O hai! How much change is owed?:\n");
f = get_float();
}
while (f < 0); //verify input is positive
num = round(f * 100); //rounds float
//commence making change
do{
int c, e, i, j;
int z = 0; //z = coins
if (num % 25 == 0) // verifies that num is divisible by 25 so only 25c coins necessary
{
z = (num/25) + z; // updates final number of 25c coins
}
else if (num % 25 > 0)
{
i = num / 25;
j = num % 25;
}
else if ((num / 25 < 0) || (num >=10 && num < 25)) //this means that f is less than 25 cents so has to be divided by 10 cent coins
{
num = c;
c = j + c; //add remainder of num to the number to start with
}
if (c % 10 == 0) // c is less than 25c but divisible by 10c pieces
{
z = (c / 10) + z; //d is the final number of 10c coins
}
else if (c /10 < 1) //this means it's less than 10c
{
c = e; // Then c must be less than 10c
}
else if (e % 5 == 0) // divisible by 5c pieces
{
z = (e / 5) + z; // g is the number of 5 cent pieces
}
else if (e % 5 < 0)
{
z = (e / 1) + z; //h is the number of pennies
}
}
while (num > 0); //num is rounded float
printf("%i\n", z);
}
Firstly, I suggest you should format your code properly with indents.
Then, the cause of error is that z is declared inside the block associated to do loop and printf("%i\n", z); is out of its scope.
To get rid of this error, declare z at the place where visible from the printf() call -- for example, just before the do loop.
Note that declaring int Z = 0 won't work because identifiers' names are case-sensitive in C.
Like already said, you are declaring z inside the do-while loop, so it's visible only inside the loop.
You should declare it before the loop starts, so you can use it after the loop ends as well. Like this:
int z = 0; //z = coins
do{
***YOUR CODE***
} while();
I have started the CS50x problem set 1; however my programme seems to stop after I have input the the number for height.
I.e. the programme will ask for a number between 8 and 23 (repetitively until it gets a correct input) and once I do so the code stops.
What have I done wrong here?
Below is the code I have written. All help would be greatly appreciated as I have looked at various questions on here S.E. but none addressing this problem.
include stdio.h
include cs50.h
int main (void)
{
printf("ok lets make a pyramid :)\n");
// height = x
int x;
// spaces = z
int z;
// hashes = a
int a;
// Get correct number for height
do
{
printf("Give me a positive number between 8 and 23 for the height of the pyramid\n");
x = GetInt();
}
while (x < 8 || x > 23);
// Build the phantom pyramid
for (int q = 0; q == x; q++)
{
// Spaces
for (z = x - 1; z == 0 ; z--)
{
printf(" ");
}
// Hashtags
for (a = 1; a == q; a++)
{
printf("#\n");
}
}}
Aside from that your #include syntax is wrong (#include <stdio.h>), your fundamental problem here, and the reason that your program exits without printing anything, is that the main for loop is never entered. C for loops are executed while the controlling expression is true, not until is is true. You have:
for (int q = 0; q == x; q++){ ... }
Since q == x evaluates to 0 (false), because q is 0 and x is between 8 and 23, this loop never executes, and the program exits. Each of your loops has this problem. You can fix it:
for (int q = 0; q < x; q++)
{
// Spaces
for (z = x - 1; z > 0 ; z--)
{
printf(" ");
}
// Hashtags
for (a = 0; a <= q; a++)
{
printf("#");
}
printf("\n");
}
Here, note that in the first pass through the loop, q is 0, so a must start at 0 to print a single hash on the first line. Also, the newline character is not printed until the loop is finished printing the line. These changes give this output for a height of 8:
#
##
###
####
#####
######
#######
########
I am not sure if this is the output that you want. The spacing on the left is tied to the height of the pyramid. If you want the pyramid steps on the left, you can change the associated for statement:
for (z = x - 1; z > q ; z--)
But I was under the impression that the Mario Pyramid had the steps on the left, and two hashes in the top line. You could modify your loop to do this, but here is a different loop. You don't need the variable a, and rather than thinking of z as "spaces", think of it as representing the line-position:
for (int q = x; q > 0; q--) {
// print spaces at beginning of line
for (z = 1; z < q; z++) {
printf(" ");
}
// print hashes at end of line
for ( ; z < x + 2; z++) {
printf("#");
}
// print newline when finished printing line
printf("\n");
}
The new loop gives this output for a height of 8:
##
###
####
#####
######
#######
########
#########