অবশিষ্ট নম্বর সিস্টেম


26

বিপুল সংখ্যক চ্যালেঞ্জের শিরাতে আমি ভেবেছিলাম এটি আকর্ষণীয় হতে পারে।

এই চ্যালেঞ্জের ক্ষেত্রে, আমরা বড় সংখ্যায় যোগ, বিয়োগ এবং গুণক সম্পাদনের জন্য অবশিষ্টাংশ নম্বর সিস্টেম (আরএনএস) ব্যবহার করব ।

আরএনএস কি

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

আসুন প্রথম তিনটি মৌলিক সংখ্যাগুলি দেখুন: 2, 3, 5। আরএনএস সিস্টেমে, আমরা এই তিনটি সংখ্যাটি 2 * 3 * 5 = 30 এর চেয়ে কম যে কোনও সংখ্যা অবশিষ্টাংশ ব্যবহার করে স্বতন্ত্রভাবে উপস্থাপন করতে ব্যবহার করতে পারি । 21 নিন:

২১ এর চেয়ে কম 30, সুতরাং আমরা 2, 3 এবং 5 দ্বারা পরিবর্তনের পরে ফলাফলগুলি ব্যবহার করে এটি উপস্থাপন করতে পারি (অর্থাত্ 2, 3, এবং 5 দ্বারা পূর্ণসংখ্যার পরে অবশিষ্ট)

আমরা নিম্নলিখিত সংখ্যার অনুক্রমের সাথে 21 চিহ্নিত করব:

21 ~ {21 মড 2, 21 মড 3, 21 মড 5} = {1, 0, 1}

এবং তাই আমাদের আরএনএস সিস্টেমে "21" এর পরিবর্তে আমরা {1,0,1} ব্যবহার করব}

সাধারণভাবে একটি পূর্ণসংখ্যার এন দেওয়া হয় , আমরা n কে { n মড 2, ..., n মোড পি_ কে represent হিসাবে প্রতিনিধিত্ব করি যেখানে পি_ কে সবচেয়ে ছোট প্রাইম যেমন এন সমস্ত প্রাইমারের পণ্যের চেয়ে পি_ কে কম বা সমান ।

আরেকটি উদাহরণ হিসাবে বলুন যে আমাদের 3412 আছে We আমাদের এখানে 2,3,5,7,11,13 ব্যবহার করা দরকার কারণ এটি 2*3*5*7*11*13=30030যখন 2*3*5*7*11=2310খুব ছোট।

3412 ~ {3412 মড 2, 3412 মড 3, 3412, 5 মড, ..., 3412 মড 13} = {0, 1, 2, 3, 2, 6}

আপনি লক্ষ্য করেছেন যে এই সিস্টেমটি ব্যবহার করে আমরা তুলনামূলকভাবে বেদাহীনভাবে খুব বড় সংখ্যক প্রতিনিধিত্ব করতে পারি। , 1, 2, 3, 4, 5, 6, 7, 8, ...} অবশিষ্টাংশগুলি ব্যবহার করে আমরা 2,6,30, 210, 2310, 30030, 510510, 9699690 ... to পর্যন্ত সংখ্যা উপস্থাপন করতে পারি ... যথাক্রমে। ( এখানে সিরিজটি দেওয়া হয়েছে )

আমাদের কাজ

আমরা এই সংशेषগুলি +, - এবং * প্রচুর সংখ্যক সম্পাদন করতে ব্যবহার করব। আমি নীচে এই প্রক্রিয়াগুলি বর্ণনা করব। আপাতত এখানে ইনপুট এবং আউটপুট চশমা রয়েছে।

ইনপুট

স্টিডিন বা ফাংশন আর্গুমেন্টের মাধ্যমে আপনাকে দুটি (সম্ভাব্য খুব বড়) নম্বর দেওয়া হবে। তাদের বেস 10 অঙ্কের স্ট্রিং হিসাবে দেওয়া হবে।

সমস্যাটি আরও রূপরেখা দেওয়ার উদ্দেশ্যে, আমরা প্রথম ইনপুট nএবং দ্বিতীয়টিকে কল করি mএন> মি> = 0 ধরে নিন

এছাড়াও আপনি দেওয়া হবে +বা -বা *অপারেশন ইঙ্গিত সম্পাদন করতে।

আউটপুট

এক্স একটি পূর্ণসংখ্যা হতে দিন । আমরা [ব্যবহার করবে এক্স ] RNS প্রতিনিধিত্বের উপরে বর্ণিত উল্লেখ করতে এক্স

আপনি আউটপুট হয় [n] <operator> [m] = [result]

আরএনএসে কীভাবে অপারেশন করবেন

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

অর্থাত

{1, 2, 3} + {1, 1, 4} = {(1 + 1) মোড 2, (2 + 1) মোড 3, (3 + 4) মোড 5} = {0, 0, 2}

মনে রাখবেন যে দুটি পৃথক সংখ্যার প্রতিনিধিত্ব করতে ব্যবহৃত অবশিষ্টাংশের সংখ্যা যদি একই না হয়, অপারেশন সম্পাদন করার সময়, আপনাকে "সংক্ষিপ্ত" সংখ্যাটি প্রসারিত করতে হবে যাতে এতে একই সংখ্যার অবশিষ্টাংশ থাকে। এটি একই প্রক্রিয়া অনুসরণ করে। উদাহরণস্বরূপ পরীক্ষার কেসগুলি দেখুন।

ফলাফলের জন্য যদি ইনপুটের চেয়ে আরও বেশি অবশিষ্টাংশের প্রয়োজন হয় তবে একই হয়। তারপরে উভয় ইনপুটগুলি "বর্ধিত" করা দরকার।

গুরুত্বপূর্ণ বিশদ

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

  • যদি কারও কারণে এটি আপনার ভাষায় ব্যবহৃত ডিফল্ট পূর্ণসংখ্যা উপস্থাপনা। ওটা দারুন.

  • আপনার ভাষার ডিফল্ট না হলে আপনি কোনও সালিশী যথার্থ পূর্ণসংখ্যার প্রকার ব্যবহার করতে পারবেন না। যদি এটি ডিফল্ট হয় তবে আপনি এটি পূর্ণসংখ্যার সঞ্চয় করতে ব্যবহার করতে পারবেন না যা সাধারণত b৪ বিটে ফিট হয় না।

  • স্পষ্টত, প্রতিটি পূর্ণসংখ্যার সর্বদা সম্ভব কয়েকটি সংখ্যক অবশিষ্টাংশের সাথে প্রতিনিধিত্ব করা হবে। এটি উভয় ইনপুট এবং আউটপুট জন্য যায়।

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

পরীক্ষার মামলা

  1. ইনপুট:

n = 10
m = 4
+

আউটপুট:

{ 0, 1, 0 } + { 0, 1 } = { 0, 2, 4 }

ব্যাখ্যা:

প্রথমে প্রতিটি নম্বরটিকে উপরে বর্ণিত হিসাবে তার আরএনএস উপস্থাপনায় পরিবর্তন করুন:

10 ~ {0,1,0}এবং 4 ~ {0,1}। লক্ষ্য করুন যে আমরা যখন উপাদান-যুক্ত সংযোজন করতে চাই তখন এর 10চেয়ে আরও বেশি উপাদান রয়েছে 4। সুতরাং আমাদের সংক্ষিপ্ত সংখ্যাটি "প্রসারিত" করতে হবে। সুতরাং আমরা সংক্ষেপে লিখব 4 ~ {0,1} --> {0,1, 4 mod 5} = {0,1,4}। এখন আমরা সংযোজন নিয়ে এগিয়ে যাব এবং তারপরে মডিউলটি নিই।

  1. ইনপুট
n=28
m=18
+

আউটপুট:

 [ 0, 1, 3 ] + [0, 0, 3 ] = [ 0, 1, 1, 4 ]
  1. ইনপুট (আমি কীবোর্ডে আমার মুখ জালাই করছি)
n=1231725471982371298419823012819231982571923
m=1288488183
*

আউটপুট (পাঠযোগ্যতার জন্য পৃথক লাইনে বিভক্ত):

[1, 2, 3, 6, 2, 10, 2, 1, 12, 16, 7, 15, 34, 29, 31, 5, 55, 32, 66, 61, 3, 76, 52, 14, 65, 44, 99, 57 ] 
* 
[1, 0, 3, 3, 4, 8, 9, 10, 8, 0 ] 
= 
[1, 0, 4, 4, 8, 2, 1, 10, 4, 0, 17, 7, 27, 21, 44, 51, 56, 9, 6, 9, 12, 0, 52, 36, 43, 68, 99, 24, 96, 39, 96, 66, 125] 

n28 প্রাইম প্রয়োজন। mপ্রয়োজন 10. n*mপ্রয়োজন 33।

  1. ইনপুট
n=8709668761379269784034173446876636639594408083936553641753483991897255703964943107588335040121154680170867105541177741204814011615930342030904704147856733048115934632145172739949220591246493529224396454328521288726490
m=1699412683745170450115957274739962577420086093042490863793456500767137147999161679589295549397604032154933975242548831536518655879433595016
-

আউটপুট:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 509]
-
[0, 2, 1, 6, 1, 12, 11, 18, 14, 28, 21, 36, 37, 42, 16, 52, 41, 60, 16, 70, 49, 78, 80, 88, 49, 100, 13, 106, 4, 112, 68, 130, 36, 138, 37, 150, 0, 162, 8, 172, 163, 180, 18, 192, 129, 198, 135, 222, 78, 228, 90, 238, 57, 250, 36, 262, 87, 270, 206, 280, 193, 292, 253, 310, 224, 316, 57, 336, 48, 348]
=
[0, 1, 4, 1, 10, 1, 6, 1, 9, 1, 10, 1, 4, 1, 31, 1, 18, 1, 51, 1, 24, 1, 3, 1, 48, 1, 90, 1, 105, 1, 59, 1, 101, 1, 112, 1, 0, 1, 159, 1, 16, 1, 173, 1, 68, 1, 76, 1, 149, 1, 143, 1, 184, 1, 221, 1, 182, 1, 71, 1, 90, 1, 54, 1, 89, 1, 274, 1, 299, 1, 266, 1, 228, 1, 340, 1, 170, 1, 107, 1, 340, 1, 88, 1, 157, 1, 143, 1, 22, 1, 22, 1, 58, 1, 296, 1, 371, 1, 140]

n100 প্রাইম ব্যবহার করে। m70 প্রাইম ব্যবহার করে। n-m99 টি প্রাইম ব্যবহার করে।

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


যারা যত্নশীল তাদের জন্য প্রথম 100 টি প্রাইমের পণ্য হ'ল:

471193079990618495316248783476026042202057477340967552018863483961641533584503
422120528925670554468197243910409777715799180438028421831503871944494399049257
9030720635990538452312528339864352999310398481791730017201031090

প্রদত্ত সিস্টেমটি (এবং 100 টি প্রাথমিক সীমাবদ্ধতা) ব্যবহার করে আমরা প্রতিনিধিত্ব করতে পারি এমন সর্বাধিক সংখ্যার চেয়ে এই সংখ্যাটি 1 টি বড়।

কিছুটা সম্পর্কিত


আমি মনে করি যে অপারেশন করা সবচেয়ে শক্ত অংশ হতে দূরে, যার জন্য আমি এই চ্যালেঞ্জটি সম্পর্কে অদ্ভুত বোধ করি।
এনজিপিপোরগান

@ এনজপিপেওরগান আমি সম্মত, অপারেশন করা কেবল (a,b,o)=>a.map((v,i)=>eval(v+o+b[i]))ES6 এ উদাহরণস্বরূপ। আমি মনে করি সবচেয়ে শক্ত অংশটি সম্ভবত নির্বিচারে নির্ভুলতা পাটিগণিত ব্যবহার না করে ফলাফলকে উপস্থাপনের জন্য প্রয়োজনীয় প্রাইম সংখ্যাটি সন্ধান করছে, যদিও পরবর্তী সময়ে আরএনএসে রূপান্তরটি একেবারেই তুচ্ছ নয়।
নিল

আমি কি ( 1234,1234,+) এর মতো ইনপুট পেতে পারি ?
ক্লিমেজিক

@derpfacePython হ্যাঁ ফাংশনগুলিও গ্রহণযোগ্য
লিয়াম

"কেবলমাত্র প্রদত্ত ক্রিয়াকলাপগুলি উপাদান-ভিত্তিতে সম্পাদন করুন" - তাহলে আউটপুটটিতে অতিরিক্ত উপাদানগুলি কোথা থেকে আসবে?
স্মিল

উত্তর:


6

GAP

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

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


কোড

### The first 100 primes;
primes := Primes{[1..100]};

### In many of the functions below, the 'string' variable is a string of digits
###


### Returns the 'index' digit of 'string' as an integer
GetValueAsInt := function(string, index) 
    return IntChar(string[index]) - 48;
end;

### Used in the 'modulus' function. See that comment for more information. 
### Calculates the contribution to the modulus of a digit 'digit' in the 10^power place.
### 'integer' is the modulus
digit_contribution := function(digit, integer, power)
    local result, i;
    result := 1;
    for i in [0..power-1] do
        result := ( result * (10 mod integer) ) mod integer;
    od;
    result := (result * (digit mod integer) ) mod integer;
    return result;
end;

### This modulus function is used to calculate the modulus of large numbers without storing them
##### as large numbers.
### It does so by breaking them into digits, and calculating the contribution of each digit.
### e.g. 1234 mod 5 = (1000 mod 5)(1 mod 5) + (200 mod 5)(2 mod 5) + (10 mod 5)(3 mod 5) + (4 mod 5)
### It actually mods after every calculation to ensure that we never get a number larger
##### than the modulus ('integer') squared, which will never be even close to 10^64-1
modulus := function(string, integer)
    local i, result, digit, len;
    len := Length(string);
    result := 0;
    for i in [1..len] do
        digit :=  IntChar(string[i]) -48;
        result := ( result + digit_contribution(digit, integer, len-i) )  mod integer;
    od;
    return result;
end;

### This returns the product of the first i-1 primes (mod j). It must not (and does not)
##### ever store an integer larger than 2^64-1
phi_i := function(i,j)
    local index, result;
    result := 1;
    for index in [1..i-1] do
        result := ( result * primes[index] ) mod primes[j];
    od;
    return result;
end;

### Calculates the first residues of 'string' mod the first 100 primes
get_residues := function(string) 
    local p, result;
    result := [];
    for p in primes do
        Add( result, modulus(string, p) );  
    od; 
    return result;
end;

### Gets the ith element in the partial_chinese array, given the previous elements
### See the explanation section and partial_chinese function for more info
get_partial_i := function( i, residues, previous_array )
    local index, result;
    result := residues[i];
    for index in [1..Length(previous_array)] do
        result := ( result - previous_array[index]*phi_i(index,i) ) mod primes[i]; 
    od;     
    result := ( result / phi_i(i,i) ) mod primes[i];
    return result;
end;

### returns an array such that the sum of prod_primes(i)*array[i] is equal to the integer value
##### that is represented by the residues. (It basically just does the CRT without
##### actually summing everything.) prod_primes(i) is the product of the first i-1 primes 
### See the explanation for a bit more info
### This is what allows us to determine the minimal number of primes to represent a RNS number
partial_chinese := function( string )
    local array, i, residues;
    residues := get_residues(string);
    array := [];        
    for i in [1 .. Length(primes)] do
        Add( array, get_partial_i( i, residues, array ) );
    od;
    return array;   
end;

### Same as partial_chinese but takes input in a different form.
partial_chinese_from_residues := function(residues)
    local array, i;
    array := [];        
    for i in [1 .. Length(primes)] do
        Add( array, get_partial_i( i, residues, array ) );
    od;
    return array;
end;

### gives you the number of primes needed to represent an integer. Basically asks how 
##### many trailing zeros there are in the chinese array.
get_size := function(string)
    local array, i, len, result;
    array := partial_chinese(string);
    len := Length(array);
    for i in [0..len-1] do
        if  not (array[len-i] = 0) then
            return len -i;
        fi; 
    od; 
    Print("ERROR: get_size().\n");
    return 0;
end;

### Same as above but with different input format
get_size_from_residues := function(residues)
    local array, i, len, result;
    array := partial_chinese_from_residues(residues);
    len := Length(array);
    for i in [0..len-1] do
        if  not (array[len-i] = 0) then
            return len -i;
        fi; 
    od; 
    Print("ERROR: get_size().\n");
    return 0;
end;

### the actual function. inputs are all strings
f := function(in1, in2, opperation)
    local residues_1, residues_2, residues_result, i;
    residues_1 := get_residues(in1);
    residues_2 := get_residues(in2);
    residues_result := [];
    if opperation = "+" then
        for i in [1..Length(primes)] do
            Add( residues_result, ( residues_1[i] + residues_2[i] ) mod primes[i]);
        od;     
    elif opperation = "*" then
        for i in [1..Length(primes)] do
            Add( residues_result, ( residues_1[i] * residues_2[i] ) mod primes[i]);
        od;     
    elif opperation = "-" then
        for i in [1..Length(primes)] do
            Add( residues_result, ( residues_1[i] - residues_2[i] ) mod primes[i]);
        od;     
    fi;
    Print(residues_1{[1..get_size(in1)]}, " ", opperation, " ", residues_2{[1..get_size(in2)]}, " = ", residues_result{[1..get_size_from_residues(residues_result)]} );
end;

ব্যাখ্যা:

শুরু করার জন্য, আমরা উভয় ইনপুটগুলির জন্য সমস্ত 100 টি অবশিষ্টাংশ গণনা করি। আমরা modulusকোডটিতে ফাংশন দিয়ে এটি করি । আমি সাবধান হওয়ার চেষ্টা করেছি যাতে modপ্রতিটি পদক্ষেপের পরে অন্তর্নির্মিত ফাংশনটি ব্যবহার করতে পারি । এটি নিশ্চিত করে যে আমাদের কখনই এর চেয়ে বড় কোনও সংখ্যা নেই 540^2, যা 100 তম প্রাইম স্কোয়ারের চেয়ে 1 কম।

আমাদের সমস্ত অবশিষ্টাংশ থাকার পরে, আমরা প্রদত্ত ক্রিয়াকলাপটি এবং modপ্রতিটি প্রবেশ আবার করতে পারি। ফলাফলের জন্য এখন আমাদের কাছে একটি অনন্য ডিজাইনার রয়েছে, তবে ফলাফল এবং প্রতিটি ইনপুট উপস্থাপনের জন্য আমাদের ন্যূনতম এন্ট্রিগুলি নির্ধারণ করতে হবে।

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

prod(i)প্রথম প্রধান i-1সংখ্যাগুলির যোগফল হওয়া যাক । উদাহরণ স্বরূপ,

prod(1) = 1
prod(2) = 2
prod(3) = 6
prod(4) = 30
etc

Xএকটি পূর্ণসংখ্যা হতে দিন । দিন {r_i}এর তলানি হতে X, যে হয়

r_i = X mod p_i

কোথায় p_iহয় iতম প্রধানমন্ত্রী। এটি 1<i<=100আমাদের ক্ষেত্রে।

এখন আমরা একটি ক্রম এটি সিআরটি ব্যবহার করতে যাচ্ছি {u_i}যেমন যে ওভার সমষ্টি iএর prod(i) * u_iসমান X। মনে রাখবেন যে, প্রতিটি u_iএছাড়াও টেকনিক্যালি একটি অবশিষ্টাংশ, কারণ u_i < p_i। তদ্ব্যতীত, যদি X < prod(i)তারপর u_i = 0। এটি সমালোচনামূলকভাবে গুরুত্বপূর্ণ। এর অর্থ হ'ল পিছনের শূন্যগুলি পরীক্ষা করে আমরা নির্ধারণ করতে পারি যে আমাদের আরএনএসে r_iআসলে কতটি অবশিষ্টাংশের প্রতিনিধিত্ব করতে হবে X

আপনি যদি কিছু সিকোয়েন্স পরীক্ষা করতে যত্নশীল হন u_iতবে partial_chineseফাংশনটি u_iঅনুক্রমটি প্রদান করে।

সিআরটি-র সাথে জগাখিচু করে, আমি u_iকতগুলি অবশিষ্টাংশের প্রয়োজন তা নির্ধারণের সমস্যাটি সমাধান করে মানগুলির জন্য একটি পুনরাবৃত্ত সূত্রটি সন্ধান করতে সক্ষম হয়েছি।

সূত্রটি হ'ল:

u_i = [ r_i - SUM ] / prod(i)       (mod p_i)

কোথায় SUMউপর সমষ্টি j in [1,i)এর u_j * prod(i)

অবশ্যই prod(i)কিছু ক্ষেত্রে এটি গণনা করা যায় না কারণ এটি অনেক বড়। এই উদ্দেশ্যে, আমি phi_iফাংশনটি ব্যবহার করেছি । এই ফাংশনটি ফেরত দেয় prod(j) (mod p_i)। এটি modপ্রতিটি পদক্ষেপে তাই আমরা আসলে খুব বড় যে কোনও কিছুই গণনা করি না।

আপনি যদি কৌতূহলী হন তবে এই সূত্রটি কোথা থেকে এসেছে, আমি সিআরটির কয়েকটি উদাহরণ ব্যবহার করার পরামর্শ দেব, যা উইকিপিডিয়া পৃষ্ঠায় পাওয়া যাবে ।

পরিশেষে, প্রতিটি ইনপুট পাশাপাশি আমাদের আউটপুটের জন্য আমরা u_iক্রমটি গণনা করি এবং তারপরে পিছনের শূন্যগুলি নির্ধারণ করি। তারপরে আমরা সেইগুলিকে r_iঅবশিষ্টাংশের ক্রমগুলির শেষে থেকে বের করে দেই ।


"গল্ফড" কোড, 2621 বাইট

primes:=Primes{[1..100]};GetValueAsInt:=function(string,index)return IntChar(string[index])-48;end;digit_contribution := function(digit, integer, power)local result, i;result:=1;for i in [0..power-1] do result := ( result * (10 mod integer) ) mod integer;od;result:=(result*(digit mod integer) ) mod integer;return result;end;modulus:=function(string, integer)local i,result,digit,len;len:=Length(string);result:=0;for i in [1..len] do digit:= IntChar(string[i])-48;result:=(result+digit_contribution(digit,integer,len-i)) mod integer;od;return result;end;phi_i:=function(i,j)local index,result;result:=1;for index in [1..i-1] do result:=(result*primes[index] ) mod primes[j];od;return result;end;get_residues:=function(string) local p,result;result:=[];for p in primes do Add(result,modulus(string,p));od;return result;end;get_partial_i:=function(i,residues,previous_array)local index,result;result:=residues[i];for index in [1..Length(previous_array)] do result:=(result-previous_array[index]*phi_i(index,i) ) mod primes[i];od;result:=(result/phi_i(i,i)) mod primes[i];return result;end;partial_chinese:=function(string)local array,i,residues;residues:=get_residues(string);array:=[];for i in [1 .. Length(primes)] do Add(array,get_partial_i(i,residues,array));od;return array;end;partial_chinese_from_residues:=function(residues)local array,i;array:=[];for i in [1..Length(primes)] do Add(array,get_partial_i(i,residues,array));od;return array;end;get_size:=function(string)local array,i,len,result;array:=partial_chinese(string);len:=Length(array);for i in [0..len-1] do if not (array[len-i] = 0) then return len-i;fi;od;Print("ERROR: get_size().\n");return 0;end;get_size_from_residues:=function(residues)local array,i,len,result;array:=partial_chinese_from_residues(residues);len:=Length(array);for i in [0..len-1] do if not (array[len-i]=0) then return len-i;fi;od;Print("ERROR: get_size().\n");return 0;end;f:=function(in1,in2,opperation)local residues_1,residues_2,residues_result,i;residues_1:=get_residues(in1);residues_2:=get_residues(in2);residues_result:=[];if opperation = "+" then for i in [1..Length(primes)] do Add(residues_result,(residues_1[i]+residues_2[i] ) mod primes[i]);od;elif opperation = "*" then for i in [1..Length(primes)] do Add(residues_result,(residues_1[i]*residues_2[i])mod primes[i]);od;elif opperation = "-" then for i in [1..Length(primes)] do Add(residues_result,(residues_1[i]-residues_2[i]) mod primes[i]);od;fi;Print(residues_1{[1..get_size(in1)]}, " ", opperation, " ", residues_2{[1..get_size(in2)]}, " = ", residues_result{[1..get_size_from_residues(residues_result)]} );end;

