Vampire Numbers

• 06-29-2010, 04:31 PM
Beginner
Vampire Numbers
This is an exercise in the book "Thinking in Java" and it says I need to find all the 4 digit Vampire Numbers

I have indeed finished the exercise and produced working code:

Code:

```import java.util.Arrays; class Vampire {         public static void main(String[] args) {                 for(int i=11; i<100; i++) {                         for(int j=i; j<100; j++) {                                 int k = i * j;                                                                 String kStr = Integer.toString(k);                                 String checkStr = Integer.toString(i) + Integer.toString(j);                                                                 //if(kStr.length() != 4) break;                                                                 char[] kChar = kStr.toCharArray();                                 char[] checkChar = checkStr.toCharArray();                                                                 Arrays.sort(kChar);                                 Arrays.sort(checkChar);                                                                 boolean isVampire = Arrays.equals(kChar, checkChar);                                                                 if(isVampire) {                                         System.out.println(i + " * " + j + " = " + k);                                 }                         }                 }         } }```
If you try and run this, it will run perfectly and find all the 4 digit vampire numbers. However, I commented out the line "if(kStr.length() != 4) break;" because if you include that line, it somehow misses some of the vampire numbers. That line of code will supposedly decrease the processing time because it will skip all non-4 digit numbers, because as the exercise asked, I need to find only the 4-digit numbers. Can anyone find out why that line of code doesn't work? Try running the code without that line, then try running it with that line.
• 06-29-2010, 05:17 PM
Sno
so --
i = 11
j = 11
k = 121
kStr = 121
checkStr = 1111

if(kStr.length() != 4) break; (Right now that would be false) Whats the point of this line?

shouldn't it be
Code:

```if(kStr.length() != 4){  break; } else {                                 char[] kChar = kStr.toCharArray(); char[] checkChar = checkStr.toCharArray();                                 Arrays.sort(kChar); Arrays.sort(checkChar);                                 boolean isVampire = Arrays.equals(kChar, checkChar);                                 if(isVampire) { System.out.println(i + " * " + j + " = " + k); }```
• 06-29-2010, 05:18 PM
JosAH
Quote:

Originally Posted by Beginner
If you try and run this, it will run perfectly and find all the 4 digit vampire numbers. However, I commented out the line "if(kStr.length() != 4) break;" because if you include that line, it somehow misses some of the vampire numbers. That line of code will supposedly decrease the processing time because it will skip all non-4 digit numbers, because as the exercise asked, I need to find only the 4-digit numbers. Can anyone find out why that line of code doesn't work? Try running the code without that line, then try running it with that line.

If you break from the inner loop if the product k doesn't have four digits you may stop the search too early, e.g. 15x15 has only three digits (225); if you break out of the loop you'll never find 15x93 which is a Vampire number. You can break out of the loop when k has more than four digits (which is never going to happen).

kind regards,

Jos

edit: you can start at j=Math.max(1000/i, i)
• 06-29-2010, 05:23 PM
Beginner
Quote:

Originally Posted by JosAH
If you break from the inner loop if the product k doesn't have four digits you may stop the search too early, e.g. 15x15 has only three digits (225); if you break out of the loop you'll never find 15x93 which is a Vampire number. You can break out of the loop when k has more than four digits (which is never going to happen).

kind regards,

Jos

Thanks for pointing that out Jos! What I wanted to do was not break, but it was continue, I mis-analyzed it. Thank you for saving me from headaches :)
• 06-29-2010, 05:25 PM
JosAH
Quote:

Originally Posted by Sno
so --
i = 11
j = 11
k = 121
kStr = 121
checkStr = 1111

if(kStr.length() != 4) break; (Right now that would be false) Whats the point of this line?

You do realize that this for loop body:

Code:

```if (<condition>) break; <statement>;```
... is identical to this for loop body?

Code:

```if (<condition>)   break; else   <statement>;```
kind regards,

Jos
• 06-29-2010, 05:36 PM
Sno
Well the way he had it,

I was taught, that if you did not have brackets, it would only effect the line that it is on, and the one below,

two lines below it wouldn't consider it to be part of the if statement.

so I figured his if statement was only affecting the break, and not dealing with anything else.
• 06-29-2010, 05:44 PM
JosAH
Quote:

Originally Posted by Beginner
Thanks for pointing that out Jos! What I wanted to do was not break, but it was continue, I mis-analyzed it. Thank you for saving me from headaches :)

Yep, the 'continue' statement will skip the failing calculations; also read my first reply (I edited it afterwards) for a tighter lowerbound on the loop variable j.

kind regards,

Jos
• 06-29-2010, 05:51 PM
Beginner
Good thinking! That will certainly eliminate all the 3 Digit results
• 06-29-2010, 07:09 PM
JosAH
Quote:

Originally Posted by Beginner
Good thinking! That will certainly eliminate all the 3 Digit results

Yep, and there won't be any five digit results (both i and j < 100) so the entire if (<condtion>) break; statement can go.

kind regards,

Jos
• 07-01-2010, 12:39 AM
toylord
Quote:

Originally Posted by JosAH
Yep, and there won't be any five digit results (both i and j < 100) so the entire if (<condtion>) break; statement can go.

kind regards,

Jos

Hi guys, I have the solution to the exercise. Let me know if you want it posted.

