একসাথে চার স্কোয়ার


19

লেগ্রঞ্জের চারটি বর্গীয় উপপাদ্য আমাদের জানায় যে কোনও প্রাকৃতিক সংখ্যা চার বর্গ সংখ্যার সমষ্টি হিসাবে উপস্থাপন করা যেতে পারে। আপনার কাজটি এমন একটি প্রোগ্রাম লিখতে হয় যা এটি করে।

ইনপুট: একটি প্রাকৃতিক সংখ্যা (1 বিলিয়ন নীচে)

আউটপুট: চারটি নম্বর যার বর্গক্ষেত্রগুলি সেই সংখ্যার সাথে সমান (অর্ডার কোনও ব্যাপার নয়)

দ্রষ্টব্য: আপনাকে একটি নিষ্ঠুর বাহিনী অনুসন্ধান করতে হবে না! এখানে এবং এখানে বিশদ । যদি কোনও ফাংশন থাকে যা এই সমস্যাটিকে তুচ্ছ করে তোলে (আমি নির্ধারণ করব), এটি অনুমোদিত নয়। অটোমেটেড প্রাইম ফাংশন এবং স্কোয়ার রুট অনুমোদিত। একাধিক উপস্থাপনা থাকলে যে কোনও একটি ভাল আছে fine আপনি যদি নিষ্ঠুর বল প্রয়োগ করা বেছে নিয়ে থাকেন তবে এটি অবশ্যই যথাযথ সময়ের মধ্যে চালানো উচিত (3 মিনিট)

নমুনা ইনপুট

123456789

নমুনা আউটপুট (হয় ভাল)

10601 3328 2 0
10601 3328 2

আমি যদি তা আমার কোডকে আরও সংক্ষিপ্ত করে তোলে তবে আমি জোর করে বলব?
মার্টিন ইন্ডার

@ এম.বয়েটনার হ্যাঁ, তবে এটি বৃহত সংখ্যক হ্যান্ডেল করা উচিত
Qwr

@ এম.বয়েটনার পোস্টটি পড়ুন, যে কোনও প্রাকৃতিক সংখ্যা 1 বিলিয়ন এর নিচে
Qwr

আহ দুঃখিত যে এটি উপেক্ষা।
মার্টিন এন্ডার

2
@ ডেনিস প্রাকৃতিক সংখ্যাগুলিতে এই ক্ষেত্রে 0.
কিউইউআর

উত্তর:


1

সিজেম, 50 বাইট

li:NmF0=~2/#:J(_{;)__*N\-[{_mqJ/iJ*__*@\-}3*])}g+p

আমার তৃতীয় (এবং চূড়ান্ত, আমি প্রতিশ্রুতি) উত্তর। এই পদ্ধতির প্রিমো উত্তর উপর ভিত্তি করে ।

সিজেএম ইন্টারপ্রেটারে এটি অনলাইনে চেষ্টা করুন ।

ব্যবহার

$ cjam 4squares.cjam <<< 999999999
[189 31617 567 90]

পটভূমি

  1. Primo আপডেট এর এলগরিদম এইজন্য পর, আমি ছিল কিভাবে CJam বাস্তবায়ন স্কোর করবে কিনা দেখতে:

    li{W):W;:N4md!}g;Nmqi)_{;(__*N\-[{_mqi__*@\-}3*])}g+2W#f*p
    

    মাত্র 58 বাইট! এই অ্যালগরিদমটি প্রায় ধ্রুবক সময়ে সঞ্চালিত হয় এবং এর বিভিন্ন মানের জন্য খুব বেশি প্রকারের প্রদর্শন করে না N। এর পরিবর্তন করা যাক ...

  2. শুরু floor(sqrt(N))এবং হ্রাসের পরিবর্তে , আমরা শুরু করতে 1এবং বৃদ্ধি করতে পারি । এটি 4 বাইট সঞ্চয় করে।

    li{W):W;:N4md!}g;0_{;)__*N\-[{_mqi__*@\-}3*])}g+2W#f*p
    
  3. Nহিসাবে প্রকাশ করার পরিবর্তে 4**a * b, আমরা এটি প্রকাশ করতে পারি p**(2a) * b- আরও 1 টি বাইট সংরক্ষণ করার pজন্য N- এর মধ্যে ক্ষুদ্রতম প্রাথমিক উপাদানটি ।

    li_mF0=~2/#:J_*/:N!_{;)__*N\-[{_mqi__*@\-}3*])}g+Jf*p
    
  4. পূর্ববর্তী পরিবর্তনটি আমাদের প্রয়োগটিকে কিছুটা পরিবর্তনের অনুমতি দেয় (নিজেই অ্যালগোরিদমকে স্পর্শ না করে): সমাধানটি দ্বারা ভাগ Nকরে p**(2a)এবং এর দ্বারা গুন করার পরিবর্তে p**aআমরা সরাসরি সম্ভাব্য সমাধানগুলি বহুগুণে সীমাবদ্ধ করতে পারি p**a। এটি আরও 2 বাইট সঞ্চয় করে।

    li:NmF0=~2/#:J!_{;J+__*N\-[{_mqJ/iJ*__*@\-}3*])}g+`
    
  5. প্রথম পূর্ণসংখ্যাকে বহুগুণে সীমাবদ্ধ না করা p**aঅতিরিক্ত বাইট সংরক্ষণ করে।

    li:NmF0=~2/#:J(_{;)__*N\-[{_mqJ/iJ*__*@\-}3*])}g+`
    

চূড়ান্ত অ্যালগরিদম

  1. সন্ধান করুন aএবং bএরকম N = p**(2a) * b, যেখানে bএকাধিক নয় p**2এবং এর pমধ্যে সবচেয়ে ছোট মৌলিক উপাদান N

  2. সেট j = p**a

  3. সেট k = floor(sqrt(N - j**2) / A) * A

  4. সেট l = floor(sqrt(N - j**2 - k**2) / A) * A

  5. সেট m = floor(sqrt(N - j**2 - k**2 - l**2) / A) * A

  6. যদি N - j**2 - k**2 - l**2 - m**2 > 0, সেট করে j = j + 13 য় ধাপে ফিরে যান।

এটি নিম্নলিখিত হিসাবে প্রয়োগ করা যেতে পারে:

li:N          " Read an integer from STDIN and save it in “N”.                        ";
mF            " Push the factorization of “N”. Result: [ [ p1 a1 ] ... [ pn an ] ]    ";
0=~           " Push “p1” and “a1”. “p1” is the smallest prime divisor of “N”.        ";
2/#:J         " Compute p1**(a1/2) and save the result “J”.                           ";
(_            " Undo the first two instructions of the loop.                          ";
{             "                                                                       ";
  ;)_         " Pop and discard. Increment “J” and duplicate.                         ";
  _*N\-       " Compute N - J**2.                                                     ";
  [{          "                                                                       ";
    _mqJ/iJ*  " Compute K = floor(sqrt(N - J**2)/J)*J.                                ";
    __*@      " Duplicate, square and rotate. Result: K   K**2   N - J**2             ";
    \-        " Swap and subtract. Result: K   N - J**2 - K**2                        ";
  }3*]        " Do the above three times and collect in an array.                     ";
  )           " Pop the array. Result: N - J**2 - K**2 - L**2 - M**2                  ";
}g            " If the result is zero, break the loop.                                ";
+p            " Unshift “J” in [ K L M ] and print a string representation.           ";

benchmarks

আমি আমার ইন্টেল কোর আই -3-70 ,70০ পর্যন্ত 999,999,999 অবধি সমস্ত ইতিবাচক পূর্ণসংখ্যার উপর 5 টি সংস্করণ চালিয়েছি, প্রয়োগের সময় পরিমাপ করেছি এবং সমাধান খুঁজতে প্রয়োজনীয় পুনরাবৃত্তি গণনা করেছি।

নিম্নলিখিত টেবিলটি একক পূর্ণসংখ্যার জন্য পুনরাবৃত্তির গড় সংখ্যা এবং সম্পাদনের সময় দেখায়:

Version               |    1    |    2    |    3    |    4    |    5
----------------------+---------+---------+---------+---------+---------
Number of iterations  |  4.005  |  28.31  |  27.25  |  27.25  |  41.80
Execution time [µs]   |  6.586  |  39.69  |  55.10  |  63.99  |  88.81
  1. প্রতি পূর্ণসংখ্যায় কেবল 4 পুনরাবৃত্তি এবং 6.6 মাইক্রো সেকেন্ডে, প্রিমোর অ্যালগরিদম অবিশ্বাস্যভাবে দ্রুত।

  2. এ থেকে শুরু করা floor(sqrt(N))আরও অর্থবোধ করে, যেহেতু এটি আমাদের বাকি তিনটি স্কোয়ারের যোগফলের জন্য ছোট মান রাখে। প্রত্যাশিত হিসাবে, 1 থেকে শুরু করা অনেক ধীর।

  3. এটি একটি খারাপভাবে প্রয়োগ করা ভাল ধারণার একটি শাস্ত্রীয় উদাহরণ। আসলে করার কমাতে কোড আকার, আমরা উপর নির্ভর mFকরে, যা পূর্ণসংখ্যা factorizes N। যদিও সংস্করণ 3 সংস্করণ 2 এর চেয়ে কম পুনরাবৃত্তি প্রয়োজন, এটি অনুশীলনে অনেক ধীর।

  4. যদিও অ্যালগরিদম পরিবর্তন হয় না, সংস্করণ 4 অনেক ধীর। কারণ এটি প্রতিটি পুনরাবৃত্তিতে একটি অতিরিক্ত ভাসমান পয়েন্ট বিভাগ এবং পূর্ণসংখ্যা গুণ করে।

  5. ইনপুটটির জন্য N = p**(2a) ** b, অ্যালগরিদম 5 এর (k - 1) * p**a + 1পুনরাবৃত্তির প্রয়োজন হবে , যেখানে kঅ্যালগরিদম 4 এর পুনরাবৃত্তির সংখ্যা প্রয়োজন। যদি k = 1বা a = 0, এটি কোনও পার্থক্য করে না।

    তবে ফর্মটির যে কোনও ইনপুট 4**a * (4**c * (8 * d + 7) + 1)বেশ খারাপভাবে পারফর্ম করতে পারে। শুরু মূল্য জন্য j = p**a, N - 4**a = 4**(a + c) * (8 * d + 7), তাই এটি তিন স্কোয়ার একটি সমষ্টি হিসাবে প্রকাশ করা যাবে না। সুতরাং, k > 1এবং কমপক্ষে p**aপুনরাবৃত্তি প্রয়োজন are

    ধন্যবাদ, প্রিমোর আসল অ্যালগরিদম অবিশ্বাস্যভাবে দ্রুত এবং N < 1,000,000,000। সবচেয়ে খারাপ ঘটনাটি আমি হাতে 265,289,728 = 4**10 * (4**1 * (7 * 8 + 7) + 1)পেয়েছি, যার জন্য 6,145 পুনরাবৃত্তি প্রয়োজন। এক্সিকিউশন সময়টি আমার মেশিনে 300 এমএসেরও কম। গড়ে, এই সংস্করণটি প্রিমোর অ্যালগরিদমের প্রয়োগের তুলনায় 13.5 গুণ বেশি ধীর।


" Nযেমনটি প্রকাশ করার পরিবর্তে 4**a * b, আমরা এটি হিসাবে প্রকাশ করতে পারি p**(2a) * b" " এটি আসলে একটি উন্নতি । আমি এটি অন্তর্ভুক্ত করতে পছন্দ করতাম তবে এটি অনেক দীর্ঘ ছিল (আদর্শ হ'ল বৃহত্তম নিখুঁত বর্গক্ষেত্রের উপাদানটি খুঁজে পাওয়া)। "1 দিয়ে শুরু করা এবং ইনক্রিমেন্টিং 4 বাইট সংরক্ষণ করে।" এটি অবশ্যই ধীর। যে কোনও প্রদত্ত পরিসরের রানটাইম 4-5 গুণ দীর্ঘ। "999,999,999 অবধি সমস্ত ধনাত্মক পূর্ণসংখ্যার সময়কৃত 0.008 মিলি সেকেন্ডের গড় কার্যকর সময় দেয়, 24.67 ঘন্টা সময় নেয়" " পার্ল পুরো ব্যাপ্তিটি সঙ্কুচিত করতে কেবল 2.5 ঘন্টা সময় নিয়েছিল এবং পাইথন অনুবাদটি 10x দ্রুত হয়;)
প্রিমো

@ প্রিমো: হ্যাঁ, আপনি ঠিক বলেছেন। ভাগ করে p**aনেওয়া একটি উন্নতি, তবে এটি একটি ছোট্ট। 1 থেকে শুরু করার সময় বৃহত্তম নিখুঁত বর্গক্ষেত্র ফ্যাক্টর দ্বারা ভাগ করা বড় পার্থক্য করে; বর্গমূলের পূর্ণসংখ্যার অংশ থেকে শুরু করার সময় এটি এখনও উন্নতি। এটি বাস্তবায়নের জন্য আরও দুটি বাইট লাগবে। অসাধারণ মৃত্যুর সময়টি সিজেএম-এর পরিবর্তে আমার সংবিধানের কারণে বলে মনে হচ্ছে। আমি সমস্ত অ্যালগোরিদমগুলির জন্য পরীক্ষাগুলি পুনরায় চালু করব (প্রাচীরের সময়টি পরিমাপ করার পরিবর্তে পুনরাবৃত্তির গণনা) proposed দেখা যাক কতদিন যে লাগে ...
ডেনিস

বৃহত্তম স্কোয়ার ফ্যাক্টর সন্ধান করতে কেবল 2 টি অতিরিক্ত বাইট খরচ হয় ?! এই জাদু কি ধরনের?
প্রিমো

@ প্রিমো: যদি পূর্ণসংখ্যা স্ট্যাকের উপরে থাকে তবে 1\এটিকে 1 (জমে থাকা) দিয়ে অদলবদল করে, mFতার অনুকরণকে ধাক্কা দেয় এবং {~2/#*}/প্রতিটি মৌলিক উপাদানকে তার বিভক্তকারীকে দুটি দ্বারা বিভক্ত করে তোলে, তারপরে এটি সংযোজকের সাহায্যে বহুগুণ করে। আপনার অ্যালগরিদমের সরাসরি বাস্তবায়নের জন্য, এটি কেবল 2 বাইট যোগ করে। ছোট পার্থক্যটি মূলত আমার কাছে 4 টির বেদীটি খুঁজে বের করার জন্য বিশ্রী পথের কারণে, যেহেতু সিজেম (মনে হয় না) কিছুক্ষণ লুপ করে না ...
ডেনিস

যাইহোক, বেঞ্চমার্ক শেষ হয়েছে। বৃহত্তম স্কোয়ার ফ্যাক্টরটি খুঁজে না পেয়ে সমস্ত 1,000,000 পূর্ণসংখ্যার গুণন করতে মোট পুনরাবৃত্তির সংখ্যা 4,004,829,417, যার কার্য সম্পাদনের সময়টি 1.83 ঘন্টা রয়েছে। বৃহত্তম স্কোয়ার ফ্যাক্টর দ্বারা বিভাজন পুনরাবৃত্তি গণনাটি 3,996,724,799 এ হ্রাস করে তবে সময়টি বাড়িয়ে 6.7 ঘন্টা করে দেয়। দেখে মনে হচ্ছে স্কোয়ারগুলি খুঁজে পাওয়ার চেয়ে আরও বেশি সময় লাগে ...
ডেনিস

7

ফ্যাক্টরান: 156 98 ভগ্নাংশ

যেহেতু এটি একটি ক্লাসিক নম্বর তত্ত্বের সমস্যা, তাই সংখ্যাগুলি ব্যবহার করার চেয়ে সমাধানের এর থেকে উত্তম উপায় আর কী!

37789/221 905293/11063 1961/533 2279/481 57293/16211 2279/611 53/559 1961/403 53/299 13/53 1/13 6557/262727 6059/284321 67/4307 67/4661 6059/3599 59/83 1/59 14279/871933 131/9701 102037079/8633 14017/673819 7729/10057 128886839/8989 13493/757301 7729/11303 89/131 1/89 31133/2603 542249/19043 2483/22879 561731/20413 2483/23701 581213/20687 2483/24523 587707/21509 2483/24797 137/191 1/137 6215941/579 6730777/965 7232447/1351 7947497/2123 193/227 31373/193 23533/37327 5401639/458 229/233 21449/229 55973/24823 55973/25787 6705901/52961 7145447/55973 251/269 24119/251 72217/27913 283/73903 281/283 293/281 293/28997 293/271 9320827/58307 9831643/75301 293/313 28213/293 103459/32651 347/104807 347/88631 337/347 349/337 349/33919 349/317 12566447/68753 13307053/107143 349/367 33197/349 135199/38419 389/137497 389/119113 389/100729 383/389 397/383 397/39911 397/373 1203/140141 2005/142523 2807/123467 4411/104411 802/94883 397/401 193/397 1227/47477 2045/47959 2863/50851 4499/53743 241/409 1/241 1/239

2 এন × 193 ফর্মটির ইনপুট নেয় এবং 3 × 5 বি × 7 সি × 11 ডি আউটপুট দেয় । আপনার যদি সত্যিই একজন ভাল দোভাষী থাকে তবে 3 মিনিটের মধ্যে রান করতে পারেন । হতে পারে.

... ঠিক আছে, আসলেই না। এই যে আমি FRACTRAN না যেমন একটি মজা সমস্যা হতে করলো ছিল এটা চেষ্টা করতে। স্পষ্টতই, এটি প্রশ্নের যথাযথ সমাধান নয় কারণ এটি সময়ের প্রয়োজনীয়তা তৈরি করে না (এটি শক্তিশালী করে তোলে) এবং এটি সবেমাত্র গল্ফ হয়েছে, তবে আমি ভেবেছিলাম যে আমি এখানে এটি পোস্ট করব কারণ এটি প্রতিদিনই কোডগল্ফের প্রশ্ন নয় ফ্রেট্র্যানে করা যেতে পারে;)

ইঙ্গিত

কোডটি নিম্নলিখিত সিউডো-পাইথনের সমতুল্য:

a, b, c, d = 0, 0, 0, 0

def square(n):
    # Returns n**2

def compare(a, b):
    # Returns (0, 0) if a==b, (1, 0) if a<b, (0, 1) if a>b

def foursquare(a, b, c, d):
    # Returns square(a) + square(b) + square(c) + square(d)

while compare(foursquare(a, b, c, d), n) != (0, 0):
    d += 1

    if compare(c, d) == (1, 0):
        c += 1
        d = 0

    if compare(b, c) == (1, 0):
        b += 1
        c = 0
        d = 0

    if compare(a, b) == (1, 0):
        a += 1
        b = 0
        c = 0
        d = 0

7

গণিত 61 61 51

তিনটি পদ্ধতি দেখানো হয়েছে। কেবলমাত্র প্রথম পদ্ধতির সময় প্রয়োজন পূরণ করে।


1-FindInstance (51 চর)

এটি একটি একক সমাধান সমীকরণ প্রদান করে।

FindInstance[a^2 + b^2 + c^2 + d^2 == #, {a, b, c, d}, Integers] &

উদাহরণ এবং সময়

FindInstance[a^2 + b^2 + c^2 + d^2 == 123456789, {a, b, c, d}, Integers] // AbsoluteTiming

{0.003584, {{এ -> 2600, বি -> 378, সি -> 10468, ডি -> 2641}}

FindInstance[a^2 + b^2 + c^2 + d^2 == #, {a, b, c, d}, Integers] &[805306368]

{0.004437, {{এ -> 16384, বি -> 16384, সি -> 16384, ডি -> 0}}


2-IntegerPartitions

এটিও কাজ করে তবে গতির প্রয়োজনীয়তা পূরণ করতে খুব ধীর is

f@n_ := Sqrt@IntegerPartitions[n, {4}, Range[0, Floor@Sqrt@n]^2, 1][[1]]

Range[0, Floor@Sqrt@n]^2সমস্ত স্কোয়ারের সেটটি বর্গমূলের চেয়ে কম n(পার্টিশনের বৃহত্তম সম্ভাব্য বর্গ)।

{4}nউপরে উল্লিখিত স্কোয়ারগুলি থেকে 4 টি উপাদান সমন্বিত পূর্ণসংখ্যার পার্টিশনগুলির প্রয়োজন ।

1ফাংশনের IntegerPartitionsমধ্যে প্রথম সমাধানটি দেয়।

[[1]]বাইরের ধনুর্বন্ধনী অপসারণ; সমাধানটি একটি উপাদানের সেট হিসাবে ফিরে এসেছিল।


f[123456]

{348, 44, 20, 4


3-PowerRepresentations

পাওয়ারআরপিভারেশনগুলি 4 স্কোয়ার সমস্যার সমস্ত সমাধান ফিরিয়ে দেয় । এটি অন্যান্য শক্তির পরিমাণের জন্যও সমাধান করতে পারে।

পাওয়ারস রিসার্চেশনগুলি 5 সেকেন্ডের নীচে, 123456789 টি 4 স্কোয়ারের যোগফল হিসাবে প্রকাশ করার 181 টি উপায়:

n= 123456;
PowersRepresentations[n, 4, 2] //AbsoluteTiming

sols

তবে অন্যান্য অঙ্কের ক্ষেত্রে এটি খুব ধীর।


বাহ, গণিত দ্রুত নিষ্ঠুর শক্তি প্রয়োগ করে। ইন্টিজার পার্টিশনগুলি সেটগুলিতে ডিএফটি কনভ্যুশনের মতো প্রতিটি সংমিশ্রণের চেষ্টা করার চেয়ে অনেক বেশি চালাক কিছু করছে? চশমাগুলি তাদের স্কোয়ারগুলি না করে উপায়গুলির জন্য জিজ্ঞাসা করে।
xnor

আমি মনে করি ম্যাথমেটিকা ​​নিষ্ঠুর শক্তি ব্যবহার করে তবে সম্ভবত অনুকূলিত হয়েছে IntegerPartitions। আপনি সময় থেকে দেখতে পাচ্ছেন, প্রথম (বৃহত্তম) সংখ্যাটি বর্গমূলের কাছাকাছি কিনা তার উপর নির্ভর করে গতি অনেক বেশি পরিবর্তিত হয় n। পূর্ববর্তী সংস্করণে অনুমানের লঙ্ঘন ধরার জন্য ধন্যবাদ Thanks
ডেভিডসি

আপনি বেনমার্ক করতে পারেন f[805306368]? প্রথম 4 টির ক্ষমতায় বিভাজন ছাড়াই, আমার সমাধানটি 999999999 এর জন্য 0.05 এস লাগে; আমি 5 মিনিটের পরে 805306368 এর জন্য বেঞ্চমার্কটি বাতিল করেছি ...
ডেনিস

f[805306368]{16384, 16384, 16384}21 মিনিটের পরে ফিরে আসে । আমি {4 of এর জায়গায় {3} ব্যবহার করেছি} 4 টি নন-শূন্য স্কোয়ারের যোগফল সহ এটি সমাধানের প্রচেষ্টা কয়েক ঘন্টা দৌড়ানোর পরেও ব্যর্থ হয়েছিল।
ডেভিডসি

আমার গাণিতিক অ্যাক্সেস নেই, তবে ডকুমেন্টেশন সেন্টারে যা পড়েছি তা থেকেও IntegerPartitions[n,4,Range[Floor@Sqrt@n]^2কাজ করা উচিত। তবে, আমি মনে করি না যে আপনার স্কোরের জন্য আপনার পদ্ধতি 1 টি ব্যবহার করা উচিত, কারণ এটি প্রশ্নের ক্ষেত্রে নির্দিষ্ট সময়সীমা মেনে চলে না।
ডেনিস

7

পার্ল - 116 বাইট 87 বাইট (নীচে আপডেট দেখুন)

#!perl -p
$.<<=1,$_>>=2until$_&3;
{$n=$_;@a=map{$n-=$a*($a-=$_%($b=1|($a=0|sqrt$n)>>1));$_/=$b;$a*$.}($j++)x4;$n&&redo}
$_="@a"

শেবাংকে এক বাইট হিসাবে গণনা করা হচ্ছে, অনুভূমিক বিগ্রহের জন্য নতুন লাইন যুক্ত হয়েছে।

একটি সংমিশ্রণ জমা দেওয়ার কিছু।

গড় (সবচেয়ে খারাপ?) কেস জটিলতায় ও (লগ এন) ও (এন 0.07 ) বলে মনে হচ্ছে । আমি কিছুই পাইনি 0.001 এর চেয়ে ধীরগতিতে রান চালিয়েছি এবং 900000000 - 999999999 থেকে পুরো পরিসরটি পরীক্ষা করেছি । আপনি যদি এর চেয়ে উল্লেখযোগ্যভাবে বেশি সময় নেয় এমন কোনও কিছু খুঁজে পান, ~ 0.1s বা তার বেশি, দয়া করে আমাকে জানান।


নমুনা ব্যবহার

$ echo 123456789 | timeit perl four-squares.pl
11110 157 6 2

Elapsed Time:     0:00:00.000

$ echo 1879048192 | timeit perl four-squares.pl
32768 16384 16384 16384

Elapsed Time:     0:00:00.000

$ echo 999950883 | timeit perl four-squares.pl
31621 251 15 4

Elapsed Time:     0:00:00.000

এগুলির মধ্যে চূড়ান্ত দুটিটি অন্যান্য জমা দেওয়ার ক্ষেত্রে খারাপ পরিস্থিতি বলে মনে হচ্ছে। উভয় উদাহরণেই দেখানো সমাধানটি বেশ আক্ষরিক অর্থেই প্রথম পরীক্ষা করা হয়েছে। কারণ 123456789এটি দ্বিতীয়।

আপনি যদি মানগুলির একটি ব্যাপ্তি পরীক্ষা করতে চান তবে আপনি নিম্নলিখিত স্ক্রিপ্টটি ব্যবহার করতে পারেন:

use Time::HiRes qw(time);

$t0 = time();

# enter a range, or comma separated list here
for (1..1000000) {
  $t1 = time();
  $initial = $_;
  $j = 0; $i = 1;
  $i<<=1,$_>>=2until$_&3;
  {$n=$_;@a=map{$n-=$a*($a-=$_%($b=1|($a=0|sqrt$n)>>1));$_/=$b;$a*$i}($j++)x4;$n&&redo}
  printf("%d: @a, %f\n", $initial, time()-$t1)
}
printf('total time: %f', time()-$t0);

কোনও ফাইলে পাইপ দেওয়ার সময় সেরা। পরিসীমাটি 1..1000000আমার কম্পিউটারে সেকেন্ডে প্রায় 14 সেকেন্ডে লাগে (প্রতি সেকেন্ডে 71000 মান) এবং ও (লগ এন) গড় জটিলতার 999000000..1000000000সাথে সামঞ্জস্য রেখে পরিসীমাটি প্রায় 20 সেকেন্ড (প্রতি সেকেন্ডে 50000 মান) লাগে ।


হালনাগাদ

সম্পাদনা : দেখা যাচ্ছে যে এই অ্যালগরিদমটি মানসিক ক্যালকুলেটর দ্বারা কমপক্ষে এক শতাব্দী ধরে ব্যবহার করা হয়েছে এমন একটির সাথে খুব মিল ।

প্রাথমিকভাবে পোস্ট করার পর থেকে, আমি ১.১০০০০০০০০০০ থেকে শুরু করে প্রতিটি মান পরীক্ষা করেছি । 'নিকৃষ্টতম ঘটনা' আচরণটি 699731569 মান দ্বারা প্রদর্শিত হয়েছিল , যা কোনও সমাধানে পৌঁছানোর আগে সর্বমোট 190 টি সংমিশ্রণ পরীক্ষা করেছিল। আপনি যদি 190 কে একটি ছোট ধ্রুবক হিসাবে বিবেচনা করেন - এবং আমি অবশ্যই করি - প্রয়োজনীয় পরিসরে সবচেয়ে খারাপ ক্ষেত্রে আচরণ ও (1) হিসাবে বিবেচনা করা যেতে পারে । এটি, একটি দৈত্য টেবিল থেকে সমাধানটি তত দ্রুত এবং সম্ভবত সম্ভবত বেশ দ্রুত।

আরেকটি জিনিস যদিও। ১৯০ টি পুনরাবৃত্তির পরে , ১৪৪৪০০ এর চেয়ে বড় কিছু এটি প্রথম পাসের বাইরেও তৈরি করতে পারেনি। প্রস্থের প্রথম ট্র্যাভারসালের জন্য যুক্তিটি মূল্যহীন - এটি এমনকি ব্যবহৃত হয় না। উপরের কোডটি বেশ কিছুটা ছোট করা যায়:

#!perl -p
$.*=2,$_/=4until$_&3;
@a=map{$=-=$%*($%=$=**.5-$_);$%*$.}$j++,(0)x3while$=&&=$_;
$_="@a"

যা কেবল অনুসন্ধানের প্রথম পাসটি করে। আমাদের নিশ্চিত করতে হবে যে 144400 এর নীচে এমন কোনও মান নেই যা দ্বিতীয় পাসের প্রয়োজন, যদিও:

for (1..144400) {
  $initial = $_;

  # reset defaults
  $.=1;$j=undef;$==60;

  $.*=2,$_/=4until$_&3;
  @a=map{$=-=$%*($%=$=**.5-$_);$%*$.}$j++,(0)x3while$=&&=$_;

  # make sure the answer is correct
  $t=0; $t+=$_*$_ for @a;
  $t == $initial or die("answer for $initial invalid: @a");
}

সংক্ষেপে, 1..1000000000 ব্যাপ্তির জন্য , একটি অবিচ্ছিন্ন সময় সমাধান উপস্থিত রয়েছে এবং আপনি এটি সন্ধান করছেন।


আপডেট আপডেট

@ ডেনিস এবং আমি এই অ্যালগরিদমটিতে বেশ কয়েকটি উন্নতি করেছি। আপনি যদি আগ্রহী হন তবে আপনি নীচের মন্তব্যে অগ্রগতি এবং পরবর্তী আলোচনা অনুসরণ করতে পারেন। প্রয়োজনীয় পরিসরের জন্য পুনরাবৃত্তির গড় সংখ্যা মাত্র 4 এর নিচে নেমে 1.229 এ নেমেছে এবং 1..1000000000 এর জন্য সমস্ত মান পরীক্ষা করার জন্য প্রয়োজনীয় সময়টি 18 মি 54 এর থেকে উন্নত করে 2 মি 41 এ পরিণত হয়েছে। সবচেয়ে খারাপ ক্ষেত্রে আগে 190 পুনরাবৃত্তি প্রয়োজন ; সবচেয়ে খারাপ ক্ষেত্রে এখন 854382778 , প্রয়োজন কেবল 21

চূড়ান্ত পাইথন কোডটি নিম্নলিখিত:

from math import sqrt

# the following two tables can, and should be pre-computed

qqr_144 = set([  0,   1,   2,   4,   5,   8,   9,  10,  13,
                16,  17,  18,  20,  25,  26,  29,  32,  34,
                36,  37,  40,  41,  45,  49,  50,  52,  53,
                56,  58,  61,  64,  65,  68,  72,  73,  74,
                77,  80,  81,  82,  85,  88,  89,  90,  97,
                98, 100, 101, 104, 106, 109, 112, 113, 116,
               117, 121, 122, 125, 128, 130, 133, 136, 137])

# 10kb, should fit entirely in L1 cache
Db = []
for r in range(72):
  S = bytearray(144)
  for n in range(144):
    c = r

    while True:
      v = n - c * c
      if v%144 in qqr_144: break
      if r - c >= 12: c = r; break
      c -= 1

    S[n] = r - c
  Db.append(S)

qr_720 = set([  0,   1,   4,   9,  16,  25,  36,  49,  64,  81, 100, 121,
              144, 145, 160, 169, 180, 196, 225, 241, 244, 256, 265, 289,
              304, 324, 340, 361, 369, 385, 400, 409, 436, 441, 481, 484,
              496, 505, 529, 544, 576, 580, 585, 601, 625, 640, 649, 676])

# 253kb, just barely fits in L2 of most modern processors
Dc = []
for r in range(360):
  S = bytearray(720)
  for n in range(720):
    c = r

    while True:
      v = n - c * c
      if v%720 in qr_720: break
      if r - c >= 48: c = r; break
      c -= 1

    S[n] = r - c
  Dc.append(S)

def four_squares(n):
  k = 1
  while not n&3:
    n >>= 2; k <<= 1

  odd = n&1
  n <<= odd

  a = int(sqrt(n))
  n -= a * a
  while True:
    b = int(sqrt(n))
    b -= Db[b%72][n%144]
    v = n - b * b
    c = int(sqrt(v))
    c -= Dc[c%360][v%720]
    if c >= 0:
      v -= c * c
      d = int(sqrt(v))

      if v == d * d: break

    n += (a<<1) - 1
    a -= 1

  if odd:
    if (a^b)&1:
      if (a^c)&1:
        b, c, d = d, b, c
      else:
        b, c = c, b

    a, b, c, d = (a+b)>>1, (a-b)>>1, (c+d)>>1, (c-d)>>1

  a *= k; b *= k; c *= k; d *= k

  return a, b, c, d

এটি দুটি প্রাক-গণিত সংশোধন টেবিল ব্যবহার করে, একটি 10kb আকারের, অন্যটি 253kb। উপরের কোডটিতে এই টেবিলগুলির জন্য জেনারেটর ফাংশন অন্তর্ভুক্ত রয়েছে, যদিও এগুলি সম্ভবত সংকলনের সময় গণনা করা উচিত।

আরও পরিমিত আকারের সংশোধন টেবিল সহ একটি সংস্করণ এখানে পাওয়া যাবে: http://codepad.org/1ebJC2OV এই সংস্করণটির গড় প্রতি গড় 1.620 পুনরাবৃত্তি প্রয়োজন, 38 টির সবচেয়ে খারাপ ক্ষেত্রে এবং পুরো পরিসীমাটি প্রায় 3 মি 21 সেকেন্ডে চলে runs মডুলোর পরিবর্তে বি সংশোধনের andজন্য বিটওয়াইজ ব্যবহার করে কিছুটা সময় তৈরি করা হয় ।


উন্নতি

এমনকি মানগুলি বিজোড় মানগুলির চেয়ে সমাধান তৈরি করার সম্ভাবনা বেশি।
পূর্ববর্তী নোটগুলির সাথে যুক্ত মানসিক গণনা নিবন্ধটি উল্লেখ করেছে যে, চারটি সমস্ত কারণকে অপসারণের পরে, পচে যাওয়া মানটি যদি সমান হয় তবে এই মানটিকে দুটি দ্বারা ভাগ করা যায় এবং সমাধানটি পুনর্গঠিত হয়:

যদিও এটি মানসিক গণনার জন্য অর্থবোধ করতে পারে (ছোট মানগুলি গণনা করা সহজ হয়) তবে এটি অ্যালগোরিদমিকভাবে খুব বেশি বোঝায় না। আপনি যদি 256 এলোমেলো 4- টিপলস নিয়ে যান এবং 8 টি বর্গাকার মডুলোর 8 যোগফলটি পরীক্ষা করেন , আপনি দেখতে পাবেন যে 1 , 3 , 5 এবং 7 এর মান প্রতিটি গড়ে 32 বার পৌঁছেছে । তবে, 2 এবং 6 এর মানগুলি প্রতিটি 48 বার পৌঁছেছে । বিজোড় মানগুলিকে 2 দ্বারা গুণিত করা , 33% কম পুনরাবৃত্তিতে একটি সমাধান খুঁজে পাবে । পুনর্গঠন নিম্নলিখিত:

যত্ন নেওয়া দরকার যে এবং সমান সমতা রয়েছে তেমনি সি এবং ডিও রয়েছে তবে যদি কোনও সমাধান পাওয়া যায় তবে একটি যথাযথ অর্ডারের অস্তিত্বের নিশ্চয়তা দেওয়া হয়।

অসম্ভব পথগুলি পরীক্ষা করার দরকার নেই।
দ্বিতীয় মান, নির্বাচন করার পরে, কোনও প্রদত্ত মডুলোর সম্ভাব্য চতুর্ভুজীয় অবশিষ্টাংশ প্রদত্ত সমাধানের পক্ষে ইতিমধ্যে এটি অসম্ভব হয়ে উঠতে পারে। যাইহোক যাইহোক পরীক্ষা করা, বা পরবর্তী পুনরাবৃত্তির দিকে যাওয়ার পরিবর্তে, এর মান সবচেয়ে কম পরিমাণে হ্রাস করে 'সংশোধন' করা যেতে পারে যা সম্ভবত সমাধানের দিকে নিয়ে যেতে পারে। দুটি সংশোধন সারণি এই মানগুলিকে সঞ্চয় করে, একটি খ এর জন্য এবং অন্যটি সি এর জন্য । উচ্চতর মডুলো (আরও সঠিকভাবে, তুলনামূলকভাবে কম চতুষ্কোণীয় অবশিষ্টাংশ সহ একটি মডিউল ব্যবহার করা) ব্যবহারের ফলে আরও উন্নতি হবে। মান একটি কোনো সংশোধনের প্রয়োজন হয় না; সমান হতে n এর সংশোধন করে , সমস্ত মানএকটি বৈধ হয়।


1
এই অবিশ্বাস্য! চূড়ান্ত অ্যালগরিদম সম্ভবত সমস্ত উত্তরগুলির মধ্যে সহজতম, তবুও 190 পুনরাবৃত্তিগুলি যা লাগে তা ...
ডেনিস

@ ডেনিস আমাকে অন্যথায় যদি এর উল্লেখ না করা হয় তবে আমি খুব অবাক করে দেব। খুব বেশি নজর দেওয়া খুব সহজ বলে মনে হচ্ছে।
প্রিমো

১. আমি কৌতূহলী: আপনার জটিলতা বিশ্লেষণের পরীক্ষার মানগুলির জন্য কি প্রস্থের প্রথম ট্র্যাভারসাল প্রয়োজন? ২. উইকিপিডিয়া নিবন্ধটি আপনি সংযুক্ত করেছেন কিছুটা বিভ্রান্তিকর। এটি রবিন-শ্যালিট অ্যালগরিদমের উল্লেখ করেছে তবে সম্পূর্ণ আলাদা একটির জন্য উদাহরণ দেয়। ৩. এটি দেখতে আকর্ষণীয় হবে যে কখন রবিন-শ্যালিট অ্যালগরিদম আপনার চেয়ে বেশি কার্যকর হবে, আমি ভাবতাম প্রাথমিক পরীক্ষাগুলি অনুশীলনে বরং ব্যয়বহুল।
ডেনিস

1. এক নয়। ২. এখানেই আমি আমার তথ্য পেয়েছি (অর্থাত্ এই অ্যালগোরিদমটি বিদ্যমান); আমি বিশ্লেষণটি দেখিনি, এমনকি কাগজটিও পড়িনি। ৩. বক্ররেখাটি 1e60-এর কাছাকাছি এতটা খাড়া হয়ে যায় যে ও (লোগান) কতটা 'ধীর' হয় তা বিবেচনা করে না , এটি এখনও প্রায় সেই বিন্দুটি অতিক্রম করবে।
প্রিমো

1
প্রশ্নের দ্বিতীয় লিঙ্কটি কীভাবে রবিন-শালিট বাস্তবায়ন করতে পারে তা ব্যাখ্যা করে, তবে জটিলতার বিষয়ে এটি কোনও কথা বলে না। ম্যাথওভারফ্লোতে এই উত্তরটি কাগজের একটি দুর্দান্ত সংক্ষিপ্তসার দেয়। যাইহোক, আপনি 1911 সালে গটফ্রিড রকল দ্বারা ব্যবহৃত একটি অ্যালগরিদম পুনরায় আবিষ্কার করেছেন ( লিঙ্ক )।
ডেনিস

6

পাইথন 3 (177)

N=int(input())
k=1
while N%4<1:N//=4;k*=2
n=int(N**.5)
R=range(int(2*n**.5)+1)
print([(a*k,b*k,c*k,d*k)for d in R for c in R for b in R for a in[n,n-1]if a*a+b*b+c*c+d*d==N][0])

আমরা N4 দ্বারা বিভাজ্য না হওয়ার জন্য ইনপুট হ্রাস করার পরে , এটি অবশ্যই চার স্কোয়ারের যোগফল হিসাবে স্পষ্টরূপে হওয়া উচিত যেখানে এর মধ্যে একটি হল সর্বাধিক সম্ভাব্য মান a=int(N**0.5)বা এর চেয়ে কম একটি, অন্য তিনটি স্কোয়ারের যোগফলের জন্য কেবলমাত্র একটি ছোট্ট বাকী অংশ রেখে যায় যত্ন নিতে. এটি অনুসন্ধানের স্থানটিকে হ্রাস করে।

এখানে একটি প্রমাণ পরে দেওয়া হয়েছে এই কোডটি সর্বদা একটি সমাধান খুঁজে পায়। আমরা একটি এটি করতে ইচ্ছুক a, যাতে n-a^2তিন বর্গের সমষ্টি নয়। থেকে লেজেন্ড্রে তিন স্কয়ার উপপাদ্য , একটি তিন নম্বর বর্গের সমষ্টি যদি না তা ফর্ম হয় 4^j(8*k+7)। বিশেষত, এই জাতীয় সংখ্যা হয় 0 বা 3 (মডিউল 4)।

আমরা দেখাই যে aটানা দু'একটিই টানা N-a^2দুটি মানের জন্য অবশিষ্ট পরিমাণের এইরকম একটি আকৃতি তৈরি করতে পারে না .. আমরা কেবলমাত্র একটি টেবিল তৈরি করে তা করতে পারি 4 aএবং Nমডুলো 4, উল্লেখ করে যে N%4!=0আমরা 4 টির বাইরে সমস্ত ক্ষমতা বের করেছি N

  a%4= 0123
      +----
     1|1010
N%4= 2|2121  <- (N-a*a)%4
     3|3232

যেহেতু টানা দু'বার aদেয় না (N-a*a)%4 in [0,3], তাদের মধ্যে একটিও ব্যবহার করা নিরাপদ। সুতরাং, আমরা লোভের nসাথে n^2<=Nএবং এর মাধ্যমে সবচেয়ে বড় সম্ভাব্য ব্যবহার করি n-1। যেহেতু N<(n+1)^2, N-a^2তিনটি স্কোয়ারের যোগফল হিসাবে উপস্থাপিত বাকিগুলি সর্বাধিক (n+1)^2 -(n-1)^2, যা সমান 4*n। সুতরাং, এটি কেবলমাত্র মানগুলির মধ্যে যাচাই করা যথেষ্ট, এটি 2*sqrt(n)হ'ল পরিসীমা R

একক একক সমাধানের পরে, শেষ মানটির জন্য পুনরাবৃত্তি করার চেয়ে গণনা করা dএবং কেবলমাত্র মানগুলির মধ্যে অনুসন্ধান করে চলমান সময়টিকে আরও অনুকূল করতে পারে b<=c<=d। তবে, এই অপ্টিমাইজেশানগুলি ছাড়াই, আমার মেশিনে আমি 45 সেকেন্ডের মধ্যে শেষ হতে পেরেছি এমন সবচেয়ে খারাপ পরিস্থিতি।

"ফর এক্স ইন আর" এর চেইনটি দুর্ভাগ্যজনক। এটি স্ট্রিং প্রতিস্থাপন বা প্রতিস্থাপন দ্বারা এনকোড (এক, বি, সি, ডি) একক সূচককে পুনরাবৃত্তি করে সংক্ষিপ্ত করা যেতে পারে। ইয়ারটুলগুলি আমদানি করা এটির পক্ষে উপযুক্ত নয়।

সম্পাদনা করুন: একই চরিত্রের গণনা, যুক্তি পরিষ্কার করার জন্য int(2*n**.5)+1থেকে পরিবর্তিত হয়েছে 2*int(n**.5)+2


এটি আমার পক্ষে কাজ করে না ...5 => (2, 1, 0, 0)
হ্যারি বিডল

আজব, এটি আমার পক্ষে কাজ করে: আমি 5 => (2, 1, 0, 0)আইডিয়ন ৩.২.৩ বা আইডিয়াল ৩.২.২ এ চালিয়ে যাচ্ছি। তুমি কি পেলে?
xnor

1
@ এক্সনর ব্রিটিশ কালর পেয়েছে 5 => (2, 1, 0, 0)। আপনি কি মন্তব্যটি পড়েছেন? (এখন আমাদের কাছে টানা 3 টি মন্তব্য রয়েছে যার কোড স্নিপেট রয়েছে we আমরা কি ধারাবাহিকতা চালিয়ে রাখতে পারি?)
জাস্টিন

@ কুইন্টাঙ্কস যদি আমরা সিদ্ধান্ত গ্রহণ করতে চাই 5 => (2, 1, 0, 0)তবে এর অর্থ 2^2 + 1^2 + 0^2 + 0^2 = 5। সুতরাং, হ্যাঁ, আমরা পারি।
ডাঃ রেবমু

1
কুইঞ্চুনস, আমি @ ব্রিটিশ কলরারের মন্তব্য পড়েছি এবং যতদূর আমি দেখতে পাচ্ছি 5 => (2, 1, 0, 0)এটি সঠিক। প্রশ্নের উদাহরণগুলি 0 ^ 2 = 0 কে একটি বৈধ বর্গ সংখ্যা হিসাবে বিবেচনা করে। অতএব আমি ব্যাখ্যা করেছি (যেমন আমি মনে করি এক্সনর করেছিল) যে ব্রিটিশ রঙটি অন্য কিছু পেয়েছিল। ব্রিটিশ রঙ যেমন আপনি আবার প্রতিক্রিয়া জানায় না, আমরা কি ধরে নিতে পারি যে আপনি বাস্তবে এটি পেয়েছেন 2,1,0,0?
স্তর নদী সেন্ট

5

সিজেম , 91 90 74 71 বাইট

q~{W):W;:N4md!}gmqi257:B_**_{;)_[Bmd\Bmd]_N\{_*-}/mq_i@+\1%}g{2W#*}%`\;

কমপ্যাক্ট, তবে আমার অন্যান্য পদ্ধতির চেয়ে ধীর।

এটি অনলাইন চেষ্টা করুন! প্রতিলেপন কোড , কাঙ্ক্ষিত পূর্ণসংখ্যা টাইপ ইনপুট এবং ক্লিক করুন চালান

পটভূমি

এই পোস্টটি 99 বাইট গল্ফস্ক্রিপ্ট উত্তর হিসাবে শুরু হয়েছিল । উন্নতির জন্য এখনও জায়গা ছিল, গল্ফস্ক্রিপ্ট অন্তর্নির্মিত স্কয়ার্ট ফাংশন অভাব আছে। আমি গল্ফস্ক্রিপ্ট সংস্করণটি 5 টি পুনর্বিবেচনার আগ পর্যন্ত রেখেছি , যেহেতু এটি সিজেএম সংস্করণের সাথে খুব মিল ছিল।

যাইহোক, সংশোধনী 6 এর পরে অপ্টিমাইজেশনের জন্য অপারেটরগুলির প্রয়োজন যা গল্ফস্ক্রিপ্টে উপলব্ধ নয়, সুতরাং উভয় ভাষার জন্য পৃথক ব্যাখ্যা পোস্ট করার পরিবর্তে, আমি কম প্রতিযোগিতামূলক (এবং অনেক ধীর) সংস্করণ বাদ দেওয়ার সিদ্ধান্ত নিয়েছি।

বাস্তবায়িত অ্যালগরিদম উদ্দীপনা দ্বারা সংখ্যাগুলি গণনা করে:

  1. ইনপুট জন্য m, সন্ধান করুন Nএবং Wযে যেমন m = 4**W * N

  2. সেট i = 257**2 * floor(sqrt(N/4))

  3. সেট i = i + 1

  4. পূর্ণসংখ্যার খুঁজুন j, k, lযেমন যে i = 257**2 * j + 257 * k + l, যেখানে k, l < 257

  5. d = N - j**2 - k**2 - l**2নিখুঁত বর্গক্ষেত্র কিনা তা পরীক্ষা করুন ।

  6. যদি তা না হয় এবং 3 ধাপে ফিরে যান।

  7. মুদ্রণ 2**W * j, 2**W * k, 2**W * l, 2**W * sqrt(m)

উদাহরণ

$ TIME='\n%e s' time cjam lagrange.cjam <<< 999999999
[27385 103 15813 14]
0.46 s
$ TIME='\n%e s' time cjam lagrange.cjam <<< 805306368
[16384 16384 0 16384]
0.23 s

সময়গুলি একটি ইন্টেল কোর i7-4700MQ এর সাথে সম্পর্কিত।

কিভাবে এটা কাজ করে

q~              " Read and interpret the input. ";
{
  W):W;         " Increment “W” (initially -1). ";
  :N            " Save the integer on the stack in “N”. ';
  4md!          " Push N / 4 and !(N % 4). ";
}g              " If N / 4 is an integer, repeat the loop.
mqi             " Compute floor(sqrt(N/4)). ";
257:B_**        " Compute i = floor(sqrt(N)) * 257**2. ";
_               " Duplicate “i” (dummy value). ";
{               " ";
  ;)_           " Pop and discard. Increment “i”. ";
  [Bmd\Bmd]     " Push [ j k l ], where i = 257**2 * j + 257 * k + l and k, l < 257. ";
  _N\           " Push “N” and swap it with a copy of [ j k l ]. ";
  {_*-}/        " Compute m = N - j**2 - k**2 - l**2. ";
  mq            " Compute sqrt(m). ";
  _i            " Duplicate sqrt(m) and compute floor(sqrt(m)). ";
  @+\           " Form [ j k l floor(sqrt(m)) ] and swap it with sqrt(m). ";
  1%            " Check if sqrt(m) is an integer. ";
}g              " If it is, we have a solution; break the loop. ";
{2W#*}%         " Push 2**W * [ j k l sqrt(m) ]. ";
`\;             " Convert the array into a string and discard “i”. ";

2

সি, 228

এটি উইকিপিডিয়া পৃষ্ঠায় থাকা অ্যালগরিদমের উপর ভিত্তি করে, যা একটি হে (এন) ব্রুট-ফোর্স।

n,*l,x,y,i;main(){scanf("%d",&n);l=calloc(n+1,8);
for(x=0;2*x*x<=n;x++)for(y=x;(i=x*x+y*y)<=n;y++)l[2*i]=x,l[2*i+1]=y;
for(x=0,y=n;;x++,y--)if(!x|l[2*x+1]&&l[2*y+1]){
printf("%d %d %d %d\n",l[2*x],l[2*x+1],l[2*y],l[2*y+1]);break;}}

2

গল্ফস্ক্রিপ্ট, 133 130 129 বাইট

~{.[4*{4/..4%1$!|!}do])\}:r~,(2\?:f;{{..*}:^~4-1??n*,}:v~)..
{;;(.^3$\-r;)8%!}do-1...{;;;)..252/@252%^@^@+4$\-v^@-}do 5$]{f*}%-4>`

দ্রুত, কিন্তু দীর্ঘ। নতুন লাইনটি সরানো যেতে পারে।

এটি অনলাইনে চেষ্টা করুন। নোট করুন যে অনলাইন দোভাষীর 5 টি দ্বিতীয় সময়সীমা রয়েছে, সুতরাং এটি সমস্ত সংখ্যার জন্য কাজ না করে।

পটভূমি

অ্যালগরিদম লেজেন্ডারের ত্রি-বর্গীয় উপপাদনের সুবিধা গ্রহণ করে , যা বলে যে প্রতিটি প্রাকৃতিক সংখ্যা এন যা রূপের নয়

                                                                   n = 4 ** এ * (8 বি + 7)

তিনটি স্কোয়ারের যোগফল হিসাবে প্রকাশ করা যেতে পারে ।

অ্যালগরিদম নিম্নলিখিতটি করে:

  1. হিসাবে নম্বর প্রকাশ করুন 4**i * j

  2. এর kমতো বৃহত্তম পূর্ণসংখ্যার সন্ধান করুন k**2 <= jএবং j - k**2লেজেন্ডারের ত্রি-বর্গীয় উপপাদ্যের অনুমানটিকে সন্তুষ্ট করে।

  3. সেট i = 0

  4. j - k**2 - (i / 252)**2 - (i % 252)**2নিখুঁত বর্গক্ষেত্র কিনা তা পরীক্ষা করুন ।

  5. যদি তা না হয় তবে ইনক্রিমেন্ট iএবং ৪ র্থ ধাপে ফিরে যান।

উদাহরণ

$ TIME='%e s' time golfscript legendre.gs <<< 0
[0 0 0 0]
0.02 s
$ TIME='%e s' time golfscript legendre.gs <<< 123456789
[32 0 38 11111]
0.02 s
$ TIME='%e s' time golfscript legendre.gs <<< 999999999
[45 1 217 31622]
0.03 s
$ TIME='%e s' time golfscript legendre.gs <<< 805306368
[16384 0 16384 16384]
0.02 s

সময়গুলি একটি ইন্টেল কোর i7-4700MQ এর সাথে সম্পর্কিত।

কিভাবে এটা কাজ করে

~              # Interpret the input string. Result: “n”
{              #
  .            # Duplicate the topmost stack item.
  [            #
    4*         # Multiply it by four.
    {          #
      4/       # Divide by four.
      ..       # Duplicate twice.
      4%1$     # Compute the modulus and duplicate the number.
      !|!      # Push 1 if both are truthy.
    }do        # Repeat if the number is divisible by four and non-zero.
  ]            # Collect the pushed values (one per iteration) into an array.
  )\           # Pop the last element from the array and swap it with the array.
}:r~           # Save this code block as “r” and execute it.
,(2\?          # Get the length of the array, decrement it and exponentiate.
:f;            # Save the result in “f”.
               # The topmost item on the stack is now “j”, which is not divisible by 
               # four and satisfies that n = f**2 * j.
{              #
  {..*}:^~     # Save a code block to square a number in “^” and execute it.
  4-1??        # Raise the previous number to the power of 1/4.
               # The two previous lines compute (x**2)**(1/4), which is sqrt(abs(x)).
  n*,          # Repeat the string "\n" that many times and compute its length.
               # This casts to integer. (GolfScript doesn't officially support Rationals.)
}:v~           # Save the above code block in “v” and execute it.
)..            # Undo the first three instructions of the loop.
{              #
   ;;(         # Discard two items from the stack and decrement.
   .^3$\-      # Square and subtract from “n”.
   r;)8%!      # Check if the result satisfies the hypothesis of the three-square theorem.
}do            # If it doesn't, repeat the loop.
-1...          # Push 0 (“i”) and undo the first four instructions of the loop.
{              #
  ;;;)         # Discard two items from the stack and increment “i”.
  ..252/@252%  # Push the digits of “i” in base 252.
  ^@^@+4$\-    # Square both, add and subtract the result 
  v^@-         # Take square root, square and compare.
}do            # If the difference is a perfect square, break the loop.
5$]            # Duplicate the difference an collect the entire stack into an array.
{f*}%          # Multiply very element of the array by “f”.
-4>            # Reduce the array to its four last elements (the four numbers).
`              # Convert the result into a string.

1
বুঝলাম না j-k-(i/252)-(i%252)। আপনার মন্তব্যগুলি থেকে (আমি আসলে কোডটি পড়তে পারি না), দেখে মনে হচ্ছে আপনার বোঝানো হচ্ছে j-k-(i/252)^2-(i%252)^2। বিটিডাব্লু, j-k-(i/r)^2-(i%r)^2যেখানে আর = স্কয়ার্ট (কে) কিছু অক্ষর বাঁচাতে পারে তার সমতুল্য (এবং আমার সি প্রোগ্রামে কে = 0 এর জন্যও সমস্যা ছাড়াই কাজ করে বলে মনে হচ্ছে।)
লেভেল রিভার সেন্ট

@ স্টিভেভারিল: হ্যাঁ, আমি একটি ভুল করেছি। দেখার জন্য আপনাকে ধন্যবাদ। এটা হওয়া উচিত j-k^2-(i/252)^2-(i%252)^2। আমি এখনও অপেক্ষার অপেক্ষায় রয়েছি 0 0 টি বৈধ ইনপুট কিনা cla আপনার প্রোগ্রাম 1414 -nan 6 4.000000ইনপুট জন্য দেয় 0
ডেনিস

আমি লেজেন্ডারের উপপাদ্যটি ব্যবহার করে আমার নতুন প্রোগ্রামটি সম্পর্কে কথা বলছি, যা আমি এখনও পোস্ট করি নি। দেখে মনে হচ্ছে এটি কখনই% বা / এর সাথে কোডটি কল করে না যখন আমার কাছে কে = 0 এর সমতুল্য রয়েছে, যার কারণে এটি সমস্যা তৈরি করছে না। আমি এটি পোস্ট করলে আপনি দেখতে পাবেন। আপনি আমার পুরানো প্রোগ্রাম চলমান খুশি। রেভ 1 এ পূর্ণ 2 জিবি টেবিলটি তৈরি করার স্মৃতি আপনার ছিল এবং এটি কতক্ষণ সময় নিয়েছে?
লেভেল রিভার সেন্ট

হ্যাঁ, সি সংকলক অনুকূলকরণের সময় বেশ অপ্রত্যাশিত আচরণ করতে পারে। গল্ফস্ক্রিপ্টে, 0/=> ক্রাশ! : পি আমি আমার ল্যাপটপে আপনার রেভ 1 চালিয়েছি (i7-4700MQ, 8 GiB র‌্যাম)। গড়ে মৃত্যুদন্ড কার্যকর সময় 18.5 সেকেন্ড।
ডেনিস

বাহ কি টেবিল তৈরি সহ 18.5 সেকেন্ড? আমার মেশিনে এটি 2 মিনিটের বেশি সময় নেয়। আমি দেখতে পাচ্ছি সমস্যাটি হ'ল উইন্ডোজ মেমরি পরিচালনা। প্রোগ্রামটি সরাসরি তাত্ক্ষণিক 2 জিবি দেওয়ার পরিবর্তে এটি ছোট ছোট অংশগুলিতে দেয়, সুতরাং সম্পূর্ণ 2 জিবি বরাদ্দ না হওয়া পর্যন্ত এটি অবশ্যই অনেক অপ্রয়োজনীয় অদলবদল করে চলেছে। প্রকৃতপক্ষে ব্যবহারকারীদের ইনপুট অনুসারে উত্তর অনুসন্ধান করা অনেক দ্রুত, কারণ ততক্ষণে প্রোগ্রামটিকে মেমরির জন্য ভিক্ষা করতে হবে না।
স্তরের নদী সেন্ট

1

রেভ 1: সি, 190

a,z,m;short s[15<<26];p(){m=s[a=z-a];printf("%d %f ",m,sqrt(a-m*m));}
main(){m=31727;for(a=m*m;--a;s[z<m*m?z:m*m]=a%m)z=a/m*(a/m)+a%m*(a%m);scanf("%d",&z);for(;a*!s[a]||!s[z-a];a++);p();p();}

এটি রেভ ০ এর চেয়ে ক্ষুধার্ত আরও ক্ষুধার্ত S একই নীতি: 2 স্কোয়ারের সমস্ত সম্ভাব্য পরিমাণের (এবং সেই সংখ্যাগুলির জন্য শূন্য যা দুটি বর্গের যোগফল নয়) এর জন্য একটি ধনাত্মক মান সহ একটি টেবিল তৈরি করুন, তারপরে এটি অনুসন্ধান করুন।

এই পুনর্বিবেগে হিটগুলি সংরক্ষণ করার shortপরিবর্তে একটি অ্যারের ব্যবহার করুন char, তাই আমি কেবল একটি পতাকার পরিবর্তে টেবিলের মধ্যে একটি জোড়া স্কোয়ারের মূল সংরক্ষণ করতে পারি। pলুপের প্রয়োজন নেই বলে উল্লেখযোগ্যভাবে এটি ফাংশনটিকে (2 স্কোয়ারের যোগফল ডিকোড করার জন্য) সহজতর করে ।

উইন্ডোজ অ্যারেতে 2 জিবি সীমাবদ্ধ করে। আমি এটি পেতে পারি short s[15<<26]যার সাথে 1006632960 উপাদানগুলির অ্যারে রয়েছে, যা অনুমিতিটি মেনে চলার জন্য যথেষ্ট। দুর্ভাগ্যক্রমে, মোট প্রোগ্রামের রানটাইম আকারটি এখনও 2 জিবি ছাড়িয়ে গেছে এবং (ওএস সেটিংসটি টুইট করেও) আমি এই আকারের উপর দিয়ে চালাতে সক্ষম হইনি (যদিও এটি তাত্ত্বিকভাবে সম্ভব) তবে আমি সবচেয়ে ভাল যা করতে পারি তা হ'ল short s[14<<26](939524096 উপাদানসমূহ)) m*mঅবশ্যই এর থেকে কঠোরভাবে কম (30651 ^ 2 = 939483801।) তবুও, প্রোগ্রামটি পুরোপুরি চলে এবং কোনও বাছাই করা উচিত যাতে এই বাধা নেই।

অবহেলিত কোড

a,z,m;
short s[15<<26];     
p(){m=s[a=z-a];printf("%d %f ",m,sqrt(a-m*m));}      
main(){       
 m=31727;             
 for(a=m*m;--a;s[z<m*m?z:m*m]=a%m)   //assignment to s[] moved inside for() is executed after the following statement. In this rev excessively large values are thrown away to s[m*m].
   z=a/m*(a/m)+a%m*(a%m);            //split a into high and low half, calculate h^2+l^2.                                  
 scanf("%d",&z); 
 for(;a*!s[a]||!s[z-a];a++);         //loop until s[a] and s[z-a] both contain an entry. s[0] requires special handling as s[0]==0, therefore a* is included to break out of the loop when a=0 and s[z] contains the sum of 2 squares.
 p();                                //print the squares for the first sum of 2 squares 
 p();}                               //print the squares for the 2nd sum of 2 squares (every time p() is called it does a=z-a so the two sums are exchanged.) 

রেভ 0 সি, 219

a,z,i,m;double t;char s[1<<30];p(){for(i=t=.1;(m=t)-t;i++)t=sqrt(a-i*i);printf("%d %f ",i-1,t);}
main(){m=1<<15;for(a=m*m;--a;){z=a/m*(a/m)+a%m*(a%m);s[z<m*m?z:0]=1;}scanf("%d",&z);for(;1-s[a]*s[z-a];a++);p();a=z-a;p();}

এটি একটি স্মৃতি ক্ষুধার্ত জন্তু। এটি 1 জিবি অ্যারে নেয়, 2 টি স্কোয়ারের সমস্ত সম্ভাব্য অঙ্কের গণনা করে এবং অ্যারেতে প্রতিটি জন্য একটি পতাকা সঞ্চয় করে। তারপরে ব্যবহারকারীর ইনপুট z এর জন্য এটি দুটি স্কোয়ার 2 এবং za এর দুটি যোগফল অনুসন্ধান করবে ray

ফাংশন pতারপর মূল স্কোয়ার যে 2 বর্গের অঙ্কের করতে ব্যবহার করা হয় reconsitutes aএবং z-aএকটি পূর্ণসংখ্যা হিসাবে প্রতিটি জোড়া প্রথম এবং তাদের ছাপে, একটি ডবল হিসাবে দ্বিতীয় (যদি এটি হয়েছে সব পূর্ণসংখ্যার আরো দুটি অক্ষর প্রয়োজন হয় হতে, t> m=t।)

স্কোয়ারের অঙ্কের টেবিলটি তৈরি করতে প্রোগ্রামটি কয়েক মিনিট সময় নেয় (আমি মনে করি এটি মেমরি পরিচালনার সমস্যার কারণে হয়েছে, আমি মনে করি মেমরির বরাদ্দ ধীরে ধীরে উপরে উঠতে হবে যার ফলস্বরূপ আশা করা যায়)) তবে একবার এটি হয়ে গেলে উত্তরগুলি খুব দ্রুত তৈরি করে (বেশ কয়েকটি সংখ্যার যদি গণনা করা হয়, তবে প্রোগ্রামটি পরে থেকে scanfএকটি লুপে রাখা যেতে পারে।

অবারিত কোড

a,z,i,m;
double t;
char s[1<<30];                              //handle numbers 0 up to 1073741823
p(){
 for(i=t=.1;(m=t)-t;i++)t=sqrt(a-i*i);      //where a contains the sum of 2 squares, search until the roots are found
 printf("%d %f ",i-1,t);}                   //and print them. m=t is used to evaluate the integer part of t. 

main(){       
 m=1<<15;                                   //max root we need is sqrt(1<<30);
 for(a=m*m;--a;)                            //loop m*m-1 down to 1, leave 0 in a
   {z=a/m*(a/m)+a%m*(a%m);s[z<m*m?z:0]=1;}  //split a into high and low half, calculate h^2+l^2. If under m*m, store flag, otherwise throw away flag to s[0]
 scanf("%d",&z);
 for(;1-s[a]*s[z-a];a++);                   //starting at a=0 (see above) loop until flags are found for sum of 2 squares of both (a) and (z-a)
 p();                                       //reconsitute and print the squares composing (a)
 a=z-a;                                     //assign (z-a) to a in order to...
 p();}                                      //reconsitute and print the squares composing (z-a)  

উদাহরণ আউটপুট

প্রথম প্রশ্ন অনুযায়ী। দ্বিতীয়টিকে অনুসন্ধান করা কঠিন হিসাবে বেছে নেওয়া হয়েছিল। এই ক্ষেত্রে প্রোগ্রামটি 8192 ^ 2 + 8192 ^ 2 = 134217728 পর্যন্ত সন্ধান করতে হবে, তবে টেবিলটি তৈরি হওয়ার পরে কেবল কয়েক সেকেন্ড সময় নেয়।

123456789
0 2.000000 3328 10601.000000

805306368
8192 8192.000000 8192 24576.000000

আপনি কি স্কয়ারটির জন্য একটি প্রোটোটাইপ যুক্ত করবেন না?
edc65

@ edc65 আমি জিসিসি সংকলক ব্যবহার করছি (যা লিনাক্সের জন্য, তবে আমার উইন্ডোজ মেশিনে সাইগউইন লিনাক্স পরিবেশ ইনস্টল করা আছে।) এর অর্থ আমার #include <stdio.h>(স্ক্যানফ / প্রিন্টফের জন্য) বা #include <math.h>( স্কয়ার্টের জন্য) সংকলকটি লাগানোর দরকার নেই don't প্রয়োজনীয় গ্রন্থাগারগুলি স্বয়ংক্রিয়ভাবে লিঙ্ক করে। এর জন্য আমাকে ডেনিসকে ধন্যবাদ জানাতে হবে (তিনি আমাকে এই প্রশ্ন কোডগল্ফ.স্ট্যাকেক্সেঞ্জাওনএ / এ / ২২63৩০/১5৫৯৯ এ বলেছিলেন ) আমার কাছে সেরা গল্ফিং টিপ ছিল।
লেভেল নদী সেন্ট

আমি ইতিমধ্যে ভাবছিলাম কেন হান্ট উইম্পাস লিঙ্কযুক্ত প্রশ্নগুলিতে হাজির হন। :) যাইহোক, উইন্ডোজে জিসিসি কী ব্যবহার করে তা আমি জানি না, তবে জিএনইউ লিঙ্কারটি গণিত লাইব্রেরিটি স্বয়ংক্রিয়ভাবে, এর সাথে বা ছাড়া লিঙ্ক করে না include। লিনাক্সে সংকলন করতে আপনার পতাকাটি দরকার-lm
ডেনিস

@Dennis যে আকর্ষণীয়, এটা জড়িত stdioবেশ কিছু লাইব্রেরি, কিন্তু না এবং mathএমনকি সঙ্গেinclude ? আপনি যেটি সংকলক পতাকাটি রেখেছেন তা দিয়ে আমি বুঝতে পারি, আপনার includeকোনওভাবেই প্রয়োজন নেই ? ভাল এটি আমার পক্ষে কাজ করছে, তাই আমি অভিযোগ করছি না, টিপটির জন্য আবারও ধন্যবাদ thanks বিটিডাব্লু আমি লেজেন্ড্রের উপপাদ্যটি ব্যবহার করে সম্পূর্ণ ভিন্ন উত্তর পোস্ট করার আশা করছি (তবে এটি এখনও ব্যবহার করবে sqrt)
লেভেল রিভার সেন্ট

-lmসংযোগকারীকে নয়, লিঙ্কারের উপর প্রভাব ফেলে। gccএটি "জানে" ফাংশনগুলির জন্য প্রোটোটাইপগুলির প্রয়োজন নেই, তাই এটি অন্তর্ভুক্ত সহ বা ছাড়াই কাজ করে। যাইহোক, শিরোনাম ফাইলস্প্রভাইড কেবলমাত্র প্রোটোটাইপগুলি ফাংশন করে না, তাদের নিজস্ব কাজ করে। লিনাক্সে (তবে উইন্ডোজ নয়, আপাতদৃষ্টিতে) গণিত গ্রন্থাগার লিবিএম স্ট্যান্ডার্ড লাইব্রেরির অংশ নয়, সুতরাং আপনাকে ldএটির সাথে লিঙ্ক দেওয়ার নির্দেশ দিতে হবে।
ডেনিস

1

গণিত, 138 অক্ষর

সুতরাং দেখা যাচ্ছে যে এটি edc65 (যেমন, 805306368) দ্বারা চিহ্নিত হিসাবে নির্দিষ্ট ইনপুটগুলির জন্য নেতিবাচক এবং কাল্পনিক ফলাফল তৈরি করে, সুতরাং এটি কোনও বৈধ সমাধান নয়। আমি আপাতত এটি ছেড়ে দেব এবং সম্ভবত, যদি আমি সত্যই আমার সময়কে ঘৃণা করি তবে আমি ফিরে গিয়ে এটি ঠিক করার চেষ্টা করব।

S[n_]:=Module[{a,b,c,d},G=Floor@Sqrt@#&;a=G@n;b:=G[n-a^2];c:=G[n-a^2-b^2];d:=G[n-a^2-b^2-c^2];While[Total[{a,b,c,d}^2]!=n,a-=1];{a,b,c,d}]

বা, অসমাপ্ত:

S[n_] := Module[{a, b, c, d}, G = Floor@Sqrt@# &;
 a = G@n;
 b := G[n - a^2];
 c := G[n - a^2 - b^2];
 d := G[n - a^2 - b^2 - c^2];
 While[Total[{a, b, c, d}^2] != n, a -= 1];
 {a, b, c, d}
]

আমি অ্যালগরিদমগুলিতে খুব শক্তভাবে দেখিনি, তবে আমি আশা করি এটি একই ধারণা। আমি কেবল সুস্পষ্ট সমাধান নিয়ে এসেছি এবং এটি কাজ না করা পর্যন্ত এটি টুইট করে রেখেছি। আমি এটি 1 থেকে এক বিলিয়ন এবং ... এর মধ্যে সমস্ত সংখ্যার জন্য পরীক্ষা করেছি it পরীক্ষায় আমার মেশিনে প্রায় 100 সেকেন্ড সময় লাগে।

এ সম্পর্কে দুর্দান্ত বিষয়টি হ'ল যেহেতু খ, সি, এবং ডি বিলম্বিত কার্যাদি দ্বারা সংজ্ঞায়িত করা হয়েছে :=, তাই যখন একটি হ্রাস পাবে তখন তাদের নতুন সংজ্ঞা দিতে হবে না। এটি আমার আগে কয়েকটি অতিরিক্ত লাইন সঞ্চয় করেছিল। আমি এটি আরও গল্ফ এবং অনর্থক অংশ বাসাতে পারে, কিন্তু এখানে প্রথম খসড়া আছে।

ওহ, এবং আপনি এটা হিসাবে চালানো S@123456789এবং আপনার সাথে পরীক্ষা করতে পারেন {S@#, Total[(S@#)^2]} & @ 123456789বা # == Total[(S@#)^2]&[123456789]। সম্পূর্ণ পরীক্ষা হয়

n=0;
AbsoluteTiming@ParallelDo[If[e != Total[(S@e)^2], n=e; Abort[]] &, {e, 1, 1000000000}]
n

আমি এর আগে একটি মুদ্রণ [] বিবৃতি ব্যবহার করেছি তবে এটি কখনই ডাকা হয় না, যদিও এটি অনেকটা ধীর হয়ে যায়। চিত্রে যান.


সত্যিই পরিষ্কার! আমি অবাক হয়েছি যে প্রতিটি মান গ্রহণ করা যথেষ্ট, তবে যতটা সম্ভব প্রথম তত বড়। গল্ফিংয়ের জন্য, n - a^2 - b^2 - c^2ভেরিয়েবল হিসাবে সংরক্ষণ করা সম্ভবত এটির চেয়ে ছোট এবং d^2এটির সমান কিনা তা পরীক্ষা করা।
xnor

2
এটা কি সত্যিই কাজ করে? 805306368 ইনপুটটির জন্য এটি কী সমাধান খুঁজে পাবে?
edc65

এস [805306368] = {- 28383, 536 আই, 32 আই, আই}} হাহ। যে করে 805306368 উত্পাদন করে যখন আপনি এটি যোগফল কিন্তু স্পষ্টত এই আলগোরিদিম সঙ্গে একটি সমস্যা। আমার ধারণা আমি আপাতত এটি প্রত্যাহার করতে হবে; এটি নির্দেশ করার জন্য ধন্যবাদ ...
krs013

2
সংখ্যার যে সব ব্যর্থ বিশেষ করে, তারা ফর্মের হবে বলে মনে হচ্ছে 2. বৃহৎ শক্তির বিভাজ্য হবে বলে মনে হচ্ছে a * 4^(2^k)জন্য k>=2, 4 সকল ক্ষমতার বাইরে নিষ্কাশিত থাকার যাতে a4 একটি একাধিক নয় (কিন্তু হতে পারে)। তদুপরি, প্রতিটি aহয় 3 মড 4 বা এই জাতীয় সংখ্যার দ্বিগুণ। সবচেয়ে ছোটটি 192
xnor

1

হাস্কেল 123 + 3 = 126

main=getLine>>=print.f.read
f n=head[map(floor.sqrt)[a,b,c,d]|a<-r,b<-r,c<-r,d<-r,a+b+c+d==n]where r=[x^2|x<-[0..n],n>=x^2]

প্রাক-গণনা করা স্কোয়ারগুলির চেয়ে সহজ ব্রুট ফোর্স।

এটি -Oসংকলন বিকল্পের প্রয়োজন (আমি এর জন্য 3 টি অক্ষর যোগ করেছি)। সবচেয়ে খারাপ ক্ষেত্রে 999950883 এর জন্য এটি 1 মিনিটেরও কম সময় নেয়।

কেবল জিএইচসি-তে পরীক্ষা করা হয়েছে।


1

সি: 198 অক্ষর

আমি সম্ভবত এটি প্রায় 100 টিরও বেশি অক্ষরে চেপে ধরতে পারি। এই সমাধানটি সম্পর্কে আমি যা পছন্দ করি তা হ'ল ন্যূনতম পরিমাণ, কেবলমাত্র একটি সরল-লুপ, লুপের জন্য কী করা উচিত তা করা (যা পাগল হওয়া) be

i,a,b,c,d;main(n){for(scanf("%d",&n);a*a+b*b-n?a|!b?a*a>n|a<b?(--a,b=1):b?++b:++a:(a=b=0,--n,++i):c*c+d*d-i?c|!d?c*c>i|c<d?(--c,d=1):d?++d:++c:(a=b=c=d=0,--n,++i):0;);printf("%d %d %d %d",a,b,c,d);}

এবং ভারীভাবে উপস্থাপিত:

#include <stdio.h>

int n, i, a, b, c, d;

int main() {
    for (
        scanf("%d", &n);
        a*a + b*b - n
            ? a | !b
                ? a*a > n | a < b
                    ? (--a, b = 1)
                    : b
                        ? ++b
                        : ++a
                : (a = b = 0, --n, ++i)
            : c*c + d*d - i
                ? c | !d
                    ? c*c > i | c < d
                        ? (--c, d = 1)
                        : d
                            ? ++d
                            : ++c
                    : (a = b = c = d = 0, --n, ++i)
                : 0;
    );
    printf("%d %d %d %d\n", a, b, c, d);
    return 0;
}

সম্পাদনা করুন: সমস্ত ইনপুটটির জন্য এটি যথেষ্ট দ্রুত নয়, তবে আমি আবার অন্য সমাধানে ফিরে আসব। আমি এই টেরিনারি অপারেশনটি এখন অবধি থাকব।


1

রেভ বি: সি, 179

a,b,c,d,m=1,n,q,r;main(){for(scanf("%d",&n);n%4<1;n/=4)m*=2;
for(a=sqrt(n),a-=(3+n-a*a)%4/2;r=n-a*a-b*b-c*c,d=sqrt(r),d*d-r;c=q%256)b=++q>>8;
printf("%d %d %d %d",a*m,b*m,c*m,d*m);}

উন্নতির জন্য @ ডেনিসকে ধন্যবাদ। নীচের বাকী উত্তর রেভ এ থেকে আপডেট করা হয়নি

রেভ এ: সি, 195

a,b,c,d,n,m,q;double r=.1;main(){scanf("%d",&n);for(m=1;!(n%4);n/=4)m*=2;a=sqrt(n);a-=(3+n-a*a)%4/2;
for(;(d=r)-r;q++){b=q>>8;c=q%256;r=sqrt(n-a*a-b*b-c*c);}printf("%d %d %d %d ",a*m,b*m,c*m,d*m);}

আমার অন্যান্য উত্তর চেয়ে অনেক দ্রুত এবং অনেক কম স্মৃতি!

এটি http://en.wikedia.org/wiki/Legendre%27s_three-square_toreore ব্যবহার করে । নিম্নলিখিত ফর্মের কোনও নম্বরই 3 স্কোয়ারের যোগ হিসাবে প্রকাশ করা যায় (আমি এটিকে নিষিদ্ধ ফর্ম বলি):

4^a*(8b+7), or equivalently 4^a*(8b-1)

মনে রাখবেন যে সমস্ত বিজোড় বর্গক্ষেত্র সংখ্যা ফর্মের (8b+1)এবং সমস্ত এমনকি বর্গ সংখ্যা ফর্মের অতিমাত্রায় 4b। তবে এটি সমস্ত বর্গ সংখ্যাও ফর্মের এই সত্যটি লুকিয়ে রাখে 4^a*(odd square)==4^a*(8b+1)2^x-(any square number < 2^(x-1))বিজোড়ের ফলস্বরূপx সর্বদা নিষিদ্ধ আকারে থাকবে। সুতরাং এই সংখ্যাগুলি এবং তাদের গুণগুলি একটি কঠিন ক্ষেত্রে, যার কারণেই এখানে এতগুলি প্রোগ্রাম প্রথম পদক্ষেপ হিসাবে 4 এর ক্ষমতা বিভক্ত করে।

@ Xnor এর উত্তরে যেমন বলা হয়েছে, টানা 2 টির N-a*aজন্য মান নিষিদ্ধ ফর্ম হতে পারে না a। নীচে আমি তার টেবিলের একটি সরলীকৃত ফর্ম উপস্থাপন করছি। 4 দ্বারা বিভাজনের পরে N%40 টি সমান হতে পারে না এগুলি ছাড়াও , মনে রাখবেন যে এর জন্য কেবল দুটি সম্ভাব্য মান রয়েছে (a*a)%4

(a*a)%4= 01
        +--
       1|10
  N%4= 2|21  <- (N-a*a)%4
       3|32

সুতরাং, আমরা এর মানগুলি (N-a*a)নিষিদ্ধ রূপের হতে পারে, যথা যেখানে (N-a*a)%43 বা 0 হয় দেখা যেতে পারে এটি Nঅদ্ভুত এবং এমনকি উভয়ের সাথে একই ঘটতে পারে না (a*a)

সুতরাং, আমার অ্যালগোরিদম এটির মতো কাজ করে:

1. Divide out powers of 4
2. Set a=int(sqrt(N)), the largest possible square
3. If (N-a*a)%4= 0 or 3, decrement a (only once)
4. Search for b and c such that N-a*a-b*b-c*c is a perfect square

আমি বিশেষত আমার ৩ য় ধাপটি পছন্দ করি I আমি 3 টি যুক্ত করি N, যাতে (3+N-a*a)%4 =3 বা 2 হলে হ্রাসের প্রয়োজন হয় (তবে 1 বা 0 নয়) এটি 2 দ্বারা ভাগ করুন এবং পুরো কাজটি মোটামুটি সরল অভিব্যক্তি দ্বারা করা যেতে পারে ।

অবহেলিত কোড

একক forলুপটি নোট করুন এবং এর থেকে এবং qএর মানগুলি সংগ্রহ করতে বিভাগ / মডুলোর ব্যবহার । বাইটগুলি সংরক্ষণ করার জন্য আমি 256 এর পরিবর্তে একটি বিভাজক হিসাবে ব্যবহার করার চেষ্টা করেছি , তবে কখনও কখনও এর মান ঠিক হয় না এবং সম্ভবত প্রোগ্রামটি অনির্দিষ্ট সময়ের জন্য স্তব্ধ হয়ে যায়। বিভাগের পরিবর্তে আমি ব্যবহার করতে পারি বলে সেরা আপোস ছিল ।bcaa>>8/256

a,b,c,d,n,m,q;double r=.1;
main(){
  scanf("%d",&n);
  for(m=1;!(n%4);n/=4)m*=2;
  a=sqrt(n);
  a-=(3+n-a*a)%4/2;
  for(;(d=r)-r;q++){b=q>>8;c=q%256;r=sqrt(n-a*a-b*b-c*c);}
  printf("%d %d %d %d ",a*m,b*m,c*m,d*m);}

আউটপুট

একটি আকর্ষণীয় বিচক্ষণতা হ'ল আপনি যদি বর্গ সংখ্যা, N-(a*a)= 0 ইনপুট করেন । তবে প্রোগ্রামটি সনাক্ত করে যে 0%4= 0 এবং পরবর্তী বর্গাকারে হ্রাস পেয়েছে। ফলস্বরূপ বর্গাকার সংখ্যার ইনপুটগুলি ফর্ম না হলে সর্বদা ছোট স্কোয়ারগুলির একটি গ্রুপে পচে যায় 4^x

999999999
31621 1 161 294

805306368
16384 0 16384 16384

999950883
31621 1 120 221

1
0 0 0 1

2
1 0 0 1

5
2 0 0 1

9
2 0 1 2

25
4 0 0 3

36
4 0 2 4

49
6 0 2 3

81
8 0 1 4

121
10 1 2 4

অ্যামেজিং! প্রতি ইনপুট জন্য 0.003 গুলি! আপনি এই 5 টি অক্ষর ফিরে পেতে পারেন: 1. m=1আগে ঘোষণা করুন main। 2. সম্পাদন scanfমধ্যে forবিবৃতি। 3. floatপরিবর্তে ব্যবহার করুন double। ৪. এর n%4<1চেয়ে কম !(n%4)। ৫. প্রিন্টফের ফর্ম্যাট স্ট্রিংয়ে একটি অপ্রচলিত স্থান রয়েছে।
ডেনিস


টিপস জন্য ধন্যবাদ! n-=a*aকাজ করে না, কারণ aএরপরে সংশোধন করা যেতে পারে (এটি কিছু ভুল উত্তর দেয় এবং 100 + 7 = 107 এর মতো অল্প সংখ্যক ক্ষেত্রে ঝুলিয়ে দেয়।) আমি বাকি সমস্তগুলি অন্তর্ভুক্ত করেছি। এটি সংক্ষিপ্ত করার জন্য কিছু ভাল লাগবে printfতবে আমি মনে করি কেবলমাত্র ভাষাটির পরিবর্তন করার একমাত্র উত্তর। গতির মূল চাবিকাঠিটি হ'ল aদ্রুত একটি ভাল মান নিয়ে স্থির হওয়া । সিতে এবং 256 ^ 2 এরও কম জায়গার সাথে অনুসন্ধানের লিখিত, এটি সম্ভবত এখানে দ্রুততম প্রোগ্রাম।
লেভেল রিভার সেন্ট

ঠিক আছে, দুঃখিত। সংক্ষেপিত printfবক্তব্য ম্যাক্রো বা একটি অ্যারের, যা বাল্ক অন্যত্র যোগ হবে ব্যবহার না করেই কঠিন বলে মনে হয়। ভাষা পরিবর্তন করা "সহজ" উপায় বলে মনে হচ্ছে। আপনার পদ্ধতির সিজোমে 82 বাইট ওজন হবে।
ডেনিস

0

জাভাস্ক্রিপ্ট - 175 191 176 173 অক্ষর

নিষ্ঠুর শক্তি, কিন্তু দ্রুত।

দ্রুত সম্পাদনা করুন তবে কিছু বাজে ইনপুট জন্য যথেষ্ট নয়। আমি 4 এর গুণক দ্বারা হ্রাস প্রথম পদক্ষেপ যোগ করতে হয়েছিল।

সম্পাদনা 2 ফাংশন থেকে মুক্তি পান, লুপের ভিতরে আউটপুট দেয় এবং তারপরে বাইরে বেরোনোর ​​সংক্রমণকে বাধ্য করে

3 0 সম্পাদনা বৈধ ইনপুট নয়

v=(p=prompt)();for(m=1;!(v%4);m+=m)v/=4;for(a=-~(q=Math.sqrt)(v);a--;)for(w=v-a*a,b=-~q(w);b--;)for(x=w-b*b,c=-~q(x);c--;)(d=q(x-c*c))==~~d&&p([m*a, m*b, m*c, m*d],a=b=c='')

Ungolfed:

v = prompt();

for (m = 1; ! (v % 4); m += m) 
{
  v /= 4;
}
for (a = - ~Math.sqrt(v); a--;) /* ~ force to negative integer, changing sign lead to original value + 1 */
{
  for ( w = v - a*a, b = - ~Math.sqrt(w); b--;)
  {
    for ( x = w - b*b, c = - ~Math.sqrt(x); c--;)
    {
      (d = Math.sqrt(x-c*c)) == ~~d && prompt([m*a, m*b, m*c, m*d], a=b=c='') /* 0s a,b,c to exit loop */
    }
  }
}

উদাহরণ আউটপুট

123456789
11111,48,10,8

805306368
16384,16384,16384,0
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.