Розв’яжіть квадратні корені


16

Ваше завдання полягає в перетворенні десяткових знаків назад у суму квадратних коренів цілих чисел. Результат повинен мати точність не менше 6 значних десяткових цифр.

Вхід :

Число, яке вказує на кількість квадратних коренів, і десяткове число, що вказує число для наближення.

Приклад введення:

2 3.414213562373095

Вихідні дані : Цілі числа, розділені пробілами, які при введенні квадрата та доданні мають приблизно початковий десятковий точний показник принаймні до 6 значних десяткових цифр.

Нулі в розчині не допускаються.

Якщо є кілька рішень, вам потрібно роздрукувати лише одне.

Приклад виведення (у будь-якому порядку):

4 2

Це працює, тому що Math.sqrt(4) + Math.sqrt(2) == 3.414213562373095.

Це код гольфу. Найкоротший код (з додатковим бонусом) виграє!

Рішення завжди буде, але -10, якщо програма надрукує "Ні", коли немає рішення з цілими числами. Крім того, -10, якщо ваша програма друкує всі рішення (розділені новими рядками або крапками з комою або будь-якими іншими), а не лише одне.

Тестові приклади:

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

І так, ваша програма повинна закінчуватись в обмежений час, використовуючи обмежену пам’ять на будь-якій розумній машині. Це не може просто працювати "теоретично", ви повинні мати можливість фактично його перевірити.


Якщо є кілька рішень, чи має значення, яке рішення ми друкуємо ?. Наприклад, для вашого останнього тестового випадку (5 13,0), це також є дійсним рішенням: 81 1 1 1 1
Jakube

І чи дозволені нуль у розчині?
Якубе

1
Чи вхід завжди розділений пробілом?
Sp3000

І чи дозволяється введення вводу через функціональний виклик?
Якубе

Крім того, що щодо дублюючих рішень? У першому прикладі, чи дозволяється нашому коду друкувати всі шість перестановок 6 7 8для другого бонуса?
Мартін Ендер

Відповіді:


9

Пітон 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

(Мега дякує @xnor за поради, особливо реструктуризацію циклу for на час)

Проста рекурсивна спроба. Він починається з цільового числа і безперервно віднімає квадратні корені, поки не досягне 0 або нижче. Функцію Sможна назвати як S(2,3.414213562373095)(другий аргумент вважається позитивним).

Програма не просто роздруковує всі рішення, вона виводить усі перестановки рішень (я знаю трохи сторонніх). Ось вихід для останнього випадку: Pastebin .

Невелике налаштування дає рішення 98 - 10 = 88, яке не друкує перестановки, що робить його більш ефективним:

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

І просто для розваги, цей 99 - 10 = 89 - настільки ж ефективний, як і отримує (на відміну від інших, він не роздуває стек на 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

Зауважте, що, хоча у нас є змінний аргумент за замовчуванням, це ніколи не викликає проблем, якщо ми повторно функціонуємо, оскільки n+[i]створюємо новий список.


Доказ правильності

Для того, щоб опинитися в нескінченному циклі, ми повинні потрапити в деяку точку, де x <0 і 0,1 + x 2 > 1 . Це задовольняє й <-0,948 ... .

Але зауважте, що ми починаємо від позитивного x і x завжди зменшується, тому для досягнення x <-0.948 ... ми повинні мати x '- i 0.5 <-0.948 ... для деяких x'> -0.948 .. . Перед х і позитивного цілого числа я . Доки цикл не працює, ми також повинні мати 0,1 + x ' 2 > i .

Переставляючи, отримуємо x ' 2 + 1,897x' + 0,948 <i <0,1 + x ' 2 , зовнішні частини означають, що x' <-0,447 . Але якщо -0,948 <x '<-0,447 , то жодне додатне ціле число я не може вписати розрив у вищевказану нерівність.

Отже, ми ніколи не опинимось у нескінченному циклі.


Ви можете уникнути absз x*x<1e-12.
xnor

1
Я думаю, що цей whileцикл працює на заміну for:, while.1+x*x>i:S(x-i**.5,n+[i]);i+=1ініціалізуючись i=1у параметрах функції. Ідея полягає у тому, щоб уникнути необхідності перетворення на ints. .1Полягає в зверненні з плаваючою точкою неточностей; Я думаю, що це безпечно від нескінченних циклів.
xnor

@xnor Я реалізував перший підказку зараз. Я все ще перевіряю правильність другого, але якщо це добре, то це збережено багато байтів! (Також я насправді очікував, що ви опублікуєте рішення: P)
Sp3000

1
І Nтепер аргумент функції коротше повторювати N-1і перевіряти, коли N==0замість цього len(n)==N.
xnor

@ Sp3000 Я переконаний, що .1це безпечно; Я можу передати вам аргумент, якщо хочете.
xnor

6

ECLiPSe Prolog - 118 (138-20)

Я використовував таку реалізацію 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).

Це дуже наївний, експоненційний підхід. Перерахування всіх можливих рішень потребує часу, щоб охопити всі комбінації ( редагувати : діапазон відвідуваних цілих чисел тепер зменшується на кожному кроці, що видаляє безліч непотрібних комбінацій).

Далі йде стенограма тестового заняття. За замовчуванням середовище намагатиметься знайти всі можливі рішення (-10) і надрукує "Ні", коли цього не зробить (-10).

Як Sp3000 правильно зазначив у коментарі, він також друкує "Так", коли це досягає успіху. Це, безумовно, означає, що я можу зняти ще 10 балів ;-)

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

