Assigning Values to a struct from text file with unkown amount of data - c

I'm stuck at this where I need to find the highest average number inside a text file with an unknown amount of data.
The data inside the txt is like this
id group score
2203 1 33
5123 2 58
3323 3 92
5542 2 86
....
....
and the file keeps going.
I'm currently trying to create a struct and then store the values inside of it, but I cannot determine the size of struct since the file has unknown amount of data and it might change every run.
What I tried is this
while(!feof(fptr)) {
for(i = 0; i < sizeoffile; i++ ) { // here i should add the size or the amount of data.
fscanf(fptr,"%d %d %d",&p[i].num, &p[i].grp, &p[i].score);
}
}
I tried adding a counter inside the while loop to get the amount of data but it doesn't work. Im not sure if i need to use malloc or something else.
Example run:
code read the following file
1312 1 30
1234 1 54
2931 2 23
2394 2 99
9545 3 95
8312 3 100
8542 4 70
2341 4 56
1233 1 70
2323 1 58
output
group 3 has the highest average of 97

Code could go through the file once and determine the count of records: N and then read again, this time saving in an array of size N.
Alternative, use a linked-list.
or allocated some memory and re-allocate as needed.

Related

How could be the algorithm for this problem?

I have this data structure problem:
Implement an external sort method with two helper files. The separation
The initial file in chunks follows the following strategy: 20 elements are read from the file in chunks.
an array and are sorted with the internal sort method quicksort. Then it
writes the smallest element of the array to the auxiliary file and reads the next element from the
source file. If the element read is greater than the element written (it is part of the section
current), then it is inserted in order into the ordered subarray; otherwise it is added in
the free positions of the array. Because the elements of the array are extracted by the head
free positions remain on the opposite end. The section ends when the
sorted subarray is empty. To form the next section, start by ordering the array
(remember that the elements that were not part of the section were added to the array) and
then the process continues in the same way: write the smaller element to another file
helper and read element from the source file... Once the distribution is done, the phase of
mixing is the same as in the direct or natural mixing algorithms.
I'm thinking of this algorithm:
File origin
75
98
3
27
37
64
19
55
22
62
81
80
87
36
68
8
33
38
72
90
24
91
6
78
54
ordered array of 20 elements: 3-8-19-22-27-33-36-37-38-55-62-64-68-72-75-80-81-87-90-98
First element in the aux file 1: 3
After this point I don't know what the algorithm has to do to order the remaining 5 elements

Add Countif to Array Formula (Subtotal) in Excel

I am new to array formulae and have noticed that while SUBTOTAL includes many functions, it does not feature COUNTIF (only COUNT and COUNTA).
I'm trying to figure out how I can integrate a COUNTIF-like feature to my array formula.
I have a matrix, a small subset of which looks like:
A B C D E
48 53 46 64 66
48 66 89
40 38 42 49 44
37 33 35 39 41
Thanks to the help of #Tom Shape in this post, I (he) was able to average the sum of each row in the matrix provided it had complete data (so rows 2 and 4 in the example above would not be included).
Now I would like to count the number of rows with complete data (so rows 2 and 4 would be ignored) which include at least one value above a given threshold (say 45).
In the current example, the result would be 2, since row 1 has 5/5 values > 45, and row 3 has 1 value > 45. Row 5 has values < 45 and rows 2 and 3 have partially or fully missing data, respectively.
I have recently discovered the SUMPRODUCT function and think that perhaps SUMPRODUCT(--(A1:E1 >= 45 could be useful but I'm not sure how to integrate it within Tom Sharpe's elegant code, e.g.,
=AVERAGE(IF(SUBTOTAL(2,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1)))=COLUMNS(A1:E1),SUBTOTAL(9,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1))),""))
Remember, I am no longer looking for the average: I want to filter rows for whether they have full data, and if they do, I want to count rows with at least 1 entry > 45.
Try the following. Enter as array formula.
=COUNT(IF(SUBTOTAL(4,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1)))>45,IF(SUBTOTAL(2,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1)))=COLUMNS(A1:E1),SUBTOTAL(9,OFFSET(A1,ROW(A1:A5)-ROW(A1),0,1,COLUMNS(A1:E1))))))
Data

Importing the result of a MATLAB numeric array into a new MATLAB script

