285 lines
No EOL
6.7 KiB
C
285 lines
No EOL
6.7 KiB
C
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#include <limits.h>
|
|
|
|
char input[] =
|
|
{
|
|
#embed "input-.txt"
|
|
,'\0' // null terminator
|
|
};
|
|
|
|
typedef struct{
|
|
uint64_t* divs;
|
|
int count;
|
|
int pos_count;
|
|
} divisors;
|
|
|
|
//char input[] = "L68\nL30\nR48\nL5\nR60\nL55\nL1\nL99\nR14\nL82\n";
|
|
int width = 0;
|
|
int height = 0;
|
|
uint64_t result = 0;
|
|
uint64_t result_2 = 0;
|
|
|
|
|
|
|
|
|
|
uint64_t parseNum(char* str, int* len){
|
|
int i = 0;
|
|
uint64_t out = 0;
|
|
while(str[i] != ',' && str[i] != '-' && str[i] != '\n'){
|
|
out += str[i]-0x30;
|
|
out *= 10;
|
|
i++;
|
|
}
|
|
out /=10;
|
|
*len = i;
|
|
return out;
|
|
}
|
|
|
|
int numPlaces (uint64_t n) {
|
|
int r = 1;
|
|
while (n > 9) {
|
|
n /= 10;
|
|
r++;
|
|
}
|
|
//printf("%d has %d places\n", n, r);
|
|
return r;
|
|
}
|
|
|
|
uint64_t power(uint64_t base, uint64_t exp) {
|
|
uint64_t i, result = 1;
|
|
for (i = 0; i < exp; i++)
|
|
result *= base;
|
|
return result;
|
|
}
|
|
|
|
uint64_t gen_div(int len, int spacing){
|
|
uint64_t div = 0;
|
|
for(int i = 0; i<len; i++){
|
|
div += power(10, i*spacing);
|
|
}
|
|
return div;
|
|
}
|
|
|
|
|
|
void sort_ranges(uint64_t* starts, uint64_t* ends, int len){
|
|
int curr_min = 0;
|
|
for(int i = 0; i<len-1; i++){
|
|
for(int o = i; o<len; o++){
|
|
if(starts[curr_min]>starts[o]){
|
|
curr_min = o;
|
|
}
|
|
}
|
|
uint64_t tmp_start = starts[curr_min];
|
|
uint64_t tmp_end = ends[curr_min];
|
|
|
|
starts[curr_min] = starts[i];
|
|
ends[curr_min] = ends[i];
|
|
|
|
starts[i] = tmp_start;
|
|
ends[i] = tmp_end;
|
|
}
|
|
}
|
|
|
|
//splits ranges that go over a decimal overflow barrier into two (or if necessary more) ranges
|
|
void optimize_ranges(uint64_t* starts, uint64_t* ends, int* len){
|
|
for(int i = 0; i<(*len); i++){
|
|
if(numPlaces(starts[i])<numPlaces(ends[i])){
|
|
//printf("Range %lu - %lu crosses barrier\n", starts[i], ends[i]);
|
|
ends[*len] = ends[i];
|
|
ends[i] = power(10, numPlaces(starts[i]))-1;
|
|
starts[*len] = power(10, numPlaces(starts[i]));
|
|
(*len)++;
|
|
|
|
|
|
//printf("Split into %lu - %lu\n", starts[i], ends[i]);
|
|
//printf("and %lu - %lu\n\n", starts[*len], ends[*len]);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
uint64_t sumup(uint64_t a, uint64_t b){
|
|
uint64_t res = 0;
|
|
for(uint64_t i = a; i<=b; i++){
|
|
res += i;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
uint64_t sum_gauss(uint64_t a){
|
|
return (a*(a+1))/2;
|
|
}
|
|
|
|
uint64_t sumup_gauss(uint64_t a, uint64_t b){
|
|
return sum_gauss(b)-sum_gauss(a-1);
|
|
}
|
|
|
|
uint64_t scm(uint64_t a, uint64_t b, uint64_t limit){
|
|
uint64_t res = a;
|
|
while(res%b!=0){
|
|
res += a;
|
|
if(res>limit){
|
|
return 0;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void gen_scms(uint64_t* divs, int* count, int* pos_count){
|
|
for(int i = 0; i<*pos_count-1; i++){
|
|
for(int o = i+1; i<*pos_count; i++){
|
|
uint64_t newdiv = scm(divs[i], divs[o], power(10, numPlaces(divs[i]*2)));
|
|
if(newdiv!=0){
|
|
printf("\t\tfound scm divisor: %lu", newdiv);
|
|
divs[*count] = newdiv;
|
|
(*count)++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
divisors* find_divs(int num){
|
|
|
|
divisors* divs = calloc(sizeof(divisors), 1);
|
|
|
|
divs->divs = calloc(num, sizeof(uint64_t));
|
|
printf("\tsearching for natural divisors\n");
|
|
for(int i = 2; i<=num; i++){
|
|
if(!(num%i)){
|
|
uint64_t newdiv = gen_div(i, num/i);
|
|
printf("\t\tfound %lu natural divisor\n", newdiv);
|
|
//bool redundant = false;
|
|
//for(int i = 0; i<count; i++){
|
|
// printf("Checking against %lu\n", divs[i]);
|
|
// if(newdiv%divs[i]==0){
|
|
// redundant = true;
|
|
// printf("rejecting...\n\n");
|
|
// }
|
|
//}
|
|
//if(!redundant){
|
|
// divs[count] = newdiv;
|
|
// count++;
|
|
//}
|
|
divs->divs[divs->count] = newdiv;
|
|
divs->count++;
|
|
|
|
}
|
|
}
|
|
|
|
printf("\tsearching for scm divisors\n");
|
|
|
|
gen_scms(divs->divs, &(divs->count), &(divs->pos_count));
|
|
return divs;
|
|
}
|
|
|
|
//4174379265
|
|
|
|
|
|
//4174601487
|
|
//4174601487
|
|
//4174823709
|
|
//4174823709
|
|
//4174823709
|
|
uint64_t check_range(uint64_t start, uint64_t end){
|
|
printf("Range %lu - %lu\n", start, end);
|
|
int num = numPlaces(start);
|
|
uint64_t res = 0;
|
|
printf("Finding Divs:\n");
|
|
divisors* divs = find_divs(num);
|
|
printf("Checking Divs:\n");
|
|
for(int i = 0; i<divs->count; i++){
|
|
uint64_t div = divs->divs[i];
|
|
//uint64_t div = gen_div(i, num/i);
|
|
uint64_t a = ((start+div-1)/div);
|
|
uint64_t b = (end)/div;
|
|
//uint64_t sum = sumup(a, b);
|
|
uint64_t sum = sumup_gauss(a, b);
|
|
if(i<divs->pos_count){
|
|
res += sum*div;
|
|
}
|
|
else{
|
|
res -= sum*div;
|
|
}
|
|
printf("div: %lu\nsumup: \t%lu\ncount: \t%lu\n", div, sum*div, res);
|
|
}
|
|
printf("=============================================================\n");
|
|
free(divs->divs);
|
|
free(divs);
|
|
|
|
return res;
|
|
}
|
|
|
|
int main(int argc, char *argv[]){
|
|
clock_t start, end;
|
|
start = clock();
|
|
|
|
//printf("INT_MAX: %d\n", INT_MAX);
|
|
|
|
int i = 0;
|
|
int num_ranges = 1;
|
|
while(input[i] != 0){
|
|
if(input[i]==','){
|
|
num_ranges++;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
uint64_t starts[num_ranges*2];
|
|
uint64_t ends[num_ranges*2];
|
|
|
|
i = 0;
|
|
int range_num = 0;
|
|
int len = 0;
|
|
while(input[i] != 0){
|
|
starts[range_num] = parseNum(&input[i], &len);
|
|
i+=len+1;
|
|
ends[range_num] = parseNum(&input[i], &len);
|
|
i+=len+1;
|
|
|
|
//printf("%d-%d\n", starts[range_num], ends[range_num]);
|
|
range_num++;
|
|
}
|
|
|
|
|
|
|
|
optimize_ranges(starts, ends, &num_ranges);
|
|
|
|
for(i = 0; i<num_ranges; i++){
|
|
//printf("checking range %lu-%lu\n", starts[i], ends[i]);
|
|
result_2 += check_range(starts[i], ends[i]);
|
|
//for(uint64_t o = starts[i]; o<=ends[i]; o++){
|
|
// //printf("checking %d for sillyness\n", o);
|
|
// if(check_silly(o)){
|
|
// result += o;
|
|
// //printf("%lu is SILLY!\t\tcount is %lu\n", o, result);
|
|
//
|
|
// }
|
|
//}
|
|
//printf("count: %lu\n", result);
|
|
//printf("count_2: %lu\n\n", result_2);
|
|
}
|
|
|
|
//if(check_silly(1212)){
|
|
// result += 1212;
|
|
// printf("%d is SILLY!\n", 1212);
|
|
//}
|
|
|
|
|
|
end = clock();
|
|
printf("count: %lu\n", result);
|
|
printf("count_2: %lu\n", result_2);
|
|
clock_t ticks_taken = end - start;
|
|
double time_taken = ((double)ticks_taken)/CLOCKS_PER_SEC;
|
|
printf("time take: %f ticks\n", time_taken);
|
|
printf("CLOCKS_PER_SEC: %ld\n", CLOCKS_PER_SEC);
|
|
|
|
|
|
exit(1);
|
|
} |