Перевірте, чи число є добутком послідовних цілих чисел


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 сек і т.д.
Level 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

Python - 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вони еквівалентні, тому ви можете надати всі рішення з однаковою кількістю символів.
isaacg

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;}

неозорений:

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++. я міг би додати непідписаний довгий час до початку, але ... це зіпсує життя
березня

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

Гольф:

<? 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
Саммітч

Х! / У! є добутком цілих чисел N таким, що Y <N <= X. Чи допомагає це взагалі?
трихоплакс

2

Піта , 35

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

Примітка: Мій код насправді знаходить найкоротше подання введення як представлення послідовних цілих чисел> = 2, тому на неправильному введенні він надрукує список елементів 1, можливо, через дуже довгий час. Оскільки в заяві проблеми сказано, що введення буде дійсним, я припускаю, що це нормально.

Коротке пояснення:

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

Довге пояснення:

Для кожного фрагмента коду я дам еквівалентний пітон, а також більш детальне пояснення та міркування.

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, гарантують, що K буде[2,4] до того часу, коли ми вперше візьмемо продукт, які є належними кінцевими точками.

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

Тепер мені потрібен фактичний перелік того, що товар буде прийнято, і він буде роздрукований, якщо нам це вдасться. Зрозуміло, ми будемо використовувати функцію діапазону. Хитрість полягає в отриманні входів до функції діапазону. Очевидним способом зробити це шляхом індексації списку було б =Yr'K@K1. Однак, використовуючи функцію зменшення у цьому списку двох елементів, ми можемо скоротити її на символ.

=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блоках з - за ;. Якщо я видаляю ;, він нічого не надрукує.
Геобіц

1
@Qwix Зміна printозначатиме, що йому потрібно додати символ пробілу, щоб уникнути числення разом.
Геобіт

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

Цей код дуже неефективний, але оптимізація його додасть лише кілька символів. Він використовує функціональний підхід для перевірки продуктів усіх можливих послідовних послідовностей. (послідовна послідовність цілих чисел у Scala представлена ​​як об'єкт діапазону)

неозорений:

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 до А-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?
isaacg

Справедливий момент, я перероблю його і
розміщу,

Якщо ви збираєтесь її переробити, видаліть цю відповідь до цього часу, або ще якось вкажіть, що наразі не вірна.
isaacg

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.