将n的幂相加


14

方向

编写一个程序,给定输入整数nn >= 0),输出最小的正整数 m,其中:

  • n = a[1]^b[1] + a[2]^b[2] + a[3]^b[3] + ... + a[k]^b[k]
  • a并且b是相同长度的有限序列
  • 的所有元素a均小于m
  • 的所有元素b均小于m
  • 的所有元素a不同且为整数a[x] >= 0
  • 的所有元素b不同且为整数b[x] >= 0
  • a[x]并且b[x]都不都是0(因为0 ^ 0是不确定的)

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

例子

In 0 -> Out 1
Possible Sum: 

In 1 -> Out 2
Possible Sum: 1^0

In 2 -> Out 3
Possible Sum: 2^1

In 3 -> Out 3
Possible Sum: 2^1 + 1^0

In 6 -> Out 4
Possible Sum: 2^2 + 3^0 + 1^1

In 16 -> Out 5
Possible Sum: 2^4

In 17 -> Out 4
Possible Sum: 3^2 + 2^3

In 23 -> Out 6
Possible Sum: 5^1 + 3^0 + 2^4 + 1^3

In 24 -> Out 5
Possible Sum: 4^2 + 2^3

In 27 -> Out 4
Possible Sum: 3^3

In 330 -> Out 7
Possible Sum: 6^1 + 4^3 + 3^5 + 2^4 + 1^0

我们应该如何制作一个具有非无限和的唯一,非负整数序列?
feersum

另外,第一种情况没有意义,因为零项之和就足够了。
feersum

@feersum我不太明白您的问题。我的这个解决方案是一个强力搜索所有的组合m<2,然后m<3m<4等,直到我发现等于总和n。另外,我考虑过让总和为0无条件,但是输出是什么?m>?
kukac67

1
对于有限序列,通常会执行n = a[1]^b[1] + a[2]^b[2] + ... + a[k]^b[k]
波动率

1
好问题。在第一个测试用例上只有一个小问题:ab是length的有限序列0,因此m没有不满足约束的整数,并且由于没有最小整数,因此未定义答案。可能的解决方法是要求提供最小的自然数m(在这种情况下,应将期望的答案更改为该数字0)或最小的正整数m
彼得·泰勒

Answers:


2

GolfScript(59个字符)

~:T),{),.0{2$0-{2${{4$2$^}2*@3$\?4$+f~}%\;~}%+\;\;}:f~T&}?)

在线演示

这使用递归来枚举给定值可实现的值,m并搜索第一个m有效的值。它的灵感来自xnor的答案,但实现方式却大不相同。

解剖

~:T                  # Evaluate input and store in T (for Target)
),{                  # Search [0 1 ... T] for the first m which matches a predicate
  ),.0               #   Push [0 ... m] to the stack twice and then 0
                     #   Stack holds: possibleAs possibleBs sum
  {                  #   Define the recursive function f
    2$0-{            #     Map over A in possibleAs (except 0)
      2${            #       Map over B in possibleBs (except 0)
        {4$2$^}2*    #         Duplicate respective possibles and remove selected values
        @3$\?4$+     #         Compute sum' = sum + A^B
        f            #         Recursive call gives an array [sums]
        ~            #         Push the sums to the stack individually
        }%           #       End map: this collects the sums into a combined array
      \;             #       Pop A, leaving just the combined [sums] inside the map
      ~              #       Repeat the trick: push to the stack individually
    }%               #     End map, collecting into a combined array
                     #     Stack now holds: possibleAs possibleBs sum [sums]
    +                #     Include the original sum in the array of reachable sums
    \;\;             #     Pop possibleAs and possibleBs
  }:f                #   End function definition
  ~                  #   Evaluate the function
  T&                 #   Test whether the sums contain T
}?                   # End search
)                    # Increment to get m

6

Python,120

f=lambda n,A,B:n*all(f(n-a**b,A-{a},B-{b})for a in A for b in B)
g=lambda n,m=1,M={0}:f(n,M-{0},M)and g(n,m+1,M|{m})or m