আমি বিভ্রান্ত কারণ নিয়মিত আরএনএস প্রয়োজন অনুযায়ী মাত্রা পরিবর্তন করে না, তবে কেবল প্রয়োজনীয় মাত্রাগুলি এবং তারপরে ক্রিয়াকলাপ সম্পাদনের পরিবর্তে আপনি কি ইনপুট থেকে বর্ধিত 100 টি অবশিষ্টাংশের সংখ্যা গণনা করে নিয়মগুলি বেঁকেন না? "প্রথমে প্রতিটি নাম্বারটিকে তার আরএনএস উপস্থাপনায় উপরে বর্ণিত হিসাবে পরিবর্তন করুন " আমার কাছে অর্থ 'আরএনএস' সংখ্যার কিছু করার আগে কেবল প্রয়োজনীয় অবশিষ্টাংশ থাকা উচিত।
লিনাস

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

@ লিনাস এবং আপনার প্রথম প্রশ্নের উত্তরে সাধারণত সমস্ত সংখ্যা একই সংখ্যার অবশিষ্টাংশ ব্যবহার করবে। এটি প্রশ্নটিকে অনেক সহজ করে তুলবে
লিয়াম

2

গাণিতিক, গল্ফ নয়

rns[d_,l_]:=Table[Reap[
    FoldPairList[Sow@QuotientRemainder[10#+#2,Prime@i]&,0,d]
  ][[2,1,-1,2]],{i,l}];
plus[a_,b_]:=Mod[a+b,Prime@Range@Length@a];
subtract[a_,b_]:=Mod[a-b,Prime@Range@Length@a];
times[a_,b_]:=Mod[a b,Prime@Range@Length@a];
mag[f_]:=LengthWhile[FoldList[#/#2&,f,Prime@Range@100],#>1.1&];
ext[m_,n_,i_]:=Fold[Mod[1##,Prime@i]&,m,Prime@Range@n];
multi[e_,p_,t_]:=Tr@Position[Mod[e Range@p,p],p-t];
appx[d_] := N@FromDigits[{d~Take~UpTo[6], Length@d}]
  • ফাংশন rns[d_,l_]একটি বেস -10 পূর্ণসংখ্যাকে dদৈর্ঘ্যের একটি আরএনএস পূর্ণসংখ্যায় রূপান্তর করে l

  • ফাংশন plus/ times/ subtractযোগ / গুণিত / একটি আরএনএস পূর্ণসংখ্যাকে অন্য / থেকে বিয়োগ করে, উভয়ই একই দৈর্ঘ্যের।

  • ফাংশনটি তার আরএনএস প্রতিনিধিত্বের দৈর্ঘ্যের নীচের সীমানার ক্ষেত্রে mag[f_]ভাসমান পয়েন্ট সংখ্যাটির আনুমানিক প্রস্থের অনুমান করে f

  • ফাংশন ext[m_,n_,i_]গুণফল বিভাজন থেকে বাকি খুঁজে বের mএবং Prime[Range@n]দ্বারা Prime[i]

  • ফাংশনটি multi[e_,p_,t_]ক্ষুদ্রতম গুণককে mসন্তুষ্ট করেDivisible[m*e+t,p]

  • ফাংশন দশমিক পূর্ণসংখ্যার appx[d_]প্রথম 6অঙ্ক নেয় এবং তার আনুমানিক ভাসমান পয়েন্টের মান দেয়।


উপরের ফাংশনগুলির সাহায্যে, এখন আমরা একটি জটিল সমস্যা সমাধান করতে সক্ষম হচ্ছি - ফলাফলটির দৈর্ঘ্য নির্ধারণ করতে

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

উদাহরণ হিসেবে বলা যায়, প্রদত্ত যে মৌলিক গুণফল 1থেকে 30হয় 3.16*10^46, প্রায় পূর্ণসংখ্যার RNS দৈর্ঘ্য 3.16*10^46সম্ভবত হতে পারে 29বা 30। ফাংশনটি এই পূর্ণসংখ্যার জন্য একটি রেফারেন্স হিসাবে magদেবে 29, এটি দেখায় যে উভয়ই সম্ভব 29এবং 30সম্ভাব্য।

মাত্রাটি জানার পরে, আমরা কেবলমাত্র তার দৈর্ঘ্যের গণনা করার আশায় সরাসরি সেই দৈর্ঘ্য অনুসারে পূর্ণসংখ্যা উপস্থাপন করি। এখানে কৌশলটি হ'ল মূল সংখ্যাটিতে কিছু নতুন সংখ্যা যুক্ত করা এবং তার আরএনএস প্রতিনিধিত্ব সংশোধন করা, যতক্ষণ না উপস্থাপনাটি সমস্ত শূন্য হয়।

উদাহরণস্বরূপ, mag[211.]হয় 4এবং এর দৈর্ঘ্যের 4প্রতিনিধিত্ব {1, 1, 1, 1}

step 1:   {1,1,1,1} -> {0,2,2,2}  by adding  (1) * 1 = 1
step 2:   {0,2,2,2} -> {0,0,1,6}  by adding  (2) * 2 = 4
step 3:   {0,0,1,6} -> {0,0,0,2}  by adding  (2*3) * 4 = 24
step 4:   {0,0,0,2} -> {0,0,0,0}  by adding  (2*3*5) * 6 = 180
step 5:   calculate 211 + (1 + 4 + 24 + 180) ~ 420

কিছু সংখ্যার যোগ করে আমরা 211ক্ষুদ্রতম সংখ্যায় বৃদ্ধি করি যা 210( 2*3*5*7) দ্বারা বিভাজ্য । এবং এখন আমরা এই সিদ্ধান্তে পৌঁছেছি যে মূল সংখ্যাটি এর চেয়ে বেশি 210, যেহেতু 420"প্রায়" দ্বিগুণ 210। এটি ধারণা করা কঠিন নয় যে আমরা যদি শুরু করি 209তবে চূড়ান্ত সংখ্যাটি "আনুমানিক" 210

প্রস্থটি অনুমান করতে এবং এটির আরএনএস উপস্থাপনার ভিত্তিতে এটি সংশোধন করে ফাংশনটি length[f_,n_]ভাসমান পয়েন্টের মান নেয় ।fn

length[f_,n_]:=With[{g=mag@f},
    g+If[#==0,1,Round[(#+f)/Times@@Prime@Range@g]-1]&[
      FoldList[Times,1.,Prime[Range[g-1]]].
      FoldPairList[
        Block[{i=#2,m},
          {m=multi[ext[1,i-1,i],Prime@i,Part@##],rnsPlus[#,ext[m,i-1,#]&/@Range[g]]}
        ]&,n,Range[g]]]]

ফাংশন rnsOperation[a_,b_,op_,rnsop_]দেয় rnsop[a,b]এবং opস্বাভাবিক ফ্লোটিং পয়েন্ট মান উপর ভিত্তি করে আনুমানিক ফলাফল পেতে ব্যবহার করা অপারেশন সংশ্লিষ্ট করা হয়।

rnsOperation[a_,b_,op_,rnsop_]:=Block[{c=op[appx@a,appx@b],m},
    m=mag[c];m=length[c,rnsop[rns[a,m],rns[b,m]]];rnsop[rns[a,m],rns[b,m]]]

উদাহরণ

rnsOperation[
    IntegerDigits@1231725471982371298419823012819231982571923,
    IntegerDigits@1288488183,
    Times, times]
(* {1,0,4,4,8,2,1,10,4,0,17,7,27,21,44,51,56,9,6,9,12,0,52,36,43,68,99,24,96,39,96,66,125} *)

1
দুর্ভাগ্যক্রমে, আমাদের সহায়তা কেন্দ্রে বর্ণিত বিধিগুলির জন্য সমস্ত সাবমিশনগুলি ব্যবহারে বিজয়ী মানদণ্ডের জন্য একটি গুরুতর প্রতিযোগী হতে হবে। একটি কোড গল্ফ প্রতিযোগিতার জন্য, এর অর্থ সমস্ত জমাটি গল্ফ করা উচিত।
ডেনিস

@ ডেনিস আমি এই বিধি সম্পর্কে জানি। তবে গল্ফ না করেও আমি মনে করি এই সমস্যাটি যথেষ্ট জটিল এবং জটিল, যাতে গল্ফিংয়ের চেয়ে এই সমস্যাটি সমাধান করা আমার উদ্দেশ্য।
njpipeorgan

এটি সম্ভবত গল্ফ নয় তবে আমার জাভা প্রোগ্রামের সাথে তুলনা করে খুব কম: পি, যদিও আমার প্রোগ্রামামটি সম্ভবত খুব দ্রুত।
আশাকরি

1
আমার মনে হচ্ছে আপনি এটি গল্ফ করতে সক্ষম
রোহান ঝুনঝুনওয়ালা

2

পাইথন 3 , 435 বাইট

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

এবং তাই, এটি লিয়ামের উত্তরের একটি বন্দর ।

এটি অনলাইন চেষ্টা করুন!

from functools import reduce as R
G=range
d=lambda s:[R(lambda z,c:(z*10+int(c))%q,s,0)for q in p]
h=lambda j,i:R(lambda z,q:z*q%p[i],p[:j],1)
def s(r):
 a=[];z=99
 for i in G(100):
  P=p[i];u=r[i]
  for j in G(len(a)):u=(u-a[j]*h(j,i))%P
  for k in G(1,P):
   if h(i,i)*k%P<2:break
  a+=u*k%P,
 while(a[z]<1)*z:z-=1
 return r[:z+1]
def f(a,b,n):u=d(a);v=d(b);print(s(u),n,s(v),'=',s([eval(str(u[i])+n+str(v[i]))%p[i]for i in G(100)]))

ব্যাখ্যা

লিয়ামের উত্তরটি বন্দরের চেষ্টা করার সময় আমি ব্যক্তিগতভাবে পেয়েছি যে প্রদত্ত কিছু ব্যাখ্যা বিভ্রান্তিকরভাবে বলা হয়েছিল, তাই তাঁর এলগরিদমকে ব্যাখ্যা করার ক্ষেত্রে এটি আমার চেষ্টা।

প্রথমত, আমরা এর তলানি পেতে nএবং m

res1 = get_residues(n)
res2 = get_residues(m)

এর মধ্যে ইনপুট স্ট্রিংয়ের সমস্ত অঙ্কগুলি ঘুরিয়ে দেওয়া এবং তাদের প্রতিটি প্রাইমগুলিকে সংখ্যায় মডুলোতে পরিণত করা, যেমন ২৮ এর জন্য আমাদের রয়েছে [(20 + 8) mod 2, (20 + 8) mod 3, (20 + 8) mod 5, etc]

def get_residues(string):
    result = []
    for p in primes:
        result.append(reduce(lambda z, c:(z*10+int(c)) % p, string, 0))

তারপরে আমরা জোড়ায় জোড় করে জোড়, যোগ বা গুণফলকে বিয়োগ করি eval()

result = []
for i in range(len(primes)):
    result.append((eval(str(res1[i]) + op + str(res2[i])) % primes[i])

তারপরে আমরা আমাদের অবশিষ্টাংশগুলির মাপগুলি পাই, অর্থাৎ আমাদের প্রয়োজনীয় ন্যূনতম সংখ্যা।

size1 = get_size(res1)
size2 = get_size(res2)
size3 = get_size(result)

আকারগুলি পাওয়া সবচেয়ে জটিল এবং সর্বাধিক কোড-নিবিড় অংশ। আমরা partial_chineseফাংশনটি ব্যবহার করি যা আমাদের u_iসাথে আকার নির্ধারণের ক্রমটি পায় । u_iএক মুহুর্তে আরও

def get_size(residues):
    array = partial_chinese(residues)
    size = len(residues)-1
    while array[size] == 0 and size:
        size -= 1
    return size+1  # to prevent off-by-one errors from 0-indexing

ক্রম u_iপ্রতিটি অবশিষ্টাংশ গ্রহণ করে গণনা করা হয় r_i, সমষ্টি বিয়োগ u_j * primorial(j) for j in [1, i), এবং তারপর dividingদ্বারা primorial(i), সমস্ত মডিউল primes[i]। তা হ'ল u_i = (r_i - SUM) / primorial(i),। এক মুহুর্তে আমাদের প্রাথমিক ও বিভাগীয় কার্য সম্পর্কে আরও।

def partial_chinese(residues):
    array = []
    for i in range(len(primes)):
        array.append(get_partial_i(i, residues, array))
    return array

def get_partial_i(i, residues, previous_array):
    result = residues[i]
    for j in range(len(previous_array)):
        result = (result - previous_array[j] * phi_i(j, i)) % primes[i]
    result = result * inverse(phi_i(i, i), primes[i]) % primes[i]
    return result

phi_i(j, i)গণনা করে primorial(j) mod primes[i]। বিভাগ modulo কোন মৌলিক pসহজেই নিজে গুণনশীল inverses জন্য চেক করে বাস্তবায়িত হয় হিসাবে আমরা নিশ্চিত যে কোন সম্ভাব্য হতে পারে u_iহয় 0 <= u_i < pপি থেকে coprime হতে নিশ্চিত করা হয় এবং তাই একটি গুণনশীল বিপরীত নিশ্চিত করা হয়।

def phi_i(j, i):
    return reduce(lambda z, q: z * q % primes[i], primes[:j], 1)

def inverse(n, p):
    for i in range(1, p):
        if n * i % p == 1:
            return i

যা কিছু হয়ে গেছে, আমরা আমাদের স্ট্রিংটি মুদ্রণ করি এবং আমাদের কাজ শেষ।

print(res1[:size1], op, res2[:size2], "=", result[:size3])

এরপর কি

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

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