撤消平方根


16

您的工作是将小数转换回整数的平方根之和。结果必须具有至少6个有效十进制数字的精度。

输入

一个数字表示平方根数,一个十进制表示近似数。

输入示例:

2 3.414213562373095

输出:整数分隔的空格,当平方根和加起来时,它们近似于原始十进制,至少精确到6个有效十进制数字。

解决方案中不允许零。

如果有多种解决方案,则只需打印一种。

输出示例(任意顺序):

4 2

这是因为Math.sqrt(4) + Math.sqrt(2) == 3.414213562373095

这是代码高尔夫。最短的代码(带有可选的奖金)获胜!

总会有一个解决方案,但是如果在没有整数的解决方案的情况下您的程序输出“ No”,则表示-10。此外,如果您的程序打印所有解决方案(用换行符,分号或其他分隔符),而不是仅打印一个,则为-10。

测试用例:

3 7.923668178593959 --> 6 7 8
2 2.8284271247461903 --> 2 2
5 5.0 --> 1 1 1 1 1
5 13.0 --> 4 4 9 9 9 --> 81 1 1 1 1 --> 36 9 4 1 1 etc. [print any, but print all for the "all solutions bonus"]

是的,您的程序必须在任何合理的机器上使用有限的内存在有限的时间内完成。它不能仅仅在理论上起作用,您必须能够对其进行实际测试。


如果有多个解决方案,我们打印哪种解决方案是否重要?例如,对于您的最后一个测试案例(5 13.0),这也是一个有效的解决方案:81 1 1 1 1
Jakube 2014年

解决方案中允许零吗?
雅库布2014年

1
输入是否始终以空格分隔?
Sp3000

并允许通过函数调用输入输入吗?
雅库布2014年

另外,重复的解决方案呢?对于第一个示例,是否允许我们的代码打印6 7 8第二个奖励的所有六个排列?
Martin Ender 2014年

Answers:


9

Python 3,90-10 = 80

def S(N,x,n=[],i=1):
 if x*x<1e-12>N==0:print(*n)
 while.1+x*x>i:S(N-1,x-i**.5,n+[i]);i+=1

(Mega感谢@xnor的技巧,特别是for循环的重组)

一个简单的递归尝试。它以目标编号开始,并连续减去平方根,直到达到0或更低。该函数S可以像这样调用S(2,3.414213562373095)(假定第二个参数为正)。

该程序不仅打印出所有解决方案,而且还打印出解决方案的所有排列(我知道有点多余)。这是最后一种情况的输出:Pastebin

稍作调整即可得出98-10 = 88的解决方案,该解决方案不会打印排列,从而使其效率更高:

def S(N,x,n=[]):
 *_,i=[1]+n
 if x*x<1e-12>N==0:print(*n)
 while.1+x*x>i:S(N-1,x-i**.5,n+[i]);i+=1

只是为了好玩,这个99-10 = 89的效率与它获得的效率差不多(不像其他的那样,它不会使堆栈堆积如山S(1,1000)

def S(N,x,n=[]):
 *_,i=[1]+n
 if x*x<1e-12>N:print(*n)
 while(.1+x*x>i)*N:S(N-1,x-i**.5,n+[i]);i+=1

请注意,尽管我们有一个可变的默认参数,但是由于我们n+[i]创建了一个新列表而重新运行该函数,因此这绝不会引起问题。


正确性证明

为了结束无限循环,我们必须达到x <00.1 + x 2的某个点 > 1的x <-0.948 ...可以满足要求。

但是请注意,我们从正数x开始,并且x总是递减,因此,要达到x <-0.948 ...,我们必须让x' -i 0.5 <-0.948 ...对于x'> -0.948。 。X和正整数。对于while循环运行,我们还必须有0.1 + X” 2 >我

重新排列,我们得到X ' 2 + 1.897x' + 0.948 <I <0.1 + X ' 2,外零件暗示X'<-0.447。但是,如果-0.948 <x'<-0.447,则没有正整数i可以拟合上述不等式中的缺口。

因此,我们永远不会陷入无限循环。


您可以abs使用来避免x*x<1e-12
xnor 2014年

1
我认为此while循环可以代替forwhile.1+x*x>i:S(x-i**.5,n+[i]);i+=1i=1在函数参数中进行初始化。这样做的目的是避免需要转换为ints。的.1是处理浮不准确; 我认为防止无限循环是安全的。
xnor 2014年

@xnor我现在已经实现了第一个技巧。我仍在检查第二个的正确性,但是如果很好,那就节省了很多字节!(我实际上还希望您发布解决方案:P)
Sp3000 2014年

1
并与N现在的功能参数,它是更短的递归下来N-1,并检查时N==0,而不是len(n)==N
xnor 2014年

@ Sp3000我现在确信它.1是安全的;如果您愿意,我可以和您聊天。
xnor 2014年

6

ECLiPSe前言-118(138-20)

我使用了以下Prolog实现:http : //eclipseclp.org/

:-lib(util).
t(0,S,[]):-!,S<0.00001,S> -0.00001.
t(N,S,[X|Y]):-A is integer(ceiling(S*S)),between(1,A,X),M is N-1,T is S-sqrt(X),t(M,T,Y).

这是一种非常幼稚的指数方法。列出所有可能的解决方案需要花费时间来覆盖所有组合(编辑:现在访问的整数的范围在每一步都会减小,从而消除了许多无用的组合)。

以下是测试会话的笔录。默认情况下,环境将尝试查找所有可能的解决方案(-10),并在失败时显示“否”(-10)。

正如Sp3000在注释中正确指出的那样,它在成功时也会打印“是”。那肯定意味着我可以再删除10点;-)

