Advertisement
Marrin

Cyclical figurate numbers

Nov 28th, 2015
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.09 KB | None | 0 0
  1. /*
  2.  * @brief    Cyclical figurate numbers
  3.  *
  4.  * Project Euler (projecteuler.net)
  5.  *
  6.  * Problem 61:  Triangle, square, pentagonal, hexagonal, heptagonal, and
  7.  *  octagonal numbers are all figurate (polygonal) numbers and are generated
  8.  *  by the following formulae:
  9.  *  
  10.  *  Triangle        P(3,n)=n(n+1)/2       1, 3, 6, 10, 15, …
  11.  *  Square          P(4,n)=n²             1, 4, 9, 16, 25, …
  12.  *  Pentagonal      P(5,n)=n(3n−1)/2      1, 5, 12, 22, 35, …
  13.  *  Hexagonal       P(6,n)=n(2n−1)        1, 6, 15, 28, 45, …
  14.  *  Heptagonal      P(7,n)=n(5n−3)/2      1, 7, 18, 34, 55, …
  15.  *  Octagonal       P(8,n)=n(3n−2)        1, 8, 21, 40, 65, …
  16.  *  
  17.  *  The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three
  18.  *  interesting properties.
  19.  *  
  20.  *  1. The set is cyclic, in that the last two digits of each number is the
  21.  *     first two digits of the next number (including the last number with
  22.  *     the first).
  23.  *  2. Each polygonal type: triangle (P(3,127)=8128), square (P(4,91)=8281),
  24.  *     and pentagonal (P(5,44)=2882), is represented by a different number in
  25.  *     the set.
  26.  *  3. This is the only set of 4-digit numbers with this property.
  27.  *  
  28.  *  Find the sum of the only ordered set of six cyclic 4-digit numbers for
  29.  *  which each polygonal type: triangle, square, pentagonal, hexagonal,
  30.  *  heptagonal, and octagonal, is represented by a different number in the set.
  31.  *  
  32.  */
  33. #include <assert.h>
  34. #include <stdbool.h>
  35. #include <stdint.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39.  
  40. struct Node;
  41.  
  42. typedef struct {
  43.     uint16_t length;
  44.     uint16_t capacity;
  45.     struct Node *items[];
  46. } NodeArray;
  47.  
  48. typedef struct Node
  49. {
  50.     struct Node *next;
  51.     uint8_t side_count;
  52.     uint16_t number;
  53.     uint8_t incoming, outgoing;
  54.     NodeArray *neighbours;
  55. } Node;
  56.  
  57. typedef uint16_t (*Function)(uint16_t n);
  58.  
  59. uint16_t triangle(uint16_t n) { return n * (n + 1) / 2; }
  60. uint16_t square(uint16_t n) { return n * n; }
  61. uint16_t pentagonal(uint16_t n) { return n * (3 * n - 1) / 2; }
  62. uint16_t hexagonal(uint16_t n) { return n * (2 * n - 1); }
  63. uint16_t heptagonal(uint16_t n) { return n * (5 * n - 3) / 2; }
  64. uint16_t octagonal(uint16_t n) { return n * (3 * n - 2); }
  65.  
  66. static const Function FUNCTIONS[] = {
  67.     triangle, square, pentagonal, hexagonal, heptagonal, octagonal
  68. };
  69. #define FUNCTION_COUNT  (sizeof(FUNCTIONS) / sizeof(FUNCTIONS[0]))
  70. #define SIDE_COUNT_OFFSET   3
  71.  
  72. NodeArray* NodeArray_new(uint16_t capacity) {
  73.     NodeArray *result;
  74.  
  75.     result = malloc(sizeof(*result) + capacity * sizeof(result->items[0]));
  76.     result->length = 0;
  77.     result->capacity = capacity;
  78.  
  79.     return result;
  80. }
  81.  
  82. void NodeArray_free(NodeArray *array)
  83. {
  84.     if (array) {
  85.         array->length = array->capacity = 0;
  86.         free(array);
  87.     }
  88. }
  89.  
  90. _Bool NodeArray_is_full(NodeArray *array)
  91. {
  92.     return array->length == array->capacity;
  93. }
  94.  
  95. _Bool NodeArray_is_cyclic(NodeArray *array)
  96. {
  97.     return
  98.         array->items[0]->incoming == array->items[array->length - 1]->outgoing;
  99. }
  100.  
  101. void NodeArray_add(NodeArray *array, Node *node)
  102. {
  103.     assert(! NodeArray_is_full(array));
  104.     array->items[array->length++] = node;
  105. }
  106.  
  107. uint16_t NodeArray_sum_and_print(NodeArray *array)
  108. {
  109.     uint16_t result, number;
  110.     uint8_t i;
  111.  
  112.     result = 0;
  113.     for (i = 0; i < array->length; ++i) {
  114.         number = array->items[i]->number;
  115.         printf("%d ", number);
  116.         result += number;
  117.     }
  118.     putchar('\n');
  119.     return result;
  120. }
  121.  
  122. Node* Node_new(Node *previous, uint8_t side_count, uint16_t number)
  123. {
  124.     Node *result;
  125.     div_t div_result;
  126.  
  127.     result = malloc(sizeof(*result));
  128.     result->next = previous;
  129.     result->side_count = side_count;
  130.     result->number = number;
  131.     div_result = div(number, 100);
  132.     result->incoming = div_result.quot;
  133.     result->outgoing = div_result.rem;
  134.     result->neighbours = NULL;
  135.  
  136.     return result;
  137. }
  138.  
  139. void Node_free(Node *node)
  140. {
  141.     Node *next;
  142.  
  143.     while (node) {
  144.         node->neighbours = NULL;
  145.         next = node->next;
  146.         free(node);
  147.         node = next;
  148.     }
  149. }
  150.  
  151. Node* create_nodes_from_function(
  152.     Node *node, uint8_t side_count, Function function
  153. ) {
  154.     uint16_t n, number;
  155.  
  156.     for (n = 0;; ++n) {
  157.         number = function(n);
  158.         if (number >= 1000) {
  159.             if (number >= 10000) return node;
  160.             node = Node_new(node, side_count, number);
  161.         }
  162.     }
  163. }
  164.  
  165. Node* create_nodes(const Function *functions, uint8_t side_count_offset)
  166. {
  167.     Node *nodes;
  168.     uint8_t i;
  169.  
  170.     nodes = NULL;
  171.     for (i = 0; i < FUNCTION_COUNT; ++i) {
  172.         nodes = create_nodes_from_function(
  173.             nodes, i + side_count_offset, functions[i]
  174.         );
  175.     }
  176.  
  177.     return nodes;
  178. }
  179.  
  180. void build_graph(Node *nodes, NodeArray **incoming2nodes)
  181. {
  182.     Node *node;
  183.     uint16_t incoming_histogram[100];
  184.     uint8_t i;
  185.  
  186.     memset(incoming_histogram, 0, sizeof(incoming_histogram));
  187.     node = nodes;
  188.     while (node) {
  189.         ++incoming_histogram[node->incoming];
  190.         node = node->next;
  191.     }
  192.  
  193.     for (i = 0; i < 100; ++i) {
  194.         incoming2nodes[i] = NodeArray_new(incoming_histogram[i]);
  195.     }
  196.  
  197.     node = nodes;
  198.     while (node) {
  199.         NodeArray_add(incoming2nodes[node->incoming], node);
  200.         node->neighbours = incoming2nodes[node->outgoing];
  201.         node = node->next;
  202.     }  
  203. }
  204.  
  205. _Bool _find_solution(Node *node, NodeArray *result, _Bool *side_counts)
  206. {
  207.     Node *neighbour;
  208.     uint16_t i;
  209.  
  210.     NodeArray_add(result, node);
  211.     side_counts[node->side_count] = true;
  212.     if (NodeArray_is_full(result)) {
  213.         if (NodeArray_is_cyclic(result)) {
  214.             return true;
  215.         }
  216.     } else {
  217.         for (i = 0; i < node->neighbours->length; ++i) {
  218.             neighbour = node->neighbours->items[i];
  219.             if (! side_counts[neighbour->side_count]) {
  220.                 if (_find_solution(neighbour, result, side_counts)) {
  221.                     return true;
  222.                 }
  223.             }
  224.         }
  225.     }
  226.     --result->length;  /* Discard last element of `result`. */
  227.     side_counts[node->side_count] = false;
  228.     return false;
  229. }
  230.  
  231. NodeArray* find_solution(Node *nodes)
  232. {
  233.     NodeArray *result;
  234.     _Bool side_counts[FUNCTION_COUNT + SIDE_COUNT_OFFSET];
  235.     Node *node;
  236.  
  237.     result = NodeArray_new(FUNCTION_COUNT);
  238.     memset(side_counts, 0, sizeof(side_counts));
  239.    
  240.     node = nodes;
  241.     while (node) {
  242.         if (_find_solution(node, result, side_counts)) return result;
  243.         node = node->next;
  244.     }
  245.  
  246.     NodeArray_free(result);
  247.     return NULL;
  248. }
  249.  
  250. int main(void)
  251. {
  252.     Node *nodes;
  253.     NodeArray *incoming2nodes[100];
  254.     NodeArray *result;
  255.     uint8_t i;
  256.    
  257.     nodes = create_nodes(FUNCTIONS, SIDE_COUNT_OFFSET);
  258.     build_graph(nodes, incoming2nodes);
  259.     result = find_solution(nodes);
  260.     if (result) {
  261.         printf("sum = %d\n", NodeArray_sum_and_print(result));
  262.     } else {
  263.         puts("No solution found!");
  264.     }
  265.  
  266.     NodeArray_free(result);
  267.     for (i = 0; i < 100; ++i) {
  268.         NodeArray_free(incoming2nodes[i]);
  269.     }
  270.     Node_free(nodes);
  271.     return 0;
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement