カプレカ数

隣の研究室の友人と飯を食いながら話に出てきたカプレカ数
どうやらカプレカ数を求める課題を新B4のプログラミングの課題に使っているらしい
そういやソフトウェア開発技術者試験でも午後IIで出てきた気がする.

同じ数字ではない4桁の整数は,「数字を並べかえてできる最大の数から最小の数を引く」という計算を繰り返すと,最後は必ず6174になる.

この6174がカプレカ数(Kaprekar number)と呼ばれる.カプレカ(Kaprekar)はこの数字を発見したインドの方らしいです.
6174の各桁の数字から作り出される最小の数は1467,同じく最大の数は7641.

7641 - 1467 = 6174

というようになります.
ちなみに2桁の場合は循環してしまいカプレカ数が存在せず,3桁のカプレカ数は495


せっかくなのでJavaで実装.なんだかんだで1hかかった
面倒なのでint型にしています.

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

public class KaprekarNumber {
    
    private int input_number;
    private int digit_number;
    private int last_number;
    private ArrayList<Integer> numberList;
    private boolean is_kaprekar = true;

    public KaprekarNumber(int input){
	this.input_number = input;
	this.last_number = input;
	this.digit_number = getDigitNumber(input);
	this.numberList = new ArrayList<Integer>();
    }
    
    /* MAIN routine */
    /* calculate next number until the same number is detected */
    public void process(){
	// System.out.println("input:" + this.input_number);
	int next_number = getNextNumber(last_number);
	
	/* push into arraylist */
	//	this.numberList.add(last_number);

	while(isNotAppearedYet(next_number) && (next_number != last_number)){
	    this.numberList.add(last_number);
	    // System.out.println("next:" + next_number);
	    last_number = next_number;
	    next_number = getNextNumber(last_number);
	}
	
	if(this.is_kaprekar){
	    System.out.println("Kaprekar number of " + this.input_number + " is " + next_number);
	}else{
	    System.out.println(this.input_number + " is NOT Kaprekar number.");
	}
    }


    /* to calculate digit number automatically */
    private int getDigitNumber(int number){
	int digit_number = 1;
	
	while(number % (int)(Math.pow(10, digit_number)) != number){
	    digit_number++;
	}	
	return digit_number;
    }
    

    private boolean isNotAppearedYet(int next_number){
	boolean detected = false;

	LOOP:
	for(int num: this.numberList){
	    if(num == next_number){
		/* print loop numbers here */
		System.out.println("Loop detected.");
		detected = true;
		this.is_kaprekar = false;
		break LOOP;
	    }
	}

	if(detected){
	    System.out.println("All numbers:");
	    for(int num: this.numberList){
		System.out.print(num);
		if(num == next_number){
		    System.out.print(" <=");
		}
		System.out.println();
	    }
	    System.out.println(next_number);
	    System.out.println("---");
	    return false;
	}
	return true;
    }
    
    private int getNextNumber(int number){
	return getMaxNumber(number) - getMinNumber(number);
    }
    
    private int getMinNumber(int number){
	int[] digit_array = getDigitArray(number);
	int min_number = 0;
	
	for(int i = 0; i < digit_array.length; i++){
	    min_number += digit_array[(digit_array.length - 1) - i] * (int)Math.pow(10,i);
	}
	return min_number;
    }
    
    private int getMaxNumber(int number){
	int[] digit_array = getDigitArray(number);
	int max_number = 0;
	
	for(int i = 0; i < digit_array.length; i++){
	    max_number += digit_array[i] * (int)Math.pow(10,i);
	}
	return max_number;

    }
    
    
    /* obtain increasing order digit array for getMinNumber(), getMaxNumebr() */
    private int[] getDigitArray(int number){
	int[] digit_array = new int[this.digit_number];
	
	/* extract numbers in each digit */
	for(int i = 0; i < digit_array.length; i++){
	    digit_array[i] = (number % (int)Math.pow(10, i + 1))
		- (number % (int)Math.pow(10, i));
	    digit_array[i] /= (int)Math.pow(10, i);
	}
	
	/* sorting the array as increasing order*/
	Arrays.sort(digit_array);
	
	return digit_array;
    }
        

    /* main */
    public static void main(String args[]){
	// receive 1st argument
	KaprekarNumber kn = new KaprekarNumber(Integer.parseInt(args[0]));
	kn.process();
    }

}


実行結果

> KaprekarNumber 1234
Kaprekar number of 1234 is 6174

> KaprekarNumber 12345
Loop detected.
All numbers:
12345
41976
82962 <=
75933
63954
82962
---
12345 is NOT Kaprekar number.