Annulla le radici quadrate


16

Il tuo compito è di riconvertire i decimali nella somma delle radici quadrate degli interi. Il risultato deve avere una precisione di almeno 6 cifre decimali significative.

Input :

Un numero che indica il numero di radici quadrate e un decimale che indica il numero da approssimare.

Esempio di input:

2 3.414213562373095

Output : numeri interi separati da spazi che, se radicati al quadrato e aggiunti, sono approssimativamente i decimali originali precisi con almeno 6 cifre decimali significative.

Gli zeri non sono ammessi nella soluzione.

Se ci sono più soluzioni, devi solo stamparne una.

Esempio di output (in qualsiasi ordine):

4 2

Questo funziona perché Math.sqrt(4) + Math.sqrt(2) == 3.414213562373095.

Questo è il codice golf. Il codice più corto (con bonus opzionale) vince!

Ci sarà sempre una soluzione ma -10 se il programma stampa "No" quando non esiste una soluzione con numeri interi. Inoltre, -10 se il programma stampa tutte le soluzioni (separate da righe o punti e virgola o altro) anziché una sola.

Casi test:

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

E sì, il tuo programma deve terminare a tempo finito usando la memoria finita su qualsiasi macchina ragionevole. Non può semplicemente funzionare "in teoria", devi essere in grado di testarlo.


Se ci sono più soluzioni, importa quale soluzione stampiamo? Ad esempio per il tuo ultimo test case (5 13.0), questa è anche una soluzione valida: 81 1 1 1 1
Jakube,

E gli zeri sono ammessi nella soluzione?
Jakube,

1
L'ingresso è sempre separato dallo spazio?
Sp3000,

È consentito inserire un input tramite la chiamata di funzione?
Jakube,

Inoltre, che dire delle soluzioni duplicate? Per il primo esempio, il nostro codice è autorizzato a stampare tutte e sei le permutazioni del 6 7 8secondo bonus?
Martin Ender,

Risposte:


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 grazie a @xnor per i suggerimenti, in particolare la ristrutturazione del ciclo for in un po ')

Un semplice tentativo ricorsivo. Inizia con il numero di destinazione e sottrae continuamente le radici quadrate fino a quando non raggiunge 0 o inferiore. La funzione Spuò essere chiamata come S(2,3.414213562373095)(il secondo argomento è considerato positivo).

Il programma non stampa solo tutte le soluzioni, stampa tutte le permutazioni delle soluzioni (un po 'estranee, lo so). Ecco l'output per l'ultimo caso: Pastebin .

Una leggera modifica fornisce una soluzione 98-10 = 88 che non stampa le permutazioni, rendendola più efficiente:

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

E solo per divertimento, questo 99 - 10 = 89 è il più efficiente possibile (a differenza degli altri, non fa impazzire 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

Si noti che, sebbene abbiamo un argomento predefinito mutabile, ciò non causa mai un problema se si esegue nuovamente la funzione poiché n+[i]crea un nuovo elenco.


Prova di correttezza

Per finire in un ciclo infinito, dobbiamo colpire un punto in cui x <0 e 0.1 + x 2 > 1 . Questo è soddisfatto da x <-0,948 ... .

Ma nota che partiamo da x e x positivi è sempre in diminuzione, quindi per colpire x <-0.948 ... dobbiamo aver avuto x '- i 0,5 <-0,948 ... per alcuni x'> -0,948 .. . prima x e intero positivo i . Per l'esecuzione del ciclo while, dobbiamo anche avere avuto 0.1 + x ' 2 > i .

Riorganizzando otteniamo x ' 2 + 1.897x' + 0.948 <i <0.1 + x ' 2 , le parti esterne implicano che x' <-0.447 . Ma se -0,948 <x'<-0,447 , quindi non intero positivo i possa adattare il gap nella suddetta diseguaglianza.

Quindi non finiremo mai in un ciclo infinito.


Puoi evitarlo abscon x*x<1e-12.
xnor

1
Penso che questo whileciclo lavora per sostituire il for: while.1+x*x>i:S(x-i**.5,n+[i]);i+=1, dopo aver inizializzato i=1nei parametri di funzione. L'idea è di evitare di dover convertire in ints. Il .1è gestire imprecisioni galleggiante; Penso che sia sicuro contro infiniti loop.
xnor

@xnor Ho implementato il primo consiglio per ora. Sto ancora verificando la correttezza del secondo, ma se è buono, allora sono risparmiati molti byte! (Inoltre mi aspettavo davvero che tu pubblicassi una soluzione: P)
Sp3000,

1
E con Nora un argomento di funzione, è più breve ricorrere N-1e controllare quando N==0anziché len(n)==N.
xnor

@ Sp3000 Sono convinto ora che .1sia sicuro; Posso parlarti di una discussione se vuoi.
xnor

6

ECLiPSe Prolog - 118 (138-20)

Ho usato la seguente implementazione di 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).

Questo è un approccio molto ingenuo ed esponenziale. Elencare tutte le possibili soluzioni richiede tempo per coprire tutte le combinazioni ( modifica : l'intervallo degli interi visitati ora diminuisce ad ogni passo, il che rimuove molte combinazioni inutili).

Di seguito una trascrizione di una sessione di prova. Per impostazione predefinita, l'ambiente tenterà di trovare tutte le possibili soluzioni (-10) e stampa "No" quando non riesce (-10).

Come Sp3000 ha correttamente notato nel commento, stampa anche "Sì" quando ha successo. Questo sicuramente significa che posso rimuovere altri 10 punti ;-)

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

(Modifica) Per quanto riguarda le prestazioni, è abbastanza buono, almeno rispetto ad altri (vedi ad esempio questo commento di FryAmTheEggman ). Innanzitutto, se si desidera stampare tutti i risultati, aggiungere il predicato seguente:

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

Vedi http://pastebin.com/ugjfEHpw per il caso (5,13,0), che si completa in 0,24 secondi e trova 495 soluzioni (ma forse mi mancano alcune soluzioni, non lo so).


3
Stampa anche "Sì" quando ha successo! 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]).

