找到动力总成!


29

获胜者(很明显)是丹尼斯♦,他用十个字节使用了果冻!

这个挑战仍然存在,但是结果将不复存在。


数字的动力总成是约翰·康威(John Conway)的概念(约翰·康威也因制作康威的《人生游戏》而闻名,但这不是重点)。它的定义如下:

对于任何数字enter image description here...,数字的动力总成是enter image description here...(即,每第二个数字,从左到右,是该数字之前的数字的幂)。重复此过程,直到结果为一位数字为止。

例子:

2592 => (2^5)(9^2) = 2592 <= Cannot be further decomposed 135 => (1^3)5 = 5 1234 => (1^2)(3^4) = 81 => (8^1) = 8 1100 => (1^1)(0^0) = 1 # (0^0) = 1 -42 => -42 # Negative numbers output the input

对于n输入中的任何数字,您面临的挑战是powertrain(n)(即n在动力总成分解完成之后)返回输出。

这是代码高尔夫,所以最短的字节数获胜。

免责声明:

  • 您可以在输入中输入奇数个数字,而最后一个数字将没有幂。
  • 0 ^ 0为1,因为如果为0,那么很多数字会立即崩溃为0或1。
  • 如果该数字在计算过程的任何部分都是坚不可摧的(例如,如果最终以结束2592),则只需输出该数字即可。
  • 如果输入为< 10(即所有个位数和负数),则输出输入。

经过几次我可能会宣布获胜者小时天。

当前排行榜:

  1. 果冻(丹尼斯♦):10
  2. 佩斯(DenkerAffe):16
  3. MATL(Don Muesli):21
  4. Perl(Ton Hospel):42
  5. 哈斯克尔(达米安):64
  6. Javascript ES6(edc65):71
  7. Mathematica(墨菲):74
  8. Mathematica(LegionMammal978)和Haskell(Renzeee):77
  9. Python 2(mathmandan):111
  10. Python 3(Erwan):161
  11. Java 8(蓝色):229
  12. Oracle SQL 11.2(Jeto):456
  13. Befunge '93(Lex):490

一些更多的测试用例,将不胜感激。
Mego

所以输入最多有4位数字?
Denker

7
如果到达一个周期,但周期不为1,或者输入数字不属于该周期怎么办?
feersum

1
“我确信在可行性范围内没有任何东西”。我们可以假设它永远不会发生吗?如果周期> 1的周期允许循环永远继续?
Stewie Griffin

6
提出的测试情况:1100-42这很容易对边缘情况下错过的规则,如果没有测试的情况下出现。
丹尼斯

Answers:


4

果冻15 14 12 10字节

Ds2*/€Pµ³¡

在线尝试!

怎么运行的

Ds2*/€Pµ³¡  Main link. Argument: n

D           Convert n into the array of its decimal digits.
 s2         Split into pairs of digits.
   */€      Reduce each pair by exponentiation.
      P     Take the product of the resulting powers.
       µ    Push the preceding chain as a link, and start a new one.
        ³¡  Execute the link n times and return the last result.

仅通过迭代n时间就可以缩短此时间,但是我没有证据表明它适用于所有可能的输入。
丹尼斯

1
您应该可以选择任何合理的数字。实际上,您几乎可以肯定,使用16次迭代可以获得任何数字:oeis.org/A133503
Ton Hospel

@Dennis Hm,这就是我的回答
Luis Mendo

1
@DonMuesli现在我已经考虑过了,它可能会起作用。获得0和奇数索引的几率非常高……
丹尼斯

在现代果冻中,这可以用7个字节完成:D*2/Pµ¡
丹尼斯

5

Haskell,67 64字节

(>> =(==))>> =直到$ p.show是一个未命名函数,将整数作为输入并返回其动力系。

Zgarb节省了3个字节

p(x:y:r)=p[x]^p[y]*p r;p[]=1;p x=read x
(>>=(==))>>=until$p.show

1
((==)=<<g)在上保存两个字节(\n->g n==n)
Zgarb

哇,我对Monad的((->)r)实例不熟悉。谢谢你的把戏。
达米安

这种标点符号的弹幕(>>=(==))>>=真的像火车一样!
安德烈·科斯蒂卡(AndreïKostyrka)

4

Perl,42 个48字节

包括+2 -lp(您也可以删除,-l但我喜欢换行符)

使用STDIN上的输入运行,例如

perl -lp powertrain.pl <<< 1234

powertrain.pl

s/\B/1&pos?"**":"*"/eg until++$.>($_=eval)

(在较早的Perls上,您也可以删除正则表达式之间的距离,直到)