该功能f是一种辅助功能,它检查是否n可以被表达为与来自不同基地功率的总和A,并从指数B。它使用自然的递归策略:n必须为非零值,并且我们尝试了base和exponent的所有可能选择,它们都需要失败。我们从允许的列表中删除它们,并减少n相应的数量。

该功能g是主要功能。它搜索m有效的。M是最多允许的一组值m-1。我们0从允许的指数中删除以停止使用0**0(Python计算为1)。这不会伤害任何人,因为对其他所有人都是0**x无用0x


您可能会更改n and all()n*all()
grc 2015年

@grc啊,实际上您不需要短路,因为它触底。感谢您的改进。
xnor 2015年

4

Python 2,138字节

from itertools import*
S=lambda n,m=0,R=[]:m*any(n==sum(map(pow,*C))for k in R for C in product(*tee(permutations(R,k))))or S(n,m+1,R+[m])

(感谢@Jakube的所有提示)

我从未itertools从这个问题中学到太多关于模块的知识。最后一种情况大约需要一分钟。

我们从搜索开始m = 1并递增,直到找到一个解决方案。要检查解决方案,我们迭代:

  • k = 0 to m-1k解决方案中的术语数在哪里
  • 术语的所有可能组合(通过将[0, 1, ... m-1]大小为的子集的两个排列压缩在一起k),然后求和并检查是否有n

注意我们迭代 k最多进行m-1 -尽管从技术上m来说术语是可能的,但总有一种解决方案带有不允许的m-1术语,0^0并且0^b毫无用处。这实际上很重要,因为0^0Python将其视为1,这似乎是一个问题,但事实并不重要!

这就是为什么。

假设错误找到的解决方案使用 0^0用作1,例如3^2 + 1^1 + 0^0 = 11。由于我们仅生成m-1术语,因此一定有一些j我们没有将其用作基础(此处j = 2)。我们可以j在此处将基数0换为有效的解决方案3^2 + 1^1 + 2^0 = 11

如果我们重复了所有的m条款,那么我们可能已经变得不正确解决方案,如m = 2用于n = 2,via 0^0 + 1^1 = 2


好一个。您可以使用imap节省4个字节。 imap(pow,C,D) ... for C,D in
雅库布2015年

@Jakube实际上,我在找文档时正在寻找itertools:PI已经有了另一个节省— tee
Sp3000

我也是。还有,我的错误。为什么会有人建议imap,当有map?-1个字节
Jakube 2015年

的默认参数tee已经是n=2。节省2个字节。
雅库布2015年

@Jakube Ahaha谢谢。这可能是我第一次使用map多次迭代,而实际上,这个问题为我带来了很多先机。
Sp3000

4

GolfScript(90 84字节)

[0.,.]](~:T),(+{:x;{:|2,{:c)|=x),^{c[1$x]=:A^x^:-;[|~-+@A-?+@A+@]}%}/+~}%.[]*T&}?)\;

在线演示

解剖

[0.,.]             # Base case: [sum As Bs] is [0 [] []]
](~:T              # Collect it in an array of cases; fetch parameter, eval, store in T.
),(+               # Create array [1 2 ... T 0]. Putting 0 at the end means that it won't
                   # be reached except when T is 0, and nicely handles that special case.
{                  # Loop over the values from that array...
  :x;              #   ...assigning each in turn to x (and popping it from the stack)
  {                #   Stack holds array of [sum As Bs] cases; map them...

    :|             #     Store [sum As Bs] in |
    2,{:c          #     For c in [0 1]...
      )|=x),^      #       Get [0 1 ... x]^ either As or Bs, depending on c
      {            #       Map these legal new As or Bs respectively...
        c[1$x]=:A  #         Work out which of that value or x is the new A
        ^x^:-;     #         And the other one is the new B
        [          #         Begin gathering in an array
          |~       #           Push sum As Bs to the stack
          -+       #           Add - to Bs to get Bs'
          @A-?+    #           Rotate sum to top and add A^- to get sum'
          @A+      #           Rotate As to top and add A to get As'
          @        #           Final rotation to put elements in the right order
        ]          #         Gather in array [sum' As' Bs']
      }%           #       End map
    }/             #     End for
    +~             #     Push all the elements corresponding to x^B and A^x on to the stack
  }%               #   End map, collecting the untouched [sum As Bs] and all the new
                   #   [sum' As' Bs'] arrays into a new array of reached cases.
  .[]*T&           #   Flatten a copy of that array and filter to values equal to T.
                   #   This gives a truthy value iff we've found a way to make T.
}?                 # Loop until we get a truthy value, and push the corresponding x
)\;                # Increment to get the value of m and discard the array of cases

