Hoàn tác các căn bậc hai


16

Công việc của bạn là chuyển đổi số thập phân trở lại thành tổng căn bậc hai của số nguyên. Kết quả phải có độ chính xác của ít nhất 6 chữ số thập phân có ý nghĩa.

Đầu vào :

Một số chỉ số căn bậc hai và số thập phân chỉ số gần đúng.

Ví dụ đầu vào:

2 3.414213562373095

Đầu ra : Các số nguyên được phân tách bằng khoảng trắng, khi căn bậc hai và được thêm vào, xấp xỉ số thập phân ban đầu chính xác đến ít nhất 6 chữ số thập phân có nghĩa.

Số không được phép trong giải pháp.

Nếu có nhiều giải pháp, bạn chỉ phải in một.

Ví dụ đầu ra (theo thứ tự bất kỳ):

4 2

Điều này hoạt động bởi vì Math.sqrt(4) + Math.sqrt(2) == 3.414213562373095.

Đây là mã golf. Mã ngắn nhất (có thưởng tùy chọn) sẽ thắng!

Luôn luôn có một giải pháp nhưng -10 nếu chương trình của bạn in "Không" khi không có giải pháp nào có số nguyên. Ngoài ra, -10 nếu chương trình của bạn in tất cả các giải pháp (được phân tách bằng dòng mới hoặc dấu chấm phẩy hoặc bất cứ thứ gì) thay vì chỉ một.

Các trường hợp thử nghiệm:

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"]

Và có, chương trình của bạn phải hoàn thành trong thời gian hữu hạn bằng cách sử dụng bộ nhớ hữu hạn trên bất kỳ máy hợp lý nào. Nó không thể hoạt động "trên lý thuyết", bạn phải có khả năng thực sự kiểm tra nó.


Nếu có nhiều giải pháp, chúng tôi có in giải pháp nào không? Ví dụ: trường hợp thử nghiệm cuối cùng của bạn (5 13.0), đây cũng là một giải pháp hợp lệ: 81 1 1 1 1
Jakube

Và số không được phép trong giải pháp?
Jakube

1
Là đầu vào luôn luôn cách nhau không gian?
Sp3000

Và được nhập đầu vào thông qua chức năng gọi cho phép?
Jakube

Ngoài ra, những gì về giải pháp trùng lặp? Ví dụ đầu tiên, mã của chúng tôi có được phép in tất cả sáu hoán vị 6 7 8cho phần thưởng thứ hai không?
Martin Ender

Câu trả lời:


9

Trăn 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 cảm ơn @xnor về các mẹo, đặc biệt là việc tái cấu trúc vòng lặp for thành một thời gian)

Một nỗ lực đệ quy đơn giản. Nó bắt đầu với số mục tiêu và liên tục trừ căn bậc hai cho đến khi nó chạm 0 hoặc thấp hơn. Hàm Scó thể được gọi như thế S(2,3.414213562373095)(đối số thứ hai được coi là dương).

Chương trình không chỉ in ra tất cả các giải pháp, nó in ra tất cả các hoán vị của các giải pháp (một chút không liên quan, tôi biết). Đây là đầu ra cho trường hợp cuối cùng: Pastebin .

Một tinh chỉnh nhỏ mang lại giải pháp 98 - 10 = 88 mà không in hoán vị, làm cho nó hiệu quả hơn:

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

Và chỉ để giải trí, 99 - 10 = 89 này có hiệu quả tương đương (không giống như những cái khác, nó không thổi vào ngăn xếp 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

Lưu ý rằng, mặc dù chúng ta có một đối số mặc định có thể thay đổi, nhưng điều này không bao giờ gây ra vấn đề nếu chúng ta chạy lại hàm kể từ khi n+[i]tạo một danh sách mới.


Bằng chứng chính xác

Để kết thúc trong một vòng lặp vô hạn, chúng ta phải đạt một số điểm trong đó x <00,1 + x 2 > 1 . Đây được thỏa mãn bởi x <-0,948 ... .

Nhưng lưu ý rằng chúng tôi bắt đầu từ dương xx luôn giảm, vì vậy để đạt x <-0.948 ... chúng tôi phải có x '- i 0,5 <-0.948 ... đối với một số x'> -0.948 .. . trước x và số nguyên dương i . Để vòng lặp while chạy, chúng ta cũng phải có 0,1 + x ' 2 > i .

Sắp xếp lại chúng ta nhận được x ' 2 + 1.897x' + 0.948 <i <0.1 + x ' 2 , các phần bên ngoài ngụ ý rằng x' <-0.447 . Nhưng nếu -0.948 <x '<-0.447 , thì không có số nguyên dương nào tôi có thể phù hợp với khoảng cách trong bất đẳng thức trên.

Do đó, chúng tôi sẽ không bao giờ kết thúc trong một vòng lặp vô hạn.


Bạn có thể tránh absvới x*x<1e-12.
xnor

1
Tôi nghĩ rằng whilevòng lặp này hoạt động để thay thế for: while.1+x*x>i:S(x-i**.5,n+[i]);i+=1, đã khởi tạo i=1trong các tham số chức năng. Ý tưởng là để tránh cần phải chuyển đổi sang ints. Là .1để xử lý không chính xác nổi; Tôi nghĩ rằng nó an toàn chống lại các vòng lặp vô hạn.
xnor

@xnor Tôi đã thực hiện mẹo đầu tiên bây giờ. Tôi vẫn đang kiểm tra tính chính xác của cái thứ hai, nhưng nếu nó tốt thì đó là rất nhiều byte được lưu! (Ngoài ra tôi thực sự mong đợi bạn đăng một giải pháp: P)
Sp3000

1
Nbây giờ với một đối số chức năng, nó ngắn hơn để lặp lại N-1và kiểm tra khi nào N==0hơn là len(n)==N.
xnor

@ Sp3000 Tôi tin chắc rằng .1nó an toàn; Tôi có thể trò chuyện với bạn một cuộc tranh luận nếu bạn muốn.
xnor

6

Prolog ECLiPSe - 118 (138-20)

Tôi đã sử dụng triển khai Prolog sau đây: 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).

Đây là một cách tiếp cận rất ngây thơ, theo cấp số nhân. Liệt kê tất cả các giải pháp có thể cần có thời gian để bao gồm tất cả các kết hợp ( chỉnh sửa : phạm vi số nguyên truy cập hiện giảm dần ở mỗi bước, loại bỏ rất nhiều kết hợp vô dụng).

Dưới đây là bảng điểm của một phiên kiểm tra. Theo mặc định, môi trường sẽ cố gắng tìm tất cả các giải pháp có thể (-10) và in "Không" khi không thực hiện được (-10).

Như Sp3000 đã lưu ý chính xác trong bình luận, nó cũng in "Có" khi thành công. Điều đó chắc chắn có nghĩa là tôi có thể loại bỏ thêm 10 điểm nữa ;-)

[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]:

(Chỉnh sửa) Về hiệu suất, nó khá tốt, ít nhất là so với các hiệu suất khác (xem ví dụ nhận xét này từ FryAmTheEggman ). Đầu tiên, nếu bạn muốn in tất cả các kết quả, hãy thêm biến vị ngữ sau:

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

Xem http://pastebin.com/ugjfEHpw để biết trường hợp (5,13.0), hoàn thành trong 0,24 giây và tìm 495 giải pháp (nhưng có lẽ tôi đang thiếu một số giải pháp, tôi không biết).


3
Nó cũng in chữ "Có" khi thành công! Ôi Prolog.
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]).

Hàm này trả về chuỗi "Không" hoặc một chuỗi có các giá trị được phân tách bằng dấu cách. Nó (không hiệu quả) xử lý mọi giá trị có thể mã hóa chúng thành một số nguyên lớn và bắt đầu với các giá trị cao hơn. 0 không được phép trong giải pháp và được mã hóa 0 đại diện cho tất cả các giải pháp. Lỗi là bình phương.

Thí dụ:

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 "

Hãy kiên nhẫn với f(5,13.0)không gian tìm kiếm chức năng là 13 ^ 10. Nó có thể được thực hiện nhanh hơn với 2 byte bổ sung.


3

Con trăn 3 2: 173 159 - 10 = 149

Giải thích: Mỗi giải pháp có dạng x_1 x_2 ... x_n với 1 <= x_1 <= x ^ 2 trong đó x là tổng mục tiêu. Do đó, chúng ta có thể mã hóa từng giải pháp dưới dạng một số nguyên trong cơ sở x ^ 2. Vòng lặp while lặp lại trên tất cả (x ^ 2) ^ n khả năng. Sau đó, tôi chuyển đổi số nguyên trở lại và kiểm tra tổng. Khá thẳng về phía trước.

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

Nó tìm thấy tất cả các giải pháp, nhưng trường hợp thử nghiệm cuối cùng mất quá nhiều thời gian.


3

JavaScript (ES6) 162 (172 - 10) 173

Chỉnh sửa ngắn hơn một chút, chậm hơn một chút.

Là một hàm có 2 tham số, xuất ra giao diện điều khiển javascript. Điều này in tất cả các giải pháp không có sự lặp lại (các bộ giải pháp được tạo đã được sắp xếp).
Tôi quan tâm nhiều hơn về thời gian hơn là về số char, để nó dễ dàng được kiểm tra trong bảng điều khiển trình duyệt trong giới hạn thời gian javascript tiêu chuẩn.

(Cập nhật tháng 2 năm 2016) Thời gian hiện tại cho trường hợp thử nghiệm cuối cùng: khoảng 1 150 giây . Yêu cầu bộ nhớ: không đáng 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];
  }
}

Phiên bản ES 5 Bất kỳ trình duyệt nào

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

Kiểm tra Snippet nó sẽ chạy trên bất kỳ trình duyệt gần đây

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>

( Chỉnh sửa ) Dưới đây là kết quả trên PC của tôi khi tôi đăng câu trả lời này 15 tháng trước. Tôi đã thử ngày hôm nay và nó nhanh hơn 100 lần trên cùng một PC, chỉ với phiên bản Firefox 64 bit (và Chrome bị tụt lại phía sau)! - thời gian hiện tại với Firefox 40 Alpha 64 bit: ~ 2 giây, Chrome 48: ~ 29 giây

Đầu ra (trên PC của tôi - số cuối cùng là thời gian chạy tính bằng mili giây)

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

Toán học - 76 - 20 = 56

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

Ví dụ

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

Làm thế nào để in này No? Ngoài ra, đầu ra không được phân tách không gian. Ngoài ra, bạn không thể sử dụng Tr@thay vì Plus@@? Và bạn có thể lưu một số ký tự bằng cách thay đổi Selectthành Cases, hàm ở cuối thành một mẫu và tạo fmột hàm thuần không tên.
Martin Ender

2

Haskell, 87 80 - 10 = 70

Đây là một thuật toán đệ quy tương tự như chương trình Python 3 của @ Sp3000. Nó bao gồm một hàm infix #trả về một danh sách tất cả các hoán vị của tất cả các giải pháp.

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

Với số điểm 102 99 92 - 10 = 82, chúng tôi chỉ có thể in mỗi giải pháp một lần, được sắp xếp:

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

Bình 55 55 47-20 = 27

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

Hãy thử trực tuyến.

Không biết xấu hổ mượn từ bình luận của xnor ;)

Điều này sẽ hết bộ nhớ trên bất kỳ máy tính lành mạnh nào ngay cả đối với một giá trị như 5,5.0. Xác định một hàm, gcó thể được gọi là nhưg 3 7.923668178593959 .

Chương trình python 3 này về cơ bản sử dụng cùng một thuật toán (chỉ không thực hiện in "Không" ở cuối, có thể được thực hiện bằng cách gán một biến cho tất cả các kết quả, sau đó viết print(K if K else "No") ), nhưng sử dụng một trình tạo, vì vậy nó không ' Tôi gặp lỗi bộ nhớ (sẽ vẫn mất rất nhiều thời gian, nhưng tôi đã in nó khi tìm thấy các giá trị):

Điều này đã cho kết quả chính xác giống như @ Sp3000. Ngoài ra, việc này mất vài ngày để hoàn thành (tôi không mất thời gian, nhưng khoảng 72 giờ).

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

Con trăn 3 - 157 174 169 - 10 = 159

Chỉnh sửa1: Thay đổi định dạng đầu ra thành các số nguyên được phân tách bằng dấu cách thay vì được phân tách bằng dấu phẩy. Cảm ơn về mẹo loại bỏ các dấu ngoặc xung quanh (n, x).

Edit2: Cảm ơn các mẹo chơi golf! Tôi có thể cắt bớt 9 ký tự khác nếu tôi chỉ sử dụng phép thử == thay vì kiểm tra tính công bằng gần đúng trong vòng 1e-6, nhưng điều đó sẽ làm mất hiệu lực các giải pháp gần đúng, nếu có tồn tại.

Sử dụng itertools để tạo tất cả các kết hợp số nguyên có thể, hy vọng có hiệu quả :)

Tôi chưa tìm được cách thêm chữ "Không" một cách hiệu quả, dường như luôn phải mất hơn 10 ký tự phụ.

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

Chương trình của bạn có định dạng đầu ra sai (dấu phẩy thay vì dấu cách). Ngoài ra, bạn có thể cạo 2 byte bằng cách loại bỏ các dấu ngoặc xung quanh n,x.
Zgarb

Tôi dường như nhận được SyntaxErrors khi tôi thử evaldòng ...
Sp3000

@ Sp3000: thử nhập 3.7.923668178593959. Bạn cần ','
Jakube

4 cải tiến nhỏ: from itertools import*tiết kiệm 1, loại bỏ không gian z**.5fortiết kiệm 1, và loại bỏ []trong sum(z**.5for z in c)tiết kiệm 2 và loại bỏ ()trong if(...)tiết kiệm 1.
Jakube

Thay đổi thành Python 2 và sử dụng n,x=input()có gọn hơn không?
Octavia Togami

0

Scala (397 byte - 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}}

Nếu không có hoán vị, thì chương trình này không in gì cả.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.