这将无法处理固定点,24547284284866560000000000但是太大的值将无法使用,因为那时perl切换为指数表示法。

实际上,上述版本可以在2592不使用指数表示法的情况下,对perl可以表示的所有数字快速(最多循环)工作,因为已证明2592和之间没有固定点24547284284866560000000000https://oeis.org/A135385

但是,这确实假设了一些尚未得到证实的东西。原则上,减少的幅度可能超过X=10^7步长(推测非固定点的步长不会超过16步,https://oeis.org/A133503),其值会降至以下X(但高于10^7)然后上升再次。如果是这种情况,我必须退回至:

s/\B/1&pos?"**":"*"/eg until$s{$_=eval}++||/-/

说明

该代码通过在数字之间放置***(交替)来工作

s/\B/1&pos?"**":"*"/eg

因此2592变得2**5*9**2123451**2*3**4*5。这些是有效的perl表达式,可以使用

$_ = eval

0**01在Perl)。然后,用一个使它过期的计数器围绕它循环。由于除了固定点之外,这些值都非常快地下降,因此动力总成级数在计数器有机会真正开始之前就收敛了


3

Pyth,25 18 11 16字节

?<Q0Qu*F^McjGT2Q

在这里尝试!

在@Jakube的帮助下保存了7个 14字节

说明

?<Q0Qu * F ^ McjGT2Q#Q = eval(输入)

?<Q0Q#如果输入为负则返回Q
     u Q#应用以下功能,直到达到周期               
                   #起始值为Q,当前值为G
           jGT#将输入拆分为数字列表
          c 2#分成2对
        ^ M#计算每对的功率
      * F#计算所有幂的乘积


1
除微小的改动外,Pyth基本上是高尔夫球版的Python吗?
clismique

1
@Jakube感谢您的提示!:)对我来说还是一大早
丹克(Denker)

@DerpfacePython是的,有点。如果您想了解它,请看一下文档
Denker

没问题。;-)
Jakube

4
@DerpfacePython Pyth最初只是“缩短的Python”,但现在称它为不真实的。Pyth与Python截然不同。
Mego

3

Python 2,111字节

def p(n,b=0,o=''):
 if n<1:return n
 for c in str(n):o+=c+'**'[b:];b=~b
 j=eval(o+'1');return p(j)if j-n else j

这个想法是制作一个字符串,其中的数字n由在*和之间交替的操作分隔**,然后eval是该字符串。(其他解决方案也使用相同的想法;例如,参见Ton Hospel的Perl答案。)

因此,操作会在'**'[0:]**'**'[-1:],这就是*

但是,在for-loop 结束时,字符串以一个操作(一个或另一个)结束,因此我们需要删除最后一个操作,或者添加另一个数字,以使该字符串有意义。

幸运的是,1无论最后执行哪个操作,在末尾附加a 都可以工作。(如果愿意的话,它1是从右侧开始的单向身份,用于乘法和乘幂运算。另一种说法是,powertrain(n) == powertrain(10*n + 1)对于所有人n>0。)

最后,如果eval碰巧的结果与输入的结果相同(在长度1循环中),则函数终止。否则,函数将根据结果调用自身。(它会在任何长度的周期上永久挂起> 1,但是根据OP的评论,我可以假定没有这样的周期。)

(注意:以上说明适用于单位正整数,因为n将完成一个单位的数字输入,n**1这将导致- 1循环。但是,我们还需要接受非正输入,因此在如果输入小于,则开始短路1。如果保证输入为非负值,我们可以消除该行,并节省17个字节。)


这听起来有些偏见,但是...赞成成为Python2。它有一个解释。
clismique

@DerpfacePython谢谢!(我猜想这在Python 3中同样适用...)
mathmandan

3

Java的8,265 244 229字节

这是我的第一个答案,但是我已经阅读了一段时间,以为我知道自己在做什么。至少它击败了befunge和SQL ...

不幸的是,与其他答案一样,此方法不适用于24547284284866560000000000,因为java'a内置了对获取大整数的限制。

@JackAmmo节省了36个字节

public int p(int n){if(n<10)return n;int i=1,t=1,s=(int)Math.log10(n)+1,r[]=new int[s];for(;i<=s;){int a=(int)Math.pow(10,i);r[s-i++]=n%a/(a/10);}for(i=0;i<s-1;i++)t*=Math.pow(r[i],r[++i]);if(s%2==1)t*=r[s-1];return n==t?n:p(t);}

空洞的解释