最优雅的技巧是处理的特殊情况0


我真的很高兴CJam这次没有比标准的python = P短太多了
瑕疵的

@flawr,这是GolfScript,而不是CJam。CJam可能会短很多,因为它具有笛卡尔积木的内置功能。可能是xnor的递归函数概念也使GolfScript变得更短。
彼得·泰勒

哦,对不起,只是让他们感到困惑=)
瑕疵的

4

哈斯克尔,143 130

import Data.List
p n=head$[1..]>>=(\m->[m|let x=permutations[0..m-1]>>=inits,a<-x,b<-x,sum(zipWith(\x y->x^y*signum(x+y))a b)==n])

用法示例:p 23-> 6

这是一个简单的蛮力搜索。对于每个列表[0..0], [0..1], [0..2] ... [0..∞],请使用排列的所有初始片段(例如[0..2]:permutations:,[012], [102], [210], [120], [201], [021]用于第一个排列的初始片段:[0], [01], [012],第二个:[1], [10], [102]等)。对于这些列表中的2个列表的每个组合,计算出幂的总和。当第一个等于n时停止。


您应该使用>>=而不是concatMap。它们是相同的,但参数已翻转。
2015年

@proudhaskeller:是的,谢谢!
nimi

2

Python:166个字符

from itertools import*;p=permutations
f=lambda n,r=[0]:any(n==sum(map(lambda x,y:(x+y>0)*x**y,a,b))for j in r for a,b in product(p(r,j),p(r,j)))*1or 1+f(n,r+[len(r)])

说明

该函数f创建所有可能的整数,这些整数可以表示为中的数字幂的和r。如果以开头r = [0]。如果这些整数中的任何一个等于n,它返回的长度r,否则以扩展形式递归调用自己r

可以表示为和的所有整数的计算是通过两个循环完成的。第一个循环是for j in r,它告诉我们表达式的长度(2 ^ 3 + 1 ^ 2的长度为2)。内部循环r对length的所有排列组合进行迭代j。我为每一个计算幂和。


2

的JavaScript(ES6)219 224

递归函数。从m = 1开始,我尝试使用整数1..m的所有底数和0..m的指数的所有组合(给定0 ^ 0 == undefined,0底数是无用的)。
如果找不到解决方案,请增加m并重试。
输入0的特殊情况(我认为这仍然是规范中的错误)

C函数递归地从给定长度的数组中生成所有组合,因此

C(3, [1,2,3]) --> [[3,2,1], [3,1,2], [2,3,1], [2,1,3], [1,3,2], [1,2,3]]

第三级every用于将基数的数组a和指数的b压缩在一起(zipJavaScript中没有函数)。every当有解决方案不使用两个数组中的所有元素时,使用早停。

F=(n,j=1,k=[],
  C=(l,a,o=[],P=(l,a,i=l)=>{
    for(l||o.push(a);i--;)
      e=[...a],P(l-1,e.concat(e.splice(i,1)))
  })=>P(l,a)||o
)=>n&&C(k.push(j++),k)[E='every'](a=>C(j,[0,...k])[E](b=>a[E](x=>t-=Math.pow(x,b.pop()),t=n)))
?F(n,j,k):j

在FireFox / FireBug控制台中测试

;[0,1,2,3,6,16,17,23,24,27,330].map(x=>[x,F(x)])

输出量

[[0,1],[1,2],[2,3],[3,3],[6,4],[16,5],[17,4],[23,6],[ 24,5],[27,4],[330,7]]

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.