-
Notifications
You must be signed in to change notification settings - Fork 1
/
p70.c
97 lines (79 loc) · 2.23 KB
/
p70.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* Note: some of this code is reused from Zig in the solution to
problem 72 (with "P72" defined to suppress e.g. main()) */
#ifndef P72
#include <stdlib.h>
#include <stdio.h>
#endif
/* Compute totients 1..n-1 (note: using n-1 so that n is the number of elements in totients) */
void compute_totients(unsigned int n, unsigned int *totients) {
unsigned long long tmp;
unsigned int i;
unsigned int j;
/* Initialize for totient sieve */
for (i = 0; i < n; i++) {
totients[i] = i;
}
/* Sieve */
for (i = 2; i < n; i++) {
/* Check to see if i is prime by checking to see if totient[i] == i */
if (totients[i] == i) {
/* For each multiple, multiply by (i - 1) / i */
for (j = i; j < n; j += i) {
tmp = (unsigned long long)totients[j];
tmp = tmp * (i - 1) / i;
totients[j] = (unsigned long)tmp;
}
}
}
}
#ifndef P72
/* Count digits in a, storing counts in *counts */
static void count_digits(unsigned int a, unsigned int *counts) {
int i;
for (i = 0; i < 10; i++) {
counts[i] = 0;
}
while (a > 0) {
counts[a % 10] += 1;
a /= 10;
}
}
/* Return non-zero if a is a permutation of the digits in b */
static int is_permutation(unsigned int a, unsigned int b) {
int i;
unsigned int ca[10];
unsigned int cb[10];
count_digits(a, ca);
count_digits(b, cb);
for (i = 0; i < 10; i++) {
if (ca[i] != cb[i]) {
return 0;
}
}
return 1;
}
/* Minimize n/phi(n) when n is a permutation of phi(n) */
static unsigned int solve(unsigned int limit) {
unsigned int i;
unsigned int n = 0;
float min = 100.0f;
float value;
unsigned int *totients = malloc(limit * sizeof(unsigned int)); /* Too big for stack */
compute_totients(limit, totients);
for (i = 2; i < limit; i++) {
if (is_permutation(i, totients[i])) {
value = ((float)i)/totients[i];
if (value < min) {
n = i;
min = value;
}
}
}
free(totients);
return n;
}
int main(int argc, char **argv) {
printf("%u\n", solve(10000000));
return 0;
}
#endif