[eclipse 19]: t(1,0.5,R).

No (0.00s cpu)
[eclipse 20]: t(2,3.414213562373095,R).

R = [2, 4]
Yes (0.00s cpu, solution 1, maybe more) ? ;

R = [4, 2]
Yes (0.00s cpu, solution 2, maybe more) ? ;

No (0.01s cpu)
[eclipse 21]: t(3,7.923668178593959,R).

R = [6, 7, 8]
Yes (0.02s cpu, solution 1, maybe more) ? ;

R = [6, 8, 7]
Yes (0.02s cpu, solution 2, maybe more) ? ;

R = [7, 6, 8]
Yes (0.02s cpu, solution 3, maybe more) ? 
[eclipse 22]: t(5,5.0,R).

R = [1, 1, 1, 1, 1]
Yes (0.00s cpu, solution 1, maybe more) ? ;
^C

interruption: type a, b, c, e, or h for help : ? abort
Aborting execution ...
Abort
[eclipse 23]: t(5,13.0,R).

R = [1, 1, 1, 1, 81]
Yes (0.00s cpu, solution 1, maybe more) ? ;

R = [1, 1, 1, 4, 64]
Yes (0.00s cpu, solution 2, maybe more) ? ;

R = [1, 1, 1, 9, 49]
Yes (0.00s cpu, solution 3, maybe more) ?
[eclipse 24]:

(编辑)关于性能,至少与其他性能相比,它是相当不错的(例如,参见FryAmTheEggman的评论)。首先,如果要打印所有结果,请添加以下谓词:

    p(N,S):-t(N,S,L),write(L),fail.
    p(_,_).

有关(5,13.0)的情况,请参见http://pastebin.com/ugjfEHpw,该情况在0.24秒内完成并找到495个解决方案(但也许我缺少一些解决方案,我不知道)。


3
成功时还会打印“是”!哦,序言
Sp3000

3

Erlang, 305-10 302-10

f(M,D)->E=round(D*D),t(p(E,M,1),{M,E,D}).
p(_,0,A)->A;p(E,N,A)->p(E,N-1,A*E).
t(-1,_)->"No";t(I,{N,E,D}=T)->L=q(I,N,E,[]),V=lists:sum([math:sqrt(M)||M<-L])-D,if V*V<0.1e-9->lists:flatten([integer_to_list(J)++" "||J<-L]);true->t(I-1,T)end.
q(I,1,_,A)->[I+1|A];q(I,N,E,A)->q(I div E,N-1,E,[I rem E+1|A]).

此函数返回字符串“ No”或值以空格分隔的字符串。它(无效率地)处理每个可能的值,并将它们编码为一个大整数,并从更高的值开始。解决方案中不允许使用0,并且编码的0表示全1。误差平方。

例:

