回文逆转加法


19

回文逆转加法

反向加法的过程是向其反向添加数字,直到创建的数字是回文。例如,如果我们从68开始,则过程将是:

68 + 86 => 154 + 451 => 605 + 506 => 1111

如您所见,这花了3次加法才得到回文数。如果从开始89,我们将需要24个步骤(您可以在此处查看细分)。

达到回文记录之前所采取的大多数步骤的世界纪录是261,该数字最高发生1186060307891929990,产生的数字大于10 118。但是,有很多数字我们还无法得到回文。这些称为Lychrel数

由于我们的工作基础是10,因此我们只能称他们为候选人,因为没有证据表明这些数字永远不会达到回文率。例如,最小的以10为底的Lychrel候选对象是196,并且已经经历了十亿多次迭代。如果回文确实存在,则比10 10 8.77大得多。作为比较,如果原子上刻有多个1 ,则假设存在,我们将需要2.26772×10 588843575个宇宙原子来写出。

你的任务

创建一个程序或函数,该程序或函数接受整数输入并返回或打印到达回文所需的步骤数。您无需与Lychrel候选者打交道(即,当您的程序被赋予Lychrel候选者时,将允许其抛出错误或永久运行)。

测试用例:

                  f(0) => 0
                 f(11) => 0
                 f(89) => 24
                f(286) => 23
          f(196196871) => 45
         f(1005499526) => 109
f(1186060307891929990) => 261

规则

  1. 没有标准漏洞。

奖金

  1. 如果按格式打印每个加法步骤,则n + rev(n) = m可以将分数乘以0.75。总数应在步数之前打印出来。
  2. 如果您的代码可以检测到数字是否为Lychrel候选者,则可以将分数乘以0.85。在这种情况下,假设需要花费超过261次迭代的任何事物都是Lychrel候选者。要么不返回任何内容,要么不返回任何可能被误解为正确答案的数字(例如:任何字符串或不在0-261范围内的数字)。任何错误均不算作有效输出(例如,超过最大递归深度),因此不能在检测中使用。
  3. 如果您同时获得这两个奖金,请乘以0.6

这是,因此最少的字节数获胜。


此代码段显示了在Python 3中具有两个优点的示例解决方案。

def do(n,c=0,s=''):
  m = str(n)
  o = m[::-1]
  if c > 261:
    return "Lychrel candidate"
  if m == o:
    print(s)
    return c
  else:
    d = int(m)+int(o)
    s+="%s + %s = %s"%(m,o,str(d))
    return do(d,c+1,s)


1
*0.6奖金之上的其他人呢?还是仅此而已?
Maltysen

@马尔蒂森0.6。
卡德2015年

在打印金额时,我们应该打印10 + 01 = 11还是10 + 1 = 11由我们决定?
马丁·恩德

3
对于lychrel检测器,我可以打印出来262吗?
Maltysen

Answers:


8

Pyth,12个字节

f_I`~+Qs_`Q0

在线尝试:演示测试工具

这使用了一项相当新的功能(仅17小时有效)。

说明

               implicit: Q = input number
f          0   repeat the following expression until it 
               evaluates to true and return the number of steps
         `Q       convert Q to string
        _         reverse the digits
       s          convert to int
     +Q           add Q
    ~             assign the result to Q
                  (this returns the old value of Q)
   `              convert the old value of Q to a string
 _I               and check if it's invariant under the operation reverse

编辑:

更改了一点代码。旧版本是

fqKs_`Q~+QK0

相同的字节数,但是新的字节数更酷。


红利得分为12。祝您好运!
丹尼斯

@丹尼斯你的权利。这是一个荒谬的意图。使用Lychrel检测,我得到的最好结果是13.6。
Jakube 2015年

14

Python,51岁

def f(n):r=int(str(n)[::-1]);return n-r and-~f(n+r)

对于Python 2,str()由于L附加了long文字,因此不能替换反引号。

这是得分为64 * 0.85 = 54.4的替代版本:

def f(n,c=262):r=int(str(n)[::-1]);return c*(n-r)and-~f(n+r,c-1)

还有Python 3的替代版本,得分为88 * 0.6 = 52.8

def f(n,c=262):r=int(str(n)[::-1]);return c*(n-r)and-~f(n+r,print(n,'+',r,'=',n+r)or~-c)

1
这真是太疯狂了。
卡德2015年

6

CJam,23 22 20.4字节

ri{__sW%i+}261*]{s_W%=}#

该代码长为24个字节,并为Lychrel候选对象打印-1

在线尝试。

怎么运行的

ri                       e# Read an integer from STDIN.
  {       }261*          e# Do the following 261 times:
   __                    e#   Push two copies of the integer on the stack.
     sW%i                e#   Cast to string, reverse and cast back to integer.
         +               e#   Add the copy and the reversed copy of the integer.
               ]         e# Wrap all 262 results in an array.
                {     }# e# Push the index of the first element such that:
                 s       e#   The string representation equals...
                  _W%=   e#   the reversed string representation.

如果{}#成功,索引也是步数。另一方面,如果数组不包含回文,{}#则将-1推入。


5

Java,200 * 0.6 = 120

import java.math.*;int f(BigInteger a){int s=-1;for(String b,c;(b=a+"").equals(c=new StringBuffer(b).reverse()+"")!=s++<999;)System.out.println(b+" + "+c+" = "+(a=a.add(new BigInteger(c))));return s;}

这是一个简单的循环,可以完成包装盒上的说明,但还增加了一些高尔夫球。返回1000Lychrel候选人以获得检测奖金。事实证明,我能够打印的字符不太多(至少对于Java而言),并且也能获得这种好处。没有奖金代码,我能做的最好的是156,所以这是非常值得的。

有一些换行符:

import java.math.*;
int f(BigInteger a){
    int s=-1;
    for(String b,c;(b=a+"").equals(c=new StringBuffer(b).reverse()+"")!=s++<999;)
        System.out.println(b+" + "+c+" = "+(a=a.add(new BigInteger(c))));
    return s;
}

旧答案:171 * 0.85 = 145.35字节

import java.math.*;int f(BigInteger a){int s=-1;for(String b,c;(b=a+"").equals(c=new StringBuffer(b).reverse()+"")!=s++<262;)a=a.add(new BigInteger(c));return s>261?-1:s;}


我想您仍然在沙箱中时就此工作了:P我正在重新考虑奖金金额,因为我意识到即使在Python(与C#/ Java相比,它是一种相对简洁的语言)中,奖金也无济于事。我认为我将使其与程序的长度有关,以使高尔夫球语言的得分不会低于10字节。
卡德2015年

我已经更新了奖金规则,所以您的新分数是145.35 :)
Kade 2015年

保存一个字节,在定义的末尾删除分号,这不是必需的,因此在之后s++<999
Christopher Wirt,2015年

@ChristopherWirt在什么编译器/版本中?我的给出了语法错误,没有它。
Geobits 2015年

5

红宝石(80 + 2)* 0.6 =〜49.2

带有标志-nl,运行

p (0..261).find{$_[b=$_.reverse]||puts($_+' + '+b+' = '+$_="#{$_.to_i+b.to_i}")}

输出看起来像

 $ ruby -nl lychrel.rb 
89
89 + 98 = 187
187 + 781 = 968
968 + 869 = 1837
1837 + 7381 = 9218
9218 + 8129 = 17347
17347 + 74371 = 91718
91718 + 81719 = 173437
173437 + 734371 = 907808
907808 + 808709 = 1716517
1716517 + 7156171 = 8872688
8872688 + 8862788 = 17735476
17735476 + 67453771 = 85189247
85189247 + 74298158 = 159487405
159487405 + 504784951 = 664272356
664272356 + 653272466 = 1317544822
1317544822 + 2284457131 = 3602001953
3602001953 + 3591002063 = 7193004016
7193004016 + 6104003917 = 13297007933
13297007933 + 33970079231 = 47267087164
47267087164 + 46178076274 = 93445163438
93445163438 + 83436154439 = 176881317877
176881317877 + 778713188671 = 955594506548
955594506548 + 845605495559 = 1801200002107
1801200002107 + 7012000021081 = 8813200023188
24

如果给定196,它将打印前261个加法步骤,然后打印nil

这里没有什么棘手的问题。我们检查$_(初始化为输入的)是否包含其反向,这只有在它们相等时才可行,因为它们的大小相同。如果是的话,我们将打印步骤号并退出,否则,我们将显示并执行加法步骤,将新值存储在$_(很遗憾,我不能只eval显示我要显示的字符串,因为它会解释一个以0结尾的反向数字。作为八进制文字)。puts返回falsey值,因此循环继续。


" + #{b} = "保存一个字节。
米奇·施瓦兹

而且,-l如果我们将数字放入文件中而不使用尾随换行符并将其插入管道,似乎在规则内删除了吗?
米奇·施瓦兹


4

K,25个字节

#1_{~x~|x}{$. x,"+",|x}\$

不是很优雅。整体形式({monad 1}{monad 2}\x)与K等效于一般的“ while”循环,其中第一个monad是暂停条件,第二个monad是对该参数的迭代应用函数x。第一个monad({~x~|x})是经典“ is xa回文”短语的否定。第二个monad将代表x和x的倒数的字符串连接在一起,对其求值,然后使用将结果转换回字符串$

显示中间结果的样本运行:

  {~x~|x}{$. x,"+",|x}\$68
("68"
 "154"
 "605"
 "1111")

按照奖金的要求进行格式化输出将非常笨拙,并且会添加大量代码。


4

CJam,23个字节

Wl{\)\__W%_@#\i@i+s\}g;

距离CJam仅有几天的时间,因此我很高兴能与一些专业人士保持同一水平。:)我确实使用了马丁的字符串比较技巧,他也在CJam提示中发布了该技巧。我还偷看了Dennis的解决方案,以弄清楚如何反转字符串。

说明:

W    Initialize counter, will keep this at bottom of stack.
     Start counting at -1 because the counter will be incremented in the
     last pass through the loop, when the palindrome is detected.
l    Get input.
{    Start block of while loop.
\)\  Increment counter. Need to swap before/after because it's one below top of stack.
__   Copy current value twice. Need 3 copies in total:
       * one for reversal
       * one for comparison
       * one for addition with reverse
W%   Reverse value.
_    Copy the reverse value once because we need 2 copies:
       * one for comparison
       * one for addition with original value
@    Rotate one copy of original value to top.
#    Test for non-equality with reverse, using Martin's trick.
\i   Swap reverse value to top, and convert it to int.
@i   Rotate remaining copy of original value to top, and convert it to int.
+s   Add the values, and convert result to string.
\    Swap, so that comparison result is at top of stack for while loop test.
}g   End of while loop.
;    Current value sits at top of stack. Pop it, leaving only counter.

在线测试


4

朱莉娅129120字节* 0.6 = 72

i->(i=big(i);n=0;d=digits;while d(i)!=reverse(d(i))&&n<262 t=BigInt(join(d(i)));println(i," + ",t," = ",i+=t);n+=1end;n)

这将创建一个未命名函数,该函数将整数作为输入并返回整数,同时打印每个步骤。Lychrel候选者的返回值为262。要为其命名,请为其命名,例如f=i->...

注意,省略仅与奖金有关的代码,此解决方案将是84个字节。

取消+说明:

function f(i)
    # Convert the input to a big integer
    i = big(i)

    # Initialize a step counter to 0
    n = 0

    # While the number is not a palindrome and we haven't exceeded 261 steps...
    while digits(i) != reverse(digits(i)) && n < 262

        # Get the reverse of the integer
        # Note that we aren't using reverse(); this is because digits()
        # returns an array of the digits in reverse order.
        t = BigInt(join(digits(i)))

        # Print the step and increment i
        println(i, " + ", t, " = ", i += t)

        # Count the step
        n += 1
    end

    # Return the number of steps or 262 for Lychrel candidates
    n
end

例子:

julia> f(286)
286 + 682 = 968
968 + 869 = 1837
1837 + 7381 = 9218
9218 + 8129 = 17347
17347 + 74371 = 91718
91718 + 81719 = 173437
173437 + 734371 = 907808
907808 + 808709 = 1716517
1716517 + 7156171 = 8872688
8872688 + 8862788 = 17735476
17735476 + 67453771 = 85189247
85189247 + 74298158 = 159487405
159487405 + 504784951 = 664272356
664272356 + 653272466 = 1317544822
1317544822 + 2284457131 = 3602001953
3602001953 + 3591002063 = 7193004016
7193004016 + 6104003917 = 13297007933
13297007933 + 33970079231 = 47267087164
47267087164 + 46178076274 = 93445163438
93445163438 + 83436154439 = 176881317877
176881317877 + 778713188671 = 955594506548
955594506548 + 845605495559 = 1801200002107
1801200002107 + 7012000021081 = 8813200023188
23

julia> f(1186060307891929990)
(steps omitted)
261

julia> f(196)
(steps omitted)
262

julia> f(11)
0

感谢Geobits,节省了2个字节!


4

CJam,24个字节

0q{__W%#}{_W%~\~+s\)\}w;

在这里测试。

说明

0q     e# Push a zero (the counter) and read input.
{      e# While this block leaves something truthy on the stack...
  __   e#   Make two copies of the current number (as a string).
  W%   e#   Reverse the second copy.
  #    e#   Check that they are not equal.
}{     e# ... run this block.
  _W%  e#   Make a copy of the current number and reverse it.
  ~\~  e#   Evaluate both N and its reverse.
  +s   e#   Add them and turn the sum into a string.
  \)\  e#   Pull up the counter, increment it, and push it back down again.
}w
;      e# Discard the palindrome to leave the counter on the stack.

有关为何#可用于检查字符串不等式的更多信息,请参见本技巧


发布前没有看到您的答案。这是的巧妙用法#
丹尼斯

2

Haskell,66 53字节

r=reverse.show
f x|show x==r x=0|1<2=1+f(x+read(r x))

用法示例:

*Main> map f [0,11,89,286,196196871,1005499526,1186060307891929990]
[0,0,24,23,45,109,261]

我以前从未用过Haskell,但是您能做到r=reverse x吗?那将把第二行更改为f x|x==r=0|1<2=1+f(show$read x+read(r)),并节省2个字节。
卡德2015年

@ Vioz-:不,这不可能,因为x不会在范围内。但是,f x|x==r=0 .... read(r)) where r=reverse x可以工作,但是时间更长。
nimi 2015年

2

Clojure,94个字节

(fn[x](#(let[r(bigint(apply str(reverse(str %1))))] (if(= %1 r)%2(recur(+ %1 r)(inc %2))))x 0))

这是我第一次尝试编码高尔夫,所以请告诉我我做错了什么。

有一些空格:

(fn [x]
(#(let [r (bigint (apply str (reverse (str %1))))]
  (if (= %1 r) %2 (recur (+ %1 r) (inc %2)))) x 0))

内部函数的简单递归。它%1带有两个参数,整数和索引%2。如果%1是回文,则返回索引。否则,该函数将使用总和和递增索引来调用自身。外部函数将索引初始化为零。

一个样品:

repl=> ((fn[x](#(let[r(bigint(apply str(reverse(str %1))))](if(= %1 r)%2(recur(+ %1 r)(inc %2))))x 0)) 1186060307891929990)
261

1

Boost.Build,304字节

并不是一种语言。仍然很酷。

import sequence ;
import regex ;
rule r ( n ) {
m = "([0-9]?)" ;
return [ sequence.join [ sequence.reverse [ regex.match "$(m)$(m)$(m)$(m)$(m)$(m)$(m)$(m)$(m)" : $(n) ] ] : "" ] ;
}
rule x ( n ) {
i = 0 ;
while $(n) != [ r $(n) ] {
n = [ CALC $(n) + [ r $(n) ] ] ;
i = [ CALC $(i) + 1 ] ;
}
echo $(i) ;
}

非常简单,除了我用来反转字符串的基于正则表达式的精心设计之外。


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.