For-loop not working as intended - c

When I run this code, the printf() function seems to give a random large number, as if it is calling an array that is out of bounds. What is going on here?
#include <stdio.h>
#include <math.h>
int main(void)
{
int test_num = 1000;
int factors[16];
for(int i = 1, j = 0; i < test_num; i++, j++) {
if(test_num % i == 0)
factors[j] = i;
}
printf("%d", factors[2]);
return 0;
}

Most likely, the problem is that you are incrementing j even when you don't assign i.
The sequence of factors you get is 1, 2, 4, 5, 8, 10, ... You probably want to assign those to the indices 0-5 (inclusive), not 0, 1, 3, 4, 7, 9, etc.
Change your loop as follows:
for(int i = 1, j = 0; i < test_num && j < 16; i++) {
if(test_num % i == 0) {
factors[j] = i;
j++;
}
}
The main point is only to increment j when i fits your criterion. You also want to make sure that you don't go out of bounds (&& j < 16).

If you print out i and j in the loop, notice that j is never 2.
Thus, factors[2] is never initialized, so you will print out junk.

When j == 2, i == 3 and 1000 % 3 does not equal 0. It equals 1. Not passing your if statement condition. Therefore factors[2] will be undefined (since you didn't initialize your array). Hence the large number.

Related

How to calculate the number of triangles that can be formed

The code below should have counted the number of triangles that can be formed out of every triplet of 3 distinct integers from the given range 1...N. However, when I input 5, it gives me 34, while the right answer is 3: the only possible triangles are (2, 3, 4), (2, 4, 5) and (3, 4, 5).
// C code to count the number of possible triangles using
#include <stdio.h>
int main()
{ int N, count=0;
setvbuf(stdout, NULL, _IONBF, 0);
printf("Please input the value of N: \n");
scanf("%d", &N );
for (int i = 1; i < N; i++) {
for (int j = 1; j < N; j++) {
// The innermost loop checks for the triangle
// property
for (int k = 1; k < N; k++) {
// Sum of two sides is greater than the
// third
if (i + j > k && i + k > j && k + j > i)
{
count++;
}
}
}
}
printf ("Total number of triangles possible is %d ",count);
return 0;
}
You do not ensure that the numbers are distinct.
You can do this be chosing your loop limits correctly:
for (int i = 1; i <= N-2; i++) {
for (int j = i+1; j <= N-1; j++) {
for (int k = j+1; k <= N; k++) {
Start each inner loop one higher than current counter of outer loop. It also does not make any sense to run each loop up to N. If they must be distinct, you can stop at N-2, N-1, N
This creates triples where numbers are increasing.
If you consider triangles (3,4,5) and (4,3,5) to be different, we must also account for permuations of these triples.
As all values are distinct, we have 6 possible permutations for each triple that was found in the inner loop.
I'm sorry, I can't go for a comment so let's go for an answer.
I don't really get what you wish to do. As I am understanding it, you wish to print this :
1, 2, 3, 4, 5-> [2, 3, 4], [2, 4, 5], [3, 4, 5] -> 3
Except, with your code, you'll never check your N since you go out of your loop when i turns into N.
Also, your "j" and "k" don't have to move starting 1 since you already tried that position with "i", so you'll only get doublons doing that.
EDIT : some changes for a smarter code (I removed my +1 but go check for "<=", which I personnaly dislike :) ):
// since [1, 2, 3] can't bring any triangle
if (N < 4) return 0;
// since there is no possible triangle with 1 as a border, start at 2
for (int i = 2; i <= N-2; i++) {
for (int j = i+1; j <= N-1; j++) {
// The innermost loop checks for the triangle
// property
for (int k = j+1; k <= N; k++) {
// Sum of two sides is greater than the
// third
// simplified as suggested by S M Samnoon Abrar
if (i + j > k)
{
count++;
}
}
}
You need to do the following:
run first loop through 1 to N, i.e.: 1 <= i <= N
don't start each nested loop from index 1. So, you need to run first nested loop in range i+1 <= j <= N and second nested loop in range j+1 <= k <=N.
Explanation
First, if you run all 3 loops from 1 to N, then you are not doing distinct counting because all numbers in the range will be iterated 3 times. So it would give an incorrect result.
Secondly, since we need to count distinct numbers only, it is efficient to count +1 from the previous outer loop each time. In this way, we are ensuring that we are not iterating over any number twice.
Check the following code:
// C code to count the number of possible triangles using
#include <stdio.h>
int main()
{ int N, count=0;
setvbuf(stdout, NULL, _IONBF, 0);
printf("Please input the value of N: \n");
scanf("%d", &N );
for (int i = 1; i <= N; i++) {
for (int j = i+1; j <= N; j++) {
// The innermost loop checks for the triangle
// property
for (int k = j+1; k <= N; k++) {
// Sum of two sides is greater than the
// third
if (i + j > k && i + k > j && k + j > i)
{
count++;
}
}
}
}
printf ("Total number of triangles possible is %d ",count);
return 0;
}
Spot the extra line of code that enforces the constraint that the 3 numbers are "distinct" (read "unique"). Funny what a little "print debugging" can turn up...
printf("Please input the value of N: ");
scanf("%d", &N );
for (int i = 1; i < N; i++) {
for (int j = 1; j < N; j++) {
for (int k = 1; k < N; k++) {
if (i + j > k && i + k > j && k + j > i) {
if( i != j && j != k && k != i ) {
printf( "%d %d %d\n", i, j, k );
count++;
}
}
}
}
}
printf ("Total number of triangles possible is %d ",count);
Output
Please input the value of N: 5
2 3 4
2 4 3
3 2 4
3 4 2
4 2 3
4 3 2
Total number of triangles possible is 6
The OP code was counting (1,1,1) or (2,3,3) in contravention of "distinct" digits.
AND, there is now ambiguity from the OP person as to whether, for instance, (4,2,3) and (4,3,2) are distinct.
printf() - the coder's friend when things don't make sense...

Why is the output 321 instead of 212?

#include <stdio.h>
int main()
{
int i;
int j;
int k;
for(i = 1, j = 0, k = 3 ; i <= 5, j <= 6, k > 1 ;i++, j++, k--);
{
printf("%d%d%d", i, j, k);
}
}
Why is this program printing 321 instead of 212?
I get 321 when I execute the program but I think it should be 212. I cannot understand why it is printing 321.
That's because you have a semicolon at the end of the for loop, so the code runs essentially like this:
// first you increment i,j and decrement k until k is 1, so twice
for(i = 1, j = 0, k = 3 ; i <= 5, j <= 6, k > 1 ;i++, j++, k--) {}
// then you print the values
printf("%d%d%d", i, j, k);
You have 2 bugs.
The first was already mentioned and should also be reported by your compiler.
You have a stray semicolon after your for loop.
The second is that your condition is rather strange: i <= 5, j <= 6, k > 1
Relational operators have higher precedence than coma operator. That means this condition is same as (i <= 5), (j <= 6), (k > 1) which again is same as k>1.
If you want to have all the relational operands evaluate to true, you must add logical operator: i <= 5 && j <= 6 && k > 1

Checking 5 ints in an array if 3 are the same

I have a int array that contains five random numbers. I am trying to check if three of the numbers match.
int die[5] = {2, 3, 5, 2, 1};
int kind = 0;
int score = 0;
int i = 0;
int x = 0;
for (i; i <= 4; i++) {
for (x; x <= 4; x++) {
if (die[i] == die[x]) {
kind++;
score += die[i];
}
}
}
The issue I am running into is the very first case it will compare itself to itself. Which will always come back true. And if I add a +1 to the index, it will end up going out of bounds.
If I start at 1 instead of 0, then when it goes to the second digit, it will return the same once it checks itself against the 2nd number(itself).
You could check if i equals j and just continue; your loop.
for(i=0; i<=4; i++){
// you can set x=i+1 and skip some numbers
for(x=0; x<=4; x++){
if(i==x)
continue;
if (die[i] == die[x]) {
kind++;
score += die[i];
}
}
}
EDIT:
There are simpler ways of doing this (checking if 3 numbers are equal), but if you just want to skip an iteration, use continue.
int die[5] = {2, 3, 5, 2, 1};
int kind = 0;
int score = 0;
for (i = 0; i < 4; i++) { // last check will be die[3] == die[4] to avoid
// die[4] == die[4]
for (x = i + 1 ; x < 5; x++) { // it always checks with the next element
if (die[i] == die[x]) {
kind++;
score += die[i];
}
}
}

How to get adjacent elements of an element in 2D array programatically?

Suppose you have a 2D array arr[N][N]. If I give an input arr[i][j] to you, I should get left, right, top and down elements i.e. arr[i][j-1], arr[i][j+1], arr[i-1][j] and arr[i+1][j].
Eg: Arr[3][3]= {1, 2, 3, 4, 5, 6, 7, 8, 9}
Input: 5
Output: 4, 6, 2, 8
Input: 1
Output: null, 2, null, 4
How can I write a program that should consider boundary conditions?
So your program consists of two parts:
Finding if the input exists at some index. Find it by looping through your array, like so:
for( int i = 0; i < N; i++ ){
for( int j = 0; j < N; j++ ){
if(arr[i][j] == input) //produce output
}
}
Producing output. For simplicity i will just print it out, though if your goal is a function that returns the values around the input number then you should malloc an array and copy over the values to the array. To print, check first if we are in bounds, and do not attempt to print if we are out of bounds, otherwise there will be issues.
for( int k = i - 1 ; k < i + 2; k++ ){
for(int l = j - 1; l < j + 2; j++ ){
if ( k > -1 && l > -1 && k < N && j < N ){ // check if in bounds
printf("%i ", arr[k][l]);
}
}
}
When you are accessing an index in array, just make sure that you are not accessing an invalid index, like index < 0 or index > size. So in your case
if(j > 0) System.out.println(a[i][j-1]);
if(i > 0) System.out.println(a[i-1][j]);
if(j < N-1) System.out.println(a[i][j+1]);
if(i < N-1) System.out.println(a[i+1][j]);
If you want to return null if the index is not valid, just add in in else part for each if.

Generate "In-Range" Random Numbers in C

I need to generated random numbers in the range [0, 10] such that:
All numbers occur once.
No repeated results are achieved.
Can someone please guide me on which algorithm to use?
The algorithm in Richard J. Ross's answer is incorrect. It generates n^n possible orderings instead of n!. This post on Jeff Atwood's blog illustrates the problem: http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html
Instead, you should use the Knuth-Fisher-Yates Shuffle:
int values[11] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
srand(time(NULL));
for (int i = 10; i > 0; i--)
{
int n = rand() % (i + 1);
int temp = values[n];
values[n] = values[i];
values[i] = temp;
}
Try out this algorithm for pseudo-random numbers:
int values[11] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
srand(time(NULL));
for (int i = 0; i < 11; i++)
{
int swap1idx = rand() % 11;
int swap2idx = rand() % 11;
int tmp = values[swap1idx];
values[swap1idx] = values[swap2idx];
values[swap2idx] = tmp;
}
// now you can iterate through the shuffled values array.
Note that this is subject to a modulo bias, but it should work for what you need.
Try to create a randomize function, like this:
void randomize(int v[], int size, int r_max) {
int i,j,flag;
v[0] = 0 + rand() % r_max; // start + rand() % end
/* the following cycle manages, discarding it,
the case in which a number who has previously been extracted, is re-extracted. */
for(i = 1; i < size; i++) {
do {
v[i]= 0 + rand() % r_max;
for(j=0; j<i; j++) {
if(v[j] == v[i]) {
flag=1;
break;
}
flag=0;
}
} while(flag == 1);
}
}
Then, simply call it passing an array v[] of 11 elements, its size, and the upper range:
randomize(v, 11, 11);
The array, due to the fact that it is passed as argument by reference, will be randomized, with no repeats and with numbers occur once.
Remember to call srand(time(0)); before calling the randomize, and to initialize int v[11]={0,1,2,3,4,5,6,7,8,9,10};

Resources