হাজার টেলিফোন নম্বর সংরক্ষণের সর্বাধিক দক্ষ উপায়


94

এটি একটি গুগল সাক্ষাত্কার প্রশ্ন:

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

এটি করার জন্য সবচেয়ে দক্ষ স্পেস সেভিংয়ের উপায় কী?

আমি হ্যাশ টেবিল এবং পরে হাফম্যান কোডিংয়ের উত্তর দিয়েছি তবে আমার সাক্ষাত্কারক বলেছেন যে আমি সঠিক পথে যাচ্ছি না। আমাকে এখানে সাহায্য করুন।

একটি প্রত্যয় ত্রি সাহায্য ব্যবহার করতে পারেন?

আদর্শভাবে 1000 নম্বর স্টোরেজ করতে প্রতি সংখ্যা 4 বাইট লাগে তাই সব মিলিয়ে 1000 নম্বর সংরক্ষণে 4000 বাইট লাগবে। পরিমাণমতো, আমি স্টোরেজটি <4000 বাইটে হ্রাস করতে চাই, আমার ইন্টারভিউয়ার আমাকে এটি ব্যাখ্যা করেছিলেন।


28
আমি উত্তর দেব যে একটি সাধারণ ডাটাবেস ব্যবহার করে আপনি এগুলি পাঠ্য হিসাবে এমনকি হাজারে / মিলিয়ন হিসাবে সঞ্চয় করতে পারেন এবং অনুসন্ধানের কাজগুলি এখনও খুব দ্রুত হবে। আমি "চতুর" কাজগুলি করার বিরুদ্ধে পরামর্শ দেব যেহেতু ভবিষ্যতে আন্তর্জাতিক সংখ্যাগুলি সমর্থন করা উচিত, বা যদি "0" দিয়ে শুরু হওয়া টেলিফোন নম্বরগুলি প্রদর্শিত হতে শুরু করে, বা যদি সরকার সিদ্ধান্ত নেয় তবে পুরো সিস্টেমটি আবার করা উচিত since ফোন নম্বর ফর্ম্যাট ইত্যাদি পরিবর্তন করুন।
থমাস বনিনি

4
@ আন্ড্রেস বোনিনি: আমি সম্ভবত উত্তরটি দেব, যদি না আমি গুগল বা ফেসবুকের মতো কোনও সংস্থায় সাক্ষাত্কার না দিই, বাক্সের সমাধান না করে কেবল সমাধান না করে। উদাহরণস্বরূপ পোস্টগ্রাগুলির চেষ্টা করার পরেও, আমি নিশ্চিত হতে পারি না যে এইগুলি কাটা ডেটা থ্রুপুট গুগল গ্রহণ করা দরকার।
LiKao

4
@ লাইকাও: মনে রাখবেন যে ওপি বিশেষত "প্রায় এক হাজার সংখ্যা" বলেছিল
টমাস বোনিনি

@ আন্ড্রেস বোনিনি: সত্য, এটিও একটি পরীক্ষা হতে পারে, যে সাক্ষাত্কারী এই ধরনের প্রতিবন্ধকতাগুলি সঠিকভাবে ব্যাখ্যা করতে এবং এটি অনুসারে সেরা সমাধানটি বেছে নিতে জানে।
LiKao

4
এই প্রশ্নের "দক্ষ" সত্যই সংজ্ঞায়িত করা দরকার - কোন উপায়ে দক্ষ? স্থান, সময়, উভয়?
ম্যাট বি

উত্তর:


36

এখানে একটি উন্নতি এর Aix এর উত্তর । ডেটা স্ট্রাকচারের জন্য তিনটি "স্তর" ব্যবহার করার কথা বিবেচনা করুন: প্রথমটি প্রথম পাঁচটি অঙ্কের (17 বিট) ধ্রুবক; সুতরাং এখান থেকে প্রতিটি ফোন নম্বরটিতে বাকী পাঁচটি সংখ্যা বাকি রয়েছে। 17-বিট বাইনারি পূর্ণসংখ্যার এবং দোকান হিসাবে আমরা এই অবশিষ্ট পাঁচটি সংখ্যা দেখতে - একটি পদ্ধতি এবং 17 ব্যবহার করছেন তাদের বিট = মি একটি ভিন্ন পদ্ধতি সঙ্গে, নির্ণয় শেষে প্রয়োজনীয় স্থান কমান।

আমরা প্রথমে ফোন নম্বরগুলি বাছাই করি (সমস্ত হ'ল 5 দশমিক অঙ্কে)। তারপরে আমরা গণনা করি যে সেখানে কতগুলি ফোন নম্বর রয়েছে যার জন্য প্রথম এম বিটগুলির সমন্বিত বাইনারি নম্বরটি সমস্ত 0, প্রথম এম বিটস কতগুলি ফোন নম্বর সর্বাধিক 0 ... 01, প্রথম মিটার কত ফোন নম্বর বিটস সর্বাধিক 0 ... 10, এসটেরা, ফোন নম্বরগুলির গণনা অবধি যার জন্য প্রথম মিটার বিটগুলি 1 ... 11 - এই শেষ গণনাটি 1000 (দশমিক)। এখানে আছে 2 ^ হয় মি যেমন সংখ্যা এবং প্রতিটি গণনা সর্বাধিক 1000. আমরা গত এক বর্জন তাহলে (কারণ আমরা জানি এটা 1000 আসলে), আমরা একটি সংলগ্ন ব্লক এই সংখ্যার সব সংরক্ষণ করতে পারেন (2 ^ M - 1) * 10 বিট (10 বিট 1024 এর চেয়ে কম সংখ্যক সঞ্চয় করার জন্য যথেষ্ট))

সমস্ত (হ্রাস) ফোন নম্বরগুলির শেষ কে বিটগুলি স্মৃতিতে স্বচ্ছ সংরক্ষণ করা হয়; সুতরাং যদি কে হয়, 7 বলে, তবে মেমরির এই ব্লকের প্রথম 7 টি বিট (বিট 0 থ্রু 6) বিটগুলি প্রথম (হ্রাস) ফোন নম্বরটির শেষ 7 বিটগুলির সাথে সামঞ্জস্যপূর্ণ, বিটগুলি 7 থেকে 13 টি শেষ 7 বিটের সাথে সামঞ্জস্য দ্বিতীয় (হ্রাস) ফোন নম্বর, ইত্যাদি। এর জন্য মোট 17 + (2 ^ (17 - কে ) - 1) * 10 + 1000 * কে এর জন্য 1000 * কে বিট প্রয়োজন , যা কে = 10 এর জন্য সর্বনিম্ন 11287 অর্জন করে So সুতরাং আমরা সমস্ত ফোন নম্বর সিলে সঞ্চয় করতে পারি ( 11287/8) = 1411 বাইট।

অতিরিক্ত স্থান সংরক্ষণ করে দেখা যায় যে আমাদের সংখ্যাগুলির কোনওটি উদাহরণস্বরূপ 1111111 (বাইনারি) দিয়ে শুরু করতে পারে না, কারণ এর সাথে শুরু হওয়া সর্বনিম্ন সংখ্যা 130048 এবং আমাদের কেবল পাঁচ দশমিক সংখ্যা রয়েছে। এটি আমাদের মেমরির প্রথম ব্লক থেকে কয়েকটি এন্ট্রি শেভ করতে দেয়: 2 ^ m - 1 গুনের পরিবর্তে আমাদের কেবল সিল (99999/2 ^ কে ) প্রয়োজন। তার মানে সূত্রটি হয়ে যায়

17 + সিল (99999/2 ^ কে ) * 10 + 1000 * কে

যা আশ্চর্যজনকভাবে যথেষ্ট পরিমাণে কে = 9 এবং কে = 10, বা সিল (10997/8) = 1375 বাইট উভয়ের জন্য তার সর্বনিম্ন 10997 অর্জন করে ।

যদি আমরা জানতে চাই যে কোনও নির্দিষ্ট ফোন নম্বর আমাদের সেটে রয়েছে কিনা, আমরা প্রথমে পরীক্ষা করে দেখি যে প্রথম পাঁচটি বাইনারি অঙ্কগুলি আমাদের সঞ্চিত পাঁচটি সংখ্যার সাথে মেলে কিনা। তারপরে আমরা অবশিষ্ট পাঁচটি সংখ্যাটিকে তার শীর্ষ মি = 7 বিটগুলিতে বিভক্ত করব (যার অর্থ, এম- বিট সংখ্যা এম ) এবং এর নিম্ন কে = 10 বিট ( কে সংখ্যা )) আমরা এখন হ্রাস ফোন নম্বরগুলির একটি [এম -1] নম্বর পেয়েছি যার জন্য প্রথম মিটার সংখ্যা সর্বাধিক এম - 1 এবং কম নম্বরযুক্ত ফোন নম্বরগুলির একটি [এম] নম্বর যার জন্য প্রথম এম সংখ্যাটি সর্বাধিক এম , বিট প্রথম ব্লক থেকে উভয়। আমরা এখন [এম-1] তম এবং একটি [এম] এর ম ক্রম মেমরি দ্বিতীয় ব্লক বিট যদি আমরা খুঁজে পায় তা দেখার কে ; সবচেয়ে খারাপ ক্ষেত্রে 1000 এর মতো ক্রম রয়েছে, সুতরাং আমরা যদি বাইনারি অনুসন্ধান ব্যবহার করি তবে আমরা ও (লগ 1000) ক্রিয়াকলাপটি শেষ করতে পারি।

সব 1000 নম্বর মুদ্রণ জন্য pseudocode, অনুসরণ আমি কোথায় অ্যাক্সেস কে 'ম -বিট যেমন মেমরি প্রথম ব্লক এন্ট্রি একটি [K-] এবং এম ' ম মি যেমন মেমরি দ্বিতীয় ব্লক -বিট এন্ট্রি [এম] (এই উভয়টিরই কিছু বিট অপারেশন প্রয়োজন যা লেখার জন্য ক্লান্তিকর)। প্রথম পাঁচটি সংখ্যার

i := 0;
for K from 0 to ceil(99999 / 2^k) do
  while i < a[K] do
    print(c * 10^5 + K * 2^k + b[i]);
    i := i + 1;
  end do;
end do;

কে = সিল (99999/2 ^ কে ) এর সীমানা ক্ষেত্রে কিছু ভুল হতে পারে তবে এটি ঠিক করা যথেষ্ট সহজ।

অবশেষে, এন্ট্রপি দৃষ্টিকোণ থেকে, সিলের চেয়ে কম 10 in 5 এর কম 10 positive 3 ধনাত্মক পূর্ণসংখ্যার একটি উপসেট সংরক্ষণ করা সম্ভব নয় (লগ [2] (দ্বিপদী (10 ^ 5, 10 ^ 3)) ) = 8073. প্রথম 5 টি সংখ্যার জন্য আমাদের 17 টি সহ, এখনও 10997 - 8090 = 2907 বিটের ফাঁক রয়েছে। আপনি এখনও তুলনামূলক দক্ষতার সাথে সংখ্যাগুলি অ্যাক্সেস করতে পারেন এমন আরও ভাল সমাধান রয়েছে কিনা তা দেখার জন্য এটি একটি আকর্ষণীয় চ্যালেঞ্জ!


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

হাই এরিক, যেহেতু আপনি বলেছিলেন যে আপনি অন্যান্য বিকল্পগুলি দেখতে আগ্রহী তাই আমার সমাধানটি দেখুন। এটি এটি 8,580 বিটে সমাধান করে, যা তাত্ত্বিক সর্বনিম্ন থেকে মাত্র 490 বিট। স্বতন্ত্র সংখ্যাগুলি অনুসন্ধান করা কিছুটা অক্ষম তবে স্টোরেজটি খুব কমপ্যাক্ট।
ব্রিগ্যুই 37

4
আমি অনুমান করব যে কোনও বুদ্ধিমান সাক্ষাত্কারকারক "জটিল কাস্টম তৈরি ডাটাবেস" এর পরিবর্তে "একটি ট্রাই" উত্তরটি পছন্দ করবেন। আপনি যদি আপনার 133 টি হ্যাকিংয়ের দক্ষতা প্রদর্শন করতে চান তবে আপনি যোগ করতে পারেন - "যদি neccesary হয় তবে এই বিশেষ ক্ষেত্রে বিশেষ গাছের অ্যালগোরিদম তৈরি করা সম্ভব হবে।"
কার্লপি

হাই, আপনি কি দয়া করে ব্যাখ্যা করতে পারেন যে কীভাবে 5 ডিজিট 17 টি বিট সংরক্ষণ করে?
তুষার বানে

@ তুষার পাঁচটি সংখ্যা সহ 00000 এবং 99999 এর মধ্যে একটি সংখ্যা এনকোড করে। বাইনারি মধ্যে যে সংখ্যা প্রতিনিধিত্ব করুন। 2 ^ 17 = 131072, সুতরাং এর জন্য 17 বিট পর্যাপ্ত তবে 16 টি নয়।
এরিক পি।

43

এরপরে, আমি সংখ্যাগুলি পূর্ণসংখ্যার ভেরিয়েবল হিসাবে বিবেচনা করি (স্ট্রিংয়ের বিপরীতে):

  1. সংখ্যা বাছাই করুন।
  2. প্রতিটি সংখ্যা প্রথম পাঁচটি অঙ্ক এবং শেষ পাঁচটি সংখ্যায় বিভক্ত করুন।
  3. প্রথম পাঁচটি সংখ্যা সংখ্যা জুড়ে একই, সুতরাং এগুলি কেবল একবার সঞ্চয় করুন। এর জন্য 17 বিট স্টোরেজ প্রয়োজন হবে।
  4. পৃথকভাবে প্রতিটি সংখ্যার চূড়ান্ত পাঁচটি সংখ্যা সঞ্চয় করুন। এটির জন্য প্রতি সংখ্যার 17 বিট লাগবে।

পুনরুদ্ধার করার জন্য: প্রথম 17 বিটগুলি সাধারণ উপসর্গ, 17 বিটের পরবর্তী 1000 টি গ্রুপ প্রতিটি ক্রমের উপরে উঠানো ক্রমে সঞ্চিত সর্বশেষ পাঁচটি অঙ্ক।

মোট আমরা 1000 নম্বরের জন্য 2128 বাইট বা 10-সংখ্যার টেলিফোন নম্বর প্রতি 17.017 বিট খুঁজছি।

অনুসন্ধান O(log n)(বাইনারি অনুসন্ধান) এবং সম্পূর্ণ গণনা হয় O(n)


আহ, স্থানের জটিলতা কোথায়?
আইয়ুব

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

@ লাইকাও: কে স্ট্রিং সম্পর্কে কিছু বলেছেন? আমি একচেটিয়াভাবে পূর্ণসংখ্যার ভেরিয়েবলগুলি নিয়ে কাজ করছি তাই kএটি অপ্রাসঙ্গিক।
এনপিই

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

