C Coding Competition - Win an Arduino - Page 1
Forum section: electronics / general

author: Chet T16
author_rank: Frequent Contributor
timestamp: July 19, 2012, 12:10:47 am
content: Firstly, I've asked Dave and he said it's fine to do this.I have a littleArduino Pro Minito give away to the winner of this coding competition. They're tiny and you could fit one anywhere!To win the competition all you have to do is write the code which can find the first five "Perfect Numbers" in the fastest time.Fromwikipedia:QuoteFor example, the first perfect number is 6, as the factors of 6 (excluding itself) are 1, 2 and 3, and 1+2+3=6.The first four numbers are:6284968128The fifth is a little biggerRules:The code must be plain old COnly standard libraries to be usedNumbers must be found based on the definition above i.e. by finding and adding factors onlynything that runs for over an hour will be disqualifiedYou can PM me your code and i will compile and run it on my machine, it's a bit slow so it may give a time greater than you measured but rest assured all code will be ran equally.Closing date is undecided until i see what interest there is but i will give plenty of notice.

author: RCMR
author_rank: Frequent Contributor
timestamp: July 19, 2012, 12:38:28 am
content: You don't state the target system -- so are we to assume it's an Arduino?

author: Chet T16
author_rank: Frequent Contributor
timestamp: July 19, 2012, 12:43:46 am
content: I'll be compiling with gcc in cygwin. I think an arduino would crap itself!

author: slateraptor
author_rank: Frequent Contributor
timestamp: July 19, 2012, 12:53:03 am
content: Quote from: Chet T16 on July 19, 2012, 12:10:47 amThe challenge states "find" rather than calculate...look-up tables count?EDIT:Quote from: Chet T16 on July 19, 2012, 12:10:47 amNot winning.

author: adam1213
author_rank: Regular Contributor
timestamp: July 19, 2012, 02:07:01 am
content: somehow this sounds like a university assignment.You could just directly print the numbers (solutions won't get much faster than this)

author: slateraptor
author_rank: Frequent Contributor
timestamp: July 19, 2012, 03:30:06 am
content: Quote from: adam1213 on July 19, 2012, 02:07:01 amMore like a Project Euler puzzle with facebook puzzle caveats.

author: slateraptor
author_rank: Frequent Contributor
timestamp: July 19, 2012, 04:01:57 am
content: @Chet T16: PM sent.P.S. Benchmarks as entries are tested would be nice.

author: free_electron
author_rank: Super Contributor
timestamp: July 19, 2012, 06:13:51 am
content: void main void{printf ("6\n28\n496\n8128\n33550336")};you can keep the arduino. don't need it.

author: nitro2k01
author_rank: Frequent Contributor
timestamp: July 19, 2012, 06:30:54 am
content: Quote from: Chet T16 on July 19, 2012, 12:10:47 amThis raises the question of what optimizations we're allowed to do, exactly. For example, are we allowed to check only every second number, under the assumption that all perfect numbers are even? (If odd perfect numbers exist, they're certainly much greater than the numbers relevant for this contest.) The current reading of that rule makes sure the programs are going to heat your room more than your brain. A more interesting rule, IMO, would be:Each number must be iterated and individually qualified according to known general mathematical properties of perfect numbers.That way, the contest would actually be interesting.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 19, 2012, 06:33:47 am
content: next stop... the fastest sin(x) generator. prize = my "untested" PC display card backyard. winner pay shipping.rule... no table lookup. memory consumption... less than 11 bytes.

author: amyk
author_rank: Super Contributor
timestamp: July 19, 2012, 06:59:56 am
content: Quote from: nitro2k01 on July 19, 2012, 06:30:54 amThe problem with competitions like this is that the output is knowna prioriand so a highly optimising compiler could replace the entire program with one output, as the program takes no external input. This would make all your attempted algorithmic optimisations useless, and in fact may confuse the optimiser so it no longer can produce that truly optimal solution. Programs that consume input, however, are much more interesting and that is why you'll see a lot of competitionslike this onespecify the expected output given a particular input.

author: Chet T16
author_rank: Frequent Contributor
timestamp: July 19, 2012, 07:18:52 am
content: OK, to clarify, the intention is to find the first five numbers by finding the factors and adding them up and checking the sum. The idea then is to find the best possible way of factorising large numbers as this is where 99.999% of the time goes.This is based on a university assignment I had a few years ago while learning C, not something due now :p

