Парни, прошу помощи.
При проверке на Long.MAX_VALUE получаю результат, совпадающий с приведенным читерами:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, .... 4498128791164624869, 4929273885928088826]
Ошибка валидатора именно "Метод getNumbers должен возвращать массив чисел удовлетворяющих условию задачи", УЖЕ без комментария ментора "массив содержит лишнее или не содержит нужного" - то есть список вроде верный формируется...Может с форматом что не так? Вроде тоже верно: long[] result = new long[in.size()];
Выкурил все комментарии на два года назад, все грабли собрал.
* при N < 0 возвращается пустой массив
* массив не начинается с нуля; начинается с единицы или пустой, если N=1
* есть проверка, что во временный сет записываются только числа меньше N
Где накосячил? День сижу без прогресса. Спасибо вам
package com.javarush.task.task20.task2025;
import java.util.Arrays;
import java.util.TreeSet;
// Алгоритмы-числа
public class Solution {
static long[][] degreeMatrix = new long[10][21]; // матрица степеней
static {
for (int i = 1; i < 10; i++) {
degreeMatrix[i][0] = 1; // нулевую степень заполнили единицами
}
for (int j = 1; j < 20; j++) {
for (int i = 0; i < 10; i++) {
degreeMatrix[i][j] = degreeMatrix[i][j - 1] * i;
}
}
}
public static long[] getNumbers(long N) {
if (N <= 0 ) return new long[0]; // проверяем на натуральный ряд
TreeSet<Long> tmpResultSet = new TreeSet<>(); // временный сет для хранения найденных чисел. Потом переведем в long[]
long isArmstrong = 0; // переменная для результата проверки: ноль если массив - не число Арм; Long-значение, если массив - ч.Армстронга
Generator generator = new Generator(N);
while (generator.isGenerationAllowed()) {
generator.decrementDigit(0);
int[] checkedArray = generator.getDigits();
if (checkedArray[0] == -1) {break;} // когда весь массив дойдет до нулей, метод возвращвет {-1,-1,-1,...}
while (true) {
int[] degreeSumm = calcDegreeSum(checkedArray); // получаем степеную сумму для текущего проверяемого числа-массива
isArmstrong = checkArmstrong(degreeSumm); // проверяем эту степенную сумму
if (isArmstrong > 0 && isArmstrong < N) {
tmpResultSet.add(isArmstrong);
}
if (checkedArray[0] == 0 && checkedArray.length > 1) { // если массив начинается с нуля - то в цикле обрезать нули и все повторить
int[] cattedClone = new int[checkedArray.length - 1];
System.arraycopy(checkedArray, 1, cattedClone, 0, checkedArray.length - 1);
checkedArray = cattedClone;
} else {
break;
}
}
}
return convertSetToArray(tmpResultSet); // дергаем метод для конвертации временного TreeSet в массив long[]
}
// Вычисление степенной суммы
private static int[] calcDegreeSum(int[] digitAsArray) {
long tempsum = 0L;
for (int i : digitAsArray) {
tempsum = tempsum + degreeMatrix[i][digitAsArray.length];
if (tempsum < 0) {break;} // проверяем, что сумма не вылезла за пределы long, что время зря терять
}
if (tempsum > 0) { // если сумма еще в пределах long...
// переведем найденную сумму long в массив int[]:
String tempsumAsString = Long.toString(tempsum);
int[] tempsumAsMassiv = new int[tempsumAsString.length()];
for (byte b = 0; b < tempsumAsString.length(); b++) { // заполняем массив цифрами, которые содержит строка
tempsumAsMassiv[b] = Integer.parseInt(tempsumAsString.substring(b, b + 1));
}
return tempsumAsMassiv;
}
else { return new int[]{1}; } // если степенная сумма превышала long - то и проверять её не нужно
}
// перевод TreeSet в требуемый массив long[]
private static long[] convertSetToArray(TreeSet<Long> in) {
int cnt = 0;
long[] result = new long[in.size()];
for (Long lo : in) {
result[cnt] = (long) lo;
cnt++;
}
return result;
}
// проверка условия, является ли переданный массив числом Армстронга
static Long checkArmstrong(int[] massivIn) {
long sumOfNumbers = 0;
StringBuilder sbFromMassiv = new StringBuilder();
for (int b : massivIn) {
sumOfNumbers += degreeMatrix[b][massivIn.length];
sbFromMassiv.append(b);
}
String stringFromMassiv = sbFromMassiv.toString();
Long parsedNum = Long.parseLong(stringFromMassiv);
if (parsedNum.equals(sumOfNumbers)) {
return parsedNum;
} else {
return 0L;
}
}
// Самодекриментируемый массив
static class Generator {
private int[] digits;
private boolean generationAllowed;
public Generator(long number) {
digits = new int[String.valueOf(number).length()];
Arrays.fill(digits, 9);
generationAllowed = true;
}
public int decrementDigit(int index) {
if (index > digits.length - 1) {
int lastDigit = digits[digits.length - 1];
if (lastDigit <= 1) {
generationAllowed = false;
return -1;
}
}
if (digits[index]-- == 0) {
digits[index] = decrementDigit(index + 1);
}
return digits[index];
}
public int[] getDigits() {
return Arrays.copyOf(digits, digits.length);
}
public boolean isGenerationAllowed() {
return generationAllowed;
}
}
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(1000000)));
b = System.currentTimeMillis();
System.out.println("memory " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (8 * 1024));
System.out.println("time = " + (b - a) / 1000);
}
}
// Число S состоит из M цифр, например, S=370 и M (количество цифр) = 3
//Реализовать логику метода getNumbers, который должен среди натуральных чисел меньше N (long)
//находить все числа, удовлетворяющие следующему критерию:
//число S равно сумме его цифр, возведенных в M степень
//getNumbers должен возвращать все такие числа в порядке возрастания.
//Пример искомого числа:
//370 = 3*3*3 + 7*7*7 + 0*0*0
//8208 = 8*8*8*8 + 2*2*2*2 + 0*0*0*0 + 8*8*8*8
//На выполнение дается 10 секунд и 50 МБ памяти.
//Метод main не участвует в тестировании.
// Требования:
//1. В классе Solution должен присутствовать метод public static long[] getNumbers(long N)
//2. В методе getNumbers не должно возникать исключений, при любых входных данных.
//3. Все найденные числа должны быть строго меньше N.
//4. Метод getNumbers должен возвращать массив чисел удовлетворяющих условию задачи.
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407]
// Long.MAX_VALUE = 9223372036854775807L
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727, 93084, 548834, 1741725,
// 4210818, 9800817, 9926315, 24678050, 24678051, 88593477, 146511208, 472335975, 534494836, 912985153,
// 4679307774, 32164049650, 32164049651, 40028394225, 42678290603, 44708635679, 49388550606, 82693916578,
// 94204591914, 28116440335967, 4338281769391370, 4338281769391371, 21897142587612075, 35641594208964132,
// 35875699062250035, 1517841543307505039, 3289582984443187032, 4498128791164624869, 4929273885928088826]
// memory 2 = 5804
// time 2 = 14
// memory 2 = 363
// time 2 = 12
// Метод getNumbers должен возвращать массив чисел удовлетворяющих условию задачи.
копипаститьэкономить ресурсы. Ну ок. А потом я видел, как он буксовал на простых задачах, имея профильное образование, опыт в программировании, а его на повороте с ветерком обходили свитчеры - музыканты и охранники. Интересное было зрелище. И достаточно ожидаемое. Смотри, а за сколько времени у тебя исполняется? На моем компе, где-то 18-19 секунд. Попробуй влезть в 10 с, чтобы хотя бы 9 было. Валидатор будет что угодно писать, пока в 10 с не влезешь. Сам по суди, он ждет 10 с, твой метод вернул ответ? нет. Вот и пункт валидации не проходит. Попробуй заменить на простые арифметические операции и массивы String, StringBuilder, парсинг и тд, эти операции под капотом вызывают кучу методов, и все это в цикле, не лучшая идея.