Can't Count - Number of Comparison Operations - c

So I have this segment of code that was given to me.
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++)
{
if (arr[j] < arr[i])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
I am trying to calculate the number of comparison operations that would occur if the code were to run.
There's the initial comparison all the way up to i=100. so there's 101 comparisons for the outer loop. The inner loop also has 101 loops, but that comparison within will only happen 100 times due to the j=100 will not have that comparison occurring.
I've made a tries but none of been the right answer so far.
I've had 101 x (101+100) = 20301 which is not the right answer.
I've searched for this on google and came up with a question identical to this but was answering how many assignment operations that occur which I was able to answer on my own. Which btw is 25201.

I got 20201.
#include <stdio.h>
int main(void) {
int i, j;
unsigned long count;
count = 0;
for (i = 0; ++count, i < 100; ++i) {
for (j = 0; ++count, j < 100; ++j) {
++count;
}
}
(void) printf("%lu\n", count);
return 0;
}

100 comparisons on the outer loop drive 101 + 100 comparisons on the inner loop. There is one more comparison on the outer loop to detect loop termination, so:
100 * (101 + 100) + 101 = 20201.
Instrumenting the program:
outer_cmps=0;
total_inner_cmps=0;
for (int i = 0; i < 100; i++) {
++outer_cmps;
inner_cmps=0;
for (int j = 0; j < 100; j++)
{
++inner_cmps;
if (arr[j] < arr[i])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
++inner_cmps;
}
++inner_cmps;
tota_inner_cmps += inner_cmps;
}
++outer_cmps;
total_cmps = outer_cmps + total_inner_cmps;

So that would be 100*200+100+1=20101
(100 times i, which runs the j loop 100 times, which performs 1 comparisson if (arr[j] < arr[i]) per loop, and one i loop that fails when i==100and 100 times j loop that fail when j==100)

Related

C insertion sort stuck in while loop

I'm writing a simple program to sort a small array but when I run my code for insertion sort the program just runs forever.
It's probably a problem with the while loop. I ran through the program on paper and looked over some other people's code but I can't figure out why it's not working.
void mySort(int d[], unsigned int n){
int i, j, k;
for (j = 1;j < n;i++){
k = d[j];
i = j-1;
while (d[i] > k && i >=0){
d[i+1] = d[i];
d[i] = k;
i = i - 1;
}
}
}
for (j = 1;j < n;i++){
You compare value j, but you increment value i.
If you Use a Debugger, you would immediately notice that the value j does not get updated, and you'd find your problem immediately!!
Always Use a Debugger
The error is in your for loop.
for (j = 1;j < n;i++){
So your terminating conditions of the for loop are that j >= n, except you never change j or n after this statement.
Try
for (j = 1;j < n;j++){

Big O Notation with function composition

I'm trying to determine the Big O notation of the following function
public static int f10(int n)
{
return f1(n*n*n)
}
Where f1() is given by:
public static int f1(int n)
{
int sum = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
sum++;
for (int j = 0; j < n; j++)
sum++;
for (int j = 0; j < n; j++)
sum++;
}
return sum;
}
I can see that O(f1) is O(n^2), but when we call f10, does this become O(n^6) because the size of n is being cubed before calling f1?
I understand the complexity of f1 is not changing from it's own perspective, but is it from f10's perspective of 'n'?
Let's analyse f1():
for (int i = 0; i < n; i++) -> O(n)
for (int j = 0; j < n; j++)
for (int j = 0; j < n; j++)
for (int j = 0; j < n; j++) -> O(n)
for (n-times) { O(n) } -> O(n^2)
So f1() is O(n^2). It's just two nested loops. But because f1() is called with n^3, make f10() indeed O(n^6).
However, the above complexity order is theoretical. In practice it may depend on how you call f10() and/or what optimizations the compiler makes. A smart C compiler could replace f1() with a simple and O(1) arithmetic expression.
Then, having f1() reduced to an expression, the compiler could replace calls like f10(42) with the result, doing all calculations at compile-time.
Do you see what I mean; how would you simplify f1() to a simple O(1) expression?
Complexity of f1 is always O(n^2), that's clear. However, the complexity of f10 is indeed O(n^6), because it relies on f1 invoked with an argument n^3. For the sake of simplicity, imagine that f1 is an inlined function. Body of f10 would then look like this:
public static int f10(int n)
{
int sum = 0;
for (int i = 0; i < n^3; i++) {
for (int j = 0; j < n^3; j++)
sum++;
for (int j = 0; j < n^3; j++)
sum++;
for (int j = 0; j < n^3; j++)
sum++;
}
return sum;
}
Now it is easy to deduce - two levels of nested loops, each with n^3 iterations -> O(n^6). If you are still not convinced, try to see how the running time of f10 increases with increased input:
n = 1 -> 3 iterations
n = 2 -> 8 * 3 * 8 = 3 * 2^6 iterations
n = 3 -> 27 * 3 * 27 = 3 * 3^6 iterations
....
n = k -> k^3 * 3 * k^3 = 3 * k^6 iterations

Code to store indices of occurrences doesn't work

In the program that I'm writing, I currently have a for-loop that goes through an array, num[5], and checks to see if there are any 1's in that array, which looks like:
int counter = 0;
for (int i = 1; i <= 5; i++)
if (num[i] == 1)
counter++;
This works successfully, but I'm now trying to go through the array and see what the indices of the 1's in the program are. So, if I have 01001, I want to make an array that holds the positions of the 1's. The following is what I've tried so far:
int b[counter];
for (int k = 0; k <= counter; k++) {
for (i = 0; i <= 5; i++) {
if (num[i] == 1) {
b[k] = i;
}
}
}
but this doesn't produce the desired result. When I type the string in, say 1001, I get 444. Can someone tell me what I'm doing incorrectly?
For each value of k, for each occurrence of a 1, you're setting b[k] to the index of the 1. Thus each b[k] will have the index of the last 1.
Try:
int b[counter];
int k = 0;
for (i = 0; i <= 5; i++) {
if (num[i] == 1) {
b[k++] = i;
}
}
So, whenever it gets a 1, it assigns b[k] to the index and then increases k.
Then you should also use k, not counter, when trying to print out b.
The problem lies in this part of your code.
int b[counter];
for (int k = 0; k <= counter; k++) {
**for (i = 0; i <= 5; i++) {
if (num[i] == 1) {
b[k] = i;
}**
}
}
Suppose you get a 1 at the index 1 of the array as in 01001. You assign b[k] = 1;
This is perfectly valid. But as the loop continues you get another 1 at the index 4. Thus the command b[k] = 4; is again executed.
Note that your value of k is constant in both the statements and hence you get the array b as 44.
So what you need to do is break the inner for loop as soon as you get a 1.
Here is the modified code. You also need to keep a track of the iterator i and I have done that here using the variable- new_pos // new position.
int b[counter];
int new_pos=0; //to keep track of the iterator
for (int k = 0; k <= counter; k++) {
for (i = new_pos; i <= 5; i++) {
if (num[i] == 1) {
b[k] = i;
new_pos = i+1;
break;
}
}
}
The code provided by Dukeling is also perfect, but I am just giving another way to make your own code work.

generating random numbers with limits

What is the easiest way to generate 5 random numbers from 1 to 200 such that
randnum[0] < randnum[1] < randnum[2] < randnum[3] < randnum[4]
My code looks like this but it always overflows at randnum[4]
limit_upper = 10; // generate random number up to 10 for randnum[0]
limit_lower = 0;
srand((time(0));
for (x = 0; x < 5; x++) {
randnum[x] = 1 + limit_lower + (unsigned int) rand() % limit_upper;
limit_lower = limit_lower + randnum[x];
limit_upper = (limit_upper * 2) + (unsigned int) rand() % limit_upper;
}
The random numbers to be generated should not repeat.
Any help?
Thank you.
Generate random numbers from 1 to 200, sort them as you go, discard duplicates, until you have 5.
As azhrei pointed out, you're over complicating things. Generate five random numbers between 0 and 200 while throwing out duplicates and sort when finished. This will work well unless you're planning on expanding your code significantly beyond five numbers or have some crazy performance requirements. You'll thank yourself later for the straight forward readable bug-free code. Also, you will remove any artificial limitations to your randomness.
As the accepted answer sugggests, here is the solution:
#include <stdio.h>
#include <stdlib.h>
void quicksort(int arr[], int left, int right) {
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
};
if (left < j)
quicksort(arr, left, j);
if (i < right)
quicksort(arr, i, right);
}
int main() {
int i;
int x;
int random[5];
srand(time(0));
for (i = 0; i < 5; i++) {
random[i] = 0;
}
for (i = 0; i < 5; i++) {
random[i] = rand() % 201;
for (x = 1; x < i; x++) {
if (random[x] == random[i]) {
i--;
continue;
}
}
}
quicksort(random, 0, 4);
for (i = 0; i < 5; i++) {
printf("random[%0d]: %0d \n", i, random[i]);
}
return 0;
}
Maybe someone will find it useful.
Looking at your last line, limit_upper could become anything up to 267 by the 3rd iteration.
The max increase being limit_upper*2 + limit_upper-1 (about 3*limit_upper).
That you get the same problem every time are you seeding your random generator?
This is a classic problem covered from several angles by Jon Bentley in Programming Perls. I highly recommend this book.

What is Innermost loop in imperfectly nested loops?

Helo, I'm a bit confused about the definition of an inner loop in the case of imperfectly nested loops. Consider this code
for (i = 0; i < n; ++i)
{
for (j = 0; j <= i - 1; ++j)
/*some statement*/
p[i] = 1.0 / sqrt (x);
for (j = i + 1; j < n; ++j)
{
x = a[i][j];
for (k = 0; k <= i - 1; ++k)
/*some statement*/
a[j][i] = x * p[i];
}
}
Here, we have two loops in the same nesting level. But, in the second loop which iterates over "j" starting from j+1, there is a again another nesting level. Considering the entire loop structure, which is the inner most loop in the code ?
Both j loops are nested inside i equally, k is the inner most loop
Lol I don't know how to explain this so i'll give it my best shot I recommend using a debugger! it may help you so much you won't even know
for (i = 0; i < n; ++i)
{
//Goes in here first.. i = 0..
for (j = 0; j <= i - 1; ++j) {
//Goes here second..
//Goes inside here and gets stuck until j is greater then (i- 1) (right now i = 0)
//So (i-1) = -1 so it does this only once.
/*some statement*/
p[i] = 1.0 / sqrt (x);
}
for (j = i + 1; j < n; ++j)
{
//Goes sixth here.. etc.. ..
//when this is done.. goes to loop for (i = 0; i < n; ++i)
//Goes here third and gets stuck
//j = i which is 0 + 1.. so, j == 1
//keeps looping inside this loop until j is greater then n.. idk what is n..
//Can stay here until it hits n.. which could be a while.
x = a[i][j];
for (k = 0; k <= i - 1; ++k) {
//Goes in here fourth until k > (i-1).. i is still 0..
//So (i-1) = -1 so it does this only once
/*some statement*/
a[j][i] = x * p[i];
}
//Goes here fifth.. which goes.... to this same loop!
}
}
I'd say that k is the inner-most loop, because if you count the number of loops required to reach it from the outside, it's three loops, and that's the most out of all four of the loops in your code.

Resources