4
@ গীক: ১ b টি বিটের ১০০১ গ্রুপ 17017 বিট বা 2128 বাইট (কিছুটা পরিবর্তন সহ)।
এনপিই

22

http://en.wikedia.org/wiki/Acyclic_deterministic_finite_automaton

আমার একবার একটি সাক্ষাত্কার হয়েছিল যেখানে তারা ডেটা কাঠামো সম্পর্কে জিজ্ঞাসা করেছিল। আমি "অ্যারে" ভুলে গেছি।


4
+1 এটি অবশ্যই যাওয়ার উপায়। আমি এটিকে অন্য নামে, লাইব্রেরি ট্রি বা লেক্সিকাল সার্চ ট্রি বা কিছু শিখেছি যখন আমি ছাত্র ছিলাম (কেউ যদি সেই পুরানো নামটি মনে রাখে তবে দয়া করে জানান)।
ভাল্মন্ড

6
এটি 4000 বাইটের প্রয়োজনীয়তা পূরণ করে না। একা পয়েন্টার স্টোরেজের জন্য, সবচেয়ে খারাপ পরিস্থিতিটি হ'ল আপনার পরবর্তী স্তরে 1-4 তম পাতার জন্য 1 পয়েন্টার, 5 তম জন্য 10 পয়েন্টার, 6 ষ্ঠের জন্য 100 এবং 7 ম, 8 ম এবং 9 ম স্তরের জন্য 1000 পয়েন্টার প্রয়োজন , যা আমাদের পয়েন্টারটিকে মোট 3114 এ নিয়ে আসে That এটি পয়েন্টারগুলিকে নির্দেশ করতে কমপক্ষে 3114 স্বতন্ত্র মেমরি অবস্থানগুলি দেয়, যার অর্থ আপনার প্রতিটি পয়েন্টারের জন্য কমপক্ষে 12 বিট লাগবে। 12 * 3114 = 37368 বিট = 4671 বাইট> 4000 বাইট, এবং এটিও আপনি প্রতিটি পাতার মান উপস্থাপন করে না তাও বোঝায় না!
ব্রিগুই 37

15

আমি সম্ভবত একটি কিছু সংকুচিত সংস্করণ ব্যবহার বিবেচনা চাই মধ্যে Trie (সম্ভবত একটি Dawg যেমন @Misha দ্বারা প্রস্তাবিত)।

এটি স্বয়ংক্রিয়ভাবে এই সিদ্ধান্তটি গ্রহণ করবে যে তাদের সকলের একটি সাধারণ উপসর্গ রয়েছে।

অনুসন্ধান স্থির সময়ে সঞ্চালিত হবে, এবং মুদ্রণ লিনিয়ার সময়ে সঞ্চালিত হবে।


প্রশ্নটি ডেটা সংরক্ষণের সর্বাধিক স্থান-দক্ষ উপায় সম্পর্কে। এই পদ্ধতিতে 1000 ফোন নম্বরগুলির জন্য কত জায়গার প্রয়োজন হবে তার একটি প্রাক্কলন সরবরাহ করতে আপনি কি আপত্তি করবেন? ধন্যবাদ
এনপিই

ট্রাইয়ের স্থান সর্বাধিক ও (এন * কে) যেখানে n স্ট্রিংয়ের সংখ্যা এবং k প্রতিটি স্ট্রিংয়ের দৈর্ঘ্য। সংখ্যার প্রতিনিধিত্ব করার জন্য আপনার কাছে 8 বিট অক্ষরের প্রয়োজন নেই তা বিবেচনা করে আমি 4 টি হেক্সাডেসিমাল সূচি হেক্সাডেক্সিমাল এবং বাকী বিটের জন্য একটি সংরক্ষণ করার পরামর্শ দেব। এইভাবে আপনার প্রতি সংখ্যায় সর্বোচ্চ 17 বিট লাগবে need কারণ আপনার কোডিংয়ের সাথে সব ক্ষেত্রেই আপনার সকল স্তরের সংঘাত হবে আপনি আসলে এটির নীচে যেতে পারেন। আশা করা যায় যে আমরা 1000 নম্বর সঞ্চয় করি, আমরা ইতিমধ্যে প্রথম স্তরে সংঘর্ষের জন্য মোট 250 বিট সংরক্ষণ করতে পারি। উদাহরণস্বরূপ ডেটাতে সঠিক কোডিংয়ের সেরা পরীক্ষা করুন।
LiKao

@ লাইকাও, ডান, এবং উল্লেখ করে যে, উদাহরণস্বরূপ, 1000 সংখ্যার শেষের দুটি সংখ্যা 100 টির বেশি থাকতে পারে না, ট্রাইটি শেষ পর্যায়ে উল্লেখযোগ্যভাবে ধসে যেতে পারে।
আইয়ুব

@ আইউব: কোনও শিশু নেই বলে পাতাগুলি শেষ স্তরে ধসে যেতে পারে। তবে, দ্বিতীয় থেকে শেষ স্তরের পাতাগুলির জন্য 2 ^ 10 = 1024 টি রাজ্যের প্রয়োজন (প্রতিটি শেষ সংখ্যাটি চালু বা বন্ধ হতে পারে), সুতরাং কেবলমাত্র 1000 সংখ্যা রয়েছে বলে এটি এ ক্ষেত্রে হ্রাসযোগ্য নয়। এর অর্থ হ'ল সবচেয়ে খারাপ ক্ষেত্রে পয়েন্টারগুলির সংখ্যা 3114 এ থাকবে (মিশার জবাব সম্পর্কে আমার মন্তব্য দেখুন) যখন প্রয়োজনীয় পাতাগুলি 5 + 10 + 100 + 1000 + 1000 + 10 = 2125 এ যায় যা প্রতিটি জন্য প্রয়োজনীয় 12 বাইট পরিবর্তন করে না পয়েন্টার সুতরাং, এটি কেবলমাত্র পয়েন্টারকে একা বিবেচনা করে 4671 বাইটে একটি ট্রাই সলিউশন রাখে।
ব্রিগ্যুই 37

@ ব্রিগুই 37, নিশ্চিত না যে আমি আপনার " প্রতিটি শেষ সংখ্যাটি " যুক্তিটি চালু বা বন্ধ হতে পারে "পেয়েছি । সমস্ত সংখ্যা 10 সংখ্যার দীর্ঘ, তাই না?
আইয়ুব

15

আমি এই সমস্যার কথা আগে শুনেছি (তবে প্রথম-5-অঙ্কগুলি একই ধারণা নয়) এবং এটি করার সহজ উপায়টি ছিল রাইস কোডিং :

1) যেহেতু আদেশের বিষয়টি বিবেচনা না করে আমরা সেগুলি বাছাই করতে পারি এবং একটানা মানগুলির মধ্যে পার্থক্যগুলি সংরক্ষণ করি। আমাদের ক্ষেত্রে গড় পার্থক্য হবে 100.000 / 1000 = 100

২) ভাত কোড (বেস 128 বা 64) বা এমনকি গোলম্ব কোড (বেস 100) ব্যবহার করে পার্থক্যগুলি এনকোড করুন।

সম্পাদনা: 128 বেস সহ রাইস কোডিংয়ের জন্য একটি অনুমান (এটি সেরা ফলাফল দেবে বলে নয়, তবে এটি গণনা করা সহজ):

আমরা প্রথম মানটি হ'ল (32 বিট) সংরক্ষণ করব।
বাকী 999 টির মধ্যে পার্থক্য রয়েছে (আমরা সেগুলি ছোট হওয়া আশা করি, গড়ে 100 টি) এতে অন্তর্ভুক্ত থাকবে:

অ্যানারি মান value / 128(টার্মিনেটর হিসাবে বিটের পরিবর্তনশীল সংখ্যা + 1 বিট) এর
বাইনারি মান value % 128(7 বিট)

VBLপরিবর্তনশীল বিটের সংখ্যার জন্য আমাদের কিছুটা সীমাবদ্ধতা (আসুন এটি কল করুন ) অনুমান করতে হবে :
নিম্ন সীমা: বিবেচনা করুন আমরা ভাগ্যবান, এবং আমাদের বেসের চেয়ে কোনও পার্থক্য বড় নয় (এই ক্ষেত্রে 128)। এর অর্থ 0 টি অতিরিক্ত বিট দেওয়া।
উচ্চ সীমা: যেহেতু বেসের চেয়ে ছোট সমস্ত পার্থক্য সংখ্যার বাইনারি অংশে এনকোড করা হবে, তাই আনারিতে এনকোড করতে আমাদের সর্বাধিক সংখ্যার প্রয়োজন 100000/128 = 781.25 (আরও কম, কারণ আমরা বেশিরভাগ পার্থক্য শূন্য হওয়ার আশা করি না) )।

সুতরাং, ফলাফল 32 + 999 * (1 + 7) + পরিবর্তনশীল (0..782) বিট = 1003 + ভেরিয়েবল (0..98) বাইট।


আপনি কীভাবে এনকোডিং করছেন এবং চূড়ান্ত আকারের গণনা সম্পর্কে আরও বিশদ দিতে পারেন। 1101 বাইট বা 8808 বিট 8091 বিটের তাত্ত্বিক সীমাটির খুব কাছাকাছি মনে হয়, তাই আমি খুব আশ্চর্য হয়েছি যে অনুশীলনে এই জাতীয় কিছু অর্জন করা সম্ভব।
লাইকাও

এটি কি 32 + 999 * (1 + 7 + variable(0..782))বিট হবে না ? 999 সংখ্যার প্রত্যেকটির প্রতিনিধিত্ব প্রয়োজন value / 128
কर्क ব্রডহর্স্ট

4
@ কির্ক: না, যদি তাদের সমস্তগুলি 5 ডিজিটের মধ্যে থাকে। এটি কারণ আমরা আশা করব যে এই সমস্ত পার্থক্যগুলির যোগফলটি (মনে রাখবেন, আমরা প্রথম এবং Nth মানের মধ্যে নয়, ধারাবাহিক মানের মধ্যে পার্থক্যগুলি এনকোড করব) 100000 (এমনকি সবচেয়ে খারাপ পরিস্থিতিতেও) এর নীচে হবে
ruslik

প্রথম মানটি উপস্থাপন করতে আপনার 32 বিটের পরিবর্তে 34 বিট প্রয়োজন (9,999,999,999> 2 ^ 32 = 4,294,967,296)। এছাড়াও, সর্বাধিক পার্থক্য হবে 00000 থেকে 99001 যেহেতু সংখ্যাগুলি অনন্য, যা 128 বেসের জন্য 782 এর পরিবর্তে 774 1 যোগ করবে Thus সুতরাং 128 বেসের জন্য 1000 সংখ্যা সংরক্ষণের জন্য আপনার পরিসীমা 8026-8800 বিট বা 1004-1100 বাইট। -৪-বিট বেসটি 879-1072 বাইটের ব্যাপ্তি সহ আরও ভাল স্টোরেজ দেয়।
ব্রিগ্যুই 37

4
@ রেজারকোস্টিন: কার্ক জিজ্ঞাসা করেছিল এটি। আপনার উদাহরণস্বরূপ, প্রথম দুটি মানের মধ্যে 20k পার্থক্য একবার এনকোড করে, কেবলমাত্র সর্বোচ্চ সীমা 80k ভবিষ্যতে ঘটানো সম্ভব হবে। এটি 20k / 128 = 156 সর্বাধিক 782 (যা 100k এর সাথে সামঞ্জস্যযুক্ত) এর
বাইরে অ্যানারি

7

এটি বেন্টলির প্রোগ্রামিং পার্লসের একটি সুপরিচিত সমস্যা।

সমাধান: প্রতিটি সংখ্যার জন্য একই হিসাবে সংখ্যা থেকে প্রথম পাঁচটি অঙ্কটি স্ট্রিপ করুন। তারপরে অবশিষ্ট 9999 সম্ভাব্য মান উপস্থাপন করতে বিটওয়াইস-অপারেশনগুলি ব্যবহার করুন। সংখ্যাগুলি উপস্থাপন করার জন্য আপনার কেবল 2 ^ 17 বিট লাগবে। প্রতিটি বিট একটি সংখ্যা প্রতিনিধিত্ব করে। বিটটি সেট করা থাকলে নম্বরটি টেলিফোনের বইটিতে রয়েছে।

সমস্ত সংখ্যা মুদ্রণের জন্য, কেবলমাত্র সমস্ত নম্বর মুদ্রণ করুন যেখানে বিটটি উপসর্গের সাথে সমাহারিত হয়। প্রদত্ত সংখ্যার সন্ধানের জন্য সংখ্যার বিটওয়াইজ উপস্থাপনা পরীক্ষা করতে প্রয়োজনীয় বিট পাটিগণিত করুন।

আপনি ও (1) এ কোনও সংখ্যার সন্ধান করতে পারেন এবং বিট উপস্থাপনের কারণে স্থান দক্ষতা সর্বাধিক।

এইচটিএইচ ক্রিস।


4
সংখ্যার ঘন সংখ্যার জন্য এটি একটি ভাল পদ্ধতির হবে। দুর্ভাগ্যক্রমে, এখানে সেটটি খুব বিরল: সম্ভাব্য 100,000 এর মধ্যে কেবল 1000 সংখ্যা রয়েছে। এই পদ্ধতির জন্য প্রতি সংখ্যায় গড়ে 100 বিট লাগবে। এমন একটি বিকল্পের জন্য আমার উত্তর দেখুন যা কেবলমাত্র 17 ডলার বিট প্রয়োজন।
এনপিই

4
সমস্ত সংখ্যা মুদ্রণের সময়টি কি 1000 এর পরিবর্তে 100,000 এর সমানুপাতিক হবে না?
আইওউব

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

এটি "এটি করার পক্ষে সবচেয়ে কার্যকর স্থান সাশ্রয়ী উপায় নয়"।
জেক বার্গার

5

1000 সংখ্যার জন্য 1073 বাইটের স্থির স্টোরেজ:

এই স্টোরেজ পদ্ধতির প্রাথমিক ফর্ম্যাটটি হ'ল প্রথম 5 টি সংখ্যা, প্রতিটি দলের জন্য একটি গণনা এবং প্রতিটি গ্রুপে প্রতিটি সংখ্যার জন্য অফসেট সংরক্ষণ করা।

উপসর্গ:
আমাদের 5-সংখ্যার উপসর্গটি প্রথম 17 টি বিট নেয় ।