Questa funzione restituisce la stringa "No" o una stringa con valori separati da spazi. Elabora (in modo inefficiente) tutti i possibili valori codificandoli in un intero grande e iniziando con valori più alti. 0 non sono consentiti nella soluzione e 0 codificato rappresenta tutti. L'errore è al quadrato.

Esempio:

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 "

Si prega di pazientare con f(5,13.0)come spazio di ricerca delle funzioni è 13 ^ 10. Può essere reso più veloce con 2 byte aggiuntivi.


3

Python 3 2: 173 159-10 = 149

Spiegazione: Ogni soluzione ha la forma x_1 x_2 ... x_n con 1 <= x_1 <= x ^ 2 dove x è la somma target. Pertanto possiamo codificare ogni soluzione come intero in base x ^ 2. Il ciclo while itera su tutte le possibilità (x ^ 2) ^ n. Quindi riconvertire nuovamente il numero intero e testare la somma. Abbastanza diretto.

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

Trova tutte le soluzioni, ma l'ultimo caso di test impiega troppo tempo.


3

JavaScript (ES6) 162 (172 - 10) 173

Modifica Un po 'più corto, un po' più lento.

Come funzione con 2 parametri, output sulla console javascript. Stampa tutte le soluzioni senza ripetizioni (le tuple delle soluzioni vengono generate già ordinate).
Mi sono preoccupato più dei tempi che del conteggio dei caratteri, in modo che sia facilmente testato in una console del browser entro il limite di tempo javascript standard.

(Aggiornamento febbraio 2016) Ora corrente per l'ultimo caso di test: circa 1 150 secondi . Requisiti di memoria: trascurabile.

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

Versione ES 5 Qualsiasi 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];
  }
}

Test Snippet dovrebbe essere eseguito su qualsiasi browser recente

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>

( Modifica ) Di seguito sono riportati i risultati sul mio PC quando ho pubblicato questa risposta 15 mesi fa. Ho provato oggi ed è 100 volte più veloce sullo stesso PC, solo con una versione alpha a 64 bit di Firefox (e Chrome è in ritardo)! - ora corrente con Firefox 40 Alpha 64 bit: ~ 2 sec, Chrome 48: ~ 29 sec

Output (sul mio PC - l'ultimo numero è runtime in millisecondi)

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

Esempi

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

Come si stampa No? Inoltre, l'output non è separato dallo spazio. Inoltre, non puoi usare Tr@invece di Plus@@? E potresti essere in grado di salvare alcuni personaggi cambiando SelectinCases , la funzione alla fine in un modello e creando funa funzione pura senza nome.
Martin Ender,

2

Haskell, 87 80-10 = 70

Questo è un algoritmo ricorsivo simile al programma Python 3 di @ Sp3000. Consiste in una funzione infix #che restituisce un elenco di tutte le permutazioni di tutte le soluzioni.

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

Con un punteggio di 102 99 92 - 10 = 82 possiamo stampare ogni soluzione una sola volta, ordinati:

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

Provalo online.

Prende spudoratamente in prestito da commento di xnor ;)

Questo esaurirà la memoria su qualsiasi computer sano anche per un valore simile 5,5.0. Definisce una funzione,g che può essere chiamata come g 3 7.923668178593959.

Questo programma python 3 utilizza essenzialmente lo stesso algoritmo (semplicemente non esegue la stampa "No" alla fine, cosa che potrebbe essere fatta assegnando una variabile a tutti i risultati, quindi scrivendo print(K if K else "No") ), ma utilizza un generatore, quindi non t ottiene un errore di memoria (ci vorrà ancora molto tempo, ma l'ho fatto stampare perché trova i valori):

Ciò ha dato gli stessi esatti risultati ottenuti da @ Sp3000. Inoltre, ci sono voluti diversi giorni per terminare (non ho avuto tempo, ma circa 72 ore).

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: modificato il formato di output in numeri interi separati da spazio anziché separati da virgola. Grazie per la punta di rimuovere le parentesi graffe intorno (n, x).

Edit2: Grazie per i suggerimenti sul golf! Posso tagliare altri 9 caratteri se uso solo un test == invece di testare l'uguaglianza approssimativa entro 1e-6, ma ciò invaliderebbe soluzioni approssimative, se presenti.

Utilizza itertools per generare tutte le possibili combinazioni di numeri interi, si spera in modo efficiente :)

Non ho trovato il modo di aggiungere la stampa "No" in modo efficiente, sembra sempre che siano necessari più di 10 caratteri in più.

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

Il tuo programma ha un formato di output errato (virgole anziché spazi). Inoltre, puoi radere 2 byte rimuovendo le parentesi graffe n,x.
Zgarb,

Mi sembra di essere SyntaxErrors quando provo la evallinea ...
Sp3000,

@ Sp3000: prova a inserire 3,7,923668178593959. Hai bisogno di ","
Jakube,

4 piccoli miglioramenti: from itertools import*salva 1, rimuovendo lo spazio z**.5forrisparmia 1, rimuovendo []in sum(z**.5for z in c)risparmi 2 e rimuovendo ()in if(...)risparmi 1.
Jakube,

Sarebbe una modifica a Python 2 e utilizzo n,x=input() sarebbe più compatta?
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}}

Se non ci sono permutazioni, questo programma non stampa nulla.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.