两个回文不足


24

一些数字(例如)是以10为底的回文数:如果以相反的顺序写数字,则会得到相同的数字。14241

一些数字是2个回文的总和。例如或。110=88+222380=939+1441

对于其他数字,仅两个回文是不够的。例如,不能将21写成2个回文的总和,而您能做的最好的就是。21=11+9+1个

编写一个函数或程序,该函数或程序采用整数输入n并输出n不能分解为2个回文之和的th数。这对应于OEIS A035137

一位数字(包括0)是回文。

序列的标准规则适用:

  • 输入/输出灵活
  • 您可以使用0或1索引
  • 您可以输出n第一n项或第一项,或无限序列

(作为旁注:所有整数都可以分解为最多三个回文的总和。)

测试用例(1索引):

1 -> 21
2 -> 32
10 -> 1031
16 -> 1061
40 -> 1103

这是代码高尔夫球,因此最短的答案为准。


2
无限输出不是序列的标准选项吗?
不相关的字符串

@UnrelatedString是的,我也允许。
罗宾·赖德


2
@Abigail给定正整数n,输出序列OEIS An的第n个成员?听起来很有希望...
瓦尔说莫妮卡

2
@Nit让我们将新的OEIS序列定义为a(n)=第n个OEIS序列,该序列可以用比生成该序列的功能最强的Jelly函数更少的字符表示。
agtoever

Answers:


13

JavaScript(ES6), 93 83 80  79字节

@tsh节省了1个字节

返回第 1索引的项。n

i=>eval("for(n=k=1;k=(a=[...k+[n-k]+k])+''!=a.reverse()?k-1||--i&&++n:++n;);n")

在线尝试!

怎么样?

给定,我们测试是否存在使得和均为回文。如果我们确实找到了一个,则是两个回文数之和。n1knknkkn

这里的技巧是通过测试由,和的串联构成的单个字符串来同时处理和。knķķñ-ķķ

例:

对于:ñ=2380

  • 我们最终达到和ķ=1441ñ-ķ=939
  • 我们测试字符串“ ”,发现它是回文14419391441

已评论

注意:这是一个版本,不eval()具有可读性。

i => {                       // i = index of requested term (1-based)
  for(                       // for loop:
    n = k = 1;               //   start with n = k = 1
    k =                      //   update k:
      ( a =                  //     split and save in a[] ...
        [...k + [n - k] + k] //     ... the concatenation of k, n-k and k
      ) + ''                 //     coerce it back to a string
      != a.reverse() ?       //     if it's different from a[] reversed:
        k - 1                //       decrement k; if the result is zero:
          || --i             //         decrement i; if the result is not zero:
            && ++n           //           increment n (and update k to n)
                             //         (otherwise, exit the for loop)
      :                      //     else:
        ++n;                 //       increment n (and update k to n)
  );                         // end of for
  return n                   // n is the requested term; return it
}                            //

i=>eval("for(n=k=1;k=(s=[...k+[n-k]+k])+''!=s.reverse()?k-1||i--&&++n:++n;);n")79个字节
tsh

代替i=>eval("...")ES6,您可以使用它i=>eval`...`,节省2个字节
VFDan

另外,如果未指定return,则eval缺省为最后一个计算的表达式,因此您可以;n在末尾删除。
VFDan

@VFDan反引号技巧不起作用,eval()因为它不会将其参数强制转换为字符串。删除;n将导致语法错误,删除仅n将导致函数返回undefined
Arnauld

12

果冻 16 10  9字节

-1个字节感谢Outgolfer的Erik。输出前ñ项。

2_ŒḂƇ⁺ṆƲ#

在线尝试!

与原始方法相比,我试图提出不同的想法。让我们回顾一下思考过程:

  • 最初,测试的工作方式如下:生成该数字的整数分区,然后过滤掉也包含非回文的分区,然后计算有多少个长度为2的合格列表。就代码长度而言,这显然不是太有效。

  • 生成ñ的整数分区然后进行过滤有两个主要缺点:长度和时间效率。为了解决该问题,我认为我首先想出一种方法,生成两个整数对(x,y,它们对总和为ñ(并非所有任意长度的列表),并且两个数字必须均为回文。

  • 但是,对于这种“经典方式”,我还是不满意。我转换了方法:让我们将程序重点放在单个回文上,而不是生成。这样,就可以简单地计算出N以下的所有回文数x,如果N - x也是回文数,那么我们就完成了。XñNX

代码说明

2_ŒḂƇ⁺ṆƲ#– Monadic链接或完整程序。争论:
2#–从2 *开始,找到满足以下条件的前n个整数:
 _ŒḂƇ⁺ṆƲ– ...助手链接。细目分类(调用当前整数N):
    Ƈ–过滤器。创建范围[1 ... N],仅保留那些...
  ŒḂ– ...是回文。例如:21-> [1,2,3,4,5,6,7,8,9,11]
 _ –从N中减去每个回文。示例:21-> [20,19,...,12,10]
     ⁺–复制上一个链接(考虑一下,好像还有一个
            而不是⁺)。这仅将回文保留在此列表中。
            如果列表非空,则意味着我们找到了一对(x,Nx)
            包含两个回文(并且显然x + Nx = N,所以它们总和为N)。
      Ṇ–逻辑非(我们正在寻找该列表为空的整数)。
       Ʋ–将最后4个链接分组(基本上使_ŒḂƇ⁺Ṇ充当单个monad)。

*就此而言,任何其他非零数字均可。


7

果冻,11字节

⁵ŻŒḂ€aṚ$EƲ#

在线尝试!

完整的程序大致如下所示:

  1. z设置为输入。
  2. x设置为10
  3. R设置为[]
  4. 对于从0x并包括x的每个整数k,检查kx-k是否均为回文。
  5. 如果L的所有元素都相等(即,与x求和的所有可能对都具有回文,或者所有此类对最多具有其一个元素为回文),则将z设置为z-1并附加xř
  6. 如果z = 0,则返回R并结束。
  7. x设置为x + 1
  8. 转到步骤4。

您可能会怀疑第5步实际上并没有完成应做的工作。如果所有加到x的对都是回文的,我们实际上就不应该减z。但是,我们可以证明这种情况永远不会发生:

ķ10ķX

ķķX-ķķ+X-ķ=X

ķķ-1个ķDFDLkDF=DL>0k1DFDLDL>0d大号=dF-1个dFķ-1个ķ-1个X-ķ-1个ķ-1个+X-ķ-1个=ķ-1个+X-ķ+1个=X

我们得出的结论是,如果我们从将x设置为大于或等于10的值开始,我们永远不可能使所有成对的x的非负整数对成为回文对。


啊,也击败了我-前n个术语节省了1个字节(我去了STDIN和ŻŒḂ€aṚ$Ṁ¬µ#
Jonathan Allan

@JonathanAllan哦,哈哈,没想到。无论如何,有人击败了我们俩。:D
暴民埃里克

10X-1010

11

3

视网膜135102字节

K`0
"$+"{0L$`\d+
*__
L$`
<$.'>$.`>
/<((.)*.?(?<-2>\2)*(?(2)$)>){2}/{0L$`\d+
*__
))L$`
<$.'>$.`>
0L`\d+

在线尝试!太慢了n10个或更多。说明:

K`0

首先尝试0。

"$+"{

重复n次数。

0L$`\d+
*__

将当前试用值转换为一元并递增。

L$`
<$.'>$.`>

创建所有求和为新的试用值的非负整数对。

/<((.)*.?(?<-2>\2)*(?(2)$)>){2}/{

重复至少存在一对包含两个回文整数的配对。

0L$`\d+
*__
))L$`
<$.'>$.`>

再次增加并扩展试用值。

0L`\d+

提取最终值。


3

Haskell,68 67 63字节

[n|n<-[1..],and[p a||p(n-a)|a<-[0..n]]]
p=((/=)=<<reverse).show

返回无限序列。

收集所有n情形之一a或者n-a是不是所有回文a <- [0..n]

在线尝试!


3

Perl 5中 -MList::Util=any -p59 55个字节

-3个字节,感谢@NahuelFouilleul

++$\while(any{$\-reverse($\-$_)==reverse}0..$\)||--$_}{

在线尝试!

注意:any可以用命令行开关代替grep并避免使用它-M,但是按照当前的评分规则,这将花费一个字节。


小改进,-3bytes,使用while代替重做
Nahuel Fouilleul

并且通过消除了+之后的问题进一步减少了while
Xcali

3

R115111字节

-4感谢Giuseppe

function(n,r=0:(n*1e3))r[!r%in%outer(p<-r[Map(Reduce,c(x<-paste0),Map(rev,strsplit(a<-x(r),"")))==a],p,'+')][n]

在线尝试!

大多数工作都打包在函数参数中,以删除{}多语句函数调用的,并减少定义对象所需的括号。r

基本策略是找到直到给定界限(包括0)的所有回文,找到所有成对的和,然后取不在该输出中的第n个数字。

的界限n*1000纯粹是根据有根据的猜测来选择的,因此,我鼓励任何人证明/证明它为有效的选择。

r=0:(n*1e3)可以通过更有效的边界进行改进。

Map(paste,Map(rev,strsplit(a,"")),collapse="")从Mark的回答中撕下,对我来说真是太聪明了。

r[!r%in%outer(p,p,'+')][n]对我来说有点低效。


1
仅需重新排列几行即可获得111个字节
朱塞佩


1

J,57/60字节

0(](>:^:(1&e.p e.]-p=:(#~(-:|.)&":&>)&i.&>:)^:_)&>:)^:[~]

在线尝试!

链接版本添加了3个字节,总共60个,以便另存为页脚可以调用的功能。

在REPL中,可以通过直接调用来避免这种情况:

   0(](>:^:(1 e.q e.]-q=:(#~(-:|.)&":&>)&i.&>:)^:_)&>:)^:[~] 1 2 10 16 40
21 32 1031 1061 1103

说明

一般结构是从这种技术的答案万里

(s(]f)^:[~]) n
          ]  Gets n
 s           The first value in the sequence
         ~   Commute the argument order, n is LHS and s is RHS
        [    Gets n
      ^:     Nest n times with an initial argument s
  (]f)         Compute f s
         Returns (f^n) s

与我最初的循环技术相比,这节省了几个字节,但是由于核心功能是我第一次编写J的尝试,因此仍有很多地方可以改进。

0(](>:^:(1&e.p e.]-p=:(#~(-:|.)&":&>)&i.&>:)^:_)&>:)^:[~]
0(]                                                 ^:[~] NB. Zero as the first term switches to one-indexing and saves a byte.
   (>:^:(1&e.p e.]-p=:(#~(-:|.)&":&>)&i.&>:)^:_)&>:)      NB. Monolithic step function.
                                                 >:       NB. Increment to skip current value.
   (>:^: <predicate>                        ^:_)          NB. Increment current value as long as predicate holds.
                   p=:(#~(-:|.)&":&>)&i.&>:               NB. Reused: get palindromes in range [0,current value].
                       #~(-:|.)&":&>                      NB. Coerce to strings keeping those that match their reverse.
                 ]-p                                      NB. Subtract all palindromes in range [0,current value] from current value.
    >:^:(1&e.p e.]-p                                      NB. Increment if at least one of these differences is itself a palindrome.

那是我的一种旧格式,结合我从那时开始学到的其他技巧,产生了41个字符的解决方案:1&(_:1&((e.((*&(-:|.)&":"0>:)&i.-))+])+)*
英里

1

05AB1E15 12 字节

°ÝDʒÂQ}ãOKIè

-3个字节,感谢@Grimy

0索引。
非常慢,因此对于大多数测试用例来说都是超时的。

在线尝试通过删除来验证前几种情况

以前的15发行版本快得多:

µNÐLʒÂQ}-ʒÂQ}g_

1个索引。

ñ

说明:

°Ý              # Create a list in the range [0, 10**input]
  D             # Duplicate this list
   ʒÂQ}         # Filter it to only keep palindromes
       ã        # Take the cartesian product with itself to create all possible pairs
        O       # Sum each pair
         K      # Remove all of these sums from the list we duplicated
          Iè    # Index the input-integer into it
                # (after which the result is output implicitly)

µ               # Loop until the counter variable is equal to the (implicit) input-integer
 NÐ             #  Push the loop-index three times
   L            #  Create a list in the range [1, N] with the last copy
    ʒÂQ}        #  Filter it to only keep palindromes
        -       #  Subtract each from N
         ʒÂQ}   #  Filter it again by palindromes
             g_ #  Check if the list is empty
                #   (and if it's truthy: increase the counter variable by 1 implicitly)
                # (after the loop: output the loop-index we triplicated implicitly as result)

1
12 :(°LDʒÂQ}ãOKIè速度上限可能比10 ^ x更好)我猜∞DʒÂQ}ãOK技术上讲是9,但是在第一个输出之前超时。
Grimmy

@Grimy不确定笛卡尔积是否可以延迟加载到无限列表中。无论如何,至于12轮,这是不正确的。它确实滤除可以通过对2个回文求和求和而形成的整数,但不能滤除作为回文本身的整数。您的序列(不带尾随)如下:[1,21,32,43,54,65,76,87,98,111,131,141,151,...]但应该这样[*,21,32,43,54,65,76,87,98,201,1031,1041,1051,1052,...](第一个1/ *可以忽略,因为我们使用1索引输入)。
凯文·克鲁伊森

1
@Grimy Hmm,我想一个简单的解决方法就是将基于1的列表更改为基于L0的列表.. :)
Kevin Cruijssen


0

Python 3,107个字节

p=lambda n:str(n)!=str(n)[::-1]
def f(n):
 m=1
 while n:m+=1;n-=all(p(k)+p(m-k)for k in range(m))
 return m

在线尝试!

反转回文检查保存2个字节:)

作为参考,直接进行正校验(109字节):

p=lambda n:str(n)==str(n)[::-1]
def f(n):
 m=1
 while n:m+=1;n-=1-any(p(k)*p(m-k)for k in range(m))
 return m

0

APL(NARS),486字节

r←f w;p;i;c;P;m;j
p←{k≡⌽k←⍕⍵}⋄i←c←0⋄P←r←⍬
:while c<w
    i+←1
    :if   p i⋄P←P,i⋄:continue⋄:endif
    m←≢P⋄j←1
    :while j≤m
         :if 1=p i-j⊃P⋄:leave⋄:endif
         j+←1
    :endwhile
    :if j=m+1⋄c+←1⋄r←i⋄:endif
:endwhile

打破循环是什么意思?好像是“:leave”,对吗? {k≡⌽k←⍕⍵}在p中是回文检验。循环中的上述函数存储了在集合P中找到的所有回文,如果对于P中的某些元素w也是如此,则iw也位于P中,这意味着i不正确,并且我们有i增量。结果:

  f 1
21
  f 2
32
  f 10
1031
  f 16
1061
  f 40
1103
  f 1000
4966
  f 1500
7536
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.