গোষ্ঠীকরণ: এর পরে
, সংখ্যার জন্য আমাদের একটি ভাল আকারের গোষ্ঠীকরণ বের করা দরকার। আসুন চেষ্টা করি প্রতি গ্রুপে প্রায় 1 নম্বর আছে। যেহেতু আমরা জানি যে সংরক্ষণের জন্য প্রায় 1000 সংখ্যা রয়েছে তাই আমরা 99,999 কে প্রায় 1000 অংশে বিভক্ত করি। আমরা যদি গ্রুপের আকারটি 100 হিসাবে বেছে নিই, তবে সেখানে নষ্ট বিট হবে, সুতরাং 128 এর একটি গ্রুপ আকারের চেষ্টা করি, যা 7 টি বিট দিয়ে উপস্থাপন করা যেতে পারে। এটি আমাদের সাথে কাজ করার জন্য 782 টি গ্রুপ দেয়।

গণনা:
পরবর্তী, ,৮২ টির প্রত্যেকটির জন্য আমাদের প্রতিটি গ্রুপে প্রবেশের গণনা সংরক্ষণ করতে হবে। প্রতিটি গ্রুপের জন্য একটি 7-বিট গণনা উত্পন্ন হবে 7*782=5,474 bits, যা অত্যন্ত অদক্ষ কারণ আমরা আমাদের গোষ্ঠীগুলি কীভাবে বেছে নিয়েছিলাম তার কারণে প্রতিনিধিত্ব করা গড় সংখ্যা প্রায় 1 হয়।

সুতরাং, পরিবর্তে আমাদের পরিবর্তে একটি গ্রুপের প্রতিটি সংখ্যার জন্য শীর্ষস্থানীয় 1 এর সাথে পরিবর্তনশীল আকারের গণনা রয়েছে যার পরে 0 রয়েছে। সুতরাং, যদি আমাদের xএকটি গ্রুপে সংখ্যা থাকে তবে আমরা গণনা উপস্থাপন করার জন্য x 1'sএকটি অনুসরণ করতাম 0। উদাহরণস্বরূপ, আমাদের একটি গোষ্ঠীতে 5 নম্বর থাকলে গণনাটি প্রতিনিধিত্ব করবে 111110। এই পদ্ধতির সাহায্যে, যদি 1000 টি সংখ্যা থাকে তবে আমরা গণনাগুলির জন্য 1000 + 782 = 1,782 বিট হিসাবে মোট 1000 1 এবং 782 0 এর সাথে শেষ করব ।

অফসেট:
সর্বশেষে, প্রতিটি সংখ্যার ফর্ম্যাট প্রতিটি গ্রুপের জন্য কেবল 7-বিট অফসেট হবে। উদাহরণস্বরূপ, যদি 00000 এবং 00001 0-127 গ্রুপের একমাত্র সংখ্যা হয় তবে সেই গোষ্ঠীর জন্য বিট হবে 110 0000000 0000001। 1000 টি সংখ্যা ধরে নিলে অফসেটগুলির জন্য 7,000 বিট থাকবে ।

এইভাবে 1000 টি সংখ্যা অনুমান করে আমাদের চূড়ান্ত গণনা নিম্নরূপ:

17 (prefix) + 1,782 (counts) + 7,000 (offsets) = 8,799 bits = 1100 bytes

এখন, আসুন পরীক্ষা করে নিন যে আমাদের গ্রুপ-আকার নির্বাচন 128 বিট পর্যন্ত গোল করে গ্রুপ আকারের জন্য সেরা পছন্দ ছিল। xপ্রতিটি গ্রুপকে উপস্থাপন করার জন্য বিটের সংখ্যা হিসাবে নির্বাচন করা, আকারের সূত্রটি হ'ল:

Size in bits = 17 (prefix) + 1,000 + 99,999/2^x + x * 1,000

এর পূর্ণসংখ্যা মানের জন্য এই সমীকরণ কমানোর xদেয় x=6, যা 8.580 বিট = উৎপাদ 1,073 বাইট । সুতরাং, আমাদের আদর্শ স্টোরেজটি নিম্নরূপ:

  • গ্রুপের আকার: 2 ^ 6 = 64
  • গোষ্ঠীর সংখ্যা: 1,562
  • মোট সঞ্চয়স্থান:

    1017 (prefix plus 1's) + 1563 (0's in count) + 6*1000 (offsets) = 8,580 bits = 1,073 bytes


1

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

এর সাথে সমস্যাগুলি হ'ল, আপনাকে নিজের প্রোগ্রামের প্রতিটি 2 ^ 8000 সেটকে একঘেয়েমি হিসাবে উপস্থাপন করতে হবে, এমনকি গুগলও এটির জন্য দূরবর্তীভাবে সক্ষম হবে না।

সমস্ত নম্বর ও (এন) মুদ্রণ করা ও (1) হবে। সন্নিবেশ O (2 ^ 8000) হবে যা তত্ত্বটি ও (1), তবে বাস্তবে ব্যবহারের অযোগ্য able

একটি সাক্ষাত্কারে আমি কেবল এই উত্তরটিই দেব, যদি আমি নিশ্চিত থাকতাম যে সংস্থাটি এমন কাউকে খুঁজছে যা বাক্স থেকে অনেক চিন্তা করতে সক্ষম। অন্যথায় এটি আপনাকে কোনও তাত্ত্বিকের মতো দেখাতে পারে যা বাস্তব জগতের উদ্বেগ নয়।

সম্পাদনা : ঠিক আছে, এখানে একটি "বাস্তবায়ন" রয়েছে।

বাস্তবায়নটি গঠনের পদক্ষেপ:

  1. আকার 100000 * (1000 চয়ন 100 000) বিট একটি ধ্রুব অ্যারে নিন। হ্যাঁ, আমি এই সত্যটি সম্পর্কে সচেতন যে এই অ্যারেটির বিভিন্ন মহাবিশ্বে মহাবিশ্বে পরমাণুর চেয়ে আরও বেশি জায়গার প্রয়োজন হবে।
  2. এই বড় অ্যারেটি 100,000 এর প্রতিটি অংশে আলাদা করুন।
  3. প্রতিটি খণ্ড দোকানে সর্বশেষ পাঁচটি সংখ্যার একটি নির্দিষ্ট সংমিশ্রণের জন্য কিছুটা অ্যারে।

এটি প্রোগ্রাম নয়, তবে এক ধরণের মেটা প্রোগ্রামাম, এটি একটি বিশাল LUT নির্মাণ করবে যা এখন প্রোগ্রামে ব্যবহৃত হতে পারে। প্রোগ্রাম দক্ষতার গণনা করার সময় প্রোগ্রামের ধ্রুবক স্টাফগুলি সাধারণত গণনা করা হয় না, সুতরাং আমাদের চূড়ান্ত গণনা করার সময় আমরা এই অ্যারেটির কোনও যত্ন নিই না।

এই LUT কীভাবে ব্যবহার করবেন তা এখানে:

  1. যখন কেউ আপনাকে 1000 নম্বর দেয় আপনি প্রথম পাঁচটি সংখ্যা আলাদাভাবে সংরক্ষণ করেন।
  2. আপনার অ্যারের অংশগুলির মধ্যে কোনটি এই সেটটির সাথে মেলে।
  3. একক 8074 বিট সংখ্যায় সেটটির নম্বর সংরক্ষণ করুন (এই সিটিতে কল করুন)।

এর অর্থ সঞ্চয়স্থানের জন্য আমাদের কেবলমাত্র 8091 বিট প্রয়োজন, যা আমরা এখানে সর্বোত্তম এনকোডিং হিসাবে প্রমাণিত করেছি। সঠিক খণ্ডটি খুঁজে পেতে তবে ও (100 000 * (100 000 বেছে নিন 1000)) লাগে যা গণিতের নিয়ম অনুসারে ও (1) হয় তবে বাস্তবে মহাবিশ্বের সময়ের চেয়ে সবসময় বেশি সময় লাগে।

চেহারা যদিও সহজ:

  1. প্রথম পাঁচটি অঙ্কের স্ট্রিপ (অবশিষ্ট সংখ্যাটি এন 'বলা হবে)।
  2. তারা মিলছে কিনা পরীক্ষা
  3. I = c * 100000 + n 'গণনা করুন
  4. LUT এ i তে থাকা বিটটি একটিতে সেট করা আছে কিনা তা দেখুন

সমস্ত সংখ্যা মুদ্রণ করাও সহজ (এবং ও (100000) = হে (1) লাগে, কারণ আপনাকে সর্বদা বর্তমান খণ্ডের সমস্ত বিট পরীক্ষা করতে হবে, সুতরাং আমি এটি উপরেরটি ভুলভাবে গণনা করেছি)।

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


4
এটি করার জন্য সবচেয়ে দক্ষ স্পেস সেভিংয়ের উপায় কী ?
সেভেন

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

1

এটি প্রতি এক লাখেরও কম এক হাজার অ-নেতিবাচক পূর্ণসংখ্যা সঞ্চয় করার সমতুল্য। এটি করার জন্য আমরা গাণিতিক এনকোডিংয়ের মতো কিছু ব্যবহার করতে পারি।

শেষ পর্যন্ত, সংখ্যাগুলি বাছাই করা তালিকায় সংরক্ষণ করা হবে। আমি নোট করেছি যে তালিকার সংলগ্ন সংখ্যার মধ্যে প্রত্যাশিত পার্থক্যটি 100,000 / 1000 = 100, যা 7 বিটে উপস্থাপন করা যেতে পারে। এমন অনেকগুলি ক্ষেত্রেও দেখা যাবে যেখানে 7 টিরও বেশি বিট প্রয়োজনীয়। এই কম সাধারণ ক্ষেত্রে প্রতিনিধিত্ব করার একটি সহজ উপায় হল utf-8 স্কিম গ্রহণ করা যেখানে কোনও বাইট প্রথম বিট সেট না করা অবধি 7-বিট পূর্ণসংখ্যার প্রতিনিধিত্ব করে, সেক্ষেত্রে পরবর্তী বাইটটি 14-বিট পূর্ণসংখ্যার উত্পাদন করতে পড়া হয় যদি না এর প্রথম বিটটি সেট করা আছে, এক্ষেত্রে পরবর্তী বাইটটি 21-বিট পূর্ণসংখ্যার প্রতিনিধিত্ব করার জন্য পড়ে is

সুতরাং একটানা পূর্ণসংখ্যার মধ্যে অন্তত অর্ধেক পার্থক্য একটি বাইট দ্বারা উপস্থাপিত হতে পারে, এবং বাকি সমস্ত প্রায় দুটি বাইট প্রয়োজন। 16,384-র চেয়ে বড় পার্থক্য দ্বারা পৃথক কয়েকটি সংখ্যার জন্য তিন বাইটের প্রয়োজন হবে, তবে এর মধ্যে 61১ এর বেশি হতে পারে না। তারপরে গড় স্টোরেজটি প্রতি সংখ্যায় প্রায় 12 বিট, বা কিছুটা কম, বা সর্বাধিক 1500 বাইট হবে।

এই পদ্ধতির নেতিবাচক দিকটি হ'ল কোনও সংখ্যার অস্তিত্ব পরীক্ষা করা এখন হে (এন)। তবে কোনও সময়ের জটিলতার প্রয়োজনীয়তা নির্দিষ্ট করা হয়নি।

লেখার পরে, আমি লক্ষ্য করেছি রসিক ইতিমধ্যে উপরের পার্থক্য পদ্ধতিটি প্রস্তাব করেছে, কেবলমাত্র পার্থক্যটিই এনকোডিং স্কিম। খনি সম্ভবত সহজ তবে কম দক্ষ।


1

কেবলমাত্র কোনও কারণ জিজ্ঞাসা করার জন্য যে আমরা সংখ্যাগুলি বেসে 36 এ পরিবর্তন করতে চাই না It এটি এত বেশি জায়গা বাঁচাতে পারে না তবে এটি অবশ্যই অনুসন্ধানে সময় সাশ্রয় করতে পারে যেহেতু আপনি তখন 10 ডিজিট খুব কম দেখবেন looking অথবা আমি তাদের প্রতিটি গ্রুপের উপর নির্ভর করে ফাইলগুলিতে বিভক্ত করব। সুতরাং আমি একটি ফাইলের নাম দেব (111) -222.txt এবং তারপরে আমি কেবল সেই সংখ্যায় সংরক্ষণ করব যেগুলি সেখানে group গোষ্ঠীতে ফিট করে এবং তারপরে সেগুলি সংখ্যার ক্রমে সন্ধানযোগ্য করে রাখি আমি সর্বদা ফাইলটি বেরিয়ে আসে কিনা তা পরীক্ষা করতে পারি। আমি একটি বাইজার অনুসন্ধান চালানোর আগে। বা সঠিক হতে আমি বাইনারি অনুসন্ধানে ছুটে যাব ফাইলটি এটির বাইরে চলে কিনা তা দেখার জন্য। এবং ফাইলের বিষয়বস্তুগুলিতে আরেকটি বোনারি অনুসন্ধান


0

কেন সহজ রাখবেন না? স্ট্রাইকগুলির একটি অ্যারে ব্যবহার করুন।

সুতরাং আমরা প্রথম 5 টি সংখ্যা ধ্রুবক হিসাবে সংরক্ষণ করতে পারি, তাই আপাতত সেগুলি ভুলে যান।

65535 সর্বাধিক যা 16-বিট সংখ্যায় সংরক্ষণ করা যায় এবং আমাদের সর্বাধিক সংখ্যাটি 99999 হতে পারে, যা সর্বাধিক 131071 এর সাথে 17 তম বিটের সংখ্যার সাথে মানিয়ে যায়।

৩২-বিট ডেটা টাইপ ব্যবহার করা একটি অপচয় নয় কারণ আমাদের কেবলমাত্র অতিরিক্ত অতিরিক্ত ১ b-বিটের ১ বিট প্রয়োজন ... সুতরাং, আমরা এমন একটি কাঠামো সংজ্ঞায়িত করতে পারি যাতে বুলিয়ান (বা চরিত্র) এবং একটি ১--বিট সংখ্যা রয়েছে ..

সি / সি ++ ধরে নিচ্ছি

typedef struct _number {

    uint16_t number;
    bool overflow;
}Number;

এই কাঠামোটি কেবল 3-বাইট নেয় এবং আমাদের 1000 এর অ্যারে প্রয়োজন, সুতরাং মোট 3000 বাইট। আমরা মোট স্থান 25% কমিয়েছি!

যতক্ষণ সংখ্যাগুলি সংরক্ষণ করা যায়, আমরা সাধারণ বিটওয়াইথ গণিত করতে পারি

overflow = (number5digits & 0x10000) >> 4;
number = number5digits & 0x1111;

এবং বিপরীত

//Something like this should work
number5digits = number | (overflow << 4);

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

for(int i=0;i<1000;i++) cout << const5digits << number5digits << endl;

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


0

আমার সমাধান: সেরা কেস 7.025 বিট / সংখ্যা, সবচেয়ে খারাপ ক্ষেত্রে 14.193 বিট / সংখ্যা, মোটামুটি গড় 8.551 বিট / সংখ্যা। স্ট্রিম-এনকোডেড, এলোমেলো অ্যাক্সেস নেই।

এমনকি রসিকের উত্তর পড়ার আগে, আমি তত্ক্ষণাত্ প্রতিটি সংখ্যার মধ্যে পার্থক্য এনকোডিংয়ের কথা ভাবলাম, যেহেতু এটি ছোট হবে এবং তুলনামূলকভাবে সামঞ্জস্যপূর্ণ হওয়া উচিত, তবে সমাধানটি অবশ্যই সবচেয়ে খারাপ পরিস্থিতি সামঞ্জস্য করতে সক্ষম হতে হবে। আমাদের 100000 সংখ্যার একটি স্পেস রয়েছে যা কেবলমাত্র 1000 টি সংখ্যা ধারণ করে। নিখুঁতভাবে অভিন্ন ফোন বইয়ে, প্রতিটি সংখ্যা 100 দ্বারা আগের সংখ্যাটির চেয়ে বেশি হবে:

55555-12 3 45
55555-12 4 45
55555-12 5 45

যদি এটি হয় তবে এটির একটি ধ্রুবক হিসাবে সংখ্যার পার্থক্যগুলি এনকোড করতে জিরো স্টোরেজ প্রয়োজন। দুর্ভাগ্যক্রমে, সংখ্যাগুলি 100 এর আদর্শ পদক্ষেপের চেয়ে পৃথক হতে পারে 100 100 এর আদর্শ বৃদ্ধি থেকে আমি পার্থক্যটি এনকোড করব, যাতে দুটি সংলগ্ন সংখ্যা যদি 103 দ্বারা পৃথক হয় তবে আমি 3 নম্বরটি এনকোড করব এবং যদি দুটি সংলগ্ন সংখ্যা 92, I দ্বারা পৃথক হয় এনকোড হবে -8। আমি 100 "এর একটি আদর্শ বৃদ্ধি থেকে ব-দ্বীপ কল ভ্যারিয়েন্স "।

ভেরিয়েন্সটি -৯৯ (অর্থাত্ টানা দুটি সংখ্যা) থেকে শুরু করে 99000 (পুরো ফোনবুকটি 00000… 00999 এবং একটি অতিরিক্ত দূরবর্তী নম্বর 99999 নিয়ে গঠিত) হতে পারে, যা 99100 সম্ভাব্য মানগুলির পরিসীমা।

আমি বড় পার্থক্য (যেমন সম্মুখীন সবচেয়ে সাধারণ পার্থক্য এনকোড এবং স্টোরেজ প্রসারিত করতে একটি ন্যূনতম স্টোরেজ বরাদ্দ করা তাগ চাই ProtoBuf এর varint)। আমি সাতটি বিট, স্টোরেজের জন্য ছয় এবং শেষে একটি অতিরিক্ত পতাকা বিট ব্যবহার করব যেটি বোঝাতে পারে যে এই বৈকল্পটি বর্তমানের পরে একটি অতিরিক্ত অংশের সাথে সর্বাধিক তিনটি অংশ পর্যন্ত সংরক্ষণ করা হবে (যা সর্বোচ্চ প্রদান করবে) 3 * 6 = 18 বিট স্টোরেজ, যা 262144 সম্ভাব্য মান, সম্ভাব্য রূপগুলির সংখ্যা (99100) এর চেয়ে বেশি a প্রতিটি উত্ক্রান্ত পতাকা যা একটি উত্থিত পতাকা অনুসরণ করে তার উচ্চতর বিট থাকে, তাই প্রথম খণ্ডটিতে সর্বদা 0- বিট থাকে 5, alচ্ছিক দ্বিতীয় অংশে 6-10 বিট রয়েছে এবং thirdচ্ছিক তৃতীয় অংশে 12-17 বিট রয়েছে।

একটি একক অংশ ছয় বিট স্টোরেজ সরবরাহ করে যা values৪ টি মানকে সমন্বিত করতে পারে। আমি সেই একক অংশে ফিট করার জন্য smal৪ টি ক্ষুদ্রতম রূপগুলি মানচিত্র করতে চাই (যেমন -32 থেকে +31 এর রূপগুলি) সুতরাং আমি প্রোটোফুফ জিগজ্যাগ এনকোডিংটি ব্যবহার করব, -99 থেকে +98 এর ভেরিয়েন্স পর্যন্ত (যেহেতু কোনও প্রয়োজন নেই) -৯৯ এর বাইরে নেতিবাচক বৈকল্পিকের জন্য), যে সময়ে আমি নিয়মিত এনকোডিংয়ে স্যুইচ করব, অফসেটটি 98 দ্বারা:  

বৈচিত্র্য | এনকোডেড মান
----------- + ----------------
    0 | 0
   -1 | ঘ
    1 | ঘ
   -২ | ঘ
    2 | ঘ
   -৩ | ৫
    3 | ।
   ... | ...
  -31 | 61
   31 | 62
  -32 | 63
----------- | --------------- 6 টি বিট
   32 | 64
  -33 | 65
   33 | 66
   ... | ...
  -98 | 195
   98 | 196
  -99 | 197
----------- | --------------- জিগজ্যাগের সমাপ্তি
   100 | 198
   101 | 199
   ... | ...
  3996 | 4094
  3997 | 4095
----------- | --------------- 12 বিট
  3998 | 4096
  3999 | 4097
   ... | ...
 262045 | 262143
----------- | --------------- 18 বিট

কীভাবে বৈকল্পিকগুলি বিট হিসাবে এনকোড করা হবে তার কয়েকটি উদাহরণ যেমন অতিরিক্ত খণ্ডটি চিহ্নিত করতে পতাকা সহ:

বৈচিত্র্য | এনকোড বিটস
----------- + ----------------
     0 | 000000 0
     5 | 001010 0
    -8 | 001111 0
   -32 | 111111 0
    32 | 000000 1 000001 0
   -99 | 000101 1 000011 0
   177 | 010011 1 000100 0
 14444 | 001110 1 100011 1 000011 0

সুতরাং একটি নমুনা ফোন বইয়ের প্রথম তিনটি নম্বর বিটগুলির প্রবাহ হিসাবে এনকোড করা হবে:

বিন 000101001011001000100110010000011001 000110 1 010110 1 00001 0
PH # 55555-12345 55555-12448 55555-12491
পস 1 2 3

সর্বোত্তম ক্ষেত্রে পরিস্থিতি , ফোন বইটি কিছুটা সমানভাবে বিতরণ করা হয়েছে এবং 32 টির চেয়ে বেশি তারতম্য রয়েছে এমন কোনও দুটি ফোন নম্বর নেই, সুতরাং এটি 32 + 7 * 999 এর মোট সংখ্যার জন্য প্রারম্ভিক সংখ্যার জন্য 32 বিট প্লাস 32 বিট ব্যবহার করবে = 7025 বিট
একটি মিশ্র দৃশ্য , যেখানে ৮০০ ফোন নম্বরগুলির প্রকারভেদ এক অংশের মধ্যে ফিট করে (৮০০ * 00 = ৫ fits০০), ১৮০ নম্বর দুটি খণ্ডে ফিট করে (১৮০ * ২ * = = ২৫২০) এবং ১৯ টি সংখ্যা তিনটি খণ্ডে খাপ খায় (২০ * ৩ * 7 = 399), প্রাথমিক 32 বিট, মোট 8551 বিট
সবচেয়ে খারাপ পরিস্থিতি , 25 টি সংখ্যা তিনটি অংশে ফিট (25 * 3 * 7 = 525 বিট) এবং বাকী 974 সংখ্যা দুটি খণ্ডে মাপসই (974 * 2 * 7 = 13636 বিট), এবং 32 টি বিট প্রথম সংখ্যার জন্য বিট মোট14193 বিট

   এনকোডড সংখ্যার পরিমাণ |
 1-খণ্ড | 2-খণ্ড | 3-খণ্ড | মোট বিট
--------- + ---------- + ---------- + ------------
   999 | 0 | 0 | 7025
   800 | 180 | 19 | 8551
    0 | 974 | 25 | 14193

আমি আরও চারটি অপটিমাইজেশন দেখতে পাচ্ছি যা প্রয়োজনীয় স্থানটি আরও কমাতে সম্পাদন করা যেতে পারে:

  1. তৃতীয় অংশটির পুরো সাতটি বিটের দরকার নেই, এটি কেবল পাঁচ বিট এবং একটি পতাকা বিট ছাড়াই হতে পারে।
  2. প্রতিটি খণ্ডের জন্য সেরা আকারের গণনা করার জন্য সংখ্যার প্রাথমিক পাস হতে পারে। কোনও নির্দিষ্ট ফোনবুকের জন্য, প্রথম খণ্ডটিতে 5 + 1 বিট, দ্বিতীয় 7 + 1 এবং তৃতীয় 5 + 1 থাকা ভাল হবে mal এটি আকারটিকে আরও সর্বনিম্ন 6 * 999 + 32 = 6026 বিট হিসাবে কমিয়ে দেবে, আরও তিনটি বিটের দুটি সেট খণ্ড 1 এবং 2 এর আকারগুলি সংরক্ষণ করবে (অংশ 3 এর আকার প্রয়োজনীয় 16 বিটের অবশিষ্টাংশ) 6032 বিট!
  3. একই প্রাথমিক পাসটি ডিফল্ট 100 এর চেয়ে ভাল প্রত্যাশিত বৃদ্ধির গণনা করতে পারে Maybe বিতরণ (সম্ভবত স্ট্যান্ডার্ড বিচ্যুতি) এবং কিছু অন্যান্য অনুকূল প্রত্যাশিত বর্ধন ব্যবহার করা যেতে পারে। এটি আদর্শ বৈকল্পিকতা হ্রাস করতে পারে এবং এটি এমনকি আরও ছোট প্রথম অংশ ব্যবহার করার অনুমতি দেয়।
  4. ফোনের বইটিকে বিভাজন করার অনুমতি দেওয়ার জন্য আরও বিশ্লেষণ প্রথম পাসে করা যেতে পারে, প্রতিটি পার্টিশনের নিজস্ব প্রত্যাশিত বর্ধন এবং খণ্ড আকারের অপ্টিমাইজেশন রয়েছে। এটি ফোনের বইয়ের নির্দিষ্ট ইউনিফর্মের কিছু অংশের (ছোট খাওয়ার বিটের সংখ্যা হ্রাস করা) এবং অ-ইউনিফর্ম অংশগুলির জন্য বৃহত্তর অংশগুলি (ধারাবাহিক পতাকাগুলিতে নষ্ট বিটের সংখ্যা হ্রাস) এর জন্য প্রথম ছোট ছোট আকারের মঞ্জুরি দেয়।

0

আসল প্রশ্নটি পাঁচ-অঙ্কের ফোন নম্বর সংরক্ষণের মধ্যে একটি।

কৌশলটি হ'ল 0..99,999 থেকে সংখ্যার পরিসীমা সঞ্চয় করতে আপনার 17 বিট লাগবে। তবে প্রচলিত 8-বাইট শব্দের সীমানায় 17-বিট সংরক্ষণ করা একটি ঝামেলা। এজন্য তারা জিজ্ঞাসা করছে যে আপনি 32-বিট পূর্ণসংখ্যা ব্যবহার না করে 4k এরও কম সময়ে করতে পারেন কিনা।

প্রশ্ন: সব সংখ্যার সমন্বয় কি সম্ভব?

টেলিফোন সিস্টেমের প্রকৃতির কারণে, 65k এর চেয়ে কম সংমিশ্রণ কম থাকতে পারে। আমি ধরে নেব যে হ্যাঁ আমরা ফোন নম্বরটিতে পরবর্তী পাঁচটি অবস্থানের বিষয়ে কথা বলছি, অঞ্চল কোড বা বিনিময় উপসর্গের বিপরীতে।

প্রশ্ন: এই তালিকাটি কি স্থির থাকবে বা আপডেটগুলি সমর্থন করার প্রয়োজন হবে?

যদি এটি স্থির হয় , তবে যখন ডাটাবেস পপুলেশন করার সময় আসে তখন <50,000 অংক এবং সংখ্যা সংখ্যা> = 50,000 গণনা করুন। বরাদ্দ দুইটি অ্যারের এর uint1650,000 নিচে পূর্ণসংখ্যার জন্য এক এবং উচ্চতর সেট এক: উপযুক্ত দৈর্ঘ্যের। উচ্চতর অ্যারেতে পূর্ণসংখ্যা সংরক্ষণ করার সময়, 50,000 বিয়োগ করুন এবং সেই অ্যারে থেকে পূর্ণসংখ্যা পড়ার সময়, 50,000 যুক্ত করুন। এখন আপনি আপনার 1,000 পূর্ণসংখ্যা 2,000 8-বাইট শব্দের মধ্যে সঞ্চয় করেছেন।

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

যদি এটি গতিশীল হয় তবে 1000 বা তার একটি অ্যারে বরাদ্দ uint16করুন এবং সাজানো ক্রমে সংখ্যা যুক্ত করুন। প্রথম বাইটটি 50,001 এ সেট করুন এবং দ্বিতীয় বাইটটি NUL বা 65,000 এর মতো উপযুক্ত নাল মানতে সেট করুন। আপনি যখন নম্বরগুলি সঞ্চয় করেন, সেগুলি সাজানো ক্রমে সংরক্ষণ করুন। যদি কোনও সংখ্যা 50,001 এর নিচে থাকে তবে এটি 50,001 এর আগে সংরক্ষণ করুন। যদি একটি সংখ্যা 50,001 বা তার বেশি হয় তবে এটি 50,001 চিহ্নিতকারীর পরে সংরক্ষণ করুন তবে সঞ্চিত মান থেকে 50,000 বিয়োগ করুন।

আপনার অ্যারে এমন কিছু দেখবে:

00001 = 00001
12345 = 12345
50001 = reserved
00001 = 50001
12345 = 62345
65000 = end-of-list

সুতরাং, আপনি যখন ফোনবুকটিতে একটি নম্বর সন্ধান করবেন, আপনি অ্যারেটি অতিক্রম করবেন এবং যদি আপনি 50,001 মানটি আঘাত করেন তবে আপনি আপনার অ্যারের মানগুলিতে 50,000 যুক্ত করা শুরু করবেন।

এটি সন্নিবেশগুলি খুব ব্যয়বহুল করে তোলে, তবে অনুসন্ধানগুলি সহজ, এবং আপনি স্টোরেজটিতে 2k এর বেশি বেশি ব্যয় করতে যাবেন না।

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