Проверьте, является ли число произведением последовательных целых чисел


18

Некоторые числа, такие как: 6, 12, 20, 30, 42, 56, 60, 90, 120 и т. Д., Могут быть выражены как произведение последовательных целых чисел, как показано ниже.

6   = 2 * 3  
12  = 3 * 4  
30  = 5 * 6
60  = 3 * 4 * 5  
90  = 9 * 10  
120 = 4 * 5 * 6  

Напишите программу или функцию, которая выводит список последовательных целых чисел, произведение которых равно указанному числу.

Примеры чисел, которые не подходят для этой логики:

99  = 9 * 11  (Product of non-consecutive numbers)
121 = 11 * 11 (Same numbers)
2   = 1 * 2   (Product of itself and 1)
13  = 13      (Product of only one number)

Обратите внимание, что в случае 2 = 2 * 1, мы не считаем его действительным результатом, поскольку целое число, умноженное на 1, дает тот же результат. Для этого вопроса мы будем рассматривать только целые числа> = 2 в произведении.

вход

Допустимое 32-разрядное положительное целое число. Может быть из стандартного ввода, аргумента функции и т. Д.

Выход

Список последовательных целых чисел> = 2 (в порядке возрастания или убывания). Если есть несколько комбинаций последовательных целых чисел, просто предоставьте один экземпляр. Если вы предоставите больше, это нормально.

ограничения

Код должен занимать разумное количество времени (<5 минут) для запуска на стандартном компьютере для всех допустимых входных данных (положительные 32-разрядные целые числа). Если есть последовательный целочисленный продукт, код должен вывести один или несколько в течение срока. Иначе, код должен завершиться без вывода в течение срока.

Это код гольф, поэтому выигрывает самый короткий код в байтах.


1
Эта головоломка, как указано, не очень подходит для формата этого сайта. Этот сайт предназначен для проведения конкурсов, где есть хороший способ определить победителя (например, самый короткий код, самый быстрый код, большинство голосов и т. Д.). Вы не предоставили такой способ.
Крис Шутер-Янг

2
Я рекомендую вам сделать этот код-гольф (кратчайший код), хотя вы должны наложить на него некоторые ограничения. Например, числа от 0 до 1000000, максимальное время выполнения 10 секунд и т. Д.
Уровень River St

Попытался отредактировать это, чтобы спасти этот вопрос. Но я не задавал вопросов раньше, поэтому, если вы видите что-либо, пожалуйста, отредактируйте.
Векторизация

@bitpwner Несмотря на несколько опечаток, мне кажется, хорошо. Проголосовал за открытие.
Seequ

5
Я думаю, что вы имеете в виду 30=5*6.
Кайл Канос,

Ответы:


8

Ява - 124

String f(int t){int s=2,h=3,p=s,i;String o="";for(;p!=t&&s*s<t;p=p<t?p*h++:p/s++);if(p==t)for(i=s;i<h;o+++=i+" ");return o;}

Начиная с 2, этот цикл повторяется до тех пор, пока начальный номер не станет> квадратным корнем цели (или цель будет достигнута точно). Если продукт низкий, он умножается на большое число и увеличивает его. Если высокий, он делится на начальный номер и увеличивает его.

Например, для 30 он будет проверять:

2*3     = 6 (too low, multiply)
2*3*4   = 24 (too low, multiply)
2*3*4*5 = 120 (too high, divide)
3*4*5   = 60 (too high, divide)
4*5     = 20 (too low, multiply)
4*5*6   = 120 (too high, divide)
5*6     = 30 (bingo!)

Выводит разделенную пробелами строку факторов в порядке возрастания.

С переносами строк:

String p(int t){
    int s=2,h=3,p=s,i;
    String o="";
    for(;p!=t&&s*s<t;p=p<t?p*h++:p/s++);
    if(p==t)
        for(i=s;i<h;o+=i+" ");
    return o;
}

7

Питон - 104 97 95 92 попробуйте

n=input()
s=i=2
c=1
while s<n:
 s*=i+c;c+=1
 if s==n:print range(i,i+c)
 if s/n:i+=1;s,c=i,1

Если n, например, предварительно установлено значение 120, программа выводит два решения:

[2, 3, 4, 5]
[4, 5, 6]

Извините, я забыл определить входные данные.
Фалько

