Как сконденсировать мои 9-ти операторы в один
Я хотел посмотреть, что наименьшее число, делящееся на все цифры с цифрами, и вместо того, чтобы искать его, я создал это.
public static void main(String[] args) {
for (int i = 100; i < 10000; i++) {
if (i % 2 ==0) {
if (i % 3 ==0) {
if (i % 4 ==0) {
if (i % 5 ==0) {
if (i % 6 ==0) {
if (i % 7 ==0) {
if (i % 8 ==0) {
if (i % 9 ==0) {
System.out.println(i);
break;
}
}
}
}
}
}
}
}
}
}
Как вы можете видеть, у меня есть оператор if в выражении if x9. Код работал, но я хотел сконденсировать свои операторы if с помощью массива, чтобы сделать это выражение if, но это не сработало.
if (i % x[1, 2, 3, 4, 5, 6, 7, 8]) {
System.out.println(i);
break;
}
Какие-либо предложения?
Ответы
Ответ 1
Сначала вы подумали, что можете проверить их все сразу, поставив продукт с 2 по 9 с правой стороны оператора %
.
if (i % (2 * 3 * 4 * 5 * 6 * 7 * 8 * 9) == 0)
Но поскольку определенные числа включают предыдущие числа в их факторизации, вы должны использовать меньшее число, в частности, наименьшее общее число. 8 кратно 2 и 4, 9 кратно 3, и если 8 и 9 находятся в произведении, то 6 (2 * 3) также покрывается.
if (i % (5 * 7 * 8 * 9) == 0)
Это оказывается 2520, что является наименее распространенным кратным. Было бы гораздо читательнее использовать 2520
и объяснить в комментарии, почему этот номер используется.
/**
* The goal is to test if the number is a multiple of all integers
* from 2 through 9. Mathematically, the least common multiple to is a
* multiple of all its input numbers. Here, the LCM of 2, 3, ..., 9 is 2520.
*/
public static final int LCM_2_THRU_9 = 2520;
Я объявил константу, и я буду использовать ее здесь:
if (i % LCM_2_THRU_9 == 0)
Ответ 2
Попробуй это.
for (int i = 100; i < 10000; ++i) {
int x = i;
if (IntStream.of(2, 3, 4, 5, 6, 7, 8, 9).allMatch(k -> x % k == 0)) {
System.out.println(i);
break;
}
}
-> 2520
Или вы можете написать это как одно утверждение.
int result = IntStream
.range(100, 10000)
.filter(i -> IntStream.of(2, 3, 4, 5, 6, 7, 8, 9).allMatch(k -> i % k == 0))
.findFirst()
.getAsInt();
System.out.println(result);
-> 2520
Ответ 3
Как уже было сказано, вероятно, самый простой способ написать то, что вы пытаетесь сделать, - проверить продукт с 2 по 9.
Однако, чтобы ответить на ваш вопрос о том, как вы можете конденсировать заявления; вложенные операторы if эквивалентны логическому оператору AND, поэтому вы также можете написать свои операторы if следующим образом:
if (i % 2 == 0 && i % 3 == 0 && i % 4 == 0 && i % 5 == 0 && i % 6 == 0 && i % 7 == 0 && i % 8 == 0 && i % 9 == 0) {
System.out.println(i);
}
Ответ 4
Почему бы тебе не..
Инвертировать IFs?
public static void main(String[] args) {
for (int i = 100; i < 10000; i++) {
//If value is not valid, continue to next value
if (i % 2 != 0) continue;
if (i % 3 != 0) continue;
if (i % 4 != 0) continue;
if (i % 5 != 0) continue;
if (i % 6 != 0) continue;
if (i % 7 != 0) continue;
if (i % 8 != 0) continue;
if (i % 9 != 0) continue;
//Valid value found. Print and break out of the loop.
System.out.println(i);
break;
}
}
В качестве альтернативы, приведенный выше код может быть реорганизован далее:
public static void main(String[] args) {
for (int i = 100; i < 10000; i++) {
if (isPrintable(i)) {
System.out.println(i);
break;
}
}
}
private static boolean isPrintable(int value) {
return value % 2 == 0
&& value % 3 == 0
&& value % 4 == 0
&& value % 5 == 0
&& value % 6 == 0
&& value % 7 == 0
&& value % 8 == 0
&& value % 9 == 0;
}
Кроме того, за предложение isPrintable()
можно свести к:
private static boolean isPrintable(int value) {
for (int divisor = 2; divisor < 10; divisor++) {
if (value % divisor != 0) return false;
}
return true;
}
1. Есть также языковые сочетания, как это предлагается в других ответах.Я согласен с ними.
2. Множество ответов использовало LCM номеров, чтобы сделать код кратким, но это неактивная ошибка, ожидающая укуса.Выполнение цикла полностью изменяется, что можно увидеть, комментируя break;
,По-видимому, простое решение представляет тонкую потенциальную ошибку.
Ответ 5
В Java 8 и далее вы можете использовать подход Stream (в частности, используя IntStream).
Во- первых, мы используем IntStream.rangeClosed(2, 9)
(или, что эквивалентно, IntStream.range(2, 10)
), чтобы получить поток последовательных Integer
, начиная с 2
и заканчивая 9
(включительно). Мы можем превратить этот поток в boolean
, используя .allMatch(...)
, который возвращает true
тогда и только тогда, когда каждый элемент потока соответствует некоторым критериям. Требуемые критерии представлены в виде лямбда-выражения, n → я % n == 0
. Это может быть написано дословно как (Integer n) → (i % n == 0)
, поэтому выражение lambda принимает как входное Integer
из потока, называемого n
, и возвращает, является ли i
(счетчик циклов) делимым на n
. Следовательно, .allMatch(n → я % n == 0)
возвращает true
если i
делится на каждое Integer
в потоке.
Нам нужно сделать еще одну модификацию: переменные, используемые в лямбда-выражениях (например, i
), должны быть фактически окончательными:
Переменная или параметр, значение которого никогда не изменяется после его инициализации, фактически является окончательным. (Документация Oracle)
Однако счетчик циклов i
не является фактически окончательным, так как он получает приращение (таким образом, переназначение) на каждую итерацию. Решение состоит в объявлении новой переменной int x = i;
внутри цикла, так что x
назначается только один раз в пределах своей области (то есть одна итерация цикла). Следовательно, x
эффективно является окончательным и может быть использовано в лямбда-выражении.
Здесь окончательное решение:
import java.util.stream.IntStream;
public static void main(String[] args) {
for (int i = 100; i < 10000; i++) {
int x = i; // x is effectively final
if (IntStream.rangeClosed(2, 9).allMatch(n -> x % n == 0)) {
System.out.println(i);
break;
}
}
}
Ответ 6
Гораздо проще:
public static boolean isDivisible(int number) {
for (int i = 2; i <= 9; i++) {
if (num % i != 0) {
return false;
}
}
return true;
}
И используя тот же тип структуры, основным методом становится:
public static void main(String[] args) {
for (int i = 100; i <= 100000; i++) {
if (isDivisible(i)) {
System.out.println("Divisible by numbers 2...9: " + i);
break;
}
}
}
Ответ 7
В основном вы пытаетесь найти число i
которое является LCM
2 * 3 * 4 * 5 * 6 * 7 * 8 * 9
. Первоначально вы можете просто писать
if (i % (2 * 3 * 4 * 5 * 6 * 7 * 8 * 9) == 0) {
System.out.println(i);
break;
}
Было бы правдой, если бы все числа были взаимно просты. Это означает, что у них не было общего фактора. Но в этом случае числа не являются взаимно простыми и имеют общие факторы. Подобно 8 = 2*2*2, 4 = 2*2, 6 = 2*3
все имеют 2. 3 = 1 * 3, 6 = 2*3, 9 = 3*9
все имеют 3. Поэтому в основном мы должны взять LCM
из чисел 2,3,4,5,6,7,8,9
. Для исправления приведенной выше формулы см. Следующее редактирование.
LCM (наименьшее общее число) чисел 2,3,4,5,6,7,8,9
= 2520
. Таким образом, правильная формула, передающая все тестовые примеры, следующая
if ( i % 2520 == 0) {
System.out.println(i);
break;
}
Другим решением для использования было бы просто проверить все условия, как показано ниже:
if(i % 9 == 0 && i % 8 ==0 && i % 7 == 0 && i % 5 == 0) {
System.out.println(i);
break;
}
Ответ 8
Вопрос на самом деле в два раза: первая часть состоит в том, как сжимать 9, если утверждения с аналогичным условием относятся к некоторой более читаемой форме. Другой, возможно, непреднамеренный вопрос заключается в том, как добавить в код такие вещи, как "LCM однозначных чисел". Давайте начнем с последнего и перейдем к предыдущему.
Google для результата
Если вам нужен такой номер в вашей программе (вместо единственной цели программы, которая его вычисляет), вы должны просто получить его с помощью самых простых необходимых средств (в этом случае поиск в Google для "наименьшего числа, делящегося на все однозначные числа",), и включите в свою программу как константу, возможно, с некоторым комментарием о том, откуда пришел этот номер.
Если вы не можете просто найти его, попробуйте вычислить его самостоятельно (например, rgettman) и снова включите его как постоянный. Если это терпит неудачу или занимает слишком много времени, напишите одноразовую программу для вычисления числа, но не делайте ее частью более крупной программы, используя константу. Однако неплохо хранить одноразовый код где-то. Комментарий может быть правильным местом.
Итерация по массиву
Теперь о сжатии оператора if.
Были решения, использующие потоки, хотя в вашем случае простой массив может быть лучше. Этот код также более общий, вы можете перенести его практически на любой язык с минимальными усилиями, и он не привязан к номерам (вы можете использовать массив чего угодно). Бонусная точка - любой должен это понимать.
static boolean divisibleByAll(int n, int[] divisors) {
for (int d : divisors) {
if (n % d != 0) {
return false;
}
}
return true;
}
static int lcmOfSingleDigits() {
int[] divisors = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 100; i < 10000; i++) {
if (divisibleByAll(i, divisors)) {
return i;
}
}
return -1; // Perhaps better to throw an exception
}
public static void main(String args[]) {
System.out.println("Smallest number divisible by all one digit numbers: " +
lcmOfSingleDigits());
}
Использовать потоки
Большинство решений Java-ish, что вы должны использовать на практике - если вам не нужны программисты, не являющиеся Java, чтобы прочитать ваш код. Покрытый saka1029 и pkpnd отвечает, поэтому я не буду повторять его.
Ответ 9
Я думаю, вы можете использовать LCM (наименьшее общее число) (1, 2, 3, 4, 5, 6, 7, 8, 9) = 2520, например:
if (i % 2520 == 0) {
System.out.println(i);
break;
}
Ответ 10
Ваша петля займет очень много времени, если вы когда-нибудь попробуете ее с цифрами от 1 до 20 или от 1 до 30. Вы можете рассчитать наименьшее общее число сразу:
package stackOverflow;
import java.util.stream.LongStream;
public class NumberTheory
{
public static void main(String[] args) {
System.out.println(gcd(15, 3) == 3);
System.out.println(gcd(13, 11) == 1);
System.out.println(gcd(60, 24) == 12);
System.out.println(gcd(1071, 462) == 21);
System.out.println(gcd(462, 1071) == 21);
System.out.println(gcd(new long[] { 10, 12, 24, 60 }) == 2);
long[] oneToNine = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
System.out.println(gcd(oneToNine) == 1);
System.out.println(lcm(oneToNine));
long[] oneToTwenty = LongStream.range(1, 21).toArray();
System.out.println(lcm(oneToTwenty));
}
/**
* Calculates the greatest common divisor of 2 numbers which are not all zero. (see
* https://en.wikipedia.org/wiki/Greatest_common_divisor)
*
* Recursive version of Euclidean algorithm (https://en.wikipedia.org/wiki/Euclidean_algorithm)
*
* @param m
* @param n
* @return greatest common divisor of m and n
*/
public static long gcd(long m, long n) {
if (m == 0 || n == 0) {
return m + n;
} else {
return gcd(n, m % n);
}
}
/**
* Calculates the greatest common divisor of n numbers. The array should have at least one number which isn't zero.
*
* @param numbers
* @return greatest common divisor of numbers
*/
public static long gcd(long[] numbers) {
long result = numbers[0];
for (int i = 1; i < numbers.length; i++) {
result = gcd(result, numbers[i]);
}
return result;
}
/**
* Calculates the least common multiple of 2 numbers which are both non zero. see
* https://en.wikipedia.org/wiki/Least_common_multiple
*
* @param m
* @param n
* @return least common multiple of m and n
*/
public static long lcm(long m, long n) {
return m * (n / gcd(m, n));
}
/**
* Calculates the least common multiple of n numbers. The array should have at least one number and shouldn't contain
* any zero.
*
* @param numbers
* @return least common multiple of numbers
*/
public static long lcm(long[] numbers) {
long result = numbers[0];
for (int i = 1; i < numbers.length; i++) {
result = lcm(result, numbers[i]);
}
return result;
}
}
Он выводит:
true
true
true
true
true
true
true
2520
232792560
Ответ 11
Хотя это может быть субоптимальным, это действительно конденсирует ваши заявления:
public static void main(String[] args)
{
int remainder;
for (int i = 100; i < 10000; i++)
{
remainder=0;
for (int j=2; j<10; j++)
remainder+=i % j;
if (remainder == 0)
System.out.println(i);
}
}
Для каждого я мы используем внутренний цикл j по модулю с каждой цифрой от 2 до 9. Мы добавляем каждый результат по модулю к переменной остатка.
В конце внутреннего цикла, только если все модули для этого я равны нулю, остаток по-прежнему будет равен нулю.
Ответ 12
То, что вы пытаетесь сделать, как упомянуто несколькими другими людьми, вычисляет наименьшее общее кратное числа 1, 2, 3,..., 9.
Но как вы это делаете на компьютере? Во-первых, вам нужно знать, как вычислить наибольший общий делитель двух чисел:
function gcd2(a, b)
while b ≠ 0
t := b;
b := a mod b;
a := t;
return a;
Теперь наименьшее общее кратное двух чисел может быть вычислено из их наибольшего общего делителя с простой формулой:
function lcm2(a, b)
if a = 0 and b = 0
return 0;
else
return abs(a*b) / gcd2(a,b);
(Особый случай, когда a и b оба равны нулю, необходимы, чтобы избежать деления на ноль.)
И, наконец, LCM(a,b,c) = LCM(LCM(a,b),c)
, поэтому для вычисления LCM более двух чисел перебираем по списку:
function lcmN(ns)
let rv := 1;
for n in ns
rv := lcm2(rv, n);
return rv;
Перевод псевдокода на Java оставлен как упражнение.
Ответ 13
Хорошо, это не лучший подход, но я хотел попробовать попробовать с произвольным набором чисел.
public interface Divisor {
boolean isDivisible(Long value);
}
public static main(String[] args) {
LCMDivisor divisor = LCMDivisor.init()
.addValue(2L)
.addValue(3L)
.addValue(4L)
.addValue(5L)
.addValue(6L)
.addValue(7L)
.addValue(8L)
.addValue(9L);
LongStream.range(1, 10000)
.filter(divisor::isDivisible)
.findFirst()
.ifPresent(System.out::println);
}
Таким образом, мы создаем объект, Divisor, который имеет метод, который сообщает вам, является ли значение делимым само по себе или нет.
Код запускается путем создания Stream of Longs от 1 до N, отфильтровывая все значения, которые не делятся на делитель, а затем берут первый (за ваш оператор break). Он возвращает Необязательный. Если значение присутствует, это значение будет напечатано на выводе.
В этом примере, в комментариях, сделанных выше, я представил реализацию Divisor, в которой хранится наименее общий кратный всех добавленных значений. При инициализации он имеет значение один; но каждый раз, когда добавляется новое значение, он возвращает новый экземпляр Divisor с наименьшим общим кратным. Реализация выглядит следующим образом:
public class LCMDivisor implements Divisor {
public final Long lcmValue;
private LCMDivisor(Long lcmValue) {
this.lcmValue = lcmValue;
}
public static LCMDivisor init() {
return new LCMDivisor(1L);
}
public Boolean isDivisible(final Long value) {
return value % lcmValue == 0;
}
public LCMDivisor addValue(final Long newValue) {
return new LCMDivisor(lcm(newValue));
}
private Long lcm(final Long newValue) {
return newValue * (lcmValue / gcd(newValue));
}
private Long gcd(final Long newValue) {
Long greater = newValue < lcmValue ? lcmValue : newValue;
Long lesser = newValue > lcmValue ? lcmValue : newValue;
while (lesser > 0)
{
long temp = lesser;
lesser = greater % lesser;
greater = temp;
}
return greater;
}
}