C - Perceptron school project - single data set, error not converging - c

Hello everyone,
I'm currently stuck working on a school project described as such:
Your program should read in the file in.csv, and adjust the weights of the perceptron so that when given the inputs it was trained with, it provides the corresponding outputs.
In reality, the error may never get to zero when training an ANN; the goal is to hopefully make it smart enough to recognize most instances. For this project start with an error of 5%, or 0.05. This would mean, for example, that the ANN correctly identified 95/100 of the inputs, and 05/100 were mistakenly classified. See if you can modify the parameters of the ANN training process to do better than 5%, but your program should not continue trying to modify the weights after 500,000 iterations.
Sample run: C:\percy in.csv 100 5 10
where the executable is percy.exe, the input file is in.csv, the learning rate is 100/1000=0.100, the error is 5/100, and max iterations is in thousands, so 10 corresponds to 10,000.
The input file is formatted per the example below. The first 16 characters in line represent sensor inputs, and the last char is always either 0 or 1, and represents which class the input corresponds to.
0000000001000000,0
0000000001000001,1
0000000001000010,1
0000000001000011,1
0000000001000100,1
these few numbers are a portion of the data set being used, the rest of the data set are similar integers
So the output is supposed to look like so:
iterationError = 0.023437500, errCnt = 3, repNum=72
wt[00]: +0.00661 wt[01]: +0.00431 wt[02]: +0.00011 wt[03]: +0.00814
wt[04]: +0.00198 wt[05]: +0.00470 wt[06]: +0.00356 wt[07]: +0.00435
wt[08]: +0.00761 wt[09]: +0.52254 wt[10]: +0.00120 wt[11]: -0.01169
wt[12]: -0.00937 wt[13]: -0.00281 wt[14]: -0.00157 wt[15]: -0.00217
STOP*****(with setting wt[10] to 0.5232)
However, when I run my code (below) with reading in the .csv data set, the program runs until it hits 10k iterations and the error doesn't change and I'm not exactly sure what may be wrong with my loop or calculations. Also I should note that my current code doesn't represent the correct output yet.
Any help would be greatly appreciated, thank you
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define LEARNING_RATE 0.1
#define MAX_ITERATION 10000
float randomFloat()
{
return (float)rand() / (float)RAND_MAX;
}
int calculateOutput(float weights[], int x)
{
float sum = x * weights[0] + weights[1];
return (sum >= 0) ? 1 : -1;
}
int main(int argc, char *argv[])
{
srand(time(NULL));
float weights[2], localError, globalError, MAX_ERROR = 0.05;
float x[208];
int outputs[208], patternCount, i, p, iteration, output;
FILE *fp;
if ((fp = fopen("in.csv", "r")) == NULL) {
printf("Cannot open file.\n");
exit(1);
}
i = 0;
while (fscanf(fp, "%f,%d", &x[i], &outputs[i]) != EOF) {
i++;
}
patternCount = i;
weights[0] = randomFloat();
weights[1] = randomFloat();
iteration = 0;
do {
printf(" Iteration: %d ***********************************\n", iteration);
iteration++;
globalError = 0;
for (p = 0; p < patternCount; p++) {
output = calculateOutput(weights, x[p]);
localError = outputs[p] - output;
weights[0] += LEARNING_RATE * localError * x[p];
weights[1] += LEARNING_RATE * localError;
globalError += (localError*localError);
printf("%.1f \n", weights[0]);
}
globalError = globalError/((float)patternCount);
printf(" iterationError = %.5f\n", globalError);
} while ((globalError > MAX_ERROR) && (i < MAX_ITERATION));
return 0;
}

Related

How to use 'fwrite' in C?