public int powertrain(int input){
    //handles negative and 1-digit cases
    if(input<10)return input;
    //initialize output variable       
    int total=1;
    // get "length" of number. Shorter than getting length of string representation
    int size=(int)Math.log10(input)+1;
    //initialize array to store digits
    int[] array=new int[size];
    //Now, because Java doesn't have support
    // for the "**" operation, and the way of turning
    // an integer into a string takes too many bytes,
    // I decided just to put every digit into an array with
    // math and iterate from there
    for(int i=1;i<=size;){
        int place=(int)Math.pow(10,i);
        //crazy math. Saved 1 byte by incrementing i when accessed
        array[size-i++]=input%place/(place/10);
    }
    for(int i=0;i<size-1;i++)
        //This is where the train happens.
        //Saved 1 byte by incrementing while accessing 
        //again, instead of i+=2 and i+1
        total*=Math.pow(array[i],array[++i]);
    //Make sure last number isn't left out if size is odd
    if(size%2==1)
        total*=array[size-1];
    //if we end up with same number, stop.
    //otherwise, keep recurring
    return input==total?input:powertrain(total);
}

在您的第一个if ... else中if(n<10)return n;else{...},不需要else ,因为从逻辑上讲,只有当n <10为false时,else块中的所有内容才能运行。删除else和2个匹配的花括号将为您节省6个字节。您的最后一个if ... else也有类似情况,否则请if(n==t)return n;else return p(t);删除else及其后的空格以节省另外5个字节。实际上,如果您使用三元运算符而不是if ... else,则可以进一步缩短它return n==t?n:p(t);
Jack Ammo

您可以通过同时声明t,s,r和for循环的i来节省几个字节(我认为是17个)int t=i=1,s=(int)Math.log10(n)+1,r[]=new int[s];for(;i<=s;){...}for(i=0;...)...
Jack Ammo

@JackAmmo我不知道可以这样声明变量,我必须尝试一下。谢谢你的帮助!
2016年

是的,您只需要注意声明它们是否要使用一个来初始化另一个的顺序(例如r如何使用s定义长度)
Jack Ammo

对于任意大数,您应该查看Java的BigInteger类docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html
Jack Ammo

2

JavaScript(ES6)71

递归函数,在发现重复时停止。这不适用于较长的循环(重复2个或更多个值),但似乎至少在javascript数字精度(17位数字)的有限范围内不会发生

f=n=>[...n+'1'].map((c,i)=>i&1?r*=Math.pow(d,c):d=c,r=1)&&n-r?f(r):n

测试

f=n=>[...n+'1'].map((c,i)=>i&1?r*=Math.pow(d,c):d=c,r=1)&&n-r?f(r):n

function go()
{
  v=+I.value
  R.textContent=f(v)
}  

go()
<input id=I value="1234"><button onclick="go()">Go</button>
<span id=R></span>


的尼斯+'1'到一举两得!
尼尔

我不知道您是否已经调查过,但是我能做的最好的replace是再增加1个字节:f=n=>`${n}1`.replace(/../g,([x,y])=>r*=Math.pow(x,y),r=1)&&n-r?f(r):n
尼尔

@Neil我也很努力,但是模板字符串是一个新主意...
edc65

1

Mathematica,77个字节