1
замените c = c + 1, i = i + 1 на c + = 1, i + = 1
Джеррат

1
Ах да, не думал о +=. Но я скучаю ++по Python ...
Фалько

1
if s>=nи if s/nэквивалентны, так что вы можете предоставить все решения в одном и том же количестве символов.
Исаак

1
Вы можете сохранить три символа, изменив s=s*(i+c)на s*=i+c.
El'endia Starman

4

Clojure - 127 109 байт

(defn f[x](first(for[r[range]y(r 2 x)v[(take-while #(<=(apply * %(r y %))x)(r y x))]:when(=(apply * v)x)]v)))

Пример:

(map f [6 12 30 60 90 120 1404816 99 121 2 13])
=> ((2 3) (3 4) (5 6) (3 4 5) (9 10) (2 3 4 5) (111 112 113) nil nil nil nil)

Объяснение:

Это базовый, довольно неоптимизированный функциональный подход. Я создаю ленивый список всех возможностей, используя простой цикл над ними (он пропускает все комбинации, которые дают слишком большие числа, предотвращая переполнение), и беру первую из них. Если возможностей нет, возвращается ноль.

Проще всего протестировать на http://tryclj.com/ .


Я также заметил, что могу вернуть все возможности: 120 байтов, 102 байта , но дает результаты в виде вложенного списка.

(defn f[x](for[r[range]y(r 2 x)v[(take-while #(<=(apply * %(r y %))x)(r y x))]:when(=(apply * v)x)]v))

Пример:

(map f [6 12 30 60 90 120 1404816 99 121 2 13])
=> (((2 3)) ((3 4)) ((5 6)) ((3 4 5)) ((9 10)) ((2 3 4 5) (4 5 6)) ((111 112 113)) () () () ())

3

CJam, 31 байт

q~:Qmq,A,m*{2f+~,f+_:*Q={p}*}%;

Это грубый подход, но время исполнения составляет всего пару секунд с использованием официального интерпретатора Java .

Если вы хотите протестировать код с помощью онлайн-переводчика , вы должны держать ввод достаточно низким. Все, что меньше 2 26, все еще работает на моей машине.

Примеры

$ TIME="%e s"
$ time cjam product.cjam <<< 2
0.12 s
$ time cjam product.cjam <<< 6
[2 3]
0.10 s
$ time cjam product.cjam <<< 120
[2 3 4 5]
[4 5 6]
0.12 s
$ time cjam product.cjam <<< 479001600
[2 3 4 5 6 7 8 9 10 11 12]
0.68 s
$ time cjam product.cjam <<< 4294901760
[65535 65536]
1.48 s
$ time cjam product.cjam <<< 4294967295
1.40 s

Как это устроено

q~:Q      " Read from STDIN, interpret the input and save the result in variable “Q”.     ";
mq,       " Push the array [ 0 1 2 … (Q ** 0.5 - 1) ].                                    ";
A,m*      " Push the array [ 0 1 2 … 9 ] and take the Cartesian product.                  ";
{         " For each pair in the Cartesian product:                                       ";
  2f+     " Add 2 to each component.                                                      ";
  ~       " Dump the array's elements on the stack.                                       ";
  ,       " Push the array [ 0 1 2 … n ], where “n” is the topmost integer on the stack.  ";
  f+      " Add “m” to each element, where “m” is the integer below the array.            ";
  _:*     " Duplicate the resulting array and push the product of its elements.           ";
  Q={p}*  " If the product is equal to “Q”, print.                                        ";
}%        " Collect the remaining results into an array.                                  ";
;         " Discard the array from the stack.                                             ";

2

Ява, 162

возвращает массив целых чисел или, nullесли последовательных чисел не существует.

int[] e(int n){for(int i=1;i<n;i++){int h=i+1,c=1,s=i;while(s<n){c++;s*=h++;}if(s==n){int[] o=new int[c];for(int j=0;j<c;j++){o[j]=h-j-1;}return o;}}return null;}

ungolfed:

int[] execute(int input){
    for(int i=1; i<input; i++){
        int highest = i+1, count = 1, sum = i;
        while(sum < input){
            count++;
            sum *= highest++;
        }
        if(sum == input){
            int[] numbers = new int[count];
            for(int j=0; j<count; j++){
                numbers[j] = highest-j-1;
            }
            return numbers;
        }
    }
    return null;
}

2

C 105 110 попробуй

n,k,l;main(i){for(scanf("%d",&n);++i<n;)for(k=1,l=i;k<n;)if(k*=l++,k==n)for(l=n;l/=i;)printf("%d ",i++);}

144 с бонусом: этот перебирает все числа и находит подходящие товары

main(i,j,k,l,m){for(scanf("%d",&m);++i<13;)for(j=0;++j<46341-i;){for(l=k=1;k<=i;)l*=j+k++;if(l==m)for(puts(""),k=0;k<i;)printf("%d ",j+k+++1);}}

Красиво, очень просто и элегантно! Определенно работал для некоторых из меньших чисел, которые я бросил в это. Затем я дал ему 50815512 (7128 x 7129), и он пошел в бесконечный цикл. Это переполняется, когда он пытается вычислить 7128 x 7129 x 7130 = 362314600560?
Тодд Леман

Благодарность! по-видимому, состояние k < nстановится слишком высоким из-за k *= l++. я мог Append без знака долго долго до начала , но ... что бы разрушить жизнь
Bebe

2

PHP 258 символов, 201 без учета факториальной функции.

Простейший способ математически выразить «последовательные факторы, равные числу», - это X!/Y!где XНаибольшее число и Yнаименьшее минус единица. К сожалению, я перестал принимать исчисление, прежде чем я научился решатьZ = X!/Y! , поэтому мне пришлось немного переборщить.

Грязная, негольфированная версия:

<?php
// PHP does not define a factorial function, so I've kludged one in.
function fact($n) {
    $r = 1;
    for($i=$n; $i>1; $i--) {
        $r *= $i;
    }
    return $r;
}

$input = intval($argv[1]);

if( $input < 2 ) { die('invalid input'); }

printf("input: %s\n", $input);

$max=min(ceil(sqrt($input)),170); // integer breakdown for > 170!
$grid = array();
for( $x=1;$x<$max;$x++ ) {
    for( $y=$max;$y>=1;$y-- ) {
        if( $y >= $x ) { continue; } // Skip results that would be < 1
        $cur = fact($x)/fact($y);
        if( $cur > $input ) { // too large!
            echo "\n"; continue 2;
        }
        if( $cur == $input ) { //just right
            printf("%7d\n\nFound %s == %s\n", $cur, implode(' * ', range($y+1, $x)), $cur);
            break 2;
        }
        printf("%7d ", $cur);
    }
    echo "\n";
}
if($cur!=$input){printf("No consecutive factors produce %d\n", $input);}

Пример вывода:

input: 518918400

  2
  3       6
  4      12      24
  5      20      60     120
  6      30     120     360     720
  7      42     210     840    2520    5040
  8      56     336    1680    6720   20160   40320
  9      72     504    3024   15120   60480  181440  362880
 10      90     720    5040   30240  151200  604800 1814400 3628800
 11     110     990    7920   55440  332640 1663200 6652800 19958400 39916800
 12     132    1320   11880   95040  665280 3991680 19958400 79833600 239500800 479001600
 13     156    1716   17160  154440 1235520 8648640 51891840 259459200
 14     182    2184   24024  240240 2162160 17297280 121080960
 15     210    2730   32760  360360 3603600 32432400 259459200
 16     240    3360   43680  524160 5765760 57657600 518918400

Found 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 == 518918400

Golfed:

<? function f($n){$r=1;for($i=$n;$i>1;$i--)$r*=$i;return $r;}$i=$argv[1];$m=min(ceil(sqrt($i)),170);for($x=1;$x<$m;$x++){for($y=$m;$y>0;$y--){if($y>=$x)continue;$c=f($x)/f($y);if($c>$i)continue 2;if($c==$i){$y++;echo "$y $x";break 2;}}}if($c!=$i){echo 'No';}

Выход:

[sammitch@vm ~/golf] time php consecutive_golf.php 518918400
9 16
real 0m0.019s
user 0m0.011s
sys  0m0.009s
[sammitch@vm ~/golf] time php consecutive_golf.php 518918401
No
real 0m0.027s
user 0m0.017s
sys  0m0.011s

Я не ожидал, что время выполнения будет таким быстрым!


эта идея пришла мне в голову, и она выглядит очень эффективной, но я сомневаюсь, что ее можно укоротить достаточно, чтобы «быть квалифицированным».
Bebe

1
@bebe это 258 символов, не так уж плохо для PHP. Если бы я не был таким ленивым и упрямым, я бы сделал это на настоящем языке. : P
Sammitch

X! / Y! произведение целых чисел N таких, что Y <N <= X. Это помогает вообще?
Трихоплакс

2

Пиф , 35

JvwKr2 4W-ZJ~@KgJZ1=YurGHK=Zu*NTY)Y

Примечание. Мой код фактически находит самое короткое представление ввода как представление последовательных целых чисел> = 2, поэтому при неверном вводе он напечатает список из 1 элемента, возможно, через очень долгое время. Поскольку в заявлении о проблеме говорится, что ввод будет действительным, я предполагаю, что это нормально.

Краткое объяснение:

По сути, программа сохраняет верхний и нижний пределы диапазона, вычисляет произведение чисел в диапазоне, используя уменьшение, корректирует конечные точки по мере необходимости и повторяет до тех пор, пока произведение не сравняется с вводом.

Длинное объяснение:

Для каждого фрагмента кода я приведу эквивалентный python, а также более подробное объяснение и обоснование.

Jvw => J=eval(input())

Стандартный способ ввода данных в Pyth.

Kr2 4=> K=range(2,4)=>K=[2,3]

Вот первая странная часть: вместо того, чтобы хранить конечные точки как отдельные переменные, я сохраняю их как элементы списка. Причина скоро будет ясна. Кроме того, вместо того, чтобы делать простое назначение, как в Pyth K[2 3), я использую диапазон для сохранения символа.

W-ZJ=> while Z-J=>while Z!=J

В этот момент вы можете спросить: «Что такое Z? Вы не определили его». В Pyth все переменные предопределены. Случается, что Z начинается с 0. Однако Z будет установлен на значение продукта позже, так что эта проверка будет служить для завершения цикла while, когда список будет иметь правильное значение.

~@K>JZ1 => K[J>Z] += 1

Вот почему я храню значения в списке, а не в отдельных переменных: я хочу увеличить одну из двух конечных точек в зависимости от того, слишком ли высок продукт в настоящее время или слишком низок. Это было бы довольно длинным условием, если бы конечные точки были отдельными переменными, но с помощью магии индексации списков она становится короткой. Кроме того, тот факт, что эта проверка предшествует продукту, и тот факт, что Z инициализируется в 0, гарантируют, что [2,4]к тому времени, когда мы впервые примем продукт, будет K , которые являются подходящими конечными точками.

=YurGHK => Y=reduce(lambda G,H: range(G,H),K)=>Y=range(K[0],K[1])

Теперь мне нужен фактический список того, что продукт будет принят, и он будет распечатан, если мы добьемся успеха. Понятно, что мы будем использовать функцию диапазона. Хитрость заключается в получении входных данных для функции диапазона. Очевидный способ сделать это путем индексации списка, будет =Yr'K@K1. Однако, используя функцию Reduce в этом списке из двух элементов, мы можем сократить это на символ.

=Zu*NTY => Z=reduce(lambda N,T: N*T,Y)

А теперь, по сути, это операция сокращения, чтобы найти произведение из списка.

) => Конец времени

Y => print(Y)

В случае успеха распечатайте список.

Пример выполнения:

$ cat seq_prod 
JvwKr2 4W-ZJ~@K>JZ1=YurGHK=Zu*NTY)Y

$ cat seq_prod | python3 pyth.py
<debug stuff>
==================================================
[9, 10, 11, 12, 13, 14, 15, 16]

1

Ява - 115

void f(int i){for(int j=2;j<i;j++)for(int k=1,x=j;(x*=j+k)<i;k++);if(x==i)for(i=j;i<j+k;i++)System.out.println(i);}

Немного меньше в гольф:

void f(int i) {
 for(int j=2; j<i; j++)
  for(int k=1, x=j; (x*=j+k) < i; k++);
   if(x == i)
    for(i=j; i<j+k; i++)
     System.out.println(i);
}

Эх, вы создали функцию и напечатали возвращаемое значение. Не видел, что сделано здесь раньше.
Seequ

Я не могу заставить его что-либо напечатать ... Но если это даст мне какой-то вывод, вы можете сыграть в гольф System.out.println, System.out.printи точка с запятой в конце for(int k=1,x=j;(x*=j+k)<i;k++)не только не нужна, но и вызывает ошибки.
Qwix

Это не работает для меня. x, j, kВыходят за рамки в последних if/forблоках из - за ;. Если я удалю ;, он ничего не печатает.
Geobits

1
@Qwix Переключение на printозначало бы, что ему нужно добавить символ пробела, чтобы избежать слияния чисел.
Geobits

1
@Geobits Хороший вопрос! Я бы, наверное, видел это, если бы дал какой-то результат.
Qwix

1

Матлаб (88)

Код ожидает, что число будет сохранено xи выведено в l.

for n=2:12
r=ceil(x^(1/n))
for s=-3*n:n
l=r-s+(1:n)
if prod(l)==x
return 
end;end;l=x;end

Поскольку 13! > 2^32этот код ищет только продукты длиной от 2 до 12. Этот код имеет постоянное время выполнения около 0,001 с.


1

Скала - 86

def p(n:Int)=(2 to n).flatMap(i=>(i to n).map(i to _-1).find(_.product==n)).headOption

Этот код очень неэффективен, но его оптимизация добавит всего несколько символов. Он использует функциональный подход для проверки продуктов всех возможных последовательных последовательностей. (последовательная последовательность целых чисел представлена ​​как объект Range в Scala)

ungolfed:

def product(n: Int): Option[Range] = {
  def productStartingAt(start: Int): Option[Range] =
    (start to n-1).map(start to _).find(_.product == n)

  (2 to n).flatMap(i => productStartingAt(i)).headOption
}

1

CJam настоящее время не работает для больших чисел из-за длительного времени вычислений

Это мой самый короткий код CJam. Тест на http://cjam.aditsu.net/ . Он работает путем: определения ввода как A; создание массива всех чисел от 0 до A-1; Пинать 0; выбрасывание самых маленьких чисел до тех пор, пока все числа в массиве не умножатся на A; проверка, больше ли оно A; если нет, создание массива от 0 до A-2; и повторять, пока ответ не будет найден. Если ничего не найдено, выдается исключение. Я не считал, что пробелы между числами нужны, поэтому они включены во второй код, который состоит из 32 символов.

ri:A,{)\;,1{;(;_{*}*_A>}gA<}g

ri:A,{)\;,1{;(;_{*}*_A>}gA<}g" "*

Я думаю, что ваш ответ слишком медленный, чтобы быть действительным. Помните, что оно должно завершаться не более чем за 5 минут для любого действительного 32-битного целого числа. Сколько времени занимает 3600060000 == 60000 * 60001?
Исаак

Честно говоря, я переделаю это и отправлю, если это будет коротким
Кейн

Если вы собираетесь его переделать, удалите этот ответ до тех пор, иначе укажите, что он в данный момент не действителен.
Исаак

1

Дротик - 102 символа

Это медленная реализация. Это можно сделать быстрее, но для этого требуется больше символов (например, выполнение цикла только до i*i<n)

f(n,[i=2]){
  t(j,p,a)=>p<n?t(++j,p*j,a..add(j)):p>n?f(n,i+1):a;
  for(;i<n;i++)if(n%i<1)return t(i,i,[i]);
}

(102 символа без разрывов строк и пробелов).

Чтобы использовать это, сделайте что-то вроде:

main() {
  print(f(123456789*123456790));
}

0

Javascript, 88

Гольф-код:

function f(a){for(i=2;i<a;i++){b=[1];for(j=i;j>1;j--)if((b[0]*=b[i-j+1]=j)==a)alert(b)}}

Легче читать (приятно разнесенный) код:

function f(a){
    for(i=2;i<a;i++){
        b=[1];
        for(j=i;j>1;j--)
            if((b[0]*=b[i-j+1]=j)==a)
                alert(b);
    }
}

Для каждого числа от 2 до входного числа он находит произведение последовательных целых чисел от текущего числа обратно до 2. Если это произведение равно входному номеру, то выводится серия последовательных чисел вместе с исходным входным номером ,

Он выводит входной номер, за которым следуют последовательные целые числа, произведением которых является входной номер.

Например, f (120) создает предупреждение с текстом «120,5,4,3,2», а затем второе предупреждение с текстом «120,6,5,4».

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.