平方根を元に戻す


16

あなたの仕事は、小数を整数の平方根の合計に戻すことです。結果には、少なくとも6桁の有効桁数の精度が必要です。

入力

平方根の数を示す数値と、近似する数値を示す小数。

入力例:

2 3.414213562373095

出力:スペースで区切られた整数。平方根で加算された場合、少なくとも6桁の有効な10進数まで正確な元の10進数になります。

ソリューションではゼロを使用できません。

複数のソリューションがある場合、1つだけを印刷する必要があります。

出力例(順不同):

4 2

これが機能するのは Math.sqrt(4) + Math.sqrt(2) == 3.414213562373095ます。

これはコードゴルフです。最短コード(オプションのボーナス付き)が勝ちます!

常に解決策がありますが、整数の解決策がないときにプログラムが「いいえ」を出力する場合は-10です。さらに、プログラムが1つではなくすべてのソリューション(改行またはセミコロンなどで区切られた)を印刷する場合は-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)の場合、これも有効なソリューションです
。811

また、ソリューションではゼロが許可されていますか?
寂部14年

1
入力は常にスペースで区切られていますか?
Sp3000 14年

また、関数呼び出しを介して入力を許可していますか?
ジャクベ14年

また、重複ソリューションについてはどうですか?最初の例では、コード6 7 8は2番目のボーナスの6つの順列すべてを出力できますか?
マーティンエンダー14年

回答:


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

(ヒント、特にforループをしばらく再構築してくれた@xnorに感謝します)

単純な再帰的な試み。ターゲット番号から開始し、0以下になるまで平方根を継続的に減算します。関数Sは次のように呼び出すことができますS(2,3.414213562373095)(2番目の引数は正と見なされます)。

このプログラムは、すべてのソリューションを印刷するだけでなく、ソリューションのすべての順列を印刷します(少し無関係なのは知っています)。最後のケースの出力は、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 <0および0.1 + xのポイントをヒットする必要があります 2 > 1のます。これは x <-0.948 ...で満たされます

ただし、正のxから開始し、xは常に減少していることに注意してください。したがって、x <-0.948 ...をヒットするには、x '-i 0.5 <-0.948 ...x'> -0.948 ...である必要があります。 。のxおよび正の整数I。whileループを実行するには、0.1 + x ' 2 > iが必要です。です。

再配置すると、x ' 2 + 1.897x' + 0.948 <i <0.1 + x ' 2が得られ、外側の部分はx' <-0.447を意味します。ただし、-0.948 <x '<-0.447の場合、正の整数iは上記の不等式のギャップに適合できません。

したがって、無限ループに陥ることは決してありません。


あなたは避けることができabsx*x<1e-12
xnor 14年

1
このwhileループは、関数パラメーターで初期化されたfor:を置き換えるために機能すると思います。アイデアは、s に変換する必要を避けることです。フロートの不正確さを処理することです。無限ループに対しては安全だと思います。while.1+x*x>i:S(x-i**.5,n+[i]);i+=1i=1int.1
xnor 14年

@xnor今のところ最初のヒントを実装しました。私はまだ2番目のものの正確さをチェックしていますが、それが良ければ、それは多くのバイトを節約します!(また、私は実際にあなたが解決策を投稿することが期待される:P)
SP3000

1
またN、関数の引数が追加されたため、で再帰するのではなく、N-1whenをチェックする方が短くなりました。N==0len(n)==N
xnor 14年

@ Sp3000私は今で.1は安全だと確信しています。必要に応じて、私はあなたと議論をすることができます。
XNOR

6

ECLiPSe Prolog-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)、失敗すると「No」を出力します(-10)。

Sp3000はコメントで適切に指摘しているように、成功すると「Yes」も出力します。それは確かに私がさらに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
また、成功すると「Yes」と表示されます!ああプロローグ。
Sp3000 14年

3

アーラン、 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:173 159-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月更新)最後のテストケースの現在の時間:約1 150秒。メモリ要件:ごくわずか。

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倍高速で、Firefoxの64ビットアルファバージョン(および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@@か?そして、パターンの最後の関数に変更SelectCasesf名前のない純粋な関数を作成することで、一部の文字を保存できる場合があります。
マーティンエンダー14年

2

Haskell、87 80-10 = 70

これは、@ Sp3000のPython 3プログラムに類似した再帰アルゴリズムです。これは、#すべてのソリューションのすべての順列のリストを返す中置関数で構成されています。

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のスコアでは、各ソリューションを1回だけ印刷し、ソートできます。

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 54 47-20 = 27

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

オンラインでお試しください。

xnorのコメントから恥知らずに借りています;)

これは、のような値であっても、正常なコンピューターのメモリーを使い果たします5,5.0。のgように呼び出すことができる関数を定義しますg 3 7.923668178593959

このpython 3プログラムは本質的に同じアルゴリズムを使用します(最後に「いいえ」の印刷は行いません。これは、すべての結果に変数を割り当ててから、 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 - 159 = 10

Edit1:出力形式を、コンマ区切りではなくスペース区切り整数に変更しました。(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
ズガルブ14年

私はなっているように見えるSyntaxError私がしようとしたときのeval...ラインを
SP3000

@ Sp3000:3,7.923668178593959と入力してみてください。'、'が必要です
ジャクベ14年

4つの少し改善:from itertools import*スペースを削除すると、1を節約z**.5for1を保存し、そして除去[]にはsum(z**.5for z in c)2を保存し、除去()にはif(...) 1を節約
Jakube

Python 2への変更と使用n,x=input()はよりコンパクトになりますか?
オクタヴィアトガミ14年

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}}

順列がない場合、このプログラムは何も出力しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.