--- /dev/null 2013-03-06 13:58:44.561061889 +0400 +++ new/test/java/lang/Math/VampireNumbers.java 2013-03-06 14:14:42.914833685 +0400 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Play around with vampire numbers + * @summary http://en.wikipedia.org/wiki/Vampire_number + * @summary com.apple.junit.java.lang.Math + * @run junit VampireNumbers + */ + +import junit.framework.*; +import javax.swing.*; +import java.awt.*; +import java.util.Arrays; +import java.util.HashSet; + +public class VampireNumbers extends TestCase { + + public static Test suite() { + return new TestSuite(VampireNumbers.class); + } + + public static void main (String[] args) { + junit.textui.TestRunner.run(suite()); + } + + // For convenince, we use a utility for composing and decomposing + // an integer into a collection of digits. This takes a seed + // number, such as 123128, and increments a counter for each + // digit in the seed. For example, with an increment of 1, + // the seed 123128 digitizes into: + // + // digits[1] --> +2 + // digits[2] --> +2 + // digits[3] --> +1 + // digits[8] --> +1 + // + // + // It will be handy to know the number of digits in the number + // so keep count and return this value. For example, 123128 is + // a six digit number, so return "6" + + private static int digitize(int seed, int incr, int digits[]) { + int cnt = 0; + while (true) { + int i = seed % 10; + seed = seed / 10; + digits[i] +=incr; + cnt++; + if (seed == 0) { + break; + } + } + return cnt; + } + + // 1st crack at a function that takes 2 possible fangs and + // returns whether or not they make a vampire number + + private static boolean isVampire(int a, int b) { + if ((a % 10 ==0) && (b % 10 ==0) ) { + return false; + } + final int[] digitCounts = new int[10]; + final int aNumDigits = digitize(a, 1, digitCounts); + final int bNumDigits = digitize(b, 1, digitCounts ); + if (aNumDigits != bNumDigits) { + return false; + } + digitize(a*b, -1, digitCounts ); + return( Arrays.equals( ZEROS, digitCounts )); + } + + static final int[] ZEROS =new int[10]; + + /* + * Play with Vampire Numbers some. Collect all the small ones, and show them + * visually as a product of 2 fangs in a frame. Throw in some asserts so that + * we have a testcase, even if it is sort of silly and should never fail. + */ + + static final int TOP = 999; + HashSet vamps= new HashSet(); + HashSet fangs = new HashSet(); + + public void testVampires() throws Exception { + for (int a = 0; a < TOP; a++) { + for (int b = 0; b <= a; b++) { + if (isVampire(a,b)) { + fangs.add(new Point(a,b)); + fangs.add(new Point(b,a)); + vamps.add(new Integer(a*b)); + } + } + } + + /* + * Check some interesting values + * The 7 vampires with 4 digits: + * 1260=21 x 60, 1395=15 x 93, 1435=35 x 41, 1530=30 x 51, 1827=21 x 87, 2187=27 x 81, 6880=80 x 86 + * + * The 5 prime vampires with 6 digits: + * 117067 = 167 x 701, 124483 = 281 x 443, 146137 = 317 x 461, 371893 = 383 x 971, 536539 = 563 x 953 + * + * Make sure that we don't over-zealously throw things out, either + * 473 x 800 = 378400 is a valid number + * + */ + assertTrue("expected v: 35, 41", fangs.contains( new Point(35,41))); + assertTrue("expected v: 30, 51", fangs.contains( new Point(30,51))); + assertTrue("expected v: 21, 60", fangs.contains( new Point(21,60))); + assertTrue("expected v: 80, 86", fangs.contains( new Point(80,86))); + assertTrue("expected v: 21, 87", fangs.contains( new Point(21,87))); + assertTrue("expected v: 15, 93", fangs.contains( new Point(15,93))); + + assertTrue("expected v: 167, 701", fangs.contains( new Point(21,60))); + assertTrue("expected v: 281, 443", fangs.contains( new Point(21,60))); + assertTrue("expected v: 317, 461", fangs.contains( new Point(21,60))); + assertTrue("expected v: 383, 971", fangs.contains( new Point(21,60))); + assertTrue("expected v: 563, 953", fangs.contains( new Point(21,60))); + + assertTrue("expected v: 473, 800", fangs.contains( new Point(473,800))); + + if (TOP == 999) { + assertEquals("There are 7 four-digit and 148 six-digit vampire numbers", 7+148, vamps.size()); + } + else if (TOP == 9999) { + assertEquals("There are 7 four-digit, 148 six-digit, and 3228 eight-digit vampire numbers", 7+148+3228, vamps.size()); + } + + /* + * Do some negative checks as well, to make sure garbage doesn't creep in. + */ + + assertTrue("Watch out for zeros: 210 x 600 = invalid", !fangs.contains( new Point(210,600))); // both end in zeros + assertTrue("Should not have v: 10, 10", !fangs.contains( new Point(10,10))); + assertTrue("Should not have v: 15, 15", !fangs.contains( new Point(15,15))); + assertTrue("Should not have v: 123, 321", !fangs.contains( new Point(123,321))); + assertTrue("Should not have v: 999, 999", !fangs.contains( new Point(999,999))); + + } +} +