Karekökleri geri al


16

İşiniz ondalık sayıları tamsayıların kare köklerinin toplamına dönüştürmektir. Sonuç, en az 6 anlamlı ondalık basamak hassasiyetine sahip olmalıdır.

Giriş :

Karekök sayısını belirten bir sayı ve yaklaşık olarak sayıyı belirten bir ondalık sayı.

Örnek girdi:

2 3.414213562373095

Çıktı : Kareköklü ve eklendiğinde, en az 6 anlamlı ondalık basamağa kadar yaklaşık olarak orijinal ondalık basamağı olan boşluklarla ayrılmış tamsayılar.

Çözümde sıfırlara izin verilmez.

Birden fazla çözüm varsa, yalnızca bir tane yazdırmanız gerekir.

Örnek çıktı (herhangi bir sırayla):

4 2

Bu işe yarıyor çünkü Math.sqrt(4) + Math.sqrt(2) == 3.414213562373095.

Bu kod golf. En kısa kod (isteğe bağlı bonus ile) kazanır!

Her zaman bir çözüm olacaktır, ancak programınız tamsayılarla bir çözüm olmadığında "Hayır" yazarsa -10 olur. Ayrıca, programınız tek bir çözüm yerine tüm satırları (satırsonu veya noktalı virgülle veya başka bir şeyle ayrılmış olarak) yazdırırsa -10.

Test senaryoları:

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

Ve evet, programınız makul herhangi bir makinede sınırlı bellek kullanarak sınırlı bir sürede bitmelidir. Sadece "teoride" işe yaramaz, bunu gerçekten test edebilmelisiniz.


Birden fazla çözüm varsa, hangi çözümü yazdırdığımız önemli mi? Örneğin, son test durumunuz için (5 13.0), bu da geçerli bir çözümdür: 81 1 1 1 1
Jakube

Ve çözümde sıfırlara izin veriliyor mu?
Jakube

1
Giriş her zaman boşlukla ayrılmış mı?
Sp3000

Fonksiyon çağrısı ile giriş girilmesine izin veriliyor mu?
Jakube

Ayrıca, yinelenen çözümler ne olacak? İlk örnekte, kodumuzun 6 7 8ikinci bonus için altı permütasyonun tümünü yazmasına izin veriliyor mu?
Martin Ender

Yanıtlar:


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

(İpuçları için @xnor sayesinde Mega, özellikle for döngüsünün bir süre sonra yeniden yapılandırılması)

Basit bir özyinelemeli girişim. Hedef sayı ile başlar ve 0 veya daha düşük olana kadar kare kökleri çıkarır. Bu fonksiyon Sşöyle adlandırılabilir S(2,3.414213562373095)(ikinci argümanın pozitif olduğu varsayılır).

Program sadece tüm çözümleri basmakla kalmaz, aynı zamanda tüm çözüm permütasyonlarını basar (biraz yabancı, biliyorum). Son durum için çıktı: Pastebin .

Hafif bir değişiklik, permütasyonları yazdırmayan ve daha verimli hale getiren 98-10 = 88'lik bir çözüm verir :

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