author: _Sin
author_rank: Regular Contributor
timestamp: July 19, 2012, 04:59:12 pm
content: Quote from: Chet T16 on July 19, 2012, 07:18:52 amWhy would you generate a number as a sum of factors, and then factorise it?The following code ought to print out the first 8 perfect numbers with all factors, but it's not done the way you've asked so I guess it's not valid (and I'm not interested in the arduino anyway)Code:#include <stdio.h>#include <math.h>int isPrime(long long val){int p,i;if(val == 2) return 1;if((val & 1) == 0) return 0;p = (int) sqrt((float)val);for(i = 3 ; i <= p ; i ++){if((val % i) == 0) return 0;}return 1;}void main(){int i,j;for(i = 2 ; i < 32 ; i++){if(isPrime(i)){long long pn = (1 << i) - 1;if(isPrime(pn)){printf("%lld\n", ((long long) (1 << (i - 1))) * pn);for(j = 0 ; j < i; j ++){printf("%d ", 1 << j);}for(j = 0 ; j < (i - 1); j ++){printf("%lld ", (((long long)1) << j) * pn);}printf("\n\n");}}}}

author: grumpydoc
author_rank: Super Contributor
timestamp: July 19, 2012, 07:35:04 pm
content: Here is an integer only solution which is fairly compact, though almost totally naïve in its approach.Code:include <stdio.h>#include <limits.h>void main(int argc, char *argv[]){unsigned int p, f, t;for (p = 2; p < UINT_MAX; p += 2) {if (p == 6 || (p-1)/9*9 == (p-1)) {for (t = 0, f = 1; f*f <= p; f++) {if (p/f*f == p) {t += f;if (p/f != f && f!=1) t += p/f;}}if (t == p)printf ("%d\n", p);}}}I'm not sure that it's a terribly interesting problem at the level of "print the first 6" though. I agree with the others who have pointed out that once you have exploited some property of perfect numbers such as "they're probably even"1to avoid factorising each positive integer summing the factors and checking to see if that equals the original number you might as well go for theprintf("6\n28\n496\n8128\n33550336\n");approach._Sin's code is actually more interesting, and much faster (Oh, BTW I don't want the Arduino either). It exploits the fact that 2p-1(2p-1) is an even perfect number if 2p-1 is prime. the test for primeality in that code is a very simple one so, it's not as interesting as it could be.If you want an interesting problem prove that 2p-1(2p-1) is perfect for p=25964951 It has not been proven that there are no odd perfect numbers.

author: Chet T16
author_rank: Frequent Contributor
timestamp: July 19, 2012, 07:52:10 pm
content: There are lots of properties of perfect numbers that can be exploited but thats not the idea, its about being able factorise and add all the numbers up to and including the last one - following the definition of a perfect number

author: grumpydoc
author_rank: Super Contributor
timestamp: July 19, 2012, 08:13:49 pm
content: So the competition is about being able to write a fast factoriser.Sorry, I'll do my own crypto cracking, not yoursIt's still not interesting if you only want the first 5 or 6 perfect Nos.

author: Chet T16
author_rank: Frequent Contributor
timestamp: July 19, 2012, 08:22:41 pm
content: Quote from: grumpydoc on July 19, 2012, 08:13:49 pmI'm sorry to disappoint but the competition is all i say it is, no other motives. I thought it might be nice to have something different than the threads that descend into negativity that have become so common on here lately but it looks likes that's failed!

author: SeanB
author_rank: Super Contributor
timestamp: July 19, 2012, 08:28:26 pm
content: Nice idea, nice to do, and I would enter if I could code better than a dyslexic gibbon let loose on a keyboard.............Oh wait, That is me all the time I think.

author: slateraptor
author_rank: Frequent Contributor
timestamp: July 19, 2012, 08:45:30 pm
content: Quote from: Chet T16 on July 19, 2012, 08:22:41 pmWell, I guess I'll be going back to Project Euler to get my coding challenge fix...a shame, really.

author: Chet T16
author_rank: Frequent Contributor
timestamp: July 19, 2012, 08:58:54 pm
content: If you want something interesting I have a program that takes a 4 digit input (numbers and letters) and outputs a 4 digit code (numbers only) that I would like to reverse engineer

author: Chet T16
author_rank: Frequent Contributor
timestamp: July 19, 2012, 09:00:55 pm
content: Oh and regarding the challenge this is obviously aimed at people who only have a little experience coding. People like me!

author: _Sin
author_rank: Regular Contributor
timestamp: July 19, 2012, 09:17:30 pm
content: I wasn't trying to be negative, I just went off on a tangent and thought someone might be interested...

author: slateraptor
author_rank: Frequent Contributor
timestamp: July 19, 2012, 09:36:16 pm
content: Quote from: Chet T16 on July 19, 2012, 08:58:54 pmRoughly 15 million input permutations mapped to 10k possible outputs...brute forcing a reverse engineered sol'n would be trivial.

author: Chet T16
author_rank: Frequent Contributor
timestamp: July 19, 2012, 09:47:33 pm
content: Quote from: slateraptor on July 19, 2012, 09:36:16 pmIs that an offer? :p

author: grumpydoc
author_rank: Super Contributor
timestamp: July 19, 2012, 09:58:23 pm
content: QuoteWhich I thought to be perfectly valid, it's much more efficient to generate perfect numbers from Mersenne primes than by factorising each positive integer. Even if you replace the "computing 101" factorisation algorithm from the code I posted with a more efficient one it will still be slower than yours at generating perfect numbers.Yours can still be improved though as your primeality test is fairly simplistic - perhaps by dividing by primes less than the square root of the number of interest, rather than potentially by all integers >= 3. Or even just dividing by odd numbers.Chet T16 - the code I posted was intentionally a bit simplistic but if you are a beginner in C programming it is probably worth making sure you understand it, then make sure you understand _Sin's. Then see if you can spot the (obviously deliberate) errors of coding style in both - there are things in _Sin's that I would reject at code review. There again there are things in mine that I would also question now that I re-read it. No-one's perfect!!

author: slateraptor
author_rank: Frequent Contributor
timestamp: July 19, 2012, 10:03:44 pm
content: Quote from: grumpydoc on July 19, 2012, 09:58:23 pm*giggles*Quote from: Chet T16 on July 19, 2012, 09:47:33 pmI'm tempted to say sure for shits and grins...but I think I'll pass. I wouldn't want to spoil a good learning opportunity.

author: _Sin
author_rank: Regular Contributor
timestamp: July 20, 2012, 05:51:07 am
content: Quote from: grumpydoc on July 19, 2012, 09:58:23 pmYes, I put in a mostly trivial primality test with the intention of replacing it with something a bit faster after proving that the code worked, but as it generates all the perfect numbers <64bits long without any appreciable time delay, it seemed pointless to optimise further.I think minor optimisations on the primality test wouldn't get very far, however. To test only primes there would need to either be a rather large table, or a recursive call to the prime test (which is significantly slower than brute force in this instance). I did originally generate the primes, but the memory requirements shoot up beyond (IIRC) the 5th perfect number and it started to take noticeable amounts of time to generate.Considering that only a tiny handful of potential primes are ever even considered in the code, it seemed that a simple test would be a far better option than trying to generate/store primes. Unless I stored only the primes I know I'd need, but then I might as well just store the answer, and that seemed like cheating.I had a simple implementation of miller-rabin, which is probabilistic (but known good over the range required here). However it seems unnecessary speed-wise, and would have complicated the code.And no, I wouldn't want anyone taking that code as a good example of anything

author: grumpydoc
author_rank: Super Contributor
timestamp: July 20, 2012, 03:02:11 pm
content: Good points.It's worth remembering that in the real world "good enough" is often just that - "good enough". I think your observations about minimal gain are very valid. One shouldn't optimise unless the section of code in question has shown to be an important bottleneck - and one shouldn't optimise implementation before optimising the (choice of) algorithm.Another important point that you touch upon is that it's sometimes necessary to trade memory use for speed, or vice versa depending on resources. This is especially true for embedded systems. Another thing is that sometimes an approach which should be faster in theory turns out not to be so in practice as you found with storing primes.Finally remember that there is a sometimes a trade off between efficiency and maintainability - miller-rabin will be faster but if the next person to maintain the code hasn't a clue how it works it might not be such a good idea.See - you can make any bit of programming interesting as long as you don't constrain it too much.

author: DavidJRobertson
author_rank: Regular Contributor
timestamp: July 29, 2012, 09:03:53 pm
content: My working but inefficient solution:Code:#include <stdio.h>void main() {int i = 2;int numfound = 0;int factorsum;int j;int hold; // Probably doesn't need to be this big but whatever...int cv;while (numfound < 6) {factorsum = 1;for (j = 2; j < i; j++){if (i % j == 0) {if (hold == 0) {factorsum +=j;hold = 1;}if (hold[i/j] == 0){factorsum += i/j;hold[i/j] = 1;}}}if (factorsum == i) {printf("%10d\n", i);numfound++;}for (cv = 0; cv < 100000; cv++) {hold = 0;}i += 2; // Assuming all answers will be even}}

author: westfw
author_rank: Super Contributor
timestamp: July 30, 2012, 03:42:27 am
content: QuoteA "known to be hard" problem. Though the 5th perfect number hardly qualifies as "large."There are probably lots of published algorithms, although they tend to be aimed at finding "prime factors." (A list of prime factors gives you all of the factors pretty easily, though. I think.)I think you should require that it actually run on an Arduino. The relative lack of RAM might add an interesting component to the challenge...