Desfazer as raízes quadradas

16

Seu trabalho é converter decimais de volta na soma das raízes quadradas dos números inteiros. O resultado deve ter uma precisão de pelo menos 6 dígitos decimais significativos.

Entrada :

Um número indicando o número de raízes quadradas e um decimal indicando o número a ser aproximado.

Exemplo de entrada:

2 3.414213562373095

Saída : números inteiros separados por espaços que, quando somados e adicionados ao quadrado, têm aproximadamente o decimal original com precisão de pelo menos 6 dígitos decimais significativos.

Zeros não são permitidos na solução.

Se houver várias soluções, você precisará imprimir apenas uma.

Exemplo de saída (em qualquer ordem):

4 2

Isso funciona porque Math.sqrt(4) + Math.sqrt(2) == 3.414213562373095.

Isso é código de golfe. O código mais curto (com bônus opcional) vence!

Sempre haverá uma solução, mas -10 se o seu programa imprimir "Não" quando não houver solução com números inteiros. Além disso, -10 se o seu programa imprimir todas as soluções (separadas por novas linhas ou ponto-e-vírgula ou o que for) em vez de apenas uma.

Casos de teste:

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 sim, seu programa precisa terminar em um tempo finito usando memória finita em qualquer máquina razoável. Não pode simplesmente funcionar "em teoria", é preciso ser capaz de testá-lo.

soktinpk
fonte
Se houver várias soluções, importa qual a solução que imprimimos? Por exemplo, para o seu último caso de teste (5 13.0), esta também é uma solução válida: 81 1 1 1 1
Jakube
E zeros são permitidos na solução?
Jakube 26/11/14
11
A entrada é sempre separada por espaço?
SP3000
E a entrada de entrada via chamada de função é permitida?
26414 Jak Jak
Além disso, e as soluções duplicadas? Para o primeiro exemplo, nosso código pode imprimir todas as seis permutações do 6 7 8segundo bônus?
Martin Ender

Respostas:

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

(Muito obrigado ao @xnor por dicas, especialmente a reestruturação do loop for em um tempo)

Uma simples tentativa recursiva. Começa com o número alvo e subtrai raízes quadradas continuamente até atingir 0 ou menos. A função Spode ser chamada como S(2,3.414213562373095)(o segundo argumento é considerado positivo).

O programa não apenas imprime todas as soluções, imprime todas as permutações de soluções (um pouco estranhas, eu sei). Aqui está a saída do último caso: Pastebin .

Um pequeno ajuste fornece uma solução de 98 - 10 = 88 que não imprime permutações, tornando-a mais eficiente:

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 apenas por diversão, este 99 - 10 = 89 é o mais eficiente possível (ao contrário dos outros, ele não empurra a pilha 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

Observe que, embora tenhamos um argumento padrão mutável, isso nunca causa um problema se executarmos novamente a função, pois n+[i]cria uma nova lista.


Prova de correção

Para terminar em um loop infinito, precisamos atingir um ponto em que x <0 e 0,1 + x 2 > 1 . Isto é satisfeito fazendo x <-0,948 ... .

Mas observe que começamos do positivo x e x está sempre diminuindo, portanto, para atingir x <-0,948 ... devemos ter x '- i 0,5 <-0,948 ... para alguns x'> -0,948 .. . antes x e número inteiro positivo i . Para que o loop while seja executado, também devemos ter 0,1 + x ' 2 > i .

Reorganizando, obtemos x ' 2 + 1,889x' + 0,948 <i <0,1 + x ' 2 , as partes externas implicando que x' <-0,447 . Mas se -0.948 <x '<-0.447 , nenhum número inteiro positivo i pode ajustar a lacuna na desigualdade acima.

Portanto, nunca terminaremos em um loop infinito.

Sp3000
fonte
Você pode evitar abscom x*x<1e-12.
Xnor
11
Eu acho que este whilecircuito funciona para substituir o for: while.1+x*x>i:S(x-i**.5,n+[i]);i+=1, tendo iniciado i=1nos parâmetros de função. A idéia é evitar a necessidade de converter para ints. O .1é para lidar com imprecisões de flutuação; Eu acho que é seguro contra loops infinitos.
Xnor
@ xnor Eu implementei a primeira dica por enquanto. Ainda estou checando a exatidão do segundo, mas se for bom, são muitos bytes salvos! (Também na verdade eu esperava que você publicasse uma solução: P)
Sp3000 27/11
11
E Nagora, com um argumento de função, é mais curto recuar N-1e verificar quando, em N==0vez de len(n)==N.
Xnor
@ Sp3000 Estou convencido agora de que .1é seguro; Posso conversar com você, se quiser.
Xnor
6

ECLiPSe Prolog - 118 (138-20)

Eu usei a seguinte implementação do 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).

Essa é uma abordagem muito ingênua e exponencial. A listagem de todas as soluções possíveis leva tempo para cobrir todas as combinações ( editar : o intervalo de números inteiros visitados agora diminui a cada etapa, o que remove muitas combinações inúteis).

Segue uma transcrição de uma sessão de teste. Por padrão, o ambiente tenta encontrar todas as soluções possíveis (-10) e imprime "Não" quando não consegue fazê-lo (-10).

Como o Sp3000 observou corretamente no comentário, ele também imprime "Sim" quando obtém êxito. Isso certamente significa que posso remover mais 10 pontos ;-)

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

(Editar) Em relação ao desempenho, é bastante bom, pelo menos em comparação com outros (veja, por exemplo, este comentário de FryAmTheEggman ). Primeiro, se você deseja imprimir todos os resultados, adicione o seguinte predicado:

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

Consulte http://pastebin.com/ugjfEHpw para obter o caso (5,13.0), que termina em 0,24 segundos e encontra 495 soluções (mas talvez eu esteja faltando algumas soluções, não sei).

coredump
fonte
3
Também imprime "Sim" quando obtém êxito! Oh Prolog.
Sp3000 26/11
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]).

Esta função retorna a string "No" ou uma string com valores separados por espaços. (Ineficientemente) processa todos os valores possíveis que os codificam em um número inteiro grande e começam com valores mais altos. 0 não são permitidos na solução e 0 codificado representa todos. Erro ao quadrado.

Exemplo:

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 "

Por favor, seja paciente, f(5,13.0)pois o espaço de pesquisa de funções é 13 ^ 10. Pode ser feito mais rápido com 2 bytes adicionais.

Paul Guyot
fonte
3

Python 3 2: 173 159 - 10 = 149

Explicação: Cada solução tem o formato x_1 x_2 ... x_n com 1 <= x_1 <= x ^ 2 em que x é a soma de destino. Portanto, podemos codificar cada solução como um número inteiro na base x ^ 2. O loop while itera sobre todas as possibilidades (x ^ 2) ^ n. Então eu converto o número inteiro de volta e testo a soma. Bem direto.

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

Ele encontra todas as soluções, mas o último caso de teste leva muito tempo.

Jakube
fonte
3

JavaScript (ES6) 162 (172 - 10) 173

Editar Um pouco mais curto, um pouco mais lento.

Como uma função com 2 parâmetros, imprima para o console javascript. Isso imprime todas as soluções sem repetições (as tuplas de soluções já são geradas e classificadas).
Eu me importava mais com o tempo do que com a contagem de caracteres, para que ele fosse facilmente testado em um console do navegador dentro do prazo padrão do javascript.

(Atualização de fevereiro de 2016) Hora atual do último caso de teste: cerca de 1 150 segundos . Requisitos de memória: insignificante.

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

Versão ES 5 Qualquer navegador

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

Snippet de teste que deve ser executado em qualquer navegador 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>

( Editar ) Abaixo estão os resultados no meu PC quando publiquei esta resposta há 15 meses. Eu tentei hoje e é 100 vezes mais rápido no mesmo PC, apenas com uma versão alfa de 64 bits do Firefox (e o Chrome fica muito atrás)! - hora atual com o Firefox 40 Alpha de 64 bits: ~ 2 s, Chrome 48: ~ 29 s

Saída (no meu PC - o último número é o tempo de execução em milissegundos)

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
fonte
2

Matemática - 76 - 20 = 56

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

Exemplos

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}}
swish
fonte
Como isso é impresso No? Além disso, a saída não é separada por espaço. Além disso, você não pode usar em Tr@vez de Plus@@? E você pode salvar alguns caracteres alterando Selectpara Cases, a função no final de um padrão, e criando fuma função pura sem nome.
Martin Ender
2

Haskell, 87 80 - 10 = 70

Este é um algoritmo recursivo semelhante ao programa Python 3 do @ Sp3000. Consiste em uma função infix #que retorna uma lista de todas as permutações de todas as soluções.

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

Com uma pontuação de 102 99 92 - 10 = 82 , podemos imprimir cada solução apenas uma vez, classificada:

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
fonte
2

Pitão 55 54 47-20 = 27

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

Experimente online.

Desavergonhadamente empresta o comentário de xnor ;)

Isso ficará sem memória em qualquer computador são, mesmo para um valor parecido 5,5.0. Define uma função,, gque pode ser chamada como g 3 7.923668178593959.

Esse programa python 3 usa essencialmente o mesmo algoritmo (simplesmente não imprime "Não" no final, o que pode ser feito atribuindo uma variável a todos os resultados e depois escrevendo print(K if K else "No")), mas usa um gerador, portanto receba um erro de memória (ainda levará muito tempo, mas eu o fiz imprimir conforme encontra os valores):

Isso deu exatamente os mesmos resultados que o @ Sp3000 obteve. Além disso, isso levou vários dias para terminar (eu não cronometrei, mas cerca de 72 horas).

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
fonte
1

Python 3 - 157 174 169 - 10 = 159

Edit1: alterado o formato de saída para números inteiros separados por espaço, em vez de separados por vírgula. Obrigado pela dica de remover os aparelhos ao redor (n, x).

Edit2: Obrigado pelas dicas de golfe! Posso cortar outros 9 caracteres se eu apenas usar um teste == em vez de testar a igualdade aproximada dentro de 1e-6, mas isso invalidaria soluções aproximadas, se houver alguma.

Usa ferramentas para gerar todas as combinações possíveis possíveis, espero que com eficiência :)

Não encontrei uma maneira de adicionar a impressão "Não" com eficiência, sempre parece ter mais de 10 caracteres extras.

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
fonte
Seu programa tem o formato de saída errado (vírgulas em vez de espaços). Além disso, você pode cortar 2 bytes removendo as chaves ao redor n,x.
Zgarb
Eu pareço estar recebendo SyntaxErrors quando tento a evallinha ... #
Sp3000 #
@ Sp3000: tente digitar 3,7.923668178593959. Você precisa do ','
Jakube 26/11
4 pequenas melhorias: from itertools import*salva 1, remove o espaço z**.5foreconomiza 1 e remove o []in sum(z**.5for z in c)saves 2 e removendo o ()in if(...)saves 1. #
Jak Jak
Uma alteração no Python 2 e o uso n,x=input()seriam mais compactos?
precisa
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}}

Se não houver permutações, este programa não imprime nada.

bb94
fonte