Consider that I have a code that returns a double array. When run, the result returned at the command window a result looks like this:
mpc.gen=
1 100 344 34 5
2 433 223 45 2
3 333 432 12 3
4 213 233 12 3
What I want to do is create a MATLAB script which would contain this array. In other words in this new MATLAB script I would have the following array, constructed like this:
mpc.gen= [ 1 100 344 34 5 ;
2 433 223 45 2 ;
3 333 432 12 3 ;
4 213 233 12 3 ;
] ;
Just calling the function would save the variable in the new script, however that is not what I need since I need to use this script for a simulation at a special power tool called MATPOWER. The array needs to be in the form shown at the new script.
The actual array is much bigger in size however I use this here for simplicity. Is there any way I can do this automatically, and not just pass the data from the command window to the new script one by one manually? Any help would be greatly appreciated. Thank you in advance for your time!
What you want to use is mat2str. It converts a matrix to a string representation that, when evaluated, results in the identical matrix.
For example:
>> result = [1 100 344 34 5;
2 433 223 45 2;
3 333 432 12 3;
4 213 233 12 3];
>> mat2str(result)
ans =
[1 100 344 34 5;2 433 223 45 2;3 333 432 12 3;4 213 233 12 3]
You could write this to a file like so:
f = fopen('test_script.m', 'w');
fprintf(f,'mpc.gen = %s\n', mat2str(result));
fclose(f);
The formatting is not identical to your example, but if the tool does proper MATLAB parsing, it shouldn't be a problem.
Is it intentional that mpc is a struct? (you are using dot in the name.) In the following, I use underscore instead, but it can certainly be adopted, if it is intentional.
This is what functions are for. So instead of making a script, you should create a new function. If I were to do what you want to do, I would have 2 functions and 1 script. Whereas the script looks like this
mpc_bus = function1;
function2(mpc_bus);
where function1 is the code that returns mpc.bus and function2 is the one where you want to work with mpc.gen, and the top would be something like this
function [] = function2(mpc_gen)
Alternatively: If you of some reason does not like functions, you can make the first code save the variable using save(*filename*.mat) and then you can load the file again in the script using dat=load(*filename*.mat); and mpc_gen = dat.mpc_bus;

How to identify breaks within an array of MATLAB?

I have an array in MATLAB containing elements such as
A=[12 13 14 15 30 31 32 33 58 59 60];
How can I identify breaks in values of data? For example, the above data exhibits breaks at elements 15 and 33. The elements are arranged in ascending order and have an increment of one. How can I identify the location of breaks of this pattern in an array? I have achieved this using a for and if statement (code below). Is there a better method to do so?
count=0;
for i=1:numel(A)-1
if(A(i+1)==A(i)+1)
continue;
else
count=count+1;
q(count)=i;
end
end
Good time to use diff and find those neighbouring differences that aren't equal to 1. However, this will return an array which is one less than the length of your input array because it finds pairwise differences up until the last element, so naturally there will be one less. As such, when you find the locations that aren't equal to 1, make sure you add 1 to the locations to account for this:
>> A=[12 13 14 15 30 31 32 33 58 59 60];
>> q = find(diff(A) ~= 1) + 1
q =
5 9
This tells us that locations 5 and 9 in your array is where the jump happens, and that's right for your example data.
However, if you want to find the locations before the jump happens, such as in your code, don't add 1 to the result:
>> q = find(diff(A) ~= 1)
q =
4 8

Get average of two consecutive values in a vector depending on logical vector

I am reading data from a file and I am trying to do some manipulation on the vector containing the data basically i want to check if the values come from consecutive lines and if so i want to average each two and put the value in a output vector
part of the data and lines
lines=[153 152 153 154 233 233 234 235 280 279 280 281];
Sail=[ 3 4 3 1.5 3 3 1 2 2.5 5 2.5 2 ];
here is what i am doing
Sail=S(lines);
Y=diff(lines)==1;
for ii=1:length(Y)
if Y(ii)
output(ceil(ii/2))=(Sail(ii)+Sail(ii+1))/2;
end
end
is this correct also is there a way to do that without a for loop
Thanks
My suggestion:
y = find(diff(lines)==1);
output = mean([Sail(y);Sail(y+1)]);
This assumes that when you have, say [233 234 235], you want one value averaging the values from lines [233 234] and one value averaging those from [234 245]. If you wanted to do something more complex when longer sets of consecutive lines exist in your data, then the problem becomes more complex.
Incidentally it's a bad idea to do something like (ceil(ii/2)) - you can't guarantee a unique index for each matching value of ii. If you did want an output the same size as Sail (will have zeros in non-matching areas) then you can do something like this:
output2 = zeros(size(Sail));
output2(y)=output;

Resources