1

I am writing program which generates Vampire numbers https://en.wikipedia.org/wiki/Vampire_number.

I have main function with numberOfDigits argument, which must be even. If numberOfDigits is equal 4, then we are searching Vampire Numbers in range 1000 to 9999 - four digits. If numberOfDigits is equal 6, then we are searching Vampire Numbers from 100000 to 999999 - which is six digits.

In following file, when I want to search Vampire numbers in range of 10 digits, Java heap space is screaming. Note that I have default settings for memory. But for, numberOfDigits == 4, 6 or 8, code is working correctly. (compared output to https://oeis.org/A014575/b014575.txt , https://oeis.org/A014575 ). So I want to ask,

  1. What I can do to optimize this code? I have thought about using String with digits inside, instead of long/BigInteger. I want to "omit" that heap problem. Saving big numbers to file would be too slow, am I right?

  2. My mate wrote (bigNum.cpp) http://pastebin.com/0HHdE848 - class in C++, to operate on big numbers. Maybe with help from community I could implement that in my a.java? More important - would it be useful for my problem?

  3. edit: My goal is to generate free range of Vampire Numbers, like 4,6,8 - a.java it can do it, even more (if I can bypass heap space problem). And that is when my questions to help comes.

a.java (permutation code from johk95, https://stackoverflow.com/a/20906510 )

import java.util.ArrayList;
import java.util.Arrays;

/**
 * 
 * @author re
 */
public class a {
    
    /**
     *
     * @param numberOfDigits {int}
     * @return ArrayList of Integer
     */
    public ArrayList<Integer> vdf(int numberOfDigits) {
        
        if ((numberOfDigits % 2) == 1) { 
            //or throw Exception of unrecognised format/variable?
            System.out.println("cant operate on odd argument");
            return new ArrayList<>();
        }
        long maxRange = 9;
        
        for (int i = 1; i < numberOfDigits; i++) {
            maxRange *= 10;
            maxRange += 9;
        }//numberOfDigits==4 then maxRange==9999, nOD==5 then maxRange==99999,..
        
        long minRange = 1;
        
        for (int i = 1; i < numberOfDigits; i++) {
            minRange *= 10;
        }//nOD==4 then minRange==1000, nOD==5 then minRange==10000, ..
   
        ArrayList<Integer> ret = new ArrayList<>();
        for (long i = minRange; i < maxRange; i++) {
            
            long a = i;
            
            long[] b = new long[numberOfDigits];
            
            for (int j = numberOfDigits-1; j >= 0 ; j--) {
                long c = a % 10;
                a = a / 10;
                b[j] = c;
            }
            
            int x = 0;
            int y = 0;
            ArrayList<long[]> list = permutations(b);
            b = null; //dont need now
            
            for(long[] s : list) {
                for (int j = 0; j < numberOfDigits/2; j++) {
                    x += s[(numberOfDigits/2)-j-1] * Math.pow(10, j);
                    y += s[numberOfDigits-j-1] * Math.pow(10, j);
                }
                StringBuilder builder = new StringBuilder();
                for (long t : s) {
                    builder.append(t);
                }
                String v = builder.toString();
                
                if ((v.charAt((v.length()/2)-1) != '0'||
                    v.charAt(v.length()-1) != '0') &&
                    x * y == i) {
                    ret.add(x);
                    ret.add(y);
                    System.out.println(x*y+"  "+x+" "+y);
                    break;
                }
                x = y = 0;
            }
        }
        System.out.printf("%d vampire numbers found\n", ret.size()/2);
        return ret;
    }
    
    /**
     * 
     *@return vdf(4)
     */
    public ArrayList<Integer> vdf() {
        return vdf(4);//without trailing zeros
    }
    
    /* permutation code copied from  
     * johk95
     * https://stackoverflow.com/a/20906510
     */
    private static ArrayList<long[]> permutations(long[] lol) {
        ArrayList<long[]> ret = new ArrayList<>();
        permutation(lol, 0, ret);
        return ret;
    }
    
    private static void permutation(long[] arr, int pos, ArrayList<long[]> list){
        if(arr.length - pos == 1)
            list.add(arr.clone());
        else
            for(int i = pos; i < arr.length; i++){
                swap(arr, pos, i);
                permutation(arr, pos+1, list);
                swap(arr, pos, i);
            }
    }

    private static void swap(long[] arr, int pos1, int pos2){
        long h = arr[pos1];
        arr[pos1] = arr[pos2];
        arr[pos2] = h;
    }
    
    public static void main(String[] args) {
        a a = new a();
        try{
            a.vdf(10); //TRY IT WITH 4, 6 or 8. <<<<
        }catch (java.lang.OutOfMemoryError e){
            System.err.println(e.getMessage());
        }
    }
}

EDIT: http://ideone.com/3rHhep - working code above with numberOfDigits == 4.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
nanomader
  • 410
  • 9
  • 22

1 Answers1

1
package testing;

import java.util.Arrays;


public class Testing
{
    final static int START = 11, END = 1000;
    public static void main(String[] args)
    {
        char[] kChar, checkChar;
        String kStr, checkStr;
        int k;
        for(int i=START; i<END; i++) {
                for(int i1=i; i1<100; i1++) {
                    k = i * i1;

                    kStr = Integer.toString(k);
                    checkStr = Integer.toString(i) + Integer.toString(i1);

                    //if(kStr.length() != 4) break;

                    kChar = kStr.toCharArray();
                    checkChar = checkStr.toCharArray();

                    Arrays.sort(kChar);
                    Arrays.sort(checkChar);

                    if(Arrays.equals(kChar, checkChar)) {
                        System.out.println(i + " * " + i1 + " = " + k);
                    }
                }
            }
    }
}

This will generate vampire numbers, just modify the start and end integers.

Kai Arakawa
  • 193
  • 1
  • 1
  • 14
  • Thanks for feedback and your code. But what if I want to generate, for example, 14 digits Vampire numbers? And i want to do it, in something like this way: generateVampireNumbers(/*numberOfDigits*/12); I don't want to edit file every time. My primary goal is to "omit", or bypass heap problem using some tricky method. Maybe Strings, as i mentioned in my question? – nanomader Jul 01 '15 at 12:04
  • @nanomader94 it's a variable, make it non final and just change it with code – Kai Arakawa Jul 06 '15 at 22:15