{"id":1001,"date":"2014-09-05T10:11:16","date_gmt":"2014-09-05T17:11:16","guid":{"rendered":"http:\/\/www.coastalvectors.com\/blog\/?p=1001"},"modified":"2014-09-05T10:44:41","modified_gmt":"2014-09-05T17:44:41","slug":"project-euler-12","status":"publish","type":"post","link":"https:\/\/www.coastalvectors.com\/blog\/2014\/09\/project-euler-12\/","title":{"rendered":"Project Euler 12"},"content":{"rendered":"<p>I was recently going through some old <a href=\"http:\/\/projecteuler.net\">Project Euler<\/a> solutions, and noticed that my solution to <a href=\"http:\/\/projecteuler.net\/problem=12\">problem 12<\/a> was never optimized. The problems asks:<\/p>\n<blockquote><p>The sequence of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Triangular_number\">triangle numbers<\/a> is generated by adding the natural numbers. So the 7<sup>th<\/sup> triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:<\/p>\n<p>1, 3, 6, 10, 15, 21, 28, 36, 45, 55, &#8230;<\/p>\n<p>Let us list the factors of the first seven triangle numbers:<\/p>\n<p><b>1<\/b>: 1<br \/>\n<b>3<\/b>: 1,3<br \/>\n<b>6<\/b>: 1,2,3,6<br \/>\n<b>10<\/b>: 1,2,5,10<br \/>\n<b>15<\/b>: 1,3,5,15<br \/>\n<b>21<\/b>: 1,3,7,21<br \/>\n<b>28<\/b>: 1,2,4,7,14,28<\/p>\n<p>We can see that 28 is the first triangle number to have over five divisors.<\/p>\n<p>What is the value of the first triangle number to have over five hundred divisors?<\/p><\/blockquote>\n<p>The way I originally solved this problem was a brute-force approach following this basic logic:<\/p>\n<ol>\n<li>Calculate next triangle number<\/li>\n<li>Try dividing number by every integer smaller than the number<\/li>\n<li>Count the number of integers that divide evenly<\/li>\n<li>Go to step 1 and repeat until divisors are greater than 500<\/li>\n<\/ol>\n<p>This process yielded the results, but it is far from elegant or optimized. it took <strong>14 minutes<\/strong> to calculate the answer! I knew that dividing by each number was a waste; there had to be a better way.<\/p>\n<p>Although I didn&#8217;t know it, I felt fairly certain that there was a relationship between prime factors and the number of divisors. It turns out I was right. There is a trick to calculate the number of divisors if you know the prime factors.<\/p>\n<p>Using the number 28 as an example, we can find that the prime factors are 2, 2, and 7, which can be written as 2<sup>2<\/sup> \u00d7 7<sup>1<\/sup>. Interestingly, if we take the exponents, add 1 to each, and then multiply them together, we can calculate the number of divisors. For this example, this becomes (2+1) \u00d7 (1+1), which is 2 \u00d7 3, which equals 6. (This is also mentioned in the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Divisor\">Wikipedia article for divisor<\/a> briefly in the section titled <a href=\"https:\/\/en.wikipedia.org\/wiki\/Divisor#Further_notions_and_facts\">&#8216;Further notions and facts&#8217;<\/a>).<\/p>\n<p>Equipped with this knowledge, I was able to devise a more efficient method to solve this problem:<\/p>\n<ol>\n<li>Pre-calculate primes up to x amount (to save effort recomputing each time)<\/li>\n<li>Calculate next triangle number that is divisible by 3 or 5 (I found a pattern that the most divisible triangle numbers were divisible by 3 or 5)<\/li>\n<li>Go through primes and divide number by primes until number equals 1<\/li>\n<li>Convert the prime factors to divisors<\/li>\n<li>Go to step 1 and repeat until divisors are greater than 500<\/li>\n<\/ol>\n<p>While this method is more complex, it yielded great results. Once I was done refining this method, I got the compute time down to <strong>.086 seconds<\/strong>. That is a very substantial improvement!<\/p>\n<p>The interesting part of the code is the findDivisors function, seen below.<\/p>\n<pre><code>int findDivisors(int input, int *primes, int primesToFind)\r\n{\r\n    int i, count=1;\r\n    int primeCount[primesToFind];\r\n    for (i=0; i&lt;primesToFind; i++)\r\n    primeCount[i] = 0;\r\n\r\n    \/\/ Prime factorization\r\n    while (input != 1)\r\n        for (i=0; i&lt;primesToFind; i++)\r\n            if (input % primes[i] == 0)\r\n            {\r\n                input = input \/ primes[i];\r\n                primeCount[i]++;\r\n            }\r\n\r\n    \/\/ Convert prime factorization to divisors\r\n    for (i=0; i&lt;primesToFind; i++)\r\n        if (primeCount[i] &gt; 0)\r\n            count *= (primeCount[i]+1);\r\n\r\n    return count;\r\n}<\/code><\/pre>\n<p>In this function, the inputs are:<\/p>\n<ul>\n<li>The triangle number (input)<\/li>\n<li>The array of pre-calculated prime numbers (primes)<\/li>\n<li>The number of primes in the array (primesToFind)<\/li>\n<\/ul>\n<p>As the division of primes occurs, I keep track in a separate array (primeCount) how many times a given prime index is used to divide. This keeps track of the prime factorization I talked about earlier so we can finally compute the number of divisors. Once computed, we pass back the count, and the program moves on to the next triangle number.<\/p>\n<p>So there you have it. My entire solution is available on my <a href=\"https:\/\/github.com\/mryingster\/ProjectEuler\/blob\/master\/problem_012.c\">GitHub<\/a> page.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was recently going through some old Project Euler solutions, and noticed that my solution to problem 12 was never optimized. The problems asks: The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + &hellip; <a href=\"https:\/\/www.coastalvectors.com\/blog\/2014\/09\/project-euler-12\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Project Euler 12<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-1001","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/posts\/1001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/comments?post=1001"}],"version-history":[{"count":21,"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/posts\/1001\/revisions"}],"predecessor-version":[{"id":1186,"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/posts\/1001\/revisions\/1186"}],"wp:attachment":[{"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/media?parent=1001"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/categories?post=1001"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.coastalvectors.com\/blog\/wp-json\/wp\/v2\/tags?post=1001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}