I'm trying to use 'fwrite' and make snd files.
I want to make IIR Filter. I made a FIR Filter and i use the codes to IIR Filter.
(of course, change coeffs)
But I think 'fwrite' doesn't work. Because the result of IIR filter is only zero.
I think I did some mistakes in my code.
Can you give me a hint? i'm totally in panic now.
When I check output[], it looks fine. It has group of integer, as i respect.
I don't know how to write it.
I know the code is so long and looks difficult.
But I have no idea so if you give me a hand, it would be pleasured.
Thanks for reading.
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
// Filter Code Definitions
#define MAX_INPUT_LEN 80
#define MAX_FLT_LEN 14
#define BUFFER_LEN (MAX_FLT_LEN - 1 + MAX_INPUT_LEN)
double insamp[BUFFER_LEN];
// IIR inititialization
void IirFloatInit(void)
{
memset(insamp, 0, sizeof(insamp));
}
// the IIR filter function
void IirFloat(double *coeffs, double *input, double *output, int length, int
filterLength)
{
double acc;
double *coeffp;
double *inputp;
int n;
int k;
// put the new samples at the high end of the buffer
memcpy(&insamp[filterLength - 1], input, length * sizeof(double));
for (n = 0; n < length; n++) {
coeffp = coeffs;
inputp = &insamp[filterLength - 1 + n];
acc = 0;
for (k = 0; k < filterLength; k++) {
acc += (*coeffp++) * (*inputp--);
}
output[n] = acc;
}
memmove(&insamp[0], &insamp[length], (filterLength - 1) * sizeof(double));
}
double coeffs[MAX_FLT_LEN];
void intToFloat(int16_t *input, double *output, int length)
{
int i;
for (i = 0; i < length; i++) {
output[i] = (double)input[i];
}
}
void floatToInt(double *input, int16_t *output, int length)
{
int i;
for (i = 0; i < length; i++)
{
input[i] += 0.5;
if (input[i] > 32767.0)
{
input[i] = 32767.0;
}
else if (input[i] < -32768.0)
{
input[i] = -32768.0;
}
output[i] = (int16_t)input[i];
}
}
// number of samples to read per loop
int main(void)
{
int size;
int16_t input[MAX_INPUT_LEN];
int16_t output[MAX_INPUT_LEN];
double floatInput[MAX_INPUT_LEN];
double floatOutput[MAX_INPUT_LEN];
double coeffs[MAX_FLT_LEN];
FILE *in_fid;
FILE *out_fid;
FILE *filter;
// open the input waveform file
in_fid = fopen("input.snd", "rb");
if (in_fid == 0) {
printf("couldn't open input.snd");
return;
}
// open the output waveform file
out_fid = fopen("outputFloatIIR.snd", "wb");
if (out_fid == 0) {
printf("couldn't open outputFloat.snd");
return;
}
filter = fopen("coeffs_iir.txt", "r");
if (filter == NULL) {
puts("couldn't open coeffs_iir.txt");
return;
}
for (int i = 0; i < MAX_FLT_LEN; i++) {
fscanf(filter, "%le", &coeffs[i]);
printf("%le \n", coeffs[i]);
}
IirFloatInit();
do {
size = fread(input, sizeof(int16_t), MAX_INPUT_LEN, in_fid);
intToFloat(input, floatInput, size);
IirFloat(coeffs, floatInput, floatOutput, size, MAX_FLT_LEN);
floatToInt(floatOutput, output, size);
fwrite(output, sizeof(int16_t), size, out_fid);
} while (size != 0);
fclose(in_fid);
fclose(out_fid);
fclose(filter);
getchar();
return 0;
}
Into the manual (man printf) I can read this:
eE The double argument is rounded and converted in the style [-]d.ddde+-dd where there is one digit before the decimal-point
character and the number of digits after it is equal to the precision;
if the
precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears. An E conversion uses the
letter E' (rather thane') to introduce the exponent. The exponent
always contains at least two digits; if the value is zero, the exponent is 00.
Into your file where coefficients are stored, are into that format? If you use a debugger, what happen with the value read into fscanf?
I mean, probably the format is not the expected and because of that you get 0. Maybe you want to use fscanf(filter, "%lf", &coeffs[i]); ?
What is the value returned by fscanf? Into the manual (man fscanf) can be read this:
RETURN VALUES
These functions return the number of input items assigned. This can be fewer than provided for, or even zero, in the event of a
matching failure. Zero indicates that, although there was input
available, no
conversions were assigned; typically this is due to an invalid input character, such as an alphabetic character for a `%d'
conversion. The value EOF is returned if an input failure occurs
before any conver-
sion such as an end-of-file occurs. If an error or end-of-file occurs after conversion has begun, the number of conversions which
were successfully completed is returned.

How to save the data which i read in an array from a file in C

So while doing this assignment i encountered a problem where i tried to save some set of values(float) in an Array so that i can use them later on producing a graph, but the problem which i face here is that i read the values and i can print them but later which i checked the array the numbers which were stored there were not the same.
Im trying to save in in avg[].
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
float maximum(float array[])
{
float max=0;
for(int i=0;i<100;i++)
{
if (array[i]>max)
max=array[i];
}
return max;
}
float minimum(float array[])
{
float min=0;
for(int i=0;i<100;i++)
{
if (array[i]<min)
min=array[i];
}
return min;
}
char * read(char *filename)
{
FILE * sample;
sample = fopen(filename,"r"); //like file open in notepad ,which file? and what to do?
int count = 0;
static char singleline[100];
int cnt = 0;
int sum = 0;
int oldyear = -1;
float avg[82];
while(!feof(sample)) //read that until end.
{
count++;
fgets(singleline,150,sample);
if (count>21 && singleline[33]!='9')
{
char y[5], t[6];
for (int i = 14; i < 18; i++)
{
y[i - 14] = singleline[i];
}
y[4]='\0';
for (int i= 24;i <29;i++)
{
t[i-24]=singleline[i];
}
t[5]='\0';
int year = atoi(y);
int temp = atoi(t);
//printf("year : %i ,temp: %i\n",year, temp);
if (year == oldyear)
{
cnt++;
sum += temp;
}
else
{
int l=0;
l++;
avg[l] = 0.1 * sum / cnt;
if (cnt != 0)
{
printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt, avg[l]);
cnt = 1;
sum = temp;
//save[l]=avg;
}
oldyear = year;
}
}
}
float last = 0.1 * sum / cnt;
printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt-1, last);
fclose(sample);
//for(int i=0;i<)
for(int i=0;i<125;i++)
{
printf("%f\n",avg[i]);
}
printf("\nMax Temp= %f",maximum(avg));
printf("\nMax Temp= %f",minimum(avg));
return singleline;
}
int main()
{
char * file1 = "TG_STAID000476.txt";
read(file1);
//char * file2 = "TG_STAID000179.txt";
//read(file2);
return 0;
}
So yea, the problem was to read the year and the corresponding values and form an Average value for that particular year and then represent it in a graph.
I can do the first part where it takes the Average, but when i tried using it later,it had wrong values stored in it, you can see that where i tried to print all the values of avg[], can anyne please help me figure out how to correct the mistake, i want them to be saved as float.
The assignment datasheet is here. https://www.scribd.com/document/333844245/TG-STAID000179
I tried reading the values and used atoi to save them, and then used them to get the Average, i used Count>21 because the text before them are not required and when it reads a '9' on 34th column,it ignores since its not a valid data(in data sheet)
The variable l, intended to count the computed year temperature averages, is defined and initialized in the block where a year change is handled, thus always reset to zero. Correct this by moving the definition outside of the line read loop, perhaps even at global scope (see 2.).
The maximum() and minimum() functions operate on array elements 0 to 99, irrespective of the fact that the passed argument is defined as avg[82] and some elements at the end are not initialized. Correct this by using the actual number l of stored elements, either as a global scope variable or an additional function argument.
The singleline buffer is too short and thus overflows.
The while(!feof(sample)) loop cycles one extra time after the last line has been read, because EOF is not recognized before the next fgets(). Correct this by using the return value of fgets() to test EOF.
avg[l] = 0.1 * sum / cnt is evaluated even if cnt is zero. Correct this by moving this expression inside the if (cnt != 0) { … } block, also the l++, but behind the printf().
cnt = 1 is not executed if cnt is zero. This causes the very first data point to not be counted. Correct this by moving this expression behind the if (cnt != 0) { … } block.
The extra loop cycle (cf. 4.) may have led to use cnt-1 in the final printf("Fuer %i - %i Werte - Durchschnitt %.2f °C\n", oldyear, cnt-1, last);, but correct is just cnt.
The loop for(int i=0;i<125;i++) should also use the actual number l of stored elements, not 125.
To be noted is that the final year's average is (maybe intentionally) not stored in avg[].

Randomly Pair Teams From Text File Twice [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm fairly new to C programming and I'm attempting to complete this random pairing program but I'm having issues with starting it. Basically, the program needs to read in the 3 letter team names from a text file, place them into an array, and then randomly pair teams against each other. There are two rounds and in the second round, there cannot be any rematches. Additionally, teams from the same school cannot play against each other. Teams from the same school share the same first character and line in the text file. Can anyone help me with how to code this? :) Here is the text file named provisions.txt:
ABA ABC ABD ABG
BAA BAB BAC
CAB CBA
DAB DBC DBE DBA
EAB
FAB FAC FAA
GAB GAA
HAA HAB
IAB
JAA
KAA
LAL LAB
MAA MAB MBA MUM
NAN NAB
My code so far is:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int main()
{
// Read characters from text file into array
FILE *file = fopen("provision.txt", "r");
char teamList[115];
char teams[32][4]; // Holds team names
int i;
for(i = 0; i < 32; i++){
fscanf(file, "%s", teams[i]);
}
for(i = 0; i < 32; i++){
printf("%s \n", teams[i]); // Test to make sure teams are read in
}
// Clean up
fclose(file);
return 0;
}
If possible, I would like to store the output of both rounds in text files named round1_pairings.txt and round2_pairings.txt.
This program attempts to solve a few subtle problems such as random selection bias, backing out of dead-end matching attempts, etc. It is not guaranteed to terminate in the case where a given round cannot be paired due to insufficient teams from other schools, which is more likely to occur at higher numbers of rounds (unlikely with only two rounds and many schools).
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define NAMELEN 3
#define ROUNDS 2
#define RETRIES 10 // max attempts before restarting matching
#define STR_HELPER(x) #x // http://stackoverflow.com/a/5459929/4323
#define STR(x) STR_HELPER(x)
#define NAMEPRINTF "%" STR(NAMELEN) "s"
typedef char team_t[NAMELEN + 1];
typedef struct
{
team_t team;
team_t opponents[ROUNDS];
} pairing_t;
// the first round is round=0
// when round>0, prior round matches will be prevented from recurring
void make_matches(pairing_t* pairings, size_t count, size_t round)
{
// clip random() range to avoid bias toward first teams
long randmax = LONG_MAX - LONG_MAX % count - 1;
begin:
for(size_t ii = 0; ii < count; ++ii) {
if(pairings[ii].opponents[round][0]) continue; // already paired
//printf("matching: %s\n", pairings[ii].team);
unsigned retry = 0;
while(retry < RETRIES) {
long rand = random();
if (rand > randmax) continue; // avoid bias
pairing_t *opp = &pairings[rand % count];
if(opp->team[0] == pairings[ii].team[0]) { // same school
++retry;
continue;
}
if(opp->opponents[round][0]) continue; // already paired
size_t prior;
for(prior = 0; prior < round; ++prior) {
if(!memcmp(opp->team, pairings[ii].opponents[prior], sizeof(team_t))) {
break;
}
}
if(prior != round) continue; // duplicate pairing
//printf("match made: %s %s\n", opp->team, pairings[ii].team);
memcpy(pairings[ii].opponents[round], opp->team, sizeof(team_t));
memcpy(opp->opponents[round], pairings[ii].team, sizeof(team_t));
break;
}
if(retry == RETRIES) { // matching failed, start again
for(size_t ii = 0; ii < count; ++ii) {
memset(pairings[ii].opponents[round], 0, sizeof(team_t));
}
goto begin;
}
}
}
int main(void)
{
srandom(time(NULL));
FILE *file = fopen("provision.txt", "r");
size_t capacity = 15; // arbitrary initial size
pairing_t *pairings = calloc(capacity, sizeof(pairing_t));
if(!pairings) abort();
size_t count = 0;
while(fscanf(file, NAMEPRINTF, pairings[count].team) != EOF) {
//printf("%s\n", pairings[count].team);
++count;
if(count >= capacity) { // expand array
capacity *= 2;
pairings = realloc(pairings, capacity * sizeof(pairing_t));
if(!pairings) abort();
memset(&pairings[count], 0, (capacity - count) * sizeof(pairing_t));
}
}
for(size_t round = 0; round < ROUNDS; ++round) {
make_matches(pairings, count, round);
}
for(size_t ii = 0; ii < count; ++ii) {
printf("%s %s %s\n", pairings[ii].team, pairings[ii].opponents[0], pairings[ii].opponents[1]);
}
free(pairings);
fclose(file);
return 0;
}
The output is a simple table with three columns: the team playing, their first opponent, and their second opponent. I'm sure you can figure out how to write these to separate files as required.

Transfer results to txt file C

so i'm completely new to programming (i've been learning for 3 days) and i find myself infront of a problem i simply don't know how to resolve.
I want this program to give me every single combination from 0 to a specific number in base 36. That is easy enough when the number is only about 50000 or so. But my goal from this is to extract actual words(with numbers too) and if i try to get words with 5 characters, the terminal will start overwriting the previous words(not helpful, i want ALL of them).
So i thought i should look for a way to transfer everything into a txt file and there resides my problem: I don't know how... Sorry for the long text but i wanted to explain precisely what i'm trying to get. Thanks for the help.
int main() {
int dec, j, i, q, r, k;
char val[80];
printf("Enter a decimal number: ");
scanf("%d", &dec);
for (k = 0; k <= dec; k++) { /*repeat for all possible combinations*/
q = k;
for (i = 1; q != 0; i++) { /*convert decimal number to value for base 36*/
r = q % 36;
if (r < 10)
r = r + 48;
else
r = r + 55;
val[i] = r;
q = q / 36;
}
for (j = i - 1; j > 0; j--) { /*print every single value*/
printf("%c", val[j]);
}
printf(" "); /*add spaces because why not*/
}
return (0);
}
A few observations that might help:
First is type related:
In your declarations you create the following:
int dec, j, i, q, r, k;
char val[80];
Then later you make the assignment:
val[i] = r;//assigning an int to a char, dangerous
While r is type int with a range (typically) of –2,147,483,648 to 2,147,483,647,
val[i] is of type char with a range (typically) of only –128 to 127.
Because of this, you may run into an overflow, leading to unexpected results.
The most immediate solution is use the same type for both variables. Pick either int or char, but not both.
The other has already been addressed correctly by #Nasim. Use the file version of printf() - fprintf(). As the link shows, the prototype for fprintf() is:
int fprintf( FILE *stream, const char *format [, argument ]...);
Usage example:
FILE *fp = fopen(".\somefile.txt", "w");//create a pointer to a FILE
if(fp)//if the FILE was successfully created, write to it...
{
// some of your previous code...
for (j = i - 1; j > 0; j--)
{ /*print every single value*/
fprintf(fp, "%c", val[j]);//if val is typed as char
//OR
fprintf(fp, "%d", val[j]);//if val is typed as int
}
fclose(fp);
}
Lastly, there are a wide range of methods to perform base conversion. Some more complicated than others.
create a file and then you can use fprintf() instead of printf the only difference between the two is that you need to specify the file as an argument
FILE *myFile = fopen("file.txt", "w"); //"w" erase previous content, "a" appends
If(myFile == NULL) {printf("Error in openning file\n"); exit(1);}
fprintf(myFile, "some integer : %d\n", myInteger); // same as printf my specify file pointer name in first argument
fclose(myFile); //dont forget to close the file

Optimizing I/O(Output) in C code + a loop

I have a code which reads around (10^5) int(s) from stdin and then after performing ## i output them on stdout. I have taken care of the INPUT part by using "setvbuf" & reading lines using "fgets_unlocked()" and then parsing them to get the required int(s).
I have 2 issues which i am not able to come over with:
1.) As i am printing int(s) 5 million on stdout its taking lot of time : IS THERE ANY WAY TO REDUCE THIS( i tried using fwrite() but the o/p prints unprintable characters due to the reason using fread to read into int buffer)
2.) After parsing the input for the int(s) say 'x' i actually find the no of divisors by doing %(mod) for the no in a loop.(See in the code below): Maybe this is also a reason for my code being times out:
Any suggestions on this to improved.
Many thanks
This is actually a problem from http://www.codechef.com/problems/PD13
# include <stdio.h>
# define SIZE 32*1024
char buf[SIZE];
main(void)
{
int i=0,chk =0;
unsigned int j =0 ,div =0;
int a =0,num =0;
char ch;
setvbuf(stdin,(char*)NULL,_IOFBF,0);
scanf("%d",&chk);
while(getchar_unlocked() != '\n');
while((a = fread_unlocked(buf,1,SIZE,stdin)) >0)
{
for(i=0;i<a;i++)
{
if(buf[i] != '\n')
{
num = (buf[i] - '0')+(10*num);
}
else
if(buf[i] == '\n')
{
div = 1;
for(j=2;j<=(num/2);j++)
{
if((num%j) == 0) // Prob 2
{
div +=j;
}
}
num = 0;
printf("%d\n",div); // problem 1
}
}
}
return 0;
}
You can print far faster than printf.
Look into itoa(), or write your own simple function that converts integers to ascii very quickly.
Here's a quick-n-dirty version of itoa that should work fast for your purposes:
char* custom_itoa(int i)
{
static char output[24]; // 64-bit MAX_INT is 20 digits
char* p = &output[23];
for(*p--=0;i/=10;*p--=i%10+0x30);
return ++p;
}
note that this function has some serious built in limits, including:
it doesn't handle negative numbers
it doesn't currently handle numbers greater than 23-characters in decimal form.
it is inherently thread-dangerous. Do not attempt in a multi-threaded environment.
the return value will be corrupted as soon as the function is called again.
I wrote this purely for speed, not for safety or convenience.
Version 2 based on suggestion by #UmNyobe and #wildplasser(see above comments)
The code execution took 0.12 seconds and 3.2 MB of memory on the online judge.
I myself checked with 2*10^5 int(input) in the range from 1 to 5*10^5 and the execution took:
real 0m0.443s
user 0m0.408s
sys 0m0.024s
**Please see if some more optimization can be done.
enter code here
/** Solution for the sum of the proper divisor problem from codechef **/
/** # author dZONE **/
# include <stdio.h>
# include <math.h>
# include <stdlib.h>
# include <error.h>
# define SIZE 200000
inline int readnum(void);
void count(int num);
int pft[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709};
unsigned long long int sum[SIZE];
int k = 0;
inline int readnum(void)
{
int num = 0;
char ch;
while((ch = getchar_unlocked()) != '\n')
{
if(ch >=48 && ch <=57)
{
num = ch -'0' + 10*num;
}
}
if(num ==0)
{
return -1;
}
return num;
}
void count(int num)
{
unsigned int i = 0;
unsigned long long tmp =0,pfac =1;
int flag = 0;
tmp = num;
sum[k] = 1;
for(i=0;i<127;i++)
{
if((tmp % pft[i]) == 0)
{
flag =1; // For Prime numbers not in pft table
pfac =1;
while(tmp % pft[i] == 0)
{
tmp =tmp /pft[i];
pfac *= pft[i];
}
pfac *= pft[i];
sum[k] *= (pfac-1)/(pft[i]-1);
}
}
if(flag ==0)
{
sum[k] = 1;
++k;
return;
}
if(tmp != 1) // For numbers with some prime factors in the pft table+some prime > 705
{
sum[k] *=((tmp*tmp) -1)/(tmp -1);
}
sum[k] -=num;
++k;
return;
}
int main(void)
{
int i=0,terms =0,num = 0;
setvbuf(stdin,(char*)NULL,_IOFBF,0);
scanf("%d",&terms);
while(getchar_unlocked() != '\n');
while(terms--)
{
num = readnum();
if(num ==1)
{
continue;
}
if(num == -1)
{
perror("\n ERROR\n");
return 0;
}
count(num);
}
i =0;
while(i<k)
{
printf("%lld\n",sum[i]);
++i;
}
return 0;
}
//Prob 2 Is your biggesr issue right now.... You just want to find the number of divisors?
My first suggestion will be to cache your result to some degree... but this requires potentially twice the amount of storage you have at the beginning :/.
What you can do is generate a list of prime numbers before hand (using the sieve algorithm). It will be ideal to know the biggest number N in your list and generate all primes till his square root. Now for each number in your list, you want to find his representation as product of factors, ie
n = a1^p1 * a1^p2 *... *an^pn
Then the sum of divisors will be.
((a1^(p1+1) - 1)/(a1 - 1))*((a2^(p2+1) - 1)/(a2-1))*...*((an^(pn+1) - 1)/(an-1))
To understand you have (for n = 8) 1+ 2 + 4 + 8 = 15 = (16 - 1)/(2 - 1)
It will drastically improve the speed but integer factorization (what you are really doing) is really costly...
Edit:
In your link the maximum is 5000000 so you have at most 700 primes
Simple decomposition algorithm
void primedecomp(int number, const int* primetable, int* primecount,
int pos,int tablelen){
while(pos < tablelen && number % primetable[pos] !=0 )
pos++;
if(pos == tablelen)
return
while(number % primetable[pos] ==0 ){
number = number / primetable[pos];
primecount[pos]++;
}
//number has been modified
//too lazy to write a loop, so recursive call
primedecomp(number,primetable,primecount, pos+1,tablelen);
}
EDIT : rather than counting, compute a^(n+1) using primepow = a; primepow = a*primepow;
It will be much cleaner in C++ or java where you have hashmap. At the end
primecount contains the pi values I was talking about above.
Even if it looks scary, you will create the primetable only once. Now this algorithm
run in worst case in O(tablelen) which is O(square root(Nmax)). your initial
loop ran in O(Nmax).

Resources