Yeamin.
• 07-01-2010, 08:33 AM
toylord
Quote:

Originally Posted by toylord
Hi guys, I have the solution to the exercise. Let me know if you want it posted.

Yeamin.

Sorry, I meant the solution as printed on the Solution Guide by B. Eckel.
• 07-02-2010, 06:47 AM
Singing Boyo
Quote:

Originally Posted by toylord
Sorry, I meant the solution as printed on the Solution Guide by B. Eckel.

You do realize they solved it right? :)
• 07-02-2010, 01:22 PM
toylord
Quote:

Originally Posted by Singing Boyo
You do realize they solved it right? :)

I do sir! It's just that the the solution to the exercise is done a bit differently I suppose therefore I thought it might be worthwhile for others if i pasted it in.

Regards
Yeamin.
• 07-02-2010, 01:53 PM
JosAH
Quote:

Originally Posted by toylord
I do sir! It's just that the the solution to the exercise is done a bit differently I suppose therefore I thought it might be worthwhile for others if i pasted it in.

Well, go ahead then, post your solution; maybe we can all learn from it. The OP's solution is quite simple: it searches 9000 possibilites for only 7 results; can your solution do better?

kind regards,

Jos
• 07-02-2010, 04:39 PM
toylord
Here it is:

Code:

``` public class E10_Vampire { public static void main(String[] args) { int[] startDigit = new int[4]; int[] productDigit = new int[4]; for(int num1 = 10; num1 <= 99; num1++) for(int num2 = num1; num2 <= 99; num2++) { // Pete Hartley's theoretical result: // If x·y is a vampire number then // x·y == x+y (mod 9) if((num1 * num2) % 9 != (num1 + num2) % 9) continue; int product = num1 * num2; startDigit[0] = num1 / 10; startDigit[1] = num1 % 10; startDigit[2] = num2 / 10; startDigit[3] = num2 % 10; productDigit[0] = product / 1000; productDigit[1] = (product % 1000) / 100; productDigit[2] = product % 1000 % 100 / 10; productDigit[3] = product % 1000 % 100 % 10; int count = 0; for(int x = 0; x < 4; x++) for(int y = 0; y < 4; y++) { if(productDigit[x] == startDigit[y]) { count++; productDigit[x] = -1; startDigit[y] = -2; if(count == 4) System.out.println(num1 + " * " + num2 + " : " + product); } } } } } /* Output: 15 * 93 : 1395 21 * 60 : 1260 21 * 87 : 1827 27 * 81 : 2187 30 * 51 : 1530 35 * 41 : 1435 80 * 86 : 6880 *///:~```
• 07-02-2010, 04:54 PM
JosAH
Quote:

Originally Posted by toylord
Code:

```for(int num1 = 10; num1 <= 99; num1++) for(int num2 = num1; num2 <= 99; num2++) { // Pete Hartley's theoretical result: // If x·y is a vampire number then // x·y == x+y (mod 9) if((num1 * num2) % 9 != (num1 + num2) % 9) continue;```

So we can conclude that your loop boundary conditions are weaker than what I suggested and your test for avoiding calculations that can never succeed are stronger than in the code OP's code (there is no such condition there).

kind regards,

Jos
• 07-02-2010, 05:14 PM
toylord
Quote:

Originally Posted by JosAH
So we can conclude that your loop boundary conditions are weaker than what I suggested and your test for avoiding calculations that can never succeed are stronger than in the code OP's code (there is no such condition there).

kind regards,

Jos

Well it is not my solution. It is the official solution to the exercise by Bruce Eckel himself. I have my own solution but it's pretty similar to the one that 'beginner' suggested.

Regards
• 08-03-2011, 11:51 AM
srinivas463
srinivas
Quote:

Originally Posted by Beginner
This is an exercise in the book "Thinking in Java" and it says I need to find all the 4 digit Vampire Numbers

I have indeed finished the exercise and produced working code:

Code:

```import java.util.Arrays; class Vampire {         public static void main(String[] args) {                 for(int i=11; i<100; i++) {                         for(int j=i; j<100; j++) {                                 int k = i * j;                                                                 String kStr = Integer.toString(k);                                 String checkStr = Integer.toString(i) + Integer.toString(j);                                                                 if(kStr.length() != 4) continue;                                                                 char[] kChar = kStr.toCharArray();                                 char[] checkChar = checkStr.toCharArray();                                                                 Arrays.sort(kChar);                                 Arrays.sort(checkChar);                                                                 boolean isVampire = Arrays.equals(kChar, checkChar);                                                                 if(isVampire) {                                         System.out.println(i + " * " + j + " = " + k);                                 }                         }                 }         } }```
If you try and run this, it will run perfectly and find all the 4 digit vampire numbers. However, I commented out the line "if(kStr.length() != 4) break;" because if you include that line, it somehow misses some of the vampire numbers. That line of code will supposedly decrease the processing time because it will skip all non-4 digit numbers, because as the exercise asked, I need to find only the 4-digit numbers. Can anyone find out why that line of code doesn't work? Try running the code without that line, then try running it with that line.

HI ...
you just put CONTINUE instead BREAK.
then it will give perfect result
• 08-03-2011, 01:26 PM
DarrylBurke
The thread is over a year old. Locking up here.

db