Ve sadece eğlence için, bu 99 - 10 = 89 biri olabildiğince verimli (diğerlerinden farklı olarak, yığını havaya uçurmuyor 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

Değişken bir varsayılan bağımsız değişkenimiz olmasına rağmen, n+[i]yeni bir liste oluşturduğundan işlevi yeniden çalıştırdığımızda bunun hiçbir zaman soruna neden olmadığını unutmayın .


Doğruluk kanıtı

Sonsuz bir döngü elde etmek için, x <0 ve 0.1 + x 2 > 1 olan bir noktaya çarpmalıyız . Bu x <-0.948 ... tarafından karşılanmaktadır .

Ancak, pozitif x'ten başladığımızı ve x'in her zaman azaldığını unutmayın, bu nedenle x <-0.948'e çarpmak için ... x '- i 0.5 <-0.948 ... ' e sahip olmalıyız ... bazı x '> -0.948 için ... . önce x ve pozitif tamsayı i . While döngüsünün çalışması için 0.1 + x ' 2 > i'ye sahip olmalıyız .

Yeniden düzenleyerek x ' 2 + 1.897x' + 0.948 <i <0.1 + x ' 2 elde ediyoruz , dış kısımlar x' <-0.447'yi gösteriyor . Fakat eğer -0.948 <x '<-0.447 ise , o zaman pozitif bir tamsayı i yukarıdaki eşitsizlikteki boşluğa sığamaz.

Böylece asla sonsuz bir döngüye girmeyeceğiz.


Sen önleyebilirsiniz absile x*x<1e-12.
xnor

1
Bu whiledöngü işlev parametrelerinde başlatılmış olan for:, yerine çalıştığını düşünüyorum . Fikir, s'ye dönüştürmek zorunda kalmamaktır . Şamandıra yanlışlıklar işlemek için; Bence sonsuz döngülere karşı güvenli. while.1+x*x>i:S(x-i**.5,n+[i]);i+=1i=1int.1
xnor

@xnor Şimdilik ilk ipucunu uyguladım. Hala ikincisinin doğruluğunu kontrol ediyorum, ama eğer iyiyse o zaman çok fazla bayt kaydedildi! (Ayrıca aslında bir çözüm göndermenizi
bekledim

1
Ve Nşimdi bir işlev argümanı ile, geri çekilmek N-1ve ne zaman kontrol etmek N==0daha kısa len(n)==N.
xnor

@ Sp3000 Artık .1güvenli olduğuna ikna oldum ; İstersen seninle tartışabilirim.
xnor

6

ECLiPSe Prolog - 118 (138-20)

Aşağıdaki Prolog uygulamasını kullandım: 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).

Bu çok naif, üstel bir yaklaşım. Olası tüm çözümleri listelemek, tüm kombinasyonları kapsamak için zaman alır ( düzenle : ziyaret edilen tamsayıların aralığı artık her adımda azalır ve bu da birçok işe yaramaz kombinasyonu ortadan kaldırır).

Aşağıda bir test oturumunun bir not dökümü yer almaktadır. Varsayılan olarak, ortam tüm olası çözümleri bulmaya çalışacaktır (-10) ve başarısız olduğunda "Hayır" yazacaktır (-10).

Sp3000 yorumda düzgün bir şekilde belirtildiği gibi, başarılı olduğunda da "Evet" yazdırabilir. Bu kesinlikle 10 puan kaldırabilirim ;-)

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

(Düzenle) İlişkin performansı, diğer olanlara kıyasla en az (örneğin bkz, oldukça iyi FryAmTheEggman bu açıklama ). İlk olarak, tüm sonuçları yazdırmak istiyorsanız, aşağıdaki yüklemi ekleyin:

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

0.24 saniyede tamamlanan ve 495 çözüm bulan (5,13.0) vaka için http://pastebin.com/ugjfEHpw adresine bakın (ama belki bazı çözümleri kaçırıyorum, bilmiyorum).


3
Ayrıca başarılı olduğunda "Evet" yazar! Ah 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]).

Bu işlev "Hayır" dizesini veya boşluklarla ayrılmış değerleri olan bir dize döndürür. Büyük bir tamsayıya kodlayan ve daha yüksek değerlerle başlayarak olası tüm değerleri (verimsiz olarak) işler. Çözeltide 0'a izin verilmez ve 0 ile kodlananlar hepsini temsil eder. Hata kare.

Misal:

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 "

Lütfen f(5,13.0)işlev arama alanı 13 ^ 10 olduğundan sabırlı olun . 2 ek bayt ile daha hızlı yapılabilir.


3

Python 3 2: 173159-10 = 149

Açıklama: Her çözüm x_1 x_2 ... x_n biçimindedir ve 1 <= x_1 <= x ^ 2 şeklindedir; burada x, hedef toplamdır. Bu nedenle her çözümü x ^ 2 tabanında bir tamsayı olarak kodlayabiliriz. While döngüsü tüm (x ^ 2) ^ n olasılıklarını yineler. Sonra tamsayı geri dönüştürmek ve toplamı test ediyorum. Oldukça düz ileri.

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

Tüm çözümleri bulur, ancak son test senaryosu çok uzun sürer.


3

JavaScript (ES6) 162 (172-10) 173

Düzenle Biraz daha kısa, biraz daha yavaş.

2 parametreli bir işlev olarak, javascript konsoluna çıktı. Bu, tüm çözümleri tekrarlama olmadan yazdırır (çözüm grupları daha önce sıralanmış olarak üretilir).
Standart javascript zaman sınırı içinde bir tarayıcı konsolunda kolayca test edilebilmesi için zamanlama hakkında daha fazla önem verdim.

