Algorithms_in_C  1.0.0
Set of algorithms implemented in C.
sol1.c File Reference

Problem 20 solution More...

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

Data Structures

struct  _big_int
 

Typedefs

typedef struct _big_int big_int
 

Functions

big_intadd_digit (big_int *digit, char value)
 
char remove_digits (big_int *digit, int N)
 
int main (int argc, char **argv)
 

Detailed Description

Problem 20 solution

Author
Krishna Vedala

Implementation uses a custom big_int structure that can store arbitrarilty large integer numbers.

Typedef Documentation

◆ big_int

typedef struct _big_int big_int

store arbitratily large integer values as a linked list of digits.

Function Documentation

◆ add_digit()

big_int* add_digit ( big_int digit,
char  value 
)

Function that allocates memory to add another digit at the MSB

38 {
39  if (digit == NULL)
40  {
41  digit = (big_int *)malloc(sizeof(big_int));
42  if (!digit)
43  {
44  perror("Unable to allocate memory!");
45  return NULL;
46  }
47  digit->value = value;
48  digit->next_digit = NULL;
49  digit->prev_digit = NULL;
50 
51  return digit;
52  }
53 
54  if (digit->next_digit)
55  {
56  digit->next_digit->value = value;
57  return digit->next_digit;
58  }
59 
60  digit->next_digit = (big_int *)malloc(sizeof(big_int));
61  if (digit->next_digit == NULL)
62  {
63  perror("Unable to allocate memory!");
64  return NULL;
65  }
66  digit->next_digit->value = value;
67  digit->next_digit->next_digit = NULL;
68  digit->next_digit->prev_digit = digit;
69  return digit->next_digit;
70 }

◆ main()

int main ( int  argc,
char **  argv 
)

Main function

sum digits on the last iteration this avoid having another loop over all digits

Notice that in the loop above, we make sure that at the end of the loop, ptr is pointing to the last digit. Thus we can avoid using another loop.

96 {
97  unsigned int N = 5;
98  big_int *ptr = add_digit(NULL, 1); /* start with 1 */
99  const big_int *ptr0 = ptr; /* save the first location */
100  unsigned long sum_digits = 0;
101  unsigned long num_digits = 0;
102 
103  if (argc == 2)
104  N = atoi(argv[1]);
105 
106  clock_t start_time = clock();
107 
108  for (unsigned int i = 1; i <= N; i++)
109  {
110  int carry = 0;
111 #ifdef DEBUG
112  printf("%3d: ", i);
113 #endif
114  ptr = (big_int *)ptr0; /* multiply every digit with i */
115  while (ptr)
116  {
117 #ifdef DEBUG
118  printf("%p\t", ptr);
119 #endif
120  unsigned int tmp = ptr->value * i + carry;
121  if (tmp >= 10)
122  {
123  div_t tmp2 = div(tmp, 10);
124  carry = tmp2.quot;
125  tmp = tmp2.rem;
126  }
127  else
128  carry = 0;
129 
130  if (carry > 0 && ptr->next_digit == NULL)
131  add_digit(ptr, 0);
132 
133  ptr->value = tmp;
134 
135  if (i == N)
136  /**
137  * sum digits on the last iteration
138  * this avoid having another loop over all digits
139  **/
140  sum_digits += tmp;
141 
142  if (ptr->next_digit)
143  /* more digits available */
144  ptr = ptr->next_digit;
145  else
146  /* no more digits left - reached MSB */
147  break;
148  }
149 #ifdef DEBUG
150  printf("\n");
151 #endif
152  }
153 
154  clock_t end_time = clock();
155 
156 #ifdef DEBUG
157  printf("ptr = %p\n", ptr);
158  printf("%d! = ", N);
159 #endif
160 
161  /** Notice that in the loop above, we make sure that at the end of the loop,
162  * ptr is pointing to the last digit. Thus we can avoid using another loop.
163  **/
164  // ptr = &my_int;
165  // /* move ptr to the MSB digit */
166  // while (ptr->next_digit)
167  // ptr = ptr->next_digit;
168  do
169  {
170  putchar(ptr->value + 0x30); /* convert digit to ASCII char */
171  ptr = ptr->prev_digit;
172  num_digits++;
173  } while (ptr); /* after coming to units place, there will be no valid ptr */
174 
175  printf("\nTime taken: %.4g millisecond\n",
176  1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
177  printf(
178  "Digit Sum = %lu\tNumber of digits = %lu\tStorage space = %.3gkb\t \n",
179  sum_digits, num_digits, num_digits * sizeof(big_int) / 1024.0);
180 
181  remove_digits((big_int *)ptr0, -1);
182  return 0;
183 }
Here is the call graph for this function:

◆ remove_digits()

char remove_digits ( big_int digit,
int  N 
)

Function to remove digits preceeding the current digit.

77 {
78  if (digit == NULL)
79  return 0;
80 
81  if (digit->next_digit == NULL)
82  {
83  free(digit);
84  digit = NULL;
85  return 0;
86  }
87 
88  if (N > 0)
89  return remove_digits(digit->next_digit, N - 1);
90 
91  return remove_digits(digit->next_digit, 0);
92 }
remove_digits
char remove_digits(big_int *digit, int N)
Definition: sol1.c:76
N
#define N
Definition: sol1.c:109
_big_int::next_digit
struct _big_int * next_digit
Definition: sol1.c:20
_big_int::prev_digit
struct _big_int * prev_digit
Definition: sol1.c:21
_big_int
Definition: sol1.c:18
add_digit
big_int * add_digit(big_int *digit, char value)
Definition: sol1.c:37