(Редагувати) Щодо продуктивності, вона досить хороша, принаймні порівняно з іншими (див., Наприклад, цей коментар від FryAmTheEggman ). По-перше, якщо ви хочете роздрукувати всі результати, додайте такий предикат:

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

Дивіться http://pastebin.com/ugjfEHpw про випадок (5,13.0), який завершується за 0,24 секунди і знаходить 495 рішень (але, можливо, я пропускаю деякі рішення, я не знаю).


3
Він також друкує "Так", коли це досягає успіху! О Пролог.
Sp3000

3

Ерланг, 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]).

Ця функція повертає рядок "Ні" або рядок зі значеннями, розділеними пробілами. Він (неефективно) обробляє всі можливі значення, що кодують їх у велике ціле число, і починаючи з більш високих значень. 0 не дозволено в розчині, а закодований 0 представляє всі. Помилка в квадраті.

Приклад:

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 "

Будьте терплячі, f(5,13.0)оскільки простір пошуку функції становить 13 ^ 10. Це можна зробити швидше за допомогою 2 додаткових байтів.


3

Пітон 3 2: 173 159 - 10 = 149

Пояснення: кожне рішення має вигляд x_1 x_2 ... x_n з 1 <= x_1 <= x ^ 2, де x - цільова сума. Тому ми можемо кодувати кожне рішення як ціле число в базі x ^ 2. Цикл while ітереює над усіма (x ^ 2) ^ n можливостями. Потім я конвертую ціле число назад і перевіряю суму. Досить прямо вперед.

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

Він знаходить усі рішення, але останній тестовий випадок триває занадто довго.


3

JavaScript (ES6) 162 (172 - 10) 173

Редагувати трохи коротше, трохи повільніше.

Як функція з 2 параметрами, виведіть на консоль javascript. Це друкує всі рішення без повторень (кортежі рішення генеруються вже відсортованими).
Я піклувався про терміни, ніж про кількість знаків, щоб його легко перевірити в консолі браузера в межах стандартного часового обмеження JavaScript.

(Оновлення лютого 2016 р.) Поточний час останнього тестового випадку: приблизно 1 150 сек . Вимоги до пам'яті: незначні.

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 Будь-який браузер

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

Тест-фрагмент він повинен працювати в будь-якому недавньому браузері

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>

( Редагувати ) Нижче наведено результат на моєму ПК, коли я опублікував цю відповідь 15 місяців тому. Я спробував сьогодні, і це на 100 разів швидше на одному ПК, тільки з 64-бітною альфа-версією Firefox (і Chrome значно відстає)! - поточний час з Firefox 40 Alpha 64 біт: ~ 2 сек, Chrome 48: ~ 29 сек

Вихід (на моєму ПК - останнє число виконання в мілісекундах)

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

Математика - 76 - 20 = 56

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

Приклади

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

Як це друкує No? Також вихід не розділений пробілом. Крім того, ви не можете використовувати Tr@замість цього Plus@@? І ви можете бути в змозі зберегти деякі символи, змінивши Selectдо Cases, функції в кінці кінців до шаблону і роблячи fненазвану чисту функцію.
Мартін Ендер

2

Хаскелл, 87 80 - 10 = 70

Це рекурсивний алгоритм, подібний програмі Python 3 @ Sp3000. Він складається з функції інфікування, #яка повертає список усіх перестановок усіх рішень.

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 ми можемо надрукувати кожне рішення лише один раз, відсортовано:

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

Піт 55 54 47-20 = 27

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

Спробуйте в Інтернеті.

Безсоромно позичає з коментаря xnor ;)

Це не вистачить пам’яті на будь-якому розумному комп’ютері навіть на таке значення 5,5.0. Визначає функцію, gяку можна назвати подібною g 3 7.923668178593959.

Ця програма python 3 використовує по суті той самий алгоритм (просто не виконує друк "Ні" в кінці, що можна зробити, призначивши змінну всім результатам, потім записавши print(K if K else "No")), але використовує генератор, так що вона не ' я не отримаю помилку пам'яті (це все ще займе дуже багато часу, але я зробив це для друку, коли він знаходить значення):

Це дало такі самі результати, які отримав @ Sp3000. Крім того, на це пішло кілька днів (я не встиг, але приблизно 72 години).

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

Пітон 3 - 157 174 169 - 10 = 159

Edit1: Змінено вихідний формат на цілі числа, розділені пробілом, а не розділені комами. Дякуємо за пораду зняття брекетів навколо (n, x).

Edit2: Дякую за поради щодо гольфу! Я можу відрізати ще 9 знаків, якщо просто використовую тест == замість тестування на приблизну рівність в межах 1e-6, але це може визнати недійсними приблизні рішення, якщо такі є.

Використовує itertools для створення всіх можливих цілих комбінацій, сподіваємось ефективно :)

Я не знайшов способу ефективно додати друк "Ні", але, здається, завжди потрібно більше 10 символів.

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

У вашій програмі неправильний формат виводу (коми замість пробілів). Також ви можете поголити 2 байти, знявши брекети навколо n,x.
Згарб

Мені здається, SyntaxErrorщо я намагаюся eval
вступити,

@ Sp3000: спробуйте ввести 3,7.923668178593959. Вам потрібно ','
Jakube

4 невеликі поліпшення: from itertools import*економить 1, видаляючи простір z**.5forзберігає 1, і видалення []ін sum(z**.5for z in c)зберігає 2 і видалення ()ін if(...)зберігає 1.
Jakube

Чи буде зміна Python 2 і використання n,x=input()більш компактним?
Octavia Togami

0

Scala (397 байт - 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}}

Якщо перестановок немає, то ця програма нічого не друкує.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.