I need help to understand this code clearly, please help. I can't figure out how this program keep track of how many number has given in responses array.
I don't understand what's going on the for loop and specially this line ++frequency[responses[answer]];
#include<stdio.h>
#define RESPONSE_SIZE 40
#define FREQUENCY_SIZE 11
int main(void)
{
int answer; /* counter to loop through 40 responses */
int rating; /* counter to loop through frequencies 1-10 */
/* initialize frequency counters to 0 */
int frequency[FREQUENCY_SIZE] = {0};
/* place the survey responses in the responses array */
int responses[RESPONSE_SIZE] = {1,2,6,4,8,5,9,7,8,10,1,6,3,8,6,10,3,8,2,7,6,5,7,6,8,6,7,5,6,6,5,6,7,5,6,4,8,6,8,10};
/* for each answer, select value of an element of array responses
and use that value as subscript in array frequency to determine element to increment */
for(answer = 0 ; answer < RESPONSE_SIZE; answer++){
++frequency[responses[answer]];
}
printf("%s%17s\n", "Rating", "Frequency");
/* output the frequencies in a tabular format */
for(rating = 1; rating < FREQUENCY_SIZE; rating++){
printf("%6d%17d\n", rating, frequency[rating]);
}
return 0;
}
++frequency[responses[answer]] is a dense way of writing
int r = response[answer];
frequency[r] = frequency[r] + 1;
with the caveat that frequency[r] is only evaluated once.
So, if answer equals 0, then responses[answer] equals 1, so we add 1 to frequency[1].
Edit
The following table shows what happens to frequency through the loop (old value => new value):
answer response[answer] frequency[response[answer]]
------ ---------------- ---------------------------
0 1 frequency[1]: 0 => 1
1 2 frequency[2]: 0 => 1
2 6 frequency[6]: 0 => 1
3 4 frequency[4]: 0 => 1
... ... ...
10 1 frequency[1]: 1 => 2
etc.
for(answer = 0 ; answer < RESPONSE_SIZE; answer++){
++frequency[responses[answer]]; // <---
}
This above loop just counts the number of times a number appear in array responses and that is stored at that number's index in array frequency. This line does that in first loop -
++frequency[responses[answer]];
So , it increments value at index responses[answer] of array frequency.
Lets say responses[answer] has value 1 , then value at index 1 of array frequency is incremented.
Second for loop is just for output as mentioned.
Related
(I'll start by noting this lab is low level 1st year programing, so high level stuff isn't usable right now for us)
I was given a lab to write a program in C that would accept a number between 1 and 36, six times, then print out those numbers as a bar graph, where the 'bar graph' is a number of # equal to the input number.
e.g. 5 would be:
So far I have this:
#include <stdio.h>
void graphCreate();
int main(void)
{
graphCreate();
}
void graphCreate()
{
static int chartLoop = 1;
int graphLength = 0;
int graphNumber = chartLoop;
while(graphLength > 36 || graphLength < 1)
{
printf("How long is chart %d?\t", graphNumber);
scanf("%d", &graphLength);
}
if(chartLoop < 6)
{
chartLoop++;
graphCreate();
}
printf("\n%d.\t%d|", graphNumber, graphLength);
while(graphLength > 0)
{
printf("#");
graphLength--;
}
}
And it does the output as expected... mostly:
How long is chart 1? 5
How long is chart 2? 10
How long is chart 3? 15
How long is chart 4? 20
How long is chart 5? 25
How long is chart 6? 30
6. 30|##############################
5. 25|#########################
4. 20|####################
3. 15|###############
2. 10|##########
1. 5|#####
However, I need the final outputs (the bars) in 1 -> 6 order, and it's reversed. What am I doing wrong that it's in reverse?
If using the recursive way to solve the problem is a requirement, you need to store the outputs and then print them in reverse order.
If recursive is not a requirement, you can loop 6 times to get and store the input numbers and print the bars in sequence.
I have written the following program in C using OpenMP library for parallel programming to find the sum of an array of size 10000000. The expected output should be sum of elements = 10000000 but the output I am getting is less than the sum.
#include <stdio.h>
#define ARR_SIZE 10000000
int a[ARR_SIZE];
int main(int argc, char* argv[])
{
int i,tid,numt;
int sum=0;
double t1,t2;
for(i=0;i<ARR_SIZE;i++)
a[i]=1;
t1=omp_get_wtime();
#pragma omp parallel default(shared) private(i,tid)
{
int from,to;
tid=omp_get_thread_num();
numt=omp_get_num_threads();
from = (ARR_SIZE/numt)*tid;
to= (ARR_SIZE/numt)*(tid+1)-1;
if(tid == numt-1)
to= ARR_SIZE-1;
printf("Hello from %d of %d , my range is from = %d to %d \n",tid,numt,from,to);
for(i=from;i<=to;i++)
sum+=a[i];
}
t2=omp_get_wtime();
printf("Sum of the array elements = %d time = %g \n",sum,t2-t1);
return 0;
}
Some of the sample outputs are :
Output 1
Hello from 0 of 4 , my range is from = 0 to 2499999
Hello from 3 of 4 , my range is from = 7500000 to 9999999
Hello from 1 of 4 , my range is from = 2500000 to 4999999
Hello from 2 of 4 , my range is from = 5000000 to 7499999
Sum of the array elements = 3235618 time = 0.118754
Output 2
Hello from 3 of 4 , my range is from = 7500000 to 9999999
Hello from 0 of 4 , my range is from = 0 to 2499999
Hello from 2 of 4 , my range is from = 5000000 to 7499999
Hello from 1 of 4 , my range is from = 2500000 to 4999999
Sum of the array elements = 2964874 time = 0.129216
What is the reason that the given sum is less than the actual sum.
The update of sum variable isn't an atomic operation and is prone to races. Races of this type are likely to yield a lesser than expected sum.
The summing boils down to something of this kind:
Load to register from memory location
Add new value to the register
Store the register value back to the memory
Now when 4 threads perform the above without consideration of one to another, some additions will be lost, resulting in a sum that is below of what was expected.
For example, with 2 threads (for simplicity):
Thread 1: Load to a register from memory location
Thread 2: Load to a register from memory location
Thread 1: Add new value to the register
Thread 2: Add new value to the register
Thread 1: Store the register value back to the memory
Thread 2: Store the register value back to the memory
In this example, at the end the addition of thread 1 will be overridden.
You should make sure the summation is done atomically to avoid races.
Without using an array, I am trying to do this. what is wrong with my code?
n is the number of elements,a is the first element(assumed to be maximum initially), b stores new element every time and sec variable stores the second-largest element. Numbers are all positive. This is from an online contest.
#include<stdio.h>
int main() {
int i,a,b,max,n,sec;
scanf("%d",&n);
scanf("%d",&a);
max=a;
while(n-1!=0) {
scanf("%d",&b);
if(b>max) {
sec=max;
max=b;
}
else if(b<max && b>sec)
sec=b;
else{}
n--;
}
printf("%d",sec);
return 0;
}
getting wrong answers in some test cases( i don't know )
Consider sequence 2, 12, 10 (leaving out surrounding code):
int sec; // unitialised!!!
max = a; // 12
if(b > max) // b got 10, so false!
{
sec = max; // this code is not hit! (b remains uninitalised)
max = b;
}
else if(b < max && b > sec)
// ^ comparing against uninitialised
// -> UNDEFINED BEHAVIOUR
You need to initialise sec appropriately, e. g. with INT_MIN (defined in <limits.h>); this is the minimal allowed value, with 32-bit int that would be a value of -232 - 1, i. e. -2 147 483 648. Pretty unlikely anybody would enter that value, so you could use it as sentinel.
You even could initialise max with that value, then you woudn't need special handling for the first value:
int sec = INT_MIN, max = INT_MIN;
int n;
scanf("%d", &n); // you should check the return value, which is number of
// successfully scanned values, i. e. 1 in given case,
// to catch invalid user input!
// you might check value of n for being out of valid range, at very least < 0
while(n--) // you can do the decrement inside loop header already...
{
// keep scope of variables as local as possible:
int a;
// scanf and comparisons as you had already
// again don't forget to check scanf's return value
}
if(sec == INT_MAX)
{
// likely hasn't been modified -> error, no second largest element
}
else
{
// ...
}
Now what if you do expect user to give you the value of INT_MIN as input?
You could have a separate counter, initialised to 0, you increment in both of the two if branches inside the loop; if this counter is < 2 after the loop, you didn't get at least two distinct numbers...
Lets look at the input
2 4 3
Two is the number of inputs.
4 ends up in max.
3 ends up in b.
b is not greater than max, the if does not do anything.
b is less than max, but b is not necessarily greater than sec,
because sec at this point can be anything - whatever currently is inside that non-initialised variable. sec at this point is for example not guaranteed to be 0. So the else if does not trigger and we end up in else {}.
So we end up executing the printf() at the end of the program with a still uninitialised sec. And that is unlikely to satisfy the judge.
To solve the problem, you need to initialise sec. Initialising to 0 might work, but actually you need to use the lowest possible input value.
Since you chose int, instead of unsigned int, I assume that 0 is NOT the lowest possible value. But you would have to quote the assignment/challenge to allow determining the lowest possible value. So you need to find that out yourself in order to make a solution code.
Alernatively, you can analyse the first input values to initialise max and sec (need to watch them coming in until you get two distinct values; credits to Aconcagua).
Usually it is however easier to determine the lowest possible value from requirements or the lowest possible int value from your environment.
At some level of nitpicking, you need to know the lowest possible value anyway, in order to select the correct data type for your implementation. I.e. even with analysing the first two values, you might fail for selecting the most narrow data type.
In case you "successfully" (as judged by the challenge) use 0 to initialise sec, try the input 2 1 -1.
It should fail.
Then try to find in your challenge/assignment description a reason why using 0 is allowed. It should be there, otherwise find a different challenge site to improve your coding skills.
I liked how OP initialized max with the first input value.
This brought me to the idea that the same can be done for sec.
(The value of max is a nice indicator that sec could not be determined whatever max contains. In regular case, max and sec can never be equal.)
Hence, one possibility is to initialize max and sec with the first input
and use max != sec as indicator whether sec has been written afterwards at all.
Demo:
#include <stdio.h>
int main()
{
/* read number of inputs */
int n;
if (scanf("%d", &n) != 1 || n < 1) {
fprintf(stderr, "ERROR!\n");
return -1;
}
/* read 1st input */
int max;
if (scanf("%d", &max) != 1) {
fprintf(stderr, "ERROR!\n");
return -1;
}
--n;
int sec = max;
/* read other input */
while (n--) {
int a;
if (scanf("%d", &a) != 1) {
fprintf(stderr, "ERROR!\n");
return -1;
}
if (max < a) { sec = max; max = a; }
else if (sec == max || (sec < a && a < max)) sec = a;
}
/* evaluate result */
if (sec == max) {
puts("No second largest value occurred!\n");
} else printf("%d\n", sec);
/* done */
return 0;
}
Output:
$ gcc -std=c11 -O2 -Wall -pedantic main.c
$ echo -e "3 3 4 5" | ./a.out
4
$ echo -e "3 3 5 4" | ./a.out
4
$ echo -e "3 4 3 5" | ./a.out
4
$ echo -e "3 4 5 3" | ./a.out
4
$ echo -e "3 5 3 4" | ./a.out
4
$ echo -e "3 5 4 3" | ./a.out
4
$ # edge case:
$ echo -e "2 3 3" | ./a.out
No second largest value occurred!
Live Demo on coliru
I wrote this implementation of Dijksta's Algorithm, which at each iteration of the loop while Q is not empty instead of finding the minimum element of the queue it takes the head of the queue.
Here is the code i wrote
#include <stdio.h>
#include <limits.h>
#define INF INT_MAX
int N;
int Dist[500];
int Q[500];
int Visited[500];
int Graph[500][500];
void Dijkstra(int b){
int H = 0;
int T = -1;
int j,k;
Dist[b] = 0;
Q[T+1] = b;
T = T+1;
while(T>=H){
j = Q[H];
Visited[j] = 1;
for (k = 0;k < N; k++){
if(!Visited[k] && Dist[k] > Graph[j][k] + Dist[j] && Graph[j][k] != -1){
Dist[k] = Dist[j]+Graph[j][k];
Q[T+1] = k;
T = T+1;
}
}
H = H+1;
}
}
int main(){
int src,target,m;
int a,w,b,i,j;
scanf("%d%d%d%d",&N,&m,&src,&target);
for(i = 0;i < N;i ++){
for(j = 0;j < N;j++){
Graph[i][j] = -1;
}
}
for(i = 0; i< N; i++){
Dist[i] = INF;
Visited[i] = 0;
}
for(i = 0;i < m; i++){
scanf("%d%d%d",&a,&b,&w);
a--;
b--;
Graph[a][b] = w;
Graph[b][a] = w;
}
Dijkstra(src-1);
if(Dist[target-1] == INF){
printf("NO");
}else {
printf("YES\n%d",Dist[target-1]);
}
return 0;
}
I ran this for all the test cases i ever found and it gave a correct answer.
My question is the why do we need to find the min at all? Can anyone explain this to me in plain english ? Also i need a test case which proves my code wrong.
Take a look at this sample:
1-(6)-> 2 -(7)->3
\ /
(7) (2)
\ /
4
I.e. you have edge with length 6 from 1 to 2, edge with length 7 from 2 to 3, edge with length 7 from 1 to 4 and edge from 4 to 3. I believe your algorithm will think shortest path from 1 to 3 has length 13 through 2, while actually best solution is with length 9 through 4.
Hope this make it clear.
EDIT: sorry this example did not brake the code. Have a look at this one:
8 9 1 3
1 5 6
5 3 2
1 2 7
2 3 2
1 4 7
4 3 1
1 7 3
7 8 2
8 3 2
Your output is Yes 8. While a path 1->7->8->3 takes only 7. Here is a link on ideone
I think your code has the wrong time complexity. Your code compares (almost) all pairs of nodes, which is of quadratic time complexity.
Try adding 10000 nodes with 10000 edges and see if the code can execute within 1 seconds.
It is always mandatory to find out the unvisited vertex with minimum distance else you will get at least one
of the edges wrong. For Example, consider the following case
4 4
1 2 8
2 4 5
1 3 2
3 2 1
(8) (5)
1-----2----4
\ /
(2)\ / (1)
3
and we start with vertex 1
distance[1]=0
when you have visited vertex 1 you have relaxed vertex 2 and vertex 3
so now
distance[2]=8 and distance[3]=2
after this, if we don't select the minimum and choose vertex 2 instead, we get
distance[4]=13
and then select vertex 3 which will give
distance[2]=3
and hence we end up with distance[4]=13 which should have been
distance[4]=8
hence we should choose minimum from unvisited at each stage of Dijkstra which can be efficiently done using priority_queue.
If you run the algorithm for the following graph it depends on the order of the children. Let's say we are looking for shortest path from 1 to 4.
If you start from the queue with 1,
dist[1] = 0
dist[2] = 21
dist[3] = 0
and seen = {1} while the queue is pushed with 2 and 3 now if we consume 2 from the queue it will make dist[4] = 51,seen={1,2}, q = [1,2,3,4] and next time when 3 is consumed from the queue 2 won't be added to queue again since it is already in seen. Hence the algorithm will later update the distance to 12+31=43 from the path of 1->3-5->4 however the shortest path is 32 and it is on 1->3->2->4.
Let me discuss some other aspects with code examples. Let's say we have a connection list of (u,v,w) where node u has a weighted and directed edge to v with weight w. And let's prepare the graph and edges as below:
graph, edges = {i: set() for i in range(1, N+1)}, dict()
for u,v,w in connection_list:
graph[u].add(v)
edges[(u,v)] = w
ALGORITHM1 - Pick any child to add if not visited
q = deque([start])
seen = set()
dist = {i:float('inf') for i in range(1, N+1)}
dist[start] = 0
while q:
top = q.pop()
seen.add(top)
for v in graph[top]:
dist[v] = min(dist[v], dist[top] + edges[(top, v)])
if v not in seen:
q.appendleft(v)
This one is already discussed above and it will give us the incorrect result 43 instead of 32 for the shortest path between 1 and 4.
The problem was not to re-add 2 to the queue, then let's get rid of seen and the children again.
ALGORITHM2 - Add all children to the queue again
while q:
top = q.pop()
seen.add(top)
for v in graph[top]:
dist[v] = min(dist[v], dist[top] + edges[(top, v)])
q.appendleft(v)
This will work in that case, but it works only for this example though. Two issues with this algorithm,
We are adding the same nodes again so for a bigger example the complexity will depend on number of edges E instead of number of nodes V and for a dense graph we can assume O(E) = O(N^2).
If we add cycles in the graph it would run forever since there is no check to stop. So this algorithm is not a fit for cyclic graphs.
So that's why we have to spend extra time to pick the minimum child if we do it with a linear search we would end up with the same complexity as above. But if we use a priority queue we can reduce the min search to O(lgN) instead of O(N). Here is the linear search update on the code.
ALGORITHM3 - Dirty Dijkstra's Algorithm with linear minimum search
q = [K]
seen = set()
dist = {i:float('inf') for i in range(1, N+1)}
dist[start] = 0
while q:
min_dist, top = min((dist[i], i) for i in q)
q.remove(top)
seen.add(top)
for v in graph[top]:
dist[v] = min(dist[v], dist[top] + edges[(top, v)])
if v not in seen:
q.append(v)
Now we know the thought process we can remember to use a heap to have the optimal Dijkstra's algorithm next time.
Suppose the Array[10] = {10,6,11,9,-18,0,91,18,24,32}
The largest sequence will be 10,11,18,24,32 or -18,0,18,24,32
The solution to this is make another Array[10] which will store the number of sequences. Starting from the last element 32 which makes just 1 sequence i.e. the number itself.
24 makes 2
18 makes 3
91 makes 1
0 makes 4
-18 makes 5
9 makes 4
11 makes 4
6 makes 4
10 makes 5
The output should be either 5 starting from -18 or 5 starting from 10.
Can anyone help me with the code please.
more or less it will look like that, now you need to translate this to language what you are using
largestSequience = [];
temporaryArray = [];
for (element in array)
{
if (temporatySize not empty and temporarySize[lastElement]>=element)
{
if (temporaryArray.length > largestSequence.length) largestSequence = temporaryArray;
temporaryArray = [element]
}
temporaryArray.add(element)
}
What you want in C++. The running time is O(NlogN), in which N is the size of Array[]
#include<stdio.h>
#include<map>
using namespace std;
int main(void) {
int Array[10] = {10,6,11,9,-18,0,91,18,24,32};
int p[10],next[10];
int i,j,n=10;
map<int,int> places;
for(i=n;i>=0;i--){
map<int,int>::iterator ii=places.upper_bound(Array[i]);
if(ii==places.end()){ //no item on the right is larger
p[i]=1;
next[i]=-1;
}else{
next[i]=ii->second;
p[i]=p[ii->second]+1;
}
places[Array[i]]=i;
ii=places.find(Array[i]);
while(ii!=places.begin()){
ii--;
if(p[ii->second]<=p[i]){
places.erase(ii);
}else
break;
ii=places.find(Array[i]);
}
}
int longestI=0;
for(i=1;i<n;i++){
if(p[i]>p[longestI])
longestI=i;
}
for(i=longestI;i>=0;i=next[i]){
printf("%d\n",Array[i]);
}
return 0;
}