Skip to content

Instantly share code, notes, and snippets.

@kinow
Created October 27, 2011 16:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kinow/1320080 to your computer and use it in GitHub Desktop.
Save kinow/1320080 to your computer and use it in GitHub Desktop.
Euler1
package euler;
import org.apache.commons.functor.UnaryPredicate;
import org.apache.commons.functor.UnaryProcedure;
import org.apache.commons.functor.core.composite.ConditionalUnaryProcedure;
import org.apache.commons.functor.generator.Generator;
import org.apache.commons.functor.generator.util.EachElement;
import org.apache.commons.functor.generator.util.IntegerRange;
/**
* An adder, or a summer, whatever.
*
* @author Bruno P. Kinoshita - http://www.kinoshita.eti.br
*/
class Adder implements UnaryProcedure<Integer> {
private int total = 0;
public void run(Integer obj) {
if (obj != null) {
total = total + (obj.intValue());
}
}
public int getTotal() {
return total;
}
}
/**
* Problem from Euler that loiane resolved in Java, now in Functional
* Programming :)
*
* I'm quite new to FP, so there may have other ways (maybe better) of using FP
* to solve this problem.
*
* @see {@link http://www.loiane.com/2011/10/project-euler-problema-1/}
*
* @author Bruno P. Kinoshita - http://www.kinoshita.eti.br
*/
public class Euler1 {
// A predicate that represents our condition for this problem: a number
// is multiple of three (3) or five (5).
private static final UnaryPredicate<Integer> IS_MULTIPLE_OF_THREE_OR_FIVE = new UnaryPredicate<Integer>() {
public boolean test(Integer obj) {
if (obj != null) {
if (obj % 3 == 0 || obj % 5 == 0) {
return true;
}
}
return false;
}
};
public int test(Integer left, Integer right){
Generator<Integer> generator = EachElement.from(new IntegerRange(left,
right).toCollection()); // From 0 to 1
Adder summer = new Adder(); // :-) We create an adder
ConditionalUnaryProcedure<Integer> proc = new ConditionalUnaryProcedure<Integer>(
IS_MULTIPLE_OF_THREE_OR_FIVE, summer); // And a procedure that
// executes another one
// if a condition is
// valid.
generator.run(proc); // Run our generator, executing the procedure above
return summer.getTotal(); // Return the total
}
}
@rbrito
Copy link

rbrito commented Oct 29, 2011

OK, that's great creating predicates and programming in functional style and so on, but can you make it faster? Oh, and by faster I mean both in terms of complexity and in real time.

@kinow
Copy link
Author

kinow commented Oct 30, 2011

Nope :-) Not faster than using imperative. I will execute some performance tests in this code against the original one, wrote with two for's I guess. I'll post the results here

@rbrito
Copy link

rbrito commented Oct 30, 2011

No, not with two loops or whatever. That's (almost) surely going to be worse. A hint here: what about not even taking the time to process the numbers that you know that won't be multiples of 3 or 5 anyway? OK, I guess that this is more than a simple hint... :)

@kinow
Copy link
Author

kinow commented Oct 31, 2011

Hmm, I will think about it tomorrow morning (that's when my brain works better :), here's the link to the original post about this problem with the source code and for's: http://www.loiane.com/2011/10/project-euler-problema-1/

@kinow
Copy link
Author

kinow commented Oct 31, 2011

BTW, perhaps what you meant is what another user commented on the blog entry I just sent to you...

@kinow
Copy link
Author

kinow commented Nov 1, 2011

0 -> 1000

Functional Programming
Took 9003354 nanos

Imperative Programming
Took 24005 nanos

@rbrito
Copy link

rbrito commented Nov 1, 2011

What about this one: https://gist.github.com/1331277 ?

It has some features that the other solutions don't:

  • it does only one pass through 0..1000 (or 1..1000, whatever you prefer).
  • it does not use any kind of division (which is expensive), either explicit or implicit (via mod).
  • it only considers the numbers that we know for sure that are multiples of 3 or of 5.

I initialized both candidates to be included in the sum with 0, but I could have just similarly have initialized them to 3 and 5, but this doesn't buy us anything good (one iteration of the body of a loop that is way lighter right now).

Comments?

@kinow
Copy link
Author

kinow commented Nov 1, 2011

Damn!!! That's neat!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment