检查数字是否为连续整数的乘积


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秒,等等
等级河圣

试图对其进行编辑以解决此问题。但是我之前没有提出任何问题,因此,如果您看到任何内容,请进行编辑。
2014年

@bitpwner除了一些错别字,对我来说似乎还不错。投票重新开放。
Seequ 2014年

5
我想你的意思是30=5*6
凯尔·坎诺斯

Answers:


8

Java-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]

抱歉,我忘记定义一些输入。
Falko 2014年

1
用c + = 1,i + = 1替换c = c + 1,i = i + 1
Gerrat

1
哦,是的,没有考虑+=。但是我很想念++Python ...
Falko 2014年

1
if s>=n并且if s/n是等效的,因此您可以使用相同数量的字符提供所有解决方案。
isaacg 2014年

1
更改s=s*(i+c)为可以保存三个字符s*=i+c
El'endia Starman 2014年

4

Clojure- 127109字节

(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)

说明:

这是基本的,尚未优化的功能方法。我使用一个简单的循环遍历它们创建了一个懒惰列表(它会跳过所有组合,这些组合会给出太大的数字,防止溢出),并采用它们中的第一个。如果不存在,则返回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

ç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++。我可以在开头加上很长的签名,但是...那会毁了生命
Bebe 2014年

2

PHP 258个字符,201个不计算阶乘函数。

用数学方式表达“等于一个数字的连续因子”的最简单方法是X!/Y!Where X是最高数字,Y最低是负1。不幸的是,我在学会求解之前就停止了微积分的研究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

我没想到运行时间会这么快!


这个想法也浮现在我的脑海,看起来非常有效,但我怀疑它可以缩短到“合格”的程度。
贝贝2014年

1
@也许是258个字符,对于PHP来说还不错。如果我不是那么懒惰和固执,我会用一种真实的语言来做。:P
Sammitch 2014年

X!/ Y!是整数N的乘积,以使Y <N <= X。这些帮助有用?
trichoplax

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)

现在,对于此事务的整个要点,请执行reduce操作以查找列表的乘积。

) =>结束片刻

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

Java-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 2014年

我无法打印任何内容...但是,如果它可以给我一些输出,您可以打高尔夫球,System.out.println直到System.out.print结尾处的分号for(int k=1,x=j;(x*=j+k)<i;k++)不仅不必要,而且还会导致错误。
Qwix 2014年

这对我不起作用。xjk超出范围,在过去if/for,因为的块;。如果删除;,它不会打印任何内容。
Geobits 2014年

1
@Qwix更改为print表示他需要添加一个空格字符,以避免数字同时运行。
Geobits 2014年

1
@Geobits好点!如果它给了我一些输出,我可能会看到的。
Qwix 2014年

1

Matlab(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.001s。


1

斯卡拉-86

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

这段代码效率很低,但是对其进行优化只会增加几个字符。它使用一种功能方法来检查所有可能的连续序列的乘积。(连续的整数序列在Scala中表示为Range对象)

松散:

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代码。在http://cjam.aditsu.net/上进行测试。它的工作原理是:将输入定义为A;将输入定义为A。创建一个从0到A-1的所有数字的数组;踢0; 踢最小的数字,直到将数组中的所有数字相乘不大于A;检查它是否大于A;如果不是,则创建一个从0到A-2的数组;并重复直到找到答案。如果未找到,则引发异常。我不认为数字之间需要空格,因此它们包含在第二个代码中,该代码长32个字符。

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

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

我认为您的答案太慢,无法生效。请记住,任何有效的32位整数都必须在不超过5分钟的时间内完成。3600060000 == 60000 * 60001需要多长时间?
isaacg 2014年

公平的观点,我会对其进行重做并发布,如果它很短
kaine 2014年

如果您要重做,请在此之前删除此答案,否则将以某种方式表明当前无效。
isaacg 2014年

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”的警报。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.