(Şubat 2016 güncellemesi) Son test senaryosunun geçerli saati: yaklaşık 150 sn . Bellek gereksinimleri: önemsiz.

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 Sürüm Herhangi bir tarayıcı

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

Deney Parçacığı herhangi üzerinde çalışmalıdır son tarayıcısı

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>

( Düzenle ) Bu yanıtı 15 ay önce gönderdiğimde bilgisayarımdaki sonuç aşağıdadır. Bugün denedim ve aynı bilgisayarda 100 kat daha hızlı, sadece Firefox'un 64 bit alfa sürümü (ve Chrome geride kaldı)! - Firefox 40 Alpha 64 bit ile geçerli zaman: ~ 2 sn, Chrome 48: ~ 29 sn

Çıktı (bilgisayarımda - son sayı milisaniye cinsinden çalışma zamanı)

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

Örnekler

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

Bu nasıl yazdırılıyor No? Ayrıca, çıktı boşlukla ayrılmaz. Ayrıca, Tr@bunun yerine kullanamaz Plus@@mısınız? Ve değiştirerek bazı karakterleri kaydetmek mümkün olabilir Selectiçin Casesbir şablona sonunda fonksiyonu ve yapım fisimsiz saf işlevi.
Martin Ender

2

Haskell, 87 80-10 = 70

Bu, @ Sp3000'in Python 3 programına benzer bir özyinelemeli algoritmadır. #Tüm çözümlerin tüm permütasyonlarının bir listesini döndüren bir infix işlevinden oluşur .

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 puanla, her çözümü sadece bir kez yazdırabiliriz:

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

Pyth 55 54 47-20 = 27

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

Çevrimiçi deneyin.

Utanmadan ödünç gelen XNOR yorumuna ;)

Böyle bir değer için bile herhangi bir aklı başında bilgisayarda bellek tükenecek 5,5.0. gGibi çağrılabilen bir işlevi tanımlar g 3 7.923668178593959.

Bu python 3 programı temelde aynı algoritmayı kullanır (sonunda "Hayır" baskısını yapmaz, bu da tüm sonuçlara bir değişken atayarak ve sonra yazarak yapılabilir print(K if K else "No")), ancak bir jeneratör kullanır, bu nedenle t Bir bellek hatası al (yine de çok uzun sürecek, ancak değerleri buldukça yazdırdım):

Bu @ Sp3000 ile aynı sonuçları verdi. Ayrıca, bu bitirmek için birkaç gün sürdü (ben zaman yoktu, ama yaklaşık 72 saat).

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

Edit1: Çıktı biçimini virgülle ayrılmış yerine boşlukla ayrılmış tamsayılarla değiştirdi. Etrafındaki parantezleri kaldırdığınız için teşekkür ederiz (n, x).

Edit2: Golf ipuçları için teşekkürler! 1e-6 içinde yaklaşık eşitliği test etmek yerine sadece bir == testi kullanırsam, başka bir 9 karakter kırpabilirim, ancak eğer varsa, yaklaşık çözümleri geçersiz kılacaktır.

Umarım verimli bir şekilde tüm olası tamsayı kombinasyonlarını oluşturmak için itertools kullanır :)

"Hayır" baskısını verimli bir şekilde eklemenin bir yolunu bulamadım, her zaman 10'dan fazla ekstra karakter alıyor gibi görünüyor.

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

Programınız yanlış çıktı biçimine sahip (boşluk yerine virgül). Ayrıca, etrafındaki parantezleri çıkararak 2 bayt tıraş edebilirsiniz n,x.
14:51

Hattı SyntaxErrordenediğimde s alıyorum gibi görünüyor eval...
Sp3000

@ Sp3000: 3,7.923668178593959 girmeyi deneyin. ',' İhtiyacınız var
Jakube

4 küçük iyileştirme: from itertools import*1 kaydeder, yerden z**.5fortasarruf sağlar 1 ve []in sum(z**.5for z in c)kaydeder 2 ve ()in if(...)kaydeder 1 kaldırır .
Jakube

Python 2 ve kullanımındaki bir değişiklik n,x=input()daha kompakt olur mu?
Octavia Togami

0

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

Hiçbir permütasyon yoksa, bu program hiçbir şey yazdırmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.