In this code I want to make Kruskal's algorithm, which calculates a minimum
spanning tree of a given graph. And I want to use min-heap and disjoint set at the code.
To make time complexity of O(e log n), where e is the number of edges and n is the number of vertices in the graph, I will use heap and disjoint set trees.
So the method I went with was:
Check the numbers of vertices and edges in the given input file and make parent array and struct edge which can include at most 10000 vertices and 50000000 edges.
Sort the edges by the weight in a min heap in descending order.
Take out edges from min heap one by one and check whether it makes cycle until min heap is empty
If the number of edges selected is vertices-1 (if all vertices already connected ) break the while loop and print each edges and sum of weights. If all vertices can make minimum spanning tree it prints connected and if all vertices can not make minimum spanning tree it prints disconnected.
I thought the code is well done but when I run this in putty, it is exiting with segmentation fault (core dumped)
input (example)
7
9
0 1 28
0 5 10
1 2 16
1 6 14
2 3 12
3 4 22
3 6 18
4 5 25
4 6 24
result(I want)
0 5 10
2 3 12
1 6 14
1 2 16
3 4 22
4 5 25
99
CONNECTED
I checked the edges are well stored in min-heap in descending order. But I think it has mistakes in making minimum spanning tree. These are points that I am suspicious in the code.
Should I make edge minheap by dynamic allocation instead of minheap[50000000]?
Should I make additional data structures apart from the array parent and struct edge.
It is the code I made! Can you give me help or advice ?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define maxvertice 10000
#define maxedge 50000000
typedef struct edge { //structure to store vertices and weight
int a, b;
int w;
}
edge;
int n = 0; //numbers of edge in the minheap
int parent[maxvertice] = {-1,};
//array to represent disjoint sets! parent which stores the vertice connected
//if it is not connected(independent) it's parent is -1
edge minheap[maxedge]; //heap that sorts edges
void insertheap(edge item, int * n); // arrange edges by the weight in descending order
edge deleteheap(int * n); //popping out from the root (in descending order)
void makeunion(int x, int y); // this make x and y combined
int findparent(int i);
int main(int argc, char * argv[]) {
double start, end;
int i, nv, ne, sumofweight = 0, isitdone;
int cnt_edge = 0;
edge item;
//////////////
if (argc != 2) {
printf("usage: ./hw3 input_filename\n");
return 0;
}
FILE * fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("The input file does not exist.\n");
return 0;
}
FILE * result = fopen("hw3_result.txt", "w");
start = (double) clock() / CLOCKS_PER_SEC;
fscanf(fp, "%d", & nv);
printf("to test : number of vertices : %d\n", nv);
fscanf(fp, "%d", & ne);
printf("to test : number of edges : %d\n", ne);
for (i = 0; i < ne; i++) {
int firstv, secondv, weight;
edge newedge;
fscanf(fp, "%d %d %d", & firstv, & secondv, & weight);
newedge.a = firstv;
newedge.b = secondv;
newedge.w = weight;
// get vertices and edge's weight from the input file and put in heap
insertheap(newedge, & n);
}
/*
for(i =0 ; i<ne; i++){
item= deleteheap(&n);
printf("%d", item.w);
}*/
while (minheap != NULL) { //pop out from the heap until mst is completed
item = deleteheap( & n);
//union at array parent
int par1, par2;
par1 = findparent(item.a);
par2 = findparent(item.b);
if (par1 != par2) {
makeunion(par1, par2);
printf("%d %d %d\n", item.a, item.b, item.w);
cnt_edge = cnt_edge + 1;
sumofweight += item.w;
}
if (cnt_edge == nv - 1) break;
}
if (cnt_edge == nv - 1) {
// fprintf(result, "CONNECTED");
printf("%d\n", sumofweight);
printf("CONNECTED");
}
if (cnt_edge < nv - 1) {
// fprintf(result, "DISCONNECTED");
printf("DISCONNECTED\n");
}
end = (((double) clock()) / CLOCKS_PER_SEC);
fclose(fp);
fclose(result);
printf("output written to hw3_result.txt.\n");
printf("running time: %1f", (end - start));
printf(" seconds\n");
}
void makeunion(int x, int y) {
parent[x] = y;
}
int findparent(int i) {
for (; parent[i] >= 0; i = parent[i]);
return i;
}
void insertheap(edge item, int * n) {
int i;
i = * n;
++( * n);
while ((i != 0) && (item.w < minheap[i / 2].w)) {
minheap[i] = minheap[i / 2];
i /= 2;
}
minheap[i] = item;
printf("to test : the wieght %d is inserted in :%d \n", item.w, i);
}
edge deleteheap(int * n) {
int parent, child;
parent = 0;
child = 1;
edge item, temp;
item = minheap[0];
temp = minheap[( * n) - 1];
( * n) --;
while (child <= * n) {
if ((child < * n) && (minheap[child].w > minheap[child + 1].w)) child++;
if (temp.w <= minheap[child].w) break;
minheap[parent] = minheap[child];
parent = child;
child *= 2;
}
minheap[parent] = temp;
return item;
}
Related
This is the code for Quick Sort. The array generated is random, using random() function, with 10,000 as upper limit.
When number of elements exceeded 109, e.g. 110, the program did not complete execution and got stuck.
This is the code:
/*
Program to sort a list of numbers using Quick sort algorithm.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// For runtime calculation
#define BILLION 1000000000
// For random number upper limit
#define UPPER_LIMIT 10000
// For printing array
#define PRINT_ARR printf("Parse %d: ", parseCount); for (int p = 0; p < eltCount; p++) printf("%d ", *(ptrMainArr + p)); printf("\n"); parseCount++;
// Declare global parse counter
int parseCount = 0;
// Declare global pointer to array
int *ptrMainArr;
// Number of elements in array
int eltCount;
float calcRunTime(struct timespec start, struct timespec end) {
long double runTime;
if (end.tv_nsec - start.tv_nsec >= 0) {
runTime = (end.tv_sec - start.tv_sec) + ((float)(end.tv_nsec - start.tv_nsec) / BILLION);
}
else {
runTime = (end.tv_sec - start.tv_sec - 1 + ((float)(end.tv_nsec - start.tv_nsec) / BILLION));
}
return runTime;
}
void swap(int *ptr1, int *ptr2) {
int temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
}
void quicksort(int *ptrArr, int numOfElts) {
// Single element in sub-array
if (numOfElts == 1) {
return;
}
// No elements in sub-array
if (numOfElts == 0) {
return;
}
// Print elements in array
PRINT_ARR
// Select pivot element (element in middle)
int pivotIdx;
// Even number of elements in array
if ((numOfElts) % 2 == 0) {
pivotIdx = ((numOfElts) / 2) - 1;
}
// Odd number of elements in array
else {
pivotIdx = (int)((numOfElts) / 2);
}
int pivot = *(ptrArr + pivotIdx);
// Initialise left and right bounds
int lb = 0, rb = numOfElts - 2;
// Swap pivot element with last element
swap(ptrArr + pivotIdx, ptrArr + numOfElts - 1);
while (1) {
while (*(ptrArr + lb) < pivot) {
lb++;
}
while (*(ptrArr + rb) > pivot && lb <= rb) {
rb--;
}
if (lb > rb) {
break;
}
swap(ptrArr + lb, ptrArr + rb);
}
swap(ptrArr + lb, ptrArr + (numOfElts - 1));
// Sort left sub-array
quicksort(ptrArr, lb);
// Sort right sub-array
quicksort(ptrArr + (lb + 1), numOfElts - lb - 1);
}
int main() {
printf("*** Quick Sort *** \n");
printf("Enter number of elements: ");
scanf("%d", &eltCount);
int arr[eltCount];
for (int i = 0; i < eltCount; i++) {
arr[i] = random() % UPPER_LIMIT + 1;
}
// Assign array to global pointer variable (to print array after each parse)
ptrMainArr = arr;
// Note: arr -> Pointer to array's first element
// Start clock
struct timespec start, end;
clock_gettime(CLOCK_REALTIME, &start);
// Sort array using quicksort
quicksort(arr, eltCount);
// End clock
clock_gettime(CLOCK_REALTIME, &end);
printf("Quick sort time taken is %f s.\n", calcRunTime(start, end));
return 0;
}
I ran this code for values under 110, and the code worked. Included is a Macro Function 'PRINT_ARR' to print the array after every parse.
I want to know the cause for the error, and how to sort an array of size > 10,000.
The partitioning function fails for any couple of equal numbers. It can be fixed just by adding an =. Moreover after swapping you can increase lb and decrease rb:
while (1) {
while (*(ptrArr + lb) < pivot) {
lb++;
}
while (*(ptrArr + rb) > pivot && lb <= rb) {
rb--;
}
if (lb >= rb) { // <--------------------------------------------------
break;
}
swap(ptrArr + lb++, ptrArr + rb--); // <------------------------------
}
Then additional suggestions:
remove the console input and use a fixed number for testing.
your calcRunTime function is broken. Just use your first equation:
long double calcRunTime(struct timespec start, struct timespec end) {
return (end.tv_sec - start.tv_sec) + ((float)(end.tv_nsec - start.tv_nsec) / BILLION);
}
don't use a VLA. malloc it, so you can grow without the risk of a stack overflow.
First I reproduced the issue by compiling your program and running it with 109 (ok) and 110 (doesn't terminate). Then I hard-coded eltCount to 110 so the program no longer requires interactive input. Removed irrelevant functionality. Modified the PRINT_ARR to take an array and len. Printed array before it's sorted paying particular attention to the last element:
#define PRINT_ARR(arr, len) for (unsigned i = 0; i < (len); i++) printf("%d ", arr[i]); printf("\n")
int main() {
unsigned eltCount = 110;
int arr[eltCount];
for (unsigned i = 0; i < eltCount; i++) {
arr[i] = random() % UPPER_LIMIT + 1;
}
PRINT_ARR(arr, eltCount);
quicksort(arr, eltCount);
PRINT_ARR(arr, eltCount);
return 0;
}
and found:
9384 887 2778 6916 7794 8336 5387 493 6650 1422 2363 28 8691 60 7764 3927 541 3427 9173 5737 5212 5369 2568 6430 5783 1531 2863 5124 4068 3136 3930 9803 4023 3059 3070 8168 1394 8457 5012 8043 6230 7374 4422 4920 3785 8538 5199 4325 8316 4371 6414 3527 6092 8981 9957 1874 6863 9171 6997 7282 2306 926 7085 6328 337 6506 847 1730 1314 5858 6125 3896 9583 546 8815 3368 5435 365 4044 3751 1088 6809 7277 7179 5789 3585 5404 2652 2755 2400 9933 5061 9677 3369 7740 13 6227 8587 8095 7540 796 571 1435 379 7468 6602 98 2903 3318 493
Nothing particular special about the last number other than it's a duplicate as #RetiredNinja noted above.
As the problem is an infinite loop, I looked the loops and particular their exit conditions. From our hint from the above, I changed it to only exist if two bounds are equal:
if(lb >= rb) break;
and the program now terminates.
I'm trying to find the total number of nodes at a given depth in a N-ary tree, but I'm stuck.
This is the data structure:
typedef struct elem2 {
int value;
struct elem2 *firstChild;
struct elem2 *sibling;
} NTree_node;
typedef NTree_node *NTree;
The following function should traverse recursively the tree and return a non-negative integer:
int NTree_depth_nodes(NTree T, int depth) {
if (T == NULL) {
/* empty tree -> depth is 0 */
return 0;
}
if (depth == 0) {
/* depth 0 means we only have the root */
return 1;
}
int left = NTree_depth_nodes(T->firstChild, depth - 1);
int right = NTree_depth_nodes(T->sibling, depth - 1);
return 1 + (left + right);
}
It runs but doesn't return the correct output since it's based on a similar function which works only for binary trees.
Any hints on what I could improve or change? I think I'm not really understanding what could be the right procedure.
There are several issues:
in the second recursive call:
int right = NTree_depth_nodes(T->sibling, depth - 1);
...the wrong depth is passed as argument. As you make the call for the sibling, you shouldn't decrease the value for the depth parameter: the siblings are at the same depth. So change to:
int right = NTree_depth_nodes(T->sibling, depth);
When depth is zero, you shouldn't return immediately: there might be siblings to check, which would add to the count.
Here is a correction:
int NTree_depth_nodes(NTree T, int depth) {
if (T == NULL) {
/* empty tree -> depth is 0 */
return 0;
}
int count = 0;
if (depth == 0) {
/* depth 0 means we have a node at the intended level */
count++;
}
count += NTree_depth_nodes(T->firstChild, depth - 1);
count += NTree_depth_nodes(T->sibling, depth);
return count;
}
I tested this code with the following driver code:
NTree node(int value) {
NTree n = malloc(sizeof(NTree_node));
n->sibling = NULL;
n->firstChild = NULL;
n->value = value;
return n;
}
int main(void) {
/* Create this tree:
1
/ | \
2 3 4
/| |\
5 6 7 8
|
9
*/
NTree root = node(1);
root->firstChild = node(2);
root->firstChild->sibling = node(3);
root->firstChild->sibling->sibling = node(4);
root->firstChild->sibling->firstChild = node(5);
root->firstChild->sibling->firstChild->sibling = node(6);
root->firstChild->sibling->sibling->firstChild = node(7);
root->firstChild->sibling->sibling->firstChild->sibling = node(8);
root->firstChild->sibling->sibling->firstChild->firstChild = node(9);
for (int depth = 0; depth < 5; depth++) {
printf("At depth %d there are %d nodes.\n", depth, NTree_depth_nodes(root, depth));
}
return 0;
}
The output is:
At depth 0 there are 1 nodes.
At depth 1 there are 3 nodes.
At depth 2 there are 4 nodes.
At depth 3 there are 1 nodes.
At depth 4 there are 0 nodes.
the problem is:
With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.
Input Specification:
Each input file contains one test case. For each case, the first line contains 4 positive numbers: C
max
(≤ 100), the maximum capacity of the tank; D (≤30000), the distance between Hangzhou and the destination city; D
avg
(≤20), the average distance per unit gas that the car can run; and N (≤ 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: P
i
, the unit gas price, and D
i
(≤D), the distance between this station and Hangzhou, for i=1,⋯,N. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print The maximum travel distance = X where X is the maximum possible distance the car can run, accurate up to 2 decimal places.
Sample Input 1:
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300
Sample Output 1:
749.17
Sample Input 2:
50 1300 12 2
7.10 0
7.00 600
Sample Output 2:
The maximum travel distance = 1200.00
I use the greedy algorithm to solve this problem, first fill the tank to reach the nearest and cheapest station, if we don't have a station like that, then we may reach the destination or find a cheaper station in the range which we can reach.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 500
typedef struct Station
{
int distance;
double price;
}Station_t;
int compare(const void *p1, const void *p2)
{
const Station_t *pleft = (Station_t *)p1;
const Station_t *pright = (Station_t *)p2;
return pleft->distance < pright->distance ? -1 : pleft->distance > pright->distance;
}
int main()
{
int capacity, totalDistance, davg, num, i;
double usedMoney = 0;
double usingC = 0;
scanf("%d %d %d %d", &capacity, &totalDistance, &davg, &num);
Station_t stas[N];
for(i = 0; i < num; ++i)
{
scanf("%lf %d", &stas[i].price, &stas[i].distance);
}
stas[num].distance = totalDistance;
stas[num].price = 0;
qsort(stas, num, sizeof(Station_t), compare);
if(stas[0].distance > 0)
{
printf("The maximum travel distance = 0.00");
return 0;
}
Station_t *cur = stas, *next = &stas[1];
while(cur != &stas[num - 1])
{
while(next->distance - cur->distance <= davg * capacity)
{
if(next->price < cur->price)
{
usedMoney += ((double)(next->distance - cur->distance - davg * usingC) / (double)davg) * cur->price;
cur = next;
if(cur == &stas[num - 1])
break;
++next;
}
else
{
if(next == &stas[num - 1])
break;
++next;
}
}
if(cur == &stas[num - 1])
break;
usedMoney += (capacity - usingC) * cur->price;
Station_t *temp = cur + 1, *fin = temp;
while(fin != next)
{
if(fin->price < temp->price)
temp = fin;
++fin;
}
usingC = capacity - (double)(temp->distance - cur->distance) / (double)davg;
cur = temp;
}
if(totalDistance - cur->distance <= davg * capacity)
{
usedMoney += (double)(totalDistance - cur->distance) / (double)davg * cur->price;
printf("%.2lf", usedMoney);
}
else
{
printf("The maximum travel distance = %.2f", (float)(cur->distance + davg * capacity));
}
return 0;
}
I cannot get through a sample named "last dist is exactly D"
Your comparison function has two problems:
1) Since the parameters are const, you need a pointer to const:
Station_t *pleft = (Station_t *)p1;
should be
const Station_t *pleft = p1; // There is no need to cast
2) Is not enough to return a > b
Return value meaning:
<0 The element pointed by p1 goes before the element pointed by p2
0 The element pointed by p1 is equivalent to the element pointed by p2
>0 The element pointed by p1 goes after the element pointed by p2
You want:
return pleft->distance < pright->distance ? -1 : pleft->distance > pright->distance;
In this way it returns -1, 0 or 1 depending on a < b, a == b or a > b
I'm having an issue figuring out the solution for this problem:
"Given a binary tree (each node has an int value), and a sum, return 1 if the tree has a path equal to the given sum (from a node to a leaf, doesn't have to be the root), else return 0".
I've done a similar question, where the path has to start from the root.
But here, the question states that the path can start anywhere, as long as it ends with a leaf..
Tried searching online for a solution, but I found some that are only working by using the buffer.
Is there any possible solution for this, without the buffer?
Thanks in advance!
(Prefer in C,C++ syntax or even a pseudo code ^.^``)
This was my first try:
int hasPathSum(Tree tr, int sum){
return hasPathSumRec(tr.root, sum, 0);
}
int hasPathSumRec(TNode* node, int sum, int current){
int num1, num2;
current += node->data;
if (current > sum)
current = 0;
if (node->left == NULL && node->right == NULL){
if (current == sum)
return 1;
return 0;
}
else if (node->left == NULL){
return hasPathSumRec(node->right, sum, current);
}
else if (node->right == NULL){
return hasPathSumRec(node->left, sum, current);
}
else{
num1=hasPathSumRec(node->left, sum, current);
num2=hasPathSumRec(node->right, sum, current);
if (num1 > 0 || num2 > 0)
return 1;
else
return 0;
}
}
and this was the second: (but it doesn't go through all of the nodes, so it's not good..)
int hasPathSum(Tree tr, int sum){
return hasPathSumRec(tr.root, sum, 0);
}
int hasPathSumRec(TNode* node, int sum, int current){
int num, num1, num2;
num = node->data;
current = num + current;
if (current > sum)
current = num;
if (node->left == NULL && node->right == NULL){
if (node->data == sum || current == sum)
return 1;
else
return 0;
}
else if (node->left == NULL){
num2 = node->right->data;
if (current + num2 > sum)
return hasPathSumRec(node->right, sum, num);
else
return hasPathSumRec(node->right, sum, current);
}
else if (node->right == NULL){
num1 = node->left->data;
if (current + num1 > sum)
return hasPathSumRec(node->left, sum, num);
else
return hasPathSumRec(node->left, sum, current);
}
else{
num1 = node->left->data;
num2 = node->right->data;
/LEFT SIDE--------------------------------------------------/
if (current + num1 > sum)
num2 = hasPathSumRec(node->left, sum, num);
else
num2 = hasPathSumRec(node->left, sum, current);
/RIGHT SIDE--------------------------------------------------/
if (current + num2 > sum)
num1 = hasPathSumRec(node->right, sum,num);
else
num1 = hasPathSumRec(node->right, sum, current);
if (num1 > 0 || num2 > 0)
return 1;
else
return 0;
}
As you already mentioned, you compute the sum of a tree values as the sum of the sums of its subtrees plus the root value. It's clear that as soon as you can compute the sum of this tree you have computed the sums of all its subtrees. So the only thing left to do is adding a check if the sum is equal to the required one and return it. Here you can find an implementation for this idea and a Minimal, Complete, and Verifiable example, which you should have provided in the first place, saving people (me) the effort to write one.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct _TNode {
int data;
struct _TNode *left, *right;
} TNode;
typedef struct {
TNode *root;
} Tree;
typedef struct {
int sum;
bool found;
} hasPathSumRec_t;
hasPathSumRec_t hasPathSumRec(TNode* node, int sum)
{
hasPathSumRec_t ret = { 0, false };
if (!node)
return ret;
hasPathSumRec_t ret_left = hasPathSumRec(node->left, sum);
hasPathSumRec_t ret_right = hasPathSumRec(node->right, sum);
ret.sum = ret_left.sum + ret_right.sum + node->data;
ret.found = ret_left.found || ret_right.found || ret.sum == sum;
return ret;
}
int hasPathSum(Tree tr, int sum) {
return hasPathSumRec(tr.root, sum).found;
}
int main(void)
{
/*
1 / 2 / 3 / *
| | \ *
| \ 5 / *
| \ *
\ 4 / 6 / 7 / *
| | \ *
| \ *
\ 8 / *
\ 9 / *
\ *
*/
TNode n[] = {
{ 1, n + 4 - 1, n + 2 - 1 },
{ 2, n + 5 - 1, n + 3 - 1 },
{ 3, NULL, NULL },
{ 4, n + 8 - 1, n + 6 - 1 },
{ 5, NULL, NULL },
{ 6, NULL, n + 7 - 1 },
{ 7, NULL, NULL },
{ 8, n + 9 - 1, NULL },
{ 9, NULL, NULL },
};
Tree t = { n };
int tests[] = { 8, 9, 10, 12, 13, 17 };
size_t ntests = sizeof tests / sizeof *tests;
for (size_t i = 0; i < ntests; ++i)
printf("%i - %i\n", tests[i], hasPathSum(t, tests[i]));
}
Further improvements could allow an early exit if sum is found or exceeded.
I've done a similar question, where the path has to start from the root. But here, the question states that the path can start anywhere, as long as it ends with a leaf..Is there any possible solution for this, without the buffer?
If you already have a solution with root node, then isn't it just one more recursion required.
Assume your root-node based solution is called IsPathHasSum(root). This will return 1 if sum of nodes on any path from root to leaf matchs given sum. This function should only find paths from root to leaf and not intermediate paths starting from arbitrary nodes.
Now to cover all nodes,
-> Start with IsPathHasSum(root), if return value = 1, program terminates
-> If not, invoke IsPathHasSum(root->left). This ignore the root and right tree.
-> If not, invoke IsPathHasSum(root->right). This ignores root and left tree
This can be invoked recursively to start from each node of the tree down to the leaf. If at any point, the return value is 1, program terminates. This re-traversal on same paths again and again is required since your requirement is not to have any buffers.
I've written a c program which can read a text file with single column of data. All the data can be read into the program with the following codes:
#include <stdio.h>
#include <cstdlib>
main()
{
char temp[20];
float t;
int a = 0, x = 0; //a is no. of data greater than 180 and x is no of data
FILE *fpt;
fpt = fopen("case i.txt", "r");
fscanf(fpt, "%s", temp); // read and display the column header
printf("%s\n", temp);
while (fscanf(fpt, "%f", &t) == 1)
{
printf("%.2f\n", t);
++x; //count for number of data
if (t > 180) {
++a; //count for number of data > 180
}
if (x > 2 && a == 2) { //place where bug is expected to occur
printf("2 out of 3 in a row is greater than 180");
a=0; //reset a back to zero
x=0;
}
}
fclose(fpt);
system("pause");
}
The problem comes when I want to detect like 2 out of 3 data are beyond 180 degree Celsius. I tried some ideas like when (no. of data > 2) and (two data > 180) then generate an error message, but it will have bug as it may have two data > 180 but when 4 data are read, that means it become 2 out of 4, not 2 out of 3, is it possible to be programmed? Thank you in advance for every help.
The following is the sample data and output:
You'll need to keep a "sliding window" of 3 values indicating how many are over 180.
So one approach would be something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char temp[20];
float t;
const int min_over = 2;
const int max_window = 3;
const int max_value = 180;
char over[max_window]; // a 1 means over, 0 otherwise
int oi = 0;
int num_values = 0;
FILE *fpt;
fpt = fopen("case i.txt", "r");
fscanf(fpt, "%s", temp); // read and display the column header
printf("%s\n", temp);
memset(over, 0, max_window);
while (fscanf(fpt, "%f", &t) == 1)
{
int num_hit, i;
printf("%.2f\n", t);
// Calculate num_hit: how many over in a window of max_window
//
over[oi] = (t > max_value) ? 1 : 0;
if (++oi >= max_window)
oi = 0;
for ( num_hit = i = 0; i < max_window; i++ ) num_hit += over[i];
// Only check for min_over/max_window after at least
// max_window values read; Reset the check
//
if ((++num_values >= max_window) && (num_hit >= min_over))
{
printf("It happened!\n");
memset(over, 0, max_window);
num_values = 0;
}
}
fclose(fpt);
system("pause");
}
Since you want a ratio of 2/3, that corresponds to min_over / max_window values.
I ran this on your commented data sample:
Temperature
190.00
190.00
170.00
It happened!
200.00
190.00
100.00
It happened!
100.00
190.00
190.00
It happened!
There are about a million billion different ways to do this, but you just need to keep track of how many samples exceed the threshold and then do whatever you want to do when you hit that mark.
Let's say, once you find your "2 out of 3" samples that exceed 180 you want to print the list and stop reading from the file:
FILE *fpt;
float t;
float samples[3] = {0}; // keep a record of 3 samples
int total = 0, i;
fpt = fopen("file1.txt", "r");
while (fscanf(fpt, "%f", &t) == 1) // read until there are no more samples
{
total = 0; // clear our counter
samples[2] = samples[1]; // toss out the old 3rd sample
samples[1] = samples[0]; // and shift them to make room for the
samples[0] = t; // one we just read
for(i = 0; i<3; i++)
if(samples[i] > 180) // if any are over 180
total++; // increment our counter
if(total == 2) { // if 2 of the 3 are over 180, we got 2 out of 3
printf("2 out of 3 samples are greater than 180!\n");
printf("1: %f\n2: %f\n3:%f\n", samples[2],samples[1],samples[0]);
break;
}
}
fclose(fpt);
It's not very efficient.. but should be pretty easy to understand.