f(1,0.5).               % returns "No"
f(2,3.414213562373095). % returns "4 2 "
f(3,7.923668178593959). % returns "8 7 6 "
f(5,5.0).               % returns "1 1 1 1 1 "
f(5,13.0).              % returns "81 1 1 1 1 "

f(5,13.0)函数搜索空间为13 ^ 10,请耐心等待。通过增加2个字节可以使其更快。


3

Python 3 2: 173159-10 = 149

说明:每个解决方案的形式均为x_1 x_2 ... x_n,其中1 <= x_1 <= x ^ 2其中x是目标总和。因此,我们可以将每个解编码为基本x ^ 2中的整数。while循环迭代所有(x ^ 2)^ n个可能性。然后,我将整数转换回去并测试总和。非常简单。

i=input;n=int(i());x=float(i());m=int(x*x);a=m**n
while a:
 s=[a/m**b%m+1for b in range(n)];a-=1
 if abs(x-sum(b**.5for b in s))<1e-5:print' '.join(map(str,s))

它找到了所有解决方案,但是最后一个测试用例花费的时间太长。


3

JavaScript(ES6)162(172-10) 173

编辑短一点,慢一点。

作为具有2个参数的函数,输出到javascript控制台。这将打印所有解决方案而没有重复(解决方案元组已经生成排序)。
我更关心计时而不是字符数,因此可以在标准JavaScript时间限制内轻松地在浏览器控制台中对其进行测试。

(2016年2月更新)最后一个测试用例的当前时间:大约1150秒。内存要求:可以忽略不计。

F=(k,t,z=t- --k,r=[])=>{
  for(r[k]=z=z*z|0;r[k];)
  { 
    for(;k;)r[--k]=z;
    for(w=t,j=0;r[j];)w-=Math.sqrt(r[j++]);
    w*w<1e-12&&console.log(r.join(' '));
    for(--r[k];r[k]<1;)z=--r[++k];
  }
}

ES 5版本任何浏览器

function F(k,t)
{
  var z=t- --k,r=[];  
  for(r[k]=z=z*z|0;r[k];)
  {
    for(;k;)r[--k]=z;
    for(w=t,j=0;r[j];)w-=Math.sqrt(r[j++]);
    w*w<1e-12&&console.log(r.join(' '));
    for(--r[k];r[k]<1;)z=--r[++k];
  }
}

测试代码段,它应在任何最新的浏览器上运行

F=(k,t)=>
{
   z=t- --k,r=[];
   for(r[k]=z=z*z|0;r[k];)
   { 
      for(;k;)r[--k]=z;
      for(w=t,j=0;r[j];)w-=Math.sqrt(r[j++]);
      w*w<1e-12&&console.log(r.join(' '));
      for(--r[k];r[k]<1;)z=--r[++k];
   }
}

console.log=x=>O.textContent+=x+'\n'

t=~new Date
console.log('\n2, 3.414213562373095')
F(2, 3.414213562373095)
console.log('\n5, 5')
F(5, 5)
console.log('\n3, 7.923668178593959')
F(3, 7.923668178593959)
console.log('\n5, 13')
F(5, 13)

t-=~new Date
O.textContent = 'Total time (ms) '+t+ '\n'+O.textContent
<pre id=O></pre>

编辑)以下是我15个月前发布此答案时在PC上的结果。我今天尝试过,在同一台PC上,它的速度是100倍,仅使用64位alpha版本的Firefox(而Chrome则远远落后)!-使用Firefox 40 Alpha 64位的当前时间:〜2秒,Chrome 48:〜29秒

输出(在我的PC上-最后一个数字是运行时间,以毫秒为单位)

2 4
1 1 1 1 1
6 7 8
1 1 1 1 81
1 1 1 4 64
1 1 1 9 49
1 1 4 4 49
1 1 1 16 36
1 1 4 9 36
1 4 4 4 36
1 1 1 25 25
1 1 4 16 25
1 1 9 9 25
1 4 4 9 25
4 4 4 4 25
1 1 9 16 16
1 4 4 16 16
1 4 9 9 16
4 4 4 9 16
1 9 9 9 9
4 4 9 9 9
281889

2

Mathematica-76-20 = 56

