package org.shapelogic.euler; import java.util.Map; import java.util.TreeMap; import org.shapelogic.calculation.Accumulator; import org.shapelogic.calculation.BaseAccumulator; import org.shapelogic.calculation.AdvanceWhile; import org.shapelogic.mathematics.ArrayOperations; import org.shapelogic.mathematics.MaxAccumulator; import org.shapelogic.mathematics.NaturalNumberStream; import org.shapelogic.mathematics.PrimeNumberStream; import org.shapelogic.mathematics.SumAccumulator; import org.shapelogic.streams.BaseListStream0; import org.shapelogic.streams.BaseListIndexedStream1; import org.shapelogic.streams.BaseListStream2; import org.shapelogic.streams.BaseListFilterStream; import org.shapelogic.streams.ListFilterStream; import junit.framework.TestCase; /** First part of implementation of Project Euler.
* * See: http://projecteuler.net.
* * @author Sami Badawi * */ public class ProjectEuler1Test extends TestCase { private boolean skipSlowTest = true; /** Problem 1. * Add all the natural numbers below 1000 that are multiples of 3 or 5. * */ public void testProblem1() { NaturalNumberStream naturalNumberStream = new NaturalNumberStream(1,999); ListFilterStream filter = new BaseListFilterStream(naturalNumberStream) { public boolean evaluate(Integer object) {return object % 3 == 0 || object % 5 == 0;} }; SumAccumulator accumulator = new SumAccumulator(filter); System.out.println(accumulator.getValue()); assertEquals(new Long(233168), accumulator.getValue()); } /** Problem 2. * Find the sum of all the even-valued terms in the Fibonacci sequence * which do not exceed one million. * */ public void testProblem2() { BaseListIndexedStream1 fibonacci = new BaseListIndexedStream1(){ { _list.add(1); _list.add(2);} public Integer invoke(Object input, int index) {return get(index-2) + get(index-1);} }; ListFilterStream filter = new BaseListFilterStream(fibonacci) { public boolean evaluate(Integer object) { return object % 2 == 0; } }; SumAccumulator accumulator = new SumAccumulator(filter) { {_inputElement = 0;} public boolean hasNext(){ return _inputElement < 1000000; } }; System.out.println(accumulator.getPreviousValue()); //Test fails after value go over 1000000 assertEquals(new Long(1089154), accumulator.getPreviousValue()); } /** Problem 3. * Find the largest prime factor of 317584931803. */ public void testProblem3() { NaturalNumberStream naturalNumberStream = new NaturalNumberStream(2,null); BaseAccumulator accumulator = new BaseAccumulator(naturalNumberStream) { long theNumber = 317584931803l; {_inputElement = 0;} public Long accumulate(Integer element, Long out) { while (theNumber % element == 0l) { theNumber /= element; } return theNumber; } public boolean hasNext(){ return _inputElement <= theNumber; } }; System.out.println(accumulator.getValue()); assertEquals(new Long(3919), accumulator.getPreviousValue()); } /** Problem 4. * Find the largest palindrome made from the product of two 3-digit numbers. */ public void testProblem4() { NaturalNumberStream naturalNumberStream = new NaturalNumberStream(1,999); BaseListStream2 cartesianProduct = new BaseListStream2(naturalNumberStream, naturalNumberStream) { public Integer invoke(Integer input0, Integer input1, int index) {return input0 * input1;} }; ListFilterStream filter = new BaseListFilterStream(cartesianProduct) { public boolean evaluate(Integer object) {return palindrome(object);} }; MaxAccumulator accumulator = new MaxAccumulator(filter); System.out.println(accumulator.getValue()); assertEquals(new Integer(906609),accumulator.getValue()); } public static boolean palindrome(int input) { String inputAsStreing = "" + input; int stringLength = inputAsStreing.length(); for (int i=0; i< stringLength/2; i++) { if (inputAsStreing.charAt(i) != inputAsStreing.charAt(stringLength-1-i)) return false; } return true; } public void testPalindrome() { assertTrue(palindrome(1001)); assertFalse(palindrome(1011)); } /** Calculated the product of factors uplifted to a power. * * @param factorsWithPower the key is the factor and the value is the power. */ static public long productWithPower(Map factorsWithPower) { long product = 1; for (Integer element: factorsWithPower.keySet()) { int rank = factorsWithPower.get(element); for (int i=0; i primesUnder20 = new AdvanceWhile(primeNumberStream){ @Override public boolean evaluate(Integer input) { return input <= 20; } }; Accumulator > accumulator = new BaseAccumulator >(naturalNumberStream) { {_value = new TreeMap();} @Override public Map accumulate(Integer element, Map out) { for (Integer prime: primeNumberStream.getList()) { if (element < prime) break; int rank = rankOfDivisor(element,prime); Integer currentRank = out.get(prime); if (0 < rank && (currentRank == null || currentRank < rank)) out.put(prime,rank); } return out; } }; System.out.println(productWithPower(accumulator.getValue())); long result = productWithPower(accumulator.getValue()); assertEquals(232792560L, result); } /** Problem 6. * What is the difference between the sum of the squares and the square of the sums? */ public void testProblem6() { NaturalNumberStream naturalNumberStream = new NaturalNumberStream(1,100); BaseListIndexedStream1 squaredStream = new BaseListIndexedStream1(naturalNumberStream) { public Integer invoke(Integer input, int index) { if (input == null) return null; return input * input; } }; SumAccumulator sumOfSquares = new SumAccumulator(squaredStream); SumAccumulator sumOfNumbers = new SumAccumulator(naturalNumberStream); long result = sumOfNumbers.getValue() * sumOfNumbers.getValue() - sumOfSquares.getValue(); System.out.println(result); assertEquals(25164150L, result); } /** Problem 7. * Find the 10001st prime. */ public void testProblem7() { PrimeNumberStream primeNumberStream = new PrimeNumberStream(); long result = primeNumberStream.get(10000); System.out.println(result); assertEquals(104743L, result); } /** Problem 8. * Discover the largest product of five consecutive digits in the 1000-digit number. * This is simple generate a stream of Integer. * Accumulate through it looking 5 number back. */ public void testProblem8() { final String inputNumbers = "73167176531330624919225119674426574742355349194934" + "96983520312774506326239578318016984801869478851843" + "85861560789112949495459501737958331952853208805511" + "12540698747158523863050715693290963295227443043557" + "66896648950445244523161731856403098711121722383113" + "62229893423380308135336276614282806444486645238749" + "30358907296290491560440772390713810515859307960866" + "70172427121883998797908792274921901699720888093776" + "65727333001053367881220235421809751254540594752243" + "52584907711670556013604839586446706324415722155397" + "53697817977846174064955149290862569321978468622482" + "83972241375657056057490261407972968652414535100474" + "82166370484403199890008895243450658541227588666881" + "16427171479924442928230863465674813919123162824586" + "17866458359124566529476545682848912883142607690042" + "24219022671055626321111109370544217506941658960408" + "07198403850962455444362981230987879927244284909188" + "84580156166097919133875499200524063689912560717606" + "05886116467109405077541002256983155200055935729725" + "71636269561882670428252483600823257530420752963450"; final int numberLength = inputNumbers.length()-1; BaseListStream0 inputNumberStream = new BaseListStream0(numberLength) { @Override public Integer invoke(int index) { char c = inputNumbers.charAt(index); return Integer.parseInt(""+c); } }; BaseListIndexedStream1 productStream = new BaseListIndexedStream1(inputNumberStream,numberLength) {//XXX you should not need to set length public Integer invoke(Integer input, int index) { if (index<4) return 0; int result = 1; for (int i=index-4; i<=index;i++) {result*=getInput(i);}; return result; } }; MaxAccumulator maxAccu = new MaxAccumulator(productStream); System.out.println(maxAccu.getValue()); assertEquals(new Integer(40824),maxAccu.getValue()); } /** Problem 9. * Find the only Pythagorean triplet, {a, b, c}, for which a + b + c = 1000. * So create a sequence for B from 1 to 500. * For each A you could use a sequence from 1 to b. * But this is just doing the full Cartesian product. * * Contraints: * a < b * c = 1000 - a - b * c*c = a*a + b*b */ public void testProblem9() { NaturalNumberStream naturalNumberStream = new NaturalNumberStream(1,500); final int[] EMPTY_ARRAY = new int[0]; BaseListStream2 cartesianProduct = new BaseListStream2(naturalNumberStream, naturalNumberStream) { public int[] invoke(Integer a, Integer b, int index) { int c = 1000 - a - b; if (b<=a) return EMPTY_ARRAY; if (c*c == a*a + b*b) return new int[] {a,b,c}; else return EMPTY_ARRAY; } }; ListFilterStream filter = new BaseListFilterStream(cartesianProduct) { public boolean evaluate(int[] object) {return EMPTY_ARRAY != object;} }; int[] result = filter.next(); long resultNumber = ArrayOperations.product(result); System.out.println("result: "+ ArrayOperations.product(result)); System.out.println("a: " + result[0] + ", b: " + result[1] + ", c: " + result[2]); assertEquals(31875000L,resultNumber); } /** Problem 10. * Calculate the sum of all the primes below one million. * This takes minutes to run. */ public void testProblem10() { if (skipSlowTest ) return; PrimeNumberStream primeNumberStream = new PrimeNumberStream(); final AdvanceWhile primesUnder1000000 = new AdvanceWhile(primeNumberStream){ public boolean evaluate(Integer input) {return input <= 1000000;} }; primeNumberStream.setMaxLast(primeNumberStream.getList().size()-1); //XXX maybe change the accumulator System.out.println("Number of primes under 1000000: " + (primeNumberStream.getList().size()-1)); SumAccumulator sumAccu = new SumAccumulator(primeNumberStream.getList().iterator()); long result = sumAccu.getPreviousValue(); System.out.println(result); assertEquals(37550402023L, result); } }