Algorithms_in_C 1.0.0
Set of algorithms implemented in C.
Loading...
Searching...
No Matches
sol2.c File Reference

Problem 23 solution - optimization using look-up array More...

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
Include dependency graph for sol2.c:

Functions

char get_perfect_number (unsigned long N)
 
char is_abundant (unsigned long N)
 Is the given number an abundant number (1) or not (0)
 
unsigned long get_next_abundant (unsigned long N)
 Find the next abundant number after N and not including N.
 
char is_sum_of_abundant (unsigned long N)
 check if a given number can be represented as a sum of two abundant numbers.
 
int main (int argc, char **argv)
 Main function.
 

Variables

char * abundant_flags = NULL
 This is the global array to be used to store a flag to identify if a particular number is abundant (1) or not (0).
 

Detailed Description

Problem 23 solution - optimization using look-up array

Author
Krishna Vedala

Optimization applied - compute & store abundant numbers once into a look-up array.

Function Documentation

◆ get_next_abundant()

unsigned long get_next_abundant ( unsigned long  N)

Find the next abundant number after N and not including N.

71{
72 unsigned long i;
73 /* keep checking successive numbers till an abundant number is found */
74 for (i = N + 1; !is_abundant(i); ++i)
75 {
76 ;
77 }
78 return i;
79}
char is_abundant(unsigned long N)
Is the given number an abundant number (1) or not (0)
Definition: sol2.c:59
Here is the call graph for this function:

◆ get_perfect_number()

char get_perfect_number ( unsigned long  N)
Returns
-1 if N is deficient
1 if N is abundant
0 if N is perfect
32{
33 unsigned long sum = 1;
34 char ret = 0;
35
36 for (unsigned long i = 2; i * i <= N; i++)
37 {
38 if (N % i == 0)
39 {
40 sum += i;
41 unsigned long tmp = N / i;
42 if (tmp != i)
43 {
44 sum += tmp;
45 }
46 }
47 }
48
49 ret = sum == N ? 0 : (sum > N ? 1 : -1);
50#ifdef DEBUG
51 printf("%5lu: %5lu : %d\n", N, sum, ret);
52#endif
53 return ret;
54}

◆ is_abundant()

char is_abundant ( unsigned long  N)

Is the given number an abundant number (1) or not (0)

60{
61 // return abundant_flags[N >> 3] & (1 << N % 8) ? 1 : 0;
62 return abundant_flags[N >> 3] & (1 << (N & 7))
63 ? 1
64 : 0; /* optimized modulo operation */
65}
char * abundant_flags
This is the global array to be used to store a flag to identify if a particular number is abundant (1...
Definition: sol2.c:24

◆ is_sum_of_abundant()

char is_sum_of_abundant ( unsigned long  N)

check if a given number can be represented as a sum of two abundant numbers.

Returns
1 - if yes
0 - if not
88{
89 /* optimized logic:
90 * i + j = N where both i and j should be abundant
91 * hence we can simply check for j = N - i as we loop through i
92 */
93 for (unsigned long i = get_next_abundant(1); i <= (N >> 1);
94 i = get_next_abundant(i))
95 {
96 if (is_abundant(N - i))
97 {
98#ifdef DEBUG
99 printf("\t%4lu + %4lu = %4lu\n", i, N - i, N);
100#endif
101 return 1;
102 }
103 }
104 return 0;
105}
unsigned long get_next_abundant(unsigned long N)
Find the next abundant number after N and not including N.
Definition: sol2.c:70
Here is the call graph for this function:

◆ main()

int main ( int  argc,
char **  argv 
)

Main function.

109{
110 long MAX_N = 28123; /* Limit of numbers to check */
111
112 unsigned long sum = 0;
113 if (argc == 2)
114 {
115 MAX_N = strtoul(argv[1], NULL, 10);
116 }
117
118 /* byte array to store flags to identify abundant numbers
119 * the flags are identified by bits
120 */
121 abundant_flags = (char *)calloc(MAX_N >> 3, 1);
122 if (!abundant_flags)
123 {
124 perror("Unable to allocate memoey!");
125 return -1;
126 }
127
128#ifdef _OPENMP
129 printf("Using OpenMP parallleization with %d threads\n",
130 omp_get_max_threads());
131#else
132 printf("Not using parallleization!\n");
133#endif
134
135 clock_t start_time = clock();
136
137 /* Loop to set abundant flags */
138 long N;
139#ifdef _OPENMP
140#pragma omp for schedule(runtime)
141#endif
142 for (N = 1; N <= MAX_N; N++)
143 {
144 char ret = get_perfect_number(N);
145 if (ret == 1)
146 {
147 // int byte_offset = N % 8, index = N >> 3;
148 int byte_offset = N & 7, index = N >> 3;
149#ifdef _OPENMP
150#pragma omp critical
151#endif
152 abundant_flags[index] |= ret << byte_offset;
153 }
154 // if (i % 100 == 0)
155 // printf("... %5lu: %8lu\r", i, sum);
156 }
157
158 clock_t end_time = clock();
159 double t1 = 1e3 * (end_time - start_time) / CLOCKS_PER_SEC;
160 printf("Time taken to get abundant numbers: %.4g ms\n", t1);
161
162 clock_t t2 = 0;
163 long i;
164#ifdef _OPENMP
165#pragma omp parallel for schedule(runtime) reduction(+ : sum)
166#endif
167 for (i = 1; i < MAX_N; i++)
168 {
169 clock_t start_time1 = clock();
170 if (!is_sum_of_abundant(i))
171 {
172 // #ifdef _OPENMP
173 // #pragma omp critical
174 // #endif
175 sum += i;
176 }
177 clock_t end_time1 = clock();
178#ifdef _OPENMP
179#pragma omp critical
180#endif
181 t2 += end_time1 - start_time1;
182
183 printf("... %5lu: %8lu\r", i, sum);
184 if (i % 100 == 0)
185 {
186 fflush(stdout);
187 }
188 }
189
190#ifdef DEBUG
191 putchar('\n');
192#endif
193 double t22 = 1e3 * t2 / CLOCKS_PER_SEC;
194 printf("Time taken for final sum: %.4g ms\nTotal Time taken: %.4g ms\n",
195 t22, t1 + t22);
196 printf("Memory used: %lu bytes\n", MAX_N >> 3);
197 printf(
198 "Sum of numbers that cannot be represented as sum of two abundant "
199 "numbers : %lu\n",
200 sum);
201
203
204 return 0;
205}
#define free(ptr)
This macro replace the standard free function with free_dbg.
Definition: malloc_dbg.h:26
#define calloc(elemCount, elemSize)
This macro replace the standard calloc function with calloc_dbg.
Definition: malloc_dbg.h:22
char get_perfect_number(unsigned long N)
Definition: sol2.c:31
char is_sum_of_abundant(unsigned long N)
check if a given number can be represented as a sum of two abundant numbers.
Definition: sol2.c:87
Here is the call graph for this function:

Variable Documentation

◆ abundant_flags

char* abundant_flags = NULL

This is the global array to be used to store a flag to identify if a particular number is abundant (1) or not (0).

Using a whole byte to store a binary info would be redundant. We will use each byte to represent 8 numbers by relying on bits. This saves memory required by 1/8