f[n_,x_]:=Select[Union[Sort/@Range[x^2]~Tuples~{n}],Abs[Plus@@√#-x]<10^-12&]

例子

f[2, 3.414213562373095]
> {{2, 4}}
f[3, 7.923668178593959]
> {{6, 7, 8}}
f[3, 12]
> {{1, 1, 100}, {1, 4, 81}, {1, 9, 64}, {1, 16, 49}, {1, 25, 36}, {4, 4, 64}, {4, 9, 49}, {4, 16, 36}, {4, 25, 25}, {9, 9, 36}, {9, 16, 25}, {16, 16, 16}}

如何打印No?同样,输出不是空格分隔的。另外,您不能使用Tr@代替Plus@@吗?并且,您可以通过将末尾的函数更改SelectCases模式,并创建f一个未命名的纯函数来保存一些字符。
Martin Ender 2014年

2

哈斯克尔,87 = 70

这是一种递归算法,类似于@ Sp3000的Python 3程序。它由一个infix函数组成#返回所有解决方案的所有排列的列表。

0#n=[[]|n^2<0.1^12]
m#n=[k:v|k<-[1..round$n^2],v<-(m-1)#(n-fromInteger k**0.5)]

根据102 99 92-10 = 82的分数,我们只能打印一次每个解决方案,排序方式为:

0#n=[[]|n^2<0.1^12]
m#n=[k:v|k<-[1..round$n^2],v<-(m-1)#(n-fromInteger k**0.5),m<2||[k]<=v]

2

55 55 47-20 = 27

DgGHKf<^-Hsm^d.5T2^10_12^r1hh*HHGR?jbmjdkKK"No

在线尝试。

无耻地借用了XNOR的评论 ;)

即使是类似的值,这也会在任何正常的计算机上用尽内存5,5.0。定义函数,g可以像这样调用g 3 7.923668178593959

这个python 3程序使用基本上相同的算法(只是最后不执行“ No”打印,这可以通过将变量分配给所有结果,然后编写 print(K if K else "No")),但是使用了生成器,因此它不会t得到内存错误(仍然会花费极长时间,但是我在找到值时将其打印出来):

这给出了与@ Sp3000完全相同的结果。另外,这花了几天时间才能完成(我没有安排时间,但大约需要72个小时)。

from itertools import*
def g(G,H):
    for x in product(range(1,int(H*H+2)),repeat=G):
        if (H-sum(map(lambda n:n**.5,x)))**2<1e-12:print(*x)

1

Python的3 - 157 174 169 - 10 = 159

编辑1:将输出格式更改为以空格分隔的整数,而不是逗号分隔的整数。感谢您删除(n,x)周围花括号的提示。

Edit2:感谢您的高尔夫技巧!如果我只使用==测试而不是测试1e-6内的近似相等性,则可以删减另外9个字符,但是如果存在这样的近似解,那将无效。

使用itertools生成所有可能的整数组合,希望能有效地进行:)

我还没有找到一种有效地添加打印“否”的方法,它似乎总是需要多于10个额外的字符。

from itertools import*
n,x=eval(input())
for c in combinations_with_replacement(range(1,int(x*x)),n):
 if abs(sum(z**.5for z in c)-x)<1e-6:print(' '.join(map(str,c)))

您的程序的输出格式错误(用逗号代替空格)。另外,您可以通过删除括号将2个字节剃掉n,x
Zgarb 2014年

SyntaxError当我尝试eval
拨打电话

@ Sp3000:尝试输入3,7.923668178593959。您需要','
Jakube 2014年

4点小改进:from itertools import*保存1,在去除空间z**.5for节省1,并除去[]sum(z**.5for z in c)保存2和除去()if(...)保存1
Jakube

对Python 2的更改和使用n,x=input()会更紧凑吗?
Octavia Togami,2014年

0

Scala(397字节-10)

import java.util.Scanner
object Z extends App{type S=Map[Int,Int]
def a(m:S,i:Int)=m updated(i,1+m.getOrElse(i,0))
def f(n:Int,x:Double):Set[S]={if(n==0){if(x.abs<1e-6)Set(Map())else Set()}
else((1 to(x*x+1).toInt)flatMap{(i:Int)=>f(n-1,x-Math.sqrt(i))map{(m:S)=>a(m,i)}}).toSet}
val s=new Scanner(System.in)
f(s.nextInt,s.nextDouble)foreach{(m:S)=>m foreach{case(k,v)=>print(s"$k "*v)};println}}

如果没有排列,则此程序不打印任何内容。

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.