#android #циклы #простые_числа
Делал приложение по ТЗ из одной компании. Сделал андроид-аппку, получил результат на эмуляторе, вроде же верный. Но HR просто отписалась, что ответ который выдало мое приложение неверен. Айчары люди довольно занятые, потому редко кто может указать на ошибку, а навязываться после отказа - дело очень неблагодарное. Но все же хочется хоть для себя выполнить задание до конца. Из требований было: Напишите программу, которая возвращает наибольшее число палиндром, которое является произведением двух простых пятизначных чисел, а также возвращает сами сомножители. Простое число - это натуральное число, которое делится нацело только на 1 и на себя само (2, 3, 5, 7, 11, …) Палиндром – строка, которая читается одинаково в обоих направлениях (например ABBA) Сам принцип поиска простых чисел мне понятен. Использовать массивы было нецелесообразно потому решето Эратосфена и аналоги пришлось отбросить - уж очень много памяти сожрало бы создание массива на такое количество значений. Потому решил использовать циклы для сопоставления и отсеивания. Вот код моего андроид-приложения: MainActivity: public class MainActivity extends AppCompatActivity implements View.OnClickListener { private int maxNum = 99999; private int minNum = 10000; private int divNumMax = 0; private int palind; private TextView tv1; private TextView tv2; private TextView tv3; private TextView tv4; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv1 = (TextView) findViewById(R.id.textView1); tv2 = (TextView) findViewById(R.id.textView2); tv3 = (TextView) findViewById(R.id.textView3); tv4 = (TextView) findViewById(R.id.textView4); Button btnStart = (Button) findViewById(R.id.button); btnStart.setOnClickListener(this); } @Override public void onClick(View v) { divNumMax = (int) Math.sqrt(maxNum); int fPM; int sPM; boolean isNotPalind; fPM = findMaxPrimeNumber(maxNum); sPM = findMaxPrimeNumber(fPM - 2); isNotPalind = findPalindrome(fPM, sPM); while (isNotPalind) { if (sPM <= fPM && sPM > minNum) { sPM = findMaxPrimeNumber(sPM - 2); isNotPalind = findPalindrome(fPM, sPM); } else if (sPM <= minNum) { fPM = findMaxPrimeNumber(fPM - 2); sPM = fPM; } tv2.setText("1-st primary number: " + fPM); tv3.setText("2-nd primary number: " + sPM); tv4.setText("1-st * 2-nd = " + palind); } } private int findMaxPrimeNumber(int maxNumPre) { int i; int j; int z; int maxNumNew; for (i = maxNumPre; i >= minNum; i = i - 2) { for (j = 3; j <= divNumMax; j++) { z = i % j; if (z == 0 && j <= divNumMax) { break; } else if (z != 0 && j == divNumMax) { maxNumNew = i; return maxNumNew; } } } return 10000; } private boolean findPalindrome(int firstPrime, int secondPrime) { int resultOfMath = firstPrime * secondPrime; String ltrResult = Integer.toString(resultOfMath); String rtlResult = new StringBuffer(ltrResult).reverse().toString(); if (ltrResult.equals(rtlResult)) { palind = resultOfMath; return false; } else { return true; } } } Скриншот полученного результата на эмуляторе: Ломаю голову где ошибся, что упустил. Не прошу делать за меня ТЗ, но не хочу оставлять позади какую-то неразобранную проблемму.
Ответы
Ответ 1
Ваше целое несколько раз завернулось вокруг максимального значения int - 2,147,483,647. Проверьте: 99923 * 87541 = 8 747 359 343 А также: На какую цифру должно заканчиваться произведение Ваших двух простых чисел?Ответ 2
решето работает отлично, ранее искал все простые числа в диапазоне 0- 10 000 000 ушло примерно 15 секунд на планшете. главное правильно написать алгоритм. возможно я не верно понял ваш алгоритм (прошу исправить меня) почему второй цикл идет по увеличению параметра, а не от большего к меньшему? for (j = 3; j <= divNumMax; j++) { есть нюанс: рассмотрим ту же задачу, но в диапазоне 0-15, пока отбросим условие палиндрома (здесь оно не играет роли). a = 13; b = 2; a*b = 26 но есть и другие простые числа произведение которых даст значительно больше результат? 11*13 > 26Ответ 3
Вот правильный ответ на задачу, также встречал на собесе: палиндром - 999949999 множитель1 - 33211 множитель2 - 30109 Реализовал алгоритм так: Метод поиска наибольшего палиндрома (на входе список простых чисел) static void palindrome(ArrayListprimeNumbers) { long palindrome = 0; long multiplier1 = 0; long multiplier2 = 0; for (int j = 0; j < primeNumbers.size(); j++) { for (int k = 0; k < primeNumbers.size(); k++) { long i = (long) primeNumbers.get(j) * (long) primeNumbers.get(k); if (palindromeCheck(i)) { if (i > palindrome) { palindrome = i; multiplier1 = primeNumbers.get(j); multiplier2 = primeNumbers.get(k); } } } } System.out.println("palindrome = " + palindrome + "\nmultiplier1 = " + multiplier1 + "\nmultiplier2 = " + multiplier2); } Метод поиска простых чисел (на входе максимальное и минимальное значения из проверяемого диапазона чисел): static ArrayList eratosthenesPrimeNumbers(int max, int min) { ArrayList primeNumbers = new ArrayList<>(); boolean[] array = new boolean[max]; for (int i = 2; Math.pow(i, 2) <= max; i++) { if (!array[i]) { for (int j = (int) Math.pow(i, 2); j < max; j += i) { array[j] = true; } } } for (int i = max - 1; i >= min; i--) { if (!array[i]) { primeNumbers.add(i); } } return primeNumbers; } Проверка на то, что найденное число является палиндромом (на входе проверяемое число): static boolean palindromeCheck(long i) { char[] palindrome = String.valueOf(i).toCharArray(); int fromBegin = 0; int fromEnd = palindrome.length - 1; while (fromBegin < fromEnd) { if (palindrome[fromBegin] == palindrome[fromEnd]) { fromBegin++; fromEnd--; } else return false; } return true; } Да и еще забыл написать, что эти методы надо вызывать :) У меня это сделано так: public class Main { static final int MAX_MULTIPLIER = 99999; static final int MIN_MULTIPLIER = 10000; public static void main(String[] args) { ArrayList primeNumbers2 = new ArrayList<>(eratosthenesPrimeNumbers(MAX_MULTIPLIER, MIN_MULTIPLIER)); palindrome(primeNumbers2); } и дальше реализация методов... Ответ 4
Немного вник в алгоритм. По моему, он работает неправильно уже здесь: while (isNotPalind) { if (sPM <= fPM && sPM > minNum) { sPM = findMaxPrimeNumber(sPM - 2); isNotPalind = findPalindrome(fPM, sPM); } else if (sPM <= minNum) { fPM = findMaxPrimeNumber(fPM - 2); sPM = fPM; } } Получается ты выведешь первый встречный палиндром, но нет гарантии, что он будет максимальный. Возьмем отвлеченный от этого пример прогонки от 10 до 1 возможных произведений всех чисел. По твоему алгоритму идем по 1-му кругу: 10*10, 10*9 , 10*8, 10*7.... <- и сразу выводим первый попавшийся палиндром далее второй круг: 9*9, 9*8, 9*7... <- или уж тут сразу выводим первый попавшийся палиндром далее третий: 8*8, 8*7, 8*6... И так далее... Допустим на 1-ом круге 10*2 - это палиндром (гипотетически!) Также допустим на 2-ом круге 9*8 - это тоже палиндром (гипотетически!) Но твоя программа выведет 10*2 (несмотря на то что 9*8 больше чем 10*2) То есть первое попавшееся - это не вариант. Надеюсь автор меня понял и поправит если я не прав.Ответ 5
условие задачи подразумевало произведение двух простых пятизначных чисел. алгоритм работает для двух, трех, четырехзначных чисел. но в упор отказывается работать для 5-ти. в чем тут ошибка? public class Palindrome { private static final boolean reverse(long value) { String str = String.valueOf(value); return str.equals(new StringBuilder(str).reverse().toString()); } private static final boolean isPrime(int n) { int i; for (i = 2; i <= n / 2; i++) { if (n % i == 0) { return false; } } return true; } public static void main(String[] args) { int i = 0; int maxPrimeNumber = 99971; int minPrimeNumber = 10007; outer: for (i = maxPrimeNumber; i >= minPrimeNumber; i--) { for (int j = maxPrimeNumber; j >= minPrimeNumber; j--) { if (isPrime(i) && isPrime(j)) { long product = j * i; if (reverse(product)) { System.out.printf("%d * %d = %d%n", i, j, product); break outer; } } } } } }
Комментариев нет:
Отправить комментарий