Times@@(If[#2<1,1,#^#2]&)@@@Partition[IntegerDigits@#,2,2,1,1]&~FixedPoint~#&

匿名函数。不太复杂。


即使这样,我还能解释一下吗?
clismique

1

Befunge 720个 490字节

从不告诉我赔率之后,无法抗拒再做一次事情。因此,我优化了上一个的“ ASCII数据”。在这种情况下,我看到无需让指令指针越过数字来读取它们,因此我没有做出任何努力使其变得可读。因此,现在更多的是数字化仪。

同样,如果你们想要一个解释,请在评论中告诉我,我将尝试创建一些有用的描述。您可以将代码复制粘贴到解释器中。我发现示例24547284284866560000000000输出0,但是从网格上的某个点获取如此大的值似乎是一个问题,因为您可以清楚地看到在最后的步骤中存储了正确的值。

v                                                    //top row is used for "variables"
>&:0`#v_.@                                           //initialize the counter                          
v     <                           g01_v#-p01:  <     //on our way back to the digitifier, check if we're done
>::>210p>55+%:10g0p-55+/:v            >10g.@         //digitifier, creates a series of ASCII characters at the top line, one for each digit in the source
        ^p01+1g01    _v#:<
v1$$                  <                              //forget some remainders of the digitifier, put 1 on the stack as a base of calculation
                      v p0-1g01-1g0-1g01*g0g01<      //taking powers of each pair of digit
>10g2-!#v_10g1-!#v_  1>                10g1-0g|
^                                  p01-2g01  *<
        >10g0g*  >                             ^     //extra multiplication with last digit if the number of digits was odd

此版本还支持否定输入。如果我自己说的话,这是对以前版本的很大改进。至少修复了1个错误,并且尺寸大大减小。


东西要输入负数还要多多少字节?
clismique

我不确定老实。我遇到一些负数问题,并将它们写在网格中的某个地方。我会再试一次。
rael_kid

我也发现了另一个错误。我确实设法增加了对负数的支持。我会尽快发布更新!因为我计算整个网格,所以它可能是相同数量的字节。
rael_kid

1

Haskell,100 79 77字节

g x|x==h x=x|1<2=g$h x;h=i.map(read.(:[])).show;i[]=1;i[a]=a;i(a:b:c)=a^b*i c

不打高尔夫球:

g x|x==h x=x|1<2=g$h x
h=i.map(read.(:[])).show
i[]=1
i[a]=a
i(a:b:c)=a^b*i c

此函数将输入拆分为数字,然后通过进行技巧i

编辑:感谢妮米的一些提示。


一些提示:a)i(a:[])=ai[a]=a,b)不需要max 1,因为0^0 = 1在Haskell中,c)替换(:[])pure,d)将let内部移动g到单独的函数中,并将其替换为if ... then ... else防护:h=i.map(read.pure).show ; g x|x==h x=x|1<2=h x
nimi

pure不在Prelude中,但是其余的技巧都可以,谢谢。我本来是想和护卫一起做的,但是最终;在护卫之前使用了,那没有用,但是现在我知道它应该如何工作了。
伦兹

pure在base-4.8.2.0随附的Prelude中。不知道什么时候引入的。您不需要( ) in i([a])=a
nimi

1

Mathematica,74个字节

0~f~0=f[]=1
f@n_=n
f[a_,b_,c___]:=f[c]a^b
#//.i_/;i>0:>f@@IntegerDigits@i&

说明

此解决方案使用辅助功能 f,该将数字的数字作为参数并应用动力传动系统操作的一次迭代。最后一行是纯函数,旨在利用该ReplaceRepeated函数(或//.简称为纯函数),它将规则应用于表达式(在本例#中为纯函数的自变量),直到不再更改为止。该规则i_/;i>0:>f@@IntegerDigits@if应用于其十进制数字的函数替换所有非负数。


第2行无效(使用:=
CalculatorFeline

请解释一下?
clismique

@CatsAreFluffy我看不到第2行的问题。它对我来说很好!
墨菲

SetDelayed::write: Tag Times in n f[a_,b_,c___] is Protected. >>Set::write: Tag Times in 1 f[n_] is Protected. >>当我使用:=vs 时,第二个错误消失了=
CalculatorFeline

抱歉,无法重现该错误。但是您的输出表明换行是问题的一部分。请尝试使用;s而不是换行符的版本:0~f~0=f[]=1;f@n_=n;f[a_,b_,c___]:=f[c]a^b;#//.i_/;i>0:>f@@IntegerDigits@i&
murphy

1

MATL,21字节

tt0>*:"V!UtQgv9L2#)^p

可能需要几秒钟才能产生输出。

编辑(2016年7月30日):链接的代码替换9L1L以适应语言的最新更改。

在线尝试!

这使用以下两个技巧来减少字节数,但以降低代码效率为代价:

  • 迭代n时间,而不是等到找到一个循环。根据OP的评论,这是可以接受的。
  • 对于奇数个数字1,必须附加末尾以完成最终的幂运算。取而代之的是,增加1的位数是位数。这样可以确保偶数,因此可以执行所有电源操作(即使最后一个是不必要的1^1操作)。

码:

t         % implicitly take input x. Duplicate
t0>*      % duplicate. Is it greater than 0? Multiply. This gives 0 if input is negative,
          % or leaves the input unchanged otherwise
:         % Generate array [1,2,...,x]
"         % for each (repeat x times)
  V       %   convert x to string
  !       %   transpose into column char array
  U       %   convert each char into number
  tQg     %   duplicate. Add 1 so that no entry is zero. Convert to logical: gives ones
  v       %   concatenate vertically
  9L2#)   %   separate odd-indexed and even-indexed entries
  ^       %   element-wise power
  p       %   product of all entries
          % implicitly end for each
          % implicitly display

呃...嘿嘿嘿...当我说“数字循环”时,我的意思是像这样的数字- a, b, a, b无穷大(不止一个术语)。如果重复一项,则应输出该数字。抱歉,如果还不清楚。
clismique

如果重复一项,我正在输出该数字。经过多次迭代后,我输出结果
Luis Mendo

哦,我现在明白了……只是问,要迭代多少次(大约)?因为当我键入2592输入内容时,似乎在相当长一段时间内都没有输出任何内容。
clismique

迭代数为输入数,因此为2592。是的,需要一些时间
Luis Mendo

0

Python 3中,169个 161字节

def f(s):
 o=[['1',s]['-'in s]]
 while s not in o:
  o+=[s];s+='1'*(len(s)%2==1);r=1;
  for i,j in zip(s[::2],s[1::2]):r*=int(i)**int(j);s=str(r);
 return o[-1]

无金

def f(s):
 o=[['1',s]['-'in s]]
 while s not in o:
  o+=[s]
  s+='1'*(len(s)%2==1)
  r=1
  for i,j in zip(s[::2],s[1::2]):
   r*=int(i)**int(j)
  s=str(r)
 return o[-1]

结果

>>> [f(i) for i in ['135', '1234', '642', '2592', '-15']]
['5', '8', '2592', '2592', '-15']

@PeterTaylor固定!
Erwan

如果将多个语句分隔开,则可以将多个语句放在一行中。;这样可以节省预期的空格。您也可以将for循环的主体放在同一行上。
Denker

建议打高尔夫球:def f(s,o=[['1',s]["-"in s]],n=int): while s not in o: o+=[s];s+=1*(len(s)%2<1);r=1 for i,j in zip(s[::2],s[1::2]):r*=n(i)**n(j) s=str(r) return o[-1]
CalculatorFeline

@CatsAreFluffy o=[['1',s]["-"in s]]在默认参数不工作对我来说,提出一个错误`不是defined`
二万

糟糕,将o移至下一行。
CalculatorFeline

0

Oracle SQL 11.2,456字节

WITH v(n,c,i,f,t)AS(SELECT:1+0,CEIL(LENGTH(:1)/2),1,'1',0 FROM DUAL UNION ALL SELECT DECODE(SIGN(c-i+1),-1,t,n),DECODE(SIGN(c-i+1),-1,CEIL(LENGTH(t)/2),c),DECODE(SIGN(c-i+1),-1,1,i+1),DECODE(SIGN(c-i+1),-1,'1',RTRIM(f||'*'||NVL(POWER(SUBSTR(n,i*2-1,1),SUBSTR(n,i*2,1)),SUBSTR(n,i*2-1,1)),'*')),DECODE(SIGN(c-i+1),-1,0,TO_NUMBER(column_value))FROM v,XMLTABLE(f)WHERE i<=c+2 AND:1>9)CYCLE n,c,i,f,t SET s TO 1 DEFAULT 0SELECT NVL(SUM(n),:1) FROM v WHERE s=1;

未打高尔夫球

WITH v(n,c,i,f,t) AS
(
  SELECT :1+0,CEIL(LENGTH(:1)/2),1,'1',0 FROM DUAL
  UNION ALL
  SELECT DECODE(SIGN(c-i+1),-1,t,n),
         DECODE(SIGN(c-i+1),-1,CEIL(LENGTH(t)/2),c),
         DECODE(SIGN(c-i+1),-1,1,i+1),
         DECODE(SIGN(c-i+1),-1,'1',RTRIM(f||'*'||NVL(POWER(SUBSTR(n,i*2-1,1),SUBSTR(n,i*2,1)),SUBSTR(n,i*2-1,1)),'*')),
         DECODE(SIGN(c-i+1),-1,0,TO_NUMBER(column_value))
  FROM v,XMLTABLE(f) WHERE i<=c+2 AND :1>9 
)  
CYCLE n,c,i,f,t SET s TO 1 DEFAULT 0
SELECT NVL(SUM(n),:1) FROM v WHERE s=1;

v是一个递归视图,参数为

n:要分割成两位数字的数字

c:2位数的位数

i:要计算的当前2位数部分

f:以*为分隔符的幂级联字符串

t:f的评估

当当前编号的所有部分都完成时,DECODE切换到下一个编号以进行拆分和计算。

XMLTABLE(f)接受一个表达式并对其求值,并将结果放在伪列“ column_value”中。这是http://tkyte.blogspot.fr/2010/04/evaluating-expression-like-calculator.html的高尔夫球版本

CYCLE是oracle内置周期检测,并用作退出条件。

由于:1 <10的结果为:1,并且在这些情况下v不返回任何行,因此SUM强制以NULL作为值的行。如果该行为空,则NVL返回:1作为结果。


解释在哪里?
clismique
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.