|
#include <stdbool.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <time.h> |
|
|
|
static void *alloc (const size_t l) { |
|
void *r = malloc(l); |
|
if (r != NULL) return r; |
|
fprintf(stderr, "Failed to allocate %zu bytes\n", l); |
|
exit(1); |
|
} |
|
static void *re_alloc (void *p, const size_t l) { |
|
void *r = realloc(p, l); |
|
if (r != NULL) return r; |
|
fprintf(stderr, "Failed to re-allocate %zu bytes\n", l); |
|
exit(1); |
|
} |
|
static int *slice_clone (const int *head, const size_t head_len, const size_t capacity) { |
|
int *r = alloc(capacity * sizeof(int)); |
|
memcpy(r, head, head_len); |
|
return r; |
|
} |
|
static size_t climb_priv (int ***r, const int max_steps, const int *n, const size_t n_len, const int cur_steps, const int *head, const size_t head_len) { |
|
size_t r_len = 0; |
|
*r = alloc(sizeof(int *)); |
|
if (cur_steps == max_steps) { |
|
*r = re_alloc(*r, sizeof(int *)); |
|
(*r)[r_len++] = slice_clone(head, head_len, head_len); |
|
return r_len; |
|
} |
|
for (size_t i = 0; i < n_len; i++) { |
|
int choice = n[i]; |
|
size_t head_cloned_len; |
|
int *head_cloned; |
|
int **t = NULL; |
|
size_t t_len; |
|
if (cur_steps + choice > max_steps) continue; |
|
head_cloned_len = head_len + 1; |
|
head_cloned = slice_clone(head, head_len, head_cloned_len); |
|
head_cloned[head_len] = choice; |
|
t_len = climb_priv(&t, max_steps, n, n_len, cur_steps + choice, head_cloned, head_cloned_len); |
|
*r = re_alloc(*r, (r_len + t_len) * sizeof(int *)); |
|
memcpy(&(*r)[r_len], t, t_len * sizeof(int *)); |
|
r_len += t_len; |
|
free(head_cloned); |
|
free(t); |
|
} |
|
return r_len; |
|
} |
|
static int climb (const int max_steps, const int *n, const size_t n_len) { |
|
int *choices = alloc(n_len * sizeof(int)); |
|
size_t choices_len = 0; |
|
int **r = NULL; |
|
size_t r_len; |
|
for (size_t i = 0; i < n_len; i++) { |
|
bool duplicate = false; |
|
if (n[i] <= 0) continue; |
|
for (size_t j = 0; j < choices_len; j++) { |
|
if (choices[j] == n[i]) { |
|
duplicate = true; |
|
break; |
|
} |
|
} |
|
if (duplicate) continue; |
|
choices[choices_len++] = n[i]; |
|
} |
|
r_len = climb_priv(&r, max_steps, choices, choices_len, 0, NULL, 0); |
|
for (size_t i = 0; i < r_len; i++) { |
|
free(r[i]); |
|
} |
|
free(choices); |
|
free(r); |
|
return (int) r_len; |
|
} |
|
int main (void) { |
|
struct timespec start, end; |
|
uint64_t delta_sum = 0; |
|
clock_gettime(CLOCK_MONOTONIC_RAW, &start); |
|
for (int i = 0; i < 100; i++) { |
|
int input[2] = {1, 2}; |
|
climb(30, input, sizeof(input) / sizeof(input[0])); |
|
} |
|
clock_gettime(CLOCK_MONOTONIC_RAW, &end); |
|
delta_sum += (end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000; |
|
printf("delta: %f\n", (double) delta_sum / 100); |
|
} |