Исправленная и улучшенная версия.
OperationsWithNumbersStarter — стартовый класс:
package chapt01.b;
import static chapt01.b.OperationsWithNumbersSolver.*;
/**
* @author m1st
*
*/
public class OperationsWithNumbersStarter {
public static void main(String[] args) {
// 0. Ввести с консоли n целых чисел и поместить их в массив. На консоль
// вывести:
int[] sourceNumbers = readInput();
if (sourceNumbers.length == 0) {
System.out.println("sourceNumbers.length == 0");
System.exit(0);
}
// 1. Четные и нечетные числа
findEvenAndOddNumbers(sourceNumbers);
// 2. Наибольшее и наименьшее число.
findMaxAndMinNumbers(sourceNumbers);
// 3. Числа, которые делятся на 3 или на 9.
findModNumbers(3, sourceNumbers);
// 4. Числа, которые делятся на 5 и на 7.
findModNumbers(5, 7, sourceNumbers);
// 5. Элементы, расположенные методом пузырька по убыванию модулей.
int[] sourceNumbersClone1 = sourceNumbers.clone();
sortNumbersWithBubbleReverseByAbs(sourceNumbersClone1);
// 6. Все трехзначные числа, в десятичной записи которых нет одинаковых
// цифр.
findNumbersWithThreeDifferentDigits(sourceNumbers);
// 7. Наибольший общий делитель и наименьшее общее кратное этих чисел.
findGreatestCommonDivisor(sourceNumbers);
findLeastCommonMultiple(sourceNumbers);
// 8. Простые числа.
findPrimeNumbers(sourceNumbers);
// 9. Отсортированные числа в порядке возрастания и убывания.
sortNumbersByAscAndDesc(sourceNumbers);
// 10. Числа в порядке убывания частоты встречаемости чисел.
findNumbersFrequencyByDesc(sourceNumbers);
// 11. “Счастливые” числа.
findHappyNumbers(sourceNumbers);
// 12. Числа Фибоначчи: f0 = f1 = 1, f (n) = f (n–1) + f (n–2).
findFibonacciNumbers(sourceNumbers);
// 13. Числа-палиндромы, значения которых в прямом и обратном порядке
// совпадают.
findPalindromicNumbers(sourceNumbers);
// 14. Элементы, которые равны полусумме соседних элементов.
int[] sourceNumbersClone2 = sourceNumbers.clone();
findNumbersOfHalfSumOfNeighbors(sourceNumbersClone2);
// 15. Период десятичной дроби p = m/n для первых двух целых
// положительных чисел n и m, расположенных подряд.
findPeriodForFirstTwoPositiveNumbersInARow(sourceNumbers);
// 16. Построить треугольник Паскаля для первого положительного числа.
buildPascalTriangleForFirstPositiveNumber(sourceNumbers);
}
}
OperationsWithNumbersSolver — класс, содержащий методы вычислений:
package chapt01.b;
import java.io.InputStream;
import java.util.*;
import java.util.Map.Entry;
/**
* @author m1st
*
*/
public class OperationsWithNumbersSolver {
public static void println(Object obj) {
System.out.println(obj);
}
public static void print(Object obj) {
System.out.print(obj);
}
public static void println() {
System.out.println();
}
public static int[] toIntArray(Collection<Integer> list) {
int[] result = new int[list.size()];
Iterator<Integer> it = list.iterator();
for (int i = 0; i < list.size(); i++) {
result[i] = it.next();
}
return result;
}
public static int[] readInput(Scanner sc) {
List<Integer> input = new ArrayList<Integer>();
print("Введите целые числа через пробел, для окончания введите q: ");
while (sc.hasNext()) {
String number = sc.next();
if (number.equals("q")) {
break;
} else {
try {
input.add(Integer.parseInt(number));
} catch (NumberFormatException e) {
sc.close();
print("Неправильный формат. Программа завершена. ");
System.exit(0);
}
}
}
return toIntArray(input);
}
public static int[] readInput(InputStream is) {
return readInput(new Scanner(is));
}
public static int[] readInput() {
return readInput(System.in);
}
public static List<Integer> toIntegerList(int[] array) {
List<Integer> result = new ArrayList<Integer>(array.length);
for (int element : array) {
result.add(element);
}
return result;
}
public static void findEvenAndOddNumbers(int[] sourceNumbers) {
List<Integer> evens = new ArrayList<Integer>();
List<Integer> odds = new ArrayList<Integer>();
for (int sourceNumber : sourceNumbers) {
if (sourceNumber % 2 == 0) {
evens.add(sourceNumber);
} else {
odds.add(sourceNumber);
}
}
println("Чётные числа: " + evens);
println("Нечётные числа: " + odds);
}
public static void findMaxAndMinNumbers(int[] sourceNumbers) {
List<Integer> numbers = toIntegerList(sourceNumbers);
println("Наибольшее число: " + Collections.max(numbers));
println("Наименьшее число: " + Collections.min(numbers));
}
public static void findModNumbers(int divider, int[] sourceNumbers) {
print("Числа, которые делятся на " + divider + ": ");
for (int sourceNumber : sourceNumbers) {
if (sourceNumber % divider == 0) {
print(sourceNumber + ", ");
}
}
println();
}
public static void findModNumbers(int divider1, int divider2,
int[] sourceNumbers) {
print("Числа, которые делятся на " + divider1 + " и на " + divider2
+ ": ");
for (int sourceNumber : sourceNumbers) {
if ((sourceNumber % divider1 == 0)
&& (sourceNumber % divider2 == 0)) {
print(sourceNumber + ", ");
}
}
println();
}
public static void sortNumbersWithBubbleReverseByAbs(int[] sourceNumbers) {
boolean swapped;
int temp, j = 0;
do {
swapped = false;
j++;
for (int i = 0; i < sourceNumbers.length - j; i++) {
if (Math.abs((long) sourceNumbers[i]) < Math
.abs((long) sourceNumbers[i + 1])) {
temp = sourceNumbers[i];
sourceNumbers[i] = sourceNumbers[i + 1];
sourceNumbers[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
print("Элементы, расположенные методом пузырька по убыванию модулей: "
+ Arrays.toString(sourceNumbers) + "\n");
}
public static void findNumbersWithThreeDifferentDigits(int[] sourceNumbers) {
int digit1, digit2, digit3;
print("Все трехзначные числа, в десятичной записи которых нет одинаковых цифр: ");
for (int sourceNumber : sourceNumbers) {
digit1 = sourceNumber / 100;
digit2 = sourceNumber / 10 % 10;
digit3 = sourceNumber % 10;
// Ищем трехзначные числа
if ((sourceNumber >= 100 && sourceNumber <= 999)
|| (sourceNumber <= -100 && sourceNumber >= -999)) {
if ((digit1 != digit2) && (digit2 != digit3)
&& (digit1 != digit3)) {
print(sourceNumber + ", ");
}
}
}
println();
}
public static long findGreatestCommonDivisor(long a, long b) {
while (b != 0) {
long temp = b;
b = a % b;
a = temp;
}
return a;
}
public static void findGreatestCommonDivisor(int[] sourceNumbers) {
long result = sourceNumbers[0];
if (result == 0) {
println("Наибольший общий делитель: " + result);
} else {
for (int i = 1; i < sourceNumbers.length; i++) {
result = findGreatestCommonDivisor(result, sourceNumbers[i]);
}
println("Наибольший общий делитель: " + result);
}
}
public static long findLeastCommonMultiple(long a, long b) {
return a * (b / findGreatestCommonDivisor(a, b));
}
/**
* Метод вычисляет НОК чисел в массиве. Вычисление завершается на первом
* нулевом числе (оно не входит в НОК). <strong>Результат метода в случае
* переполнения не определен</strong>
*
* @param sourceNumbers
* числа для нахождения НОК
* @return НОК. В случае переполнения результат не определен.
*/
public static void findLeastCommonMultiple(int[] sourceNumbers) {
long result = sourceNumbers[0];
if (result == 0) {
println("Наименьшее общее кратное: " + result);
} else {
for (int i = 1; i < sourceNumbers.length; i++) {
if (sourceNumbers[i] == 0) {
break;
}
result = findLeastCommonMultiple(result, sourceNumbers[i]);
}
}
println("Наименьшее общее кратное: " + result);
}
public static boolean isPrimeNumber(int number) {
if (number <= 1) {
return false;
}
if (number == 2) {
return true;
}
if (number % 2 != 0) {
return true;
}
final double ceiledNumberSqrt = Math.ceil(Math.sqrt(number));
for (long i = 3; i <= ceiledNumberSqrt; i += 2) {
if (number % i == 0) {
return false;
}
}
return false;
}
public static void findPrimeNumbers(int[] sourceNumbers) {
print("Простые числа: ");
for (int sourceNumber : sourceNumbers) {
if (isPrimeNumber(sourceNumber)) {
print(sourceNumber + ", ");
}
}
println();
}
public static void sortNumbersByAscAndDesc(int[] sourceNumbers) {
List<Integer> numbers = toIntegerList(sourceNumbers);
Collections.sort(numbers);
println("Отсортированные числа в порядке возрастания: " + numbers);
Collections.reverse(numbers);
println("Отсортированные числа в порядке убывания: " + numbers);
}
public static Map<Integer, Integer> sortNumbersWithDescByValue(
Map<Integer, Integer> map) {
List<Entry<Integer, Integer>> frequencyList = new ArrayList<Entry<Integer, Integer>>(
map.entrySet());
Collections.sort(frequencyList,
new Comparator<Entry<Integer, Integer>>() {
public int compare(Entry<Integer, Integer> o1,
Entry<Integer, Integer> o2) {
return ((Entry<Integer, Integer>) (o2)).getValue()
.compareTo(
((Entry<Integer, Integer>) (o1))
.getValue());
}
});
Map<Integer, Integer> result = new LinkedHashMap<Integer, Integer>();
for (Entry<Integer, Integer> frequency : frequencyList) {
result.put(frequency.getKey(), frequency.getValue());
}
return result;
}
public static void findNumbersFrequencyByDesc(int[] sourceNumbers) {
List<Integer> numbers = toIntegerList(sourceNumbers);
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int frequency = 1;
for (Integer number : numbers) {
if (map.containsKey(number)) {
map.put(number, ++frequency);
} else {
map.put(number, 1);
}
}
println("Числа в порядке убывания частоты встречаемости чисел (число=встречаемость): "
+ sortNumbersWithDescByValue(map));
}
public static void findHappyNumbers(int[] sourceNumbers) {
print("“Счастливые” числа (сумма 1-ой пары чисел = сумме 2-ой пары): ");
int digit1, digit2, digit3, digit4;
for (int sourceNumber : sourceNumbers) {
if ((sourceNumber >= 1000 && sourceNumber <= 9999)
|| (sourceNumber <= -1000 && sourceNumber >= -9999)) {
digit1 = sourceNumber / 1000;
digit2 = sourceNumber / 100 % 10;
digit3 = sourceNumber % 100 / 10;
digit4 = sourceNumber % 10;
if (digit1 + digit2 == digit3 + digit4) {
print(sourceNumber + ", ");
}
}
}
println();
}
/**
* Метод находит числа Фибоначчи в массиве. <strong>Результат метода в
* случае переполнения не определен</strong>
*
* @param sourceNumbers
* числа для нахождения чисел Фибоначчи
* @return числа Фибоначчи. В случае переполнения результат не определен.
*/
public static void findFibonacciNumbers(int[] sourceNumbers) {
print("Числа Фибоначчи: ");
if (sourceNumbers.length >= 3) {
if (sourceNumbers[0] == 0) {
print("0, ");
if (sourceNumbers[1] == 1) {
print("1, ");
}
}
for (int i = 2; i < sourceNumbers.length; i++) {
if (sourceNumbers[i] == ((long) sourceNumbers[i - 2] + (long) sourceNumbers[i - 1])) {
print(sourceNumbers[i] + ", ");
}
}
} else {
print("sourceNumbers.length < 3");
}
println();
}
public static long reverseInt(int value) {
long result = 0;
while (value != 0) {
result = result * 10 + value % 10;
value /= 10;
}
return result;
}
public static void findPalindromicNumbers(int[] sourceNumbers) {
print("Числа-палиндромы: ");
for (int sourceNumber : sourceNumbers) {
if (sourceNumber == reverseInt(sourceNumber)) {
print(sourceNumber + ", ");
}
}
println();
}
/**
* Метод находит элементы, которые равны полусумме соседних элементов в
* массиве. <strong>Результат метода в случае переполнения не
* определен</strong>
*
* @param sourceNumbers
* числа для нахождения элементов, которые равны полусумме
* соседних элементов в массиве
* @return элементы, которые равны полусумме соседних элементов в массиве. В
* случае переполнения результат не определен.
*/
public static void findNumbersOfHalfSumOfNeighbors(int[] sourceNumbers) {
print("Элементы, которые равны полусумме соседних элементов: ");
if (sourceNumbers.length >= 3) {
for (int i = 1; i < sourceNumbers.length - 1; i++) {
if (sourceNumbers[i] == ((double) ((long) sourceNumbers[i - 1] + (long) sourceNumbers[i + 1]) / 2)) {
print(sourceNumbers[i] + ", ");
}
}
} else {
print("sourceNumbers.length < 3");
}
println();
}
public static int[] findFirstTwoPositiveNumbersInARow(int[] sourceNumbers) {
int[] twoPositiveNumbers = new int[2];
for (int i = 0; i < sourceNumbers.length - 1; i++) {
if ((sourceNumbers[i] > 0) && (sourceNumbers[i + 1] > 0)) {
twoPositiveNumbers[0] = sourceNumbers[i];
twoPositiveNumbers[1] = sourceNumbers[i + 1];
break;
}
}
return twoPositiveNumbers;
}
public static void findPeriodForFirstTwoPositiveNumbersInARow(
int[] sourceNumbers) {
String message = "Период десятичной дроби для первых двух целых положительных чисел, расположенных подряд: ";
if (sourceNumbers.length < 2) {
println(message + "sourceNumbers.length < 2");
return;
}
int[] twoPositiveNumbers = findFirstTwoPositiveNumbersInARow(sourceNumbers);
if (twoPositiveNumbers.length < 2) {
println(message
+ "нет двух целых положительных чисел, расположенных подряд");
return;
}
int numerator = twoPositiveNumbers[0];
int denominator = twoPositiveNumbers[1];
if (numerator % denominator == 0) {
print(numerator / denominator + ".(0)");
return;
}
// Выделение из знаменателя наибольшей 2^
int s = denominator % 2;
int l = 0;
while (s == 0) {
denominator = denominator / 2;
s = denominator % 2;
l++;
}
// Выделение из знаменателя наибольшей 5^
s = denominator % 5;
int l1 = 0;
while (s == 0) {
denominator = denominator / 5;
s = denominator % 5;
l1++;
}
// Вычисление длины периода с новым знаменателем
int periodLenth = 1;
int r = 10;
while (r != 1) {
r = (10 * r) % denominator;
if (r == 0) {
break;
}
periodLenth++;
}
long beforePeriodLenth;
if (l1 > l) {
beforePeriodLenth = l1;
} else {
beforePeriodLenth = l;
}
denominator = twoPositiveNumbers[1];
print(message + numerator / denominator + ".");
numerator = numerator % denominator;
for (int i = 0; i < beforePeriodLenth; i++) {
print((numerator * 10) / denominator);
numerator = (numerator * 10) % denominator;
}
print("(");
for (int i = 0; i < periodLenth; i++) {
print((numerator * 10) / denominator);
numerator = (numerator * 10) % denominator;
}
print(") = " + twoPositiveNumbers[0] + " / " + twoPositiveNumbers[1] + "\n");
}
public static int findFirstPositiveNumber(int[] sourceNumbers) {
for (int sourceNumber : sourceNumbers) {
if (sourceNumber > 0) {
return sourceNumber;
}
}
return 0;
}
public static void buildPascalTriangleForFirstPositiveNumber(
int[] sourceNumbers) {
final int firstPositiveNumber = findFirstPositiveNumber(sourceNumbers);
if (firstPositiveNumber == 0) {
println("!in.hasNext()");
} else {
print("Сколько строк треугольника Паскаля для числа "
+ firstPositiveNumber + " отображать? ");
Scanner sc = new Scanner(System.in);
if (!sc.hasNext()) {
sc.close();
println("Треугольник Паскаля для первого положительного числа: нет чисел > 0");
} else {
final int rows = sc.nextInt();
for (int y = 0; y < rows; y++) {
int c = firstPositiveNumber;
for (int i = 0; i < rows - y; i++) {
print(" ");
}
for (int x = 0; x <= y; x++) {
print(" " + c + " ");
c = c * (y - x) / (x + 1);
}
println();
}
}
sc.close();
}
}
}
Здравствуйте, m1st, Вы писали:
M>Код наиболее последней версии переехал сюда: http://ideone.com/a72cO
По текущей версии.
findModNumbers что-то он не то делает "в общем случае". Там явно не проверка на все числа (достаточно только делимости на четыре числа). Да и два вложенных цикла пугают. В одном из правильных вариантов код вообще не должен смотреть на длину args. И может даже на его пустоту не проверять, там все случаи абсолютно одинаковы.
findNumbersWithThreeDifferentDigits — вычисление цифр лучше делать уже после проверки диапазона. В этом случае для "непрошедших" чисел выполняется меньше вычислений. На мелких задачах это незаметно. На больших объемах данных разница может стать заметной. Кстати, в счастливых числах это как раз сделано правильно.
isPrimeNumber — все нечетные числа считаются простыми. Вообще, похоже на опечатку. Там должно быть обратное условие и обратный результат 
isPrimeNumber — а ceiledNumberSqrt лучше бы тоже целым сделать (и скастить в целочисленный тип, если нужно). Меньше лишних конвертаций типов.
findNumbersFrequencyByDesc — frequency считается неправильно. Попробуйте на массиве [1,1,1,2,2,2,3,3,3] протестировать. "частоту" тоже нужно брать из map. Если она null — класть 1, иначе увеличивать частоту на 1. Тогда и containsKey не понадобится (если ключа нет, будет прочитан null). Два варианта (нашли/не нашли), естественно, останутся.
findNumbersOfHalfSumOfNeighbors — Преобразования в числы с плавающей точкой мне не очень нрваятся. Я уже предлагал умножить обе части на 2L, тогда и каст в double не понадобится
. Да, еще — переполнения после каста в long больше быть не может. Т.е. условие будет (2L * sourceNumbers[i] == sourceNumbers[i-1] + (long) sourceNumbers[i-1]).
Отдельно отмечу, что в findPeriodForFirstTwoPositiveNumbersInARow появились комментарии. В нем стали видны законченные логические блоки. Хотя я в алгоритм не вчитывался, для восприятия общая структура метода стала гораздо проще, чем раньше.