Batalkan akar kuadrat

16

Tugas Anda adalah mengubah desimal kembali menjadi jumlah akar kuadrat dari bilangan bulat. Hasilnya harus memiliki akurasi setidaknya 6 digit desimal yang signifikan.

Masukan :

Angka yang menunjukkan jumlah akar kuadrat dan desimal yang menunjukkan angka untuk perkiraan.

Contoh input:

2 3.414213562373095

Keluaran : Bilangan bulat dipisahkan oleh spasi yang, ketika kuadrat dan ditambahkan, kira-kira desimal asli akurat hingga setidaknya 6 angka desimal yang signifikan.

Nol tidak diizinkan dalam solusi.

Jika ada beberapa solusi, Anda hanya perlu mencetak satu.

Contoh output (dalam urutan apa pun):

4 2

Ini berhasil karena Math.sqrt(4) + Math.sqrt(2) == 3.414213562373095.

Ini kode golf. Kode terpendek (dengan bonus opsional) menang!

Akan selalu ada solusi tetapi -10 jika program Anda mencetak "Tidak" ketika tidak ada solusi dengan bilangan bulat. Selain itu, -10 jika program Anda mencetak semua solusi (dipisahkan oleh baris baru atau titik koma atau apa pun) alih-alih hanya satu.

Kasus uji:

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

Dan ya, program Anda harus selesai dalam waktu yang terbatas menggunakan memori yang terbatas pada mesin yang masuk akal. Itu tidak bisa hanya berfungsi "secara teori," Anda harus dapat benar-benar mengujinya.

soktinpk
sumber
Jika ada beberapa solusi, apakah penting solusi mana yang kita cetak? Misalnya untuk test case terakhir Anda (5 13.0), ini juga merupakan solusi yang valid: 81 1 1 1 1
Jakube
Dan apakah nol diperbolehkan dalam solusi?
Jakube
1
Apakah input selalu dipisahkan dengan ruang?
Sp3000
Dan apakah memasukkan input melalui pemanggilan fungsi diizinkan?
Jakube
Juga, bagaimana dengan solusi duplikat? Sebagai contoh pertama, apakah kode kami diizinkan untuk mencetak keenam permutasi 6 7 8untuk bonus kedua?
Martin Ender

Jawaban:

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 terima kasih kepada @xnor untuk kiat, terutama restrukturisasi for for loop sementara)

Upaya rekursif sederhana. Dimulai dengan angka target dan terus mengurangi akar kuadrat hingga mencapai 0 atau lebih rendah. Fungsi Sdapat disebut seperti S(2,3.414213562373095)(argumen kedua diasumsikan positif).

Program ini tidak hanya mencetak semua solusi, ia mencetak semua permutasi solusi (agak asing, saya tahu). Inilah output untuk kasus terakhir: Pastebin .

Tweak sedikit memberikan solusi 98 - 10 = 88 yang tidak mencetak permutasi, membuatnya lebih efisien:

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

Dan hanya untuk bersenang-senang, 99 - 10 = 89 yang satu ini seefisien yang didapatnya (tidak seperti yang lain, ini tidak membuat tumpukan 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

Perhatikan bahwa, meskipun kami memiliki argumen default yang dapat diubah, ini tidak pernah menyebabkan masalah jika kami menjalankan kembali fungsinya karena n+[i]membuat daftar baru.


Bukti kebenaran

Untuk berakhir dalam loop tak terbatas, kita harus menekan beberapa titik di mana x <0 dan 0,1 + x 2 > 1 . Hal ini puas dengan x <-0,948 ... .

Tetapi perhatikan bahwa kita mulai dari x positif dan x selalu menurun, jadi untuk mencapai x <-0,948 ... kita harus memiliki x '- i 0,5 <-0,948 ... untuk beberapa x'> -0,948 .. . sebelum x dan bilangan bulat positif saya . Agar loop sementara berjalan, kita juga harus memiliki 0,1 + x ' 2 > i .

Penyusunan ulang kita dapatkan x ' 2 + 1,897x' + 0,948 <i <0,1 + x ' 2 , bagian luar menyiratkan bahwa x' <-0,447 . Tetapi jika -0.948 <x '<-0.447 , maka tidak ada bilangan bulat positif saya bisa cocok dengan kesenjangan dalam ketidaksetaraan di atas.

Karenanya kita tidak akan pernah berakhir dalam loop yang tak terbatas.

Sp3000
sumber
Anda dapat menghindari absdengan x*x<1e-12.
xnor
1
Saya pikir ini whilelingkaran bekerja untuk menggantikan for: while.1+x*x>i:S(x-i**.5,n+[i]);i+=1, setelah diinisialisasi i=1dalam parameter fungsi. Idenya adalah untuk menghindari keharusan mengkonversi ke ints. The .1adalah untuk menangani ketidakakuratan mengapung; Saya pikir itu aman terhadap loop tak terbatas.
xnor
@ xnor Saya sudah menerapkan tip pertama untuk saat ini. Saya masih memeriksa kebenaran yang kedua, tetapi jika itu bagus maka banyak byte yang disimpan! (Juga saya sebenarnya mengharapkan Anda untuk mengirim solusi: P)
Sp3000
1
Dan dengan Nsekarang argumen fungsi, lebih pendek untuk berulang dengan N-1dan memeriksa kapan N==0daripada len(n)==N.
xnor
@ Sp3000 Saya yakin sekarang bahwa .1ini aman; Saya dapat ngobrol argumen Anda jika Anda mau.
xnor
6

ECLiPSe Prolog - 118 (138-20)

Saya menggunakan implementasi Prolog berikut ini: 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).

Ini adalah pendekatan yang sangat naif dan eksponensial. Mendaftarkan semua solusi yang mungkin membutuhkan waktu untuk mencakup semua kombinasi ( edit : kisaran bilangan bulat yang dikunjungi sekarang berkurang di setiap langkah, yang menghilangkan banyak kombinasi yang tidak berguna).

Berikut ini transkrip sesi tes. Secara default, lingkungan akan mencoba menemukan semua solusi yang mungkin (-10) dan mencetak "Tidak" ketika gagal melakukannya (-10).

Seperti Sp3000 dicatat dengan benar dalam komentar, itu juga mencetak "Ya" ketika berhasil. Itu pasti berarti saya dapat menghapus 10 poin lagi ;-)

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

(Sunting) Mengenai kinerja, itu cukup bagus, setidaknya dibandingkan dengan yang lain (lihat misalnya komentar ini dari FryAmTheEggman ). Pertama, jika Anda ingin mencetak semua hasil, tambahkan predikat berikut:

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

Lihat http://pastebin.com/ugjfEHpw untuk kasus (5,13.0), yang selesai dalam 0,24 detik dan menemukan 495 solusi (tapi mungkin saya kehilangan beberapa solusi, saya tidak tahu).

coredump
sumber
3
Itu juga mencetak "Ya" ketika berhasil! Oh 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]).

Fungsi ini mengembalikan string "Tidak" atau string dengan nilai yang dipisahkan oleh spasi. Ini (tidak efisien) memproses setiap nilai yang mungkin mengkodekannya menjadi bilangan bulat besar, dan mulai dengan nilai yang lebih tinggi. 0 tidak diperbolehkan dalam solusi, dan 0 yang disandikan mewakili semua. Kesalahan dikuadratkan.

Contoh:

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 "

Harap bersabar f(5,13.0)karena ruang fungsi pencarian adalah 13 ^ 10. Itu dapat dibuat lebih cepat dengan 2 byte tambahan.

Paul Guyot
sumber
3

Python 3 2: 173 159 - 10 = 149

Penjelasan: Setiap solusi berbentuk x_1 x_2 ... x_n dengan 1 <= x_1 <= x ^ 2 di mana x adalah jumlah target. Oleh karena itu kita dapat menyandikan setiap solusi sebagai bilangan bulat di basis x ^ 2. Loop sementara iterates atas semua kemungkinan (x ^ 2) ^ n. Lalu saya mengonversi bilangan bulat kembali dan menguji jumlahnya. Cukup lurus ke depan.

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

Ia menemukan semua solusi, tetapi test case terakhir terlalu lama.

Jakube
sumber
3

JavaScript (ES6) 162 (172 - 10) 173

Sunting Sedikit lebih pendek, sedikit lebih lambat.

Sebagai fungsi dengan 2 parameter, output ke konsol javascript. Ini mencetak semua solusi tanpa pengulangan (solusi tuple yang dihasilkan sudah diurutkan).
Saya lebih peduli tentang waktu daripada tentang jumlah char, sehingga mudah diuji di konsol browser dalam batas waktu javascript standar.

(Pembaruan Feb 2016) Waktu saat ini untuk kasus uji terakhir: sekitar 1 150 detik . Persyaratan memori: dapat diabaikan.

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

Versi ES 5 Semua browser

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

Cuplikan Uji harus dijalankan pada browser terbaru apa pun

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>

( Sunting ) Di bawah ini adalah hasil pada PC saya ketika saya memposting jawaban ini 15 bulan yang lalu. Saya mencoba hari ini dan 100 kali lebih cepat pada PC yang sama, hanya dengan versi 64-bit alpha dari Firefox (dan Chrome tertinggal jauh di belakang)! - waktu saat ini dengan Firefox 40 Alpha 64 bit: ~ 2 detik, Chrome 48: ~ 29 detik

Output (pada PC saya - angka terakhir adalah runtime dalam milidetik)

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
edc65
sumber
2

Mathematica - 76 - 20 = 56

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

Contohnya

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}}
desir
sumber
Bagaimana cara mencetak ini No? Juga, output tidak dipisahkan ruang. Juga, tidak bisakah Anda menggunakan Tr@bukan Plus@@? Dan Anda mungkin dapat menyimpan beberapa karakter dengan mengubah Selectke Cases, fungsi di akhir pola, dan membuat ffungsi murni tanpa nama.
Martin Ender
2

Haskell, 87 80 - 10 = 70

Ini adalah algoritma rekursif mirip dengan program Python 3 dari @ Sp3000. Ini terdiri dari fungsi infiks #yang mengembalikan daftar semua permutasi semua solusi.

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

Dengan skor 102 99 92 - 10 = 82 kita dapat mencetak setiap solusi hanya sekali, diurutkan:

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]
Zgarb
sumber
2

Pyth 55 54 47-20 = 27

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

Cobalah online.

Tanpa malu meminjam dari komentar xnor ;)

Ini akan kehabisan memori pada komputer waras apa pun bahkan untuk nilai seperti 5,5.0. Mendefinisikan fungsi g,, yang bisa disebut seperti g 3 7.923668178593959.

Program python 3 ini pada dasarnya menggunakan algoritma yang sama (hanya tidak melakukan pencetakan "Tidak" pada akhirnya, yang dapat dilakukan dengan menetapkan variabel ke semua hasil, lalu menulis print(K if K else "No")), tetapi menggunakan generator, jadi ia tidak t mendapatkan kesalahan memori (masih akan memakan waktu sangat lama, tetapi saya telah membuatnya mencetak ketika menemukan nilai-nilai):

Ini memberikan hasil yang sama persis dengan yang didapat @ Sp3000. Juga, ini butuh beberapa hari untuk menyelesaikannya (saya tidak menghitung waktu, tetapi sekitar 72 jam).

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)
FryAmTheEggman
sumber
1

Python 3 - 157 174 169 - 10 = 159

Sunting1: Mengubah format output ke integer yang dipisahkan ruang alih-alih dipisahkan oleh koma. Terima kasih atas tip melepas kawat gigi di sekitar (n, x).

Sunting2: Terima kasih atas tip golfnya! Saya dapat memotong 9 karakter lain jika saya hanya menggunakan uji == alih-alih menguji untuk persamaan perkiraan dalam 1e-6, tapi itu akan membatalkan solusi perkiraan, jika ada.

Gunakan itertools untuk menghasilkan semua kombinasi integer yang mungkin, semoga efisien :)

Saya belum menemukan cara untuk menambahkan pencetakan "Tidak" secara efisien, sepertinya selalu butuh lebih dari 10 karakter tambahan.

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)))
RT
sumber
Program Anda memiliki format output yang salah (koma bukan spasi). Anda juga dapat mengurangi 2 byte dengan melepas kawat gigi di sekitarnya n,x.
Zgarb
Saya tampaknya mendapatkan SyntaxErrorketika saya mencoba evalgaris ...
Sp3000
@ Sp3000: coba masukkan 3,7.923668178593959. Anda membutuhkan ','
Jakube
4 perbaikan kecil: from itertools import*menghemat 1, menghapus ruang z**.5formenghemat 1, dan menghapus []dalam sum(z**.5for z in c)menghemat 2 dan menghapus ()dalam if(...)menyimpan 1.
Jakube
Apakah perubahan ke Python 2 dan menggunakan n,x=input()menjadi lebih ringkas?
Octavia Togami
0

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

Jika tidak ada permutasi, maka program ini tidak mencetak apa pun.

bb94
sumber