Вхожу в ограничение по времени со свистом при Long.maxValue - (~8с). Но программа кушает больше 50МБ ОЗУ. Не постоянно, а пиками. Иногда доходит даже до 100МБ.
Вероятно, один из методов прожорливый (подорзреваю, что addIfAmstrong(long n)), но эксперименты не привели к желаемому результату. Выручайте:)
p.s. готовое решение по возможности не скидывать, пожалуйста.
package com.javarush.task.task20.task2025;
import java.util.*;
/*
Алгоритмы-числа
*/
public class Solution {
static List<Long> list = new ArrayList<>(88);
public static long[] getNumbers(long N) throws InterruptedException {
if (N<1) return null;
Thread t1 = new Thread(() -> {
foo(1, N);
foo(2, N);
foo(3, N);
foo(4, N);
foo(5, N);
foo(6, N);
foo(7, N);
foo(8, N);
});
Thread t2 = new Thread(() -> {
foo(9, N);
});
t1.start();
t2.start();
t1.join();
t2.join();
long[] result = new long[list.size()];
for (int i = 0; i < result.length; i++) {
result[i] = list.get(i);
}
Arrays.sort(result);
return result;
}
private static void foo(long n, long N) {
addIfAmstrong(n);
if (getDepth(n) < 19 & n < N / 10) {
for (byte i = 0; i <= n % 10; i++) {
foo(n * 10 + i, N);
}
}
}
private static void addIfAmstrong(long n) {
long s = sum(n);
char[] num = Long.toString(n).toCharArray();
char[] sum = Long.toString(s).toCharArray();
Arrays.sort(num);
Arrays.sort(sum);
if (Arrays.equals(num, sum) & !list.contains(s)) list.add(s);
}
private static long sum(long n) {
long s = 0;
byte m = getDepth(n);
for (int i = 0; i < m; i++) {
s += Math.pow(n % 10, m);
n /= 10;
}
return s;
}
private static byte getDepth(long n) {
if (n < 10_000_000_000L) {
//10 and less
if (n < 100000) {
// 5 or less
if (n < 100) {
// 1 or 2
if (n < 10)
return 1;
else
return 2;
} else {
// 3 or 4 or 5
if (n < 1000)
return 3;
else {
// 4 or 5
if (n < 10000)
return 4;
else
return 5;
}
}
} else {
// 6 or more
if (n < 10000000) {
// 6 or 7
if (n < 1000000)
return 6;
else
return 7;
} else {
// 8 to 10
if (n < 100000000)
return 8;
else {
// 9 or 10
if (n < 1000000000)
return 9;
else
return 10;
}
}
}
} else {
//11 and more
if (n < 1_000_000_000_000_000L) {
//15 end less
if (n < 100_000_000_000L) {
//11
return 11;
}
if (n < 10_000_000_000_000L) {
//12 or 13
if (n < 1_000_000_000_000L) return 12;
else return 13;
} else {
//14 or 15
if (n < 100_000_000_000_000L) return 14;
else return 15;
}
} else {
//16 and more
if (n < 100_000_000_000_000_000L) {
//16 or 17
if (n < 10_000_000_000_000_000L) return 16;
else return 17;
} else {
//18 or 19
if (n < 1_000_000_000_000_000_000L) return 18;
else return 19;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Runtime runtime = Runtime.getRuntime();
Thread t = new Thread(() -> {
while (true) {
double mem = (runtime.totalMemory() - runtime.freeMemory()) / 1024d / 1024d;
if (mem >= 50) System.err.printf("\t\t\t\t\t%4.2f MB\n", mem);
else System.out.printf("\t\t\t\t\t%.2f MB\n", mem);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
});
// t.start();
long beginTime = System.currentTimeMillis();
try {
for (long number : Objects.requireNonNull(Solution.getNumbers(Long.MAX_VALUE))) {
System.out.println(number);
}
} finally {
// t.interrupt();
}
System.out.println("====TIME===");
System.out.println(System.currentTimeMillis() - beginTime);
}
}