package com.javarush.task.task20.task2025;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/*
Алгоритмы-числа
*/

public class Solution {
    public static long[] posl;
    public static long max = 0;
    public static int znak = 0;
    public static long [] [] power = new long[10][30];
    static {

        for (int i = 1; i < 10; i++) {
            for (int j = 0; j < 30; j++) {
                Double d = Math.pow(i, j);
                power[i][j] = d.longValue();
            }
        }
    }
    public static long[] getArmNums(){
        ArrayList<Long> results = new ArrayList<>();
        long[] sums;
        while (posl[posl.length - 1] != 0){
            sums = getSums(posl);
            for (int i = 0; i < sums.length; i++) {
                if(sums[i] > 0 && sums[i] < max){
                    if(isArm(sums[i], znak)){
                        results.add(sums[i]);
                    }
                }

            }
            for (int i = 0; i < posl.length - 1; i++) {
                if(posl[i] != 0){
                    posl[i]--;
                    break;
                }
                if(posl[i] == 0 && posl[i + 1] != 0){
                    posl[i + 1]--;
                    for (int k = i; k >= 0; k--) {
                        posl[k] = posl[i + 1];
                    }
                }

            }
        }
        sums = new long[results.size()];
        for (int i = 0; i < results.size(); i++) {
            sums[i] = results.get(i);

        }
        return sums;
    }
    public static long[] getSums(long[] number){
        ArrayList<Long> sums = new ArrayList<>();
        long[] genSums;
        long sum = 0;
        int countZero = 0;
        for (int i = 0; i < number.length; i++) {
            if(number[i] == 0){
                countZero++;
            }
        }
        if(countZero == 0){
            for (int i = 0; i < number.length; i++) {
                sum += power[(int) number[i]] [number.length];
            }
                genSums = new long[] {sum};
                return genSums;


        }
        else {
            for (int i = 0; i < countZero + 1; i++) {
                for (int j = 0; j < number.length; j++) {
                    sum += power[(int) number[j]] [number.length - i];
                }

                    sums.add(sum);
                    sum = 0;


            }
            genSums = new long[sums.size()];
            for (int i = 0; i < sums.size(); i++) {
                genSums[i] = sums.get(i);

            }
            return genSums;
        }

    }
    public static boolean isArm(long num, int znak1){
        long temp = num;
        long sum = 0;
        while (temp != 0){
            sum += power[(int) temp % 10] [znak1];
            temp /= 10;
        }
        if (sum == num){
            return true;
        }
        else{
            return false;
        }
    }

    public static void create(int znak1) {
        posl = new long[znak1];
        for (int i = 0; i < posl.length; i++) {
            posl[i] = 9;
        }
    }


    public static long[] getNumbers(long N) {

        max = N;
        long f = N;
        while(f != 0){
            znak++;
            f /= 10;
        }
        create(znak);

        long[] result1 = getArmNums();

        return result1;

    }




    public static void main(String[] args) {
        long a = System.currentTimeMillis();
        System.out.println(Arrays.toString(getNumbers(1000)));
        long b = System.currentTimeMillis();
        System.out.println("memory " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (8 * 1024));
        System.out.println("time = " + (b - a) / 1000);

        a = System.currentTimeMillis();
        System.out.println(Arrays.toString(getNumbers(Long.MAX_VALUE)));
        b = System.currentTimeMillis();
        System.out.println("memory " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (8 * 1024));
        System.out.println("time = " + (b - a) / 1000);
    }
}