1 এমবি র‌্যামের সাহায্যে 1 মিলিয়ন 8-দশমিক-সংখ্যা সংখ্যা বাছাই করা


726

আমার কাছে 1 এমবি র‌্যামযুক্ত একটি কম্পিউটার রয়েছে এবং অন্য কোনও স্থানীয় স্টোরেজ নেই। আমার টিসিপি সংযোগের মাধ্যমে 1 মিলিয়ন 8-ডিজিটের দশমিক সংখ্যা গ্রহণ করতে, এগুলি বাছাই করতে এবং তারপরে অন্য টিসিপি সংযোগের মাধ্যমে বাছাই করা তালিকাটি পাঠাতে হবে must

সংখ্যার তালিকায় নকল থাকতে পারে, যা আমি অবশ্যই বাতিল করতে হবে না। কোডটি রোমে স্থাপন করা হবে, সুতরাং আমার 1 এমবি থেকে আমার কোডের আকারটি বিয়োগ করার দরকার নেই। ইথারনেট পোর্টটি চালনা করতে এবং টিসিপি / আইপি সংযোগগুলি পরিচালনা করার জন্য আমার কাছে ইতিমধ্যে কোড রয়েছে এবং এটির জন্য 1 কেবি বাফার সহ তার স্টেটের ডেটার জন্য 2 কেবি লাগবে যার মাধ্যমে কোডটি পড়তে এবং ডেটা লিখতে হবে। এই সমস্যার কি কোন সমাধান আছে?

প্রশ্নোত্তরের উত্স:

slashdot.org

cleaton.net


45
এহম, এক মিলিয়ন গুণ 8-অঙ্কের দশমিক সংখ্যা (সর্বনিম্ন 27-বিট পূর্ণসংখ্যার বাইনারি)> 1 এমবি র‌্যাম
মিঃ 47

15
1 এম র‌্যাম মানে 2 ^ 20 বাইট? এবং এই স্থাপত্যে বাইটে কয়টি বিট রয়েছে? এবং "1 মিলিয়ন 8 ডিজিটের দশমিক সংখ্যার" মিলিয়ন "এসআই মিলিয়ন (10 ^ 6)? একটি 8 ডিজিটের দশমিক সংখ্যা, একটি প্রাকৃতিক সংখ্যা <10 ^ 8, একটি যুক্তিযুক্ত সংখ্যা যার দশমিক প্রতিনিধিত্ব দশমিক বিন্দু বাদে 8 ডিজিট নেয়, বা অন্য কিছু?

13
1 মিলিয়ন 8 দশমিক সংখ্যা সংখ্যা বা 1 মিলিয়ন 8 বিট সংখ্যা?
প্যাট্রিক হোয়াইট

13
এটি আমাকে "ডাঃ ডবস জার্নাল" (১৯৯৯-২০০১ এর মধ্যে কোথাও) এর একটি নিবন্ধের স্মরণ করিয়ে দেয়, যেখানে লেখক ফোন নম্বরগুলি পড়ার সময় সেগুলি সাজানোর জন্য একটি সন্নিবেশ সাজান ব্যবহার করেছিলেন: এটিই প্রথম আমি বুঝতে পেরেছিলাম, কখনও কখনও, ধীর গতিতে অ্যালগরিদম আরও দ্রুত হতে পারে ...
অ্যাড্রিয়েন প্লিসন

103
এখনও অন্য সমাধানের কথা কেউ উল্লেখ করেনি: 2 এমবি র‌্যাম সহ হার্ডওয়্যার কিনুন। এটি আরও বেশি ব্যয়বহুল হওয়া উচিত নয় এবং এটি সমস্যার সমাধান করতে আরও অনেক সহজ করে দেবে।
ড্যানিয়েল ওয়াগনার

উত্তর:


716

এখানে বরং এতক্ষণে উল্লেখ করা হয়নি এমন একটি ছদ্মবেশী কৌশল রয়েছে। আমরা ধরে নিই যে আপনার কাছে ডেটা সঞ্চয় করার কোনও অতিরিক্ত উপায় নেই, তবে এটি কঠোরভাবে সত্য নয়।

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

আপনি নিম্নলিখিত কয়েকটি উপায়ে র‌্যামের কয়েকটি বাইট দিয়ে নম্বরগুলি বাছাই করতে পারেন:

  • প্রথমে 2 টি ভেরিয়েবল নিন: COUNTERএবং VALUE
  • প্রথমে সমস্ত নিবন্ধগুলি সেট করুন 0;
  • প্রতিবার আপনি কোনও পূর্ণসংখ্যা প্রাপ্ত হন I, বৃদ্ধি COUNTERএবং এতে সেট VALUEহন max(VALUE, I);
  • তারপরে একটি আইসিএমপি ইকো অনুরোধ প্যাকেট ডেটা সেট Iকরে রাউটারে প্রেরণ করুন । মুছুন Iএবং পুনরাবৃত্তি করুন।
  • প্রতিবার আপনি ফিরে আসা আইসিএমপি প্যাকেটটি গ্রহণ করার পরে, আপনি কেবল পূর্ণসংখ্যাটি বের করেন এবং অন্য প্রতিধ্বনির অনুরোধে এটি আবার ফেরত প্রেরণ করেন। এটি সংখ্যাসমৃদ্ধ পশ্চাদপদ এবং ফরোয়ার্ড বিছিন্ন করে বিপুল সংখ্যক আইসিএমপি অনুরোধ তৈরি করে।

একবার COUNTERপৌঁছে গেলে 1000000আপনার কাছে সমস্ত মান VALUEরয়েছে আইসিএমপি অনুরোধের অবিরাম প্রবাহে সঞ্চিত এবং এখন সর্বাধিক পূর্ণসংখ্যা রয়েছে। কিছু বাছুন threshold T >> 1000000COUNTERশূন্যে সেট করুন । প্রতিবার আপনি যখন কোনও আইএমএমপি প্যাকেট পান, ইনক্রিমেন্ট হয় COUNTERএবং Iঅন্য ইকো অনুরোধে অন্তর্ভুক্ত পূর্ণসংখ্যাটি ফেরত পাঠান , যদি I=VALUEনা হয় সেক্ষেত্রে সাজানো পূর্ণসংখ্যার জন্য গন্তব্যে প্রেরণ করে। একবার COUNTER=T, হ্রাস VALUEদ্বারা 1, রিসেট COUNTERশূন্য এবং পুনরাবৃত্তি করতে। একবার VALUEশূন্যে পৌঁছানোর পরে আপনার সমস্ত পূর্ণসংখ্যার বৃহত্তম থেকে ছোট থেকে গন্তব্যস্থলে সঞ্চারিত হওয়া উচিত ছিল এবং দুটি স্থায়ী ভেরিয়েবলের জন্য র‌্যামের প্রায় 47 বিট ব্যবহার করেছেন (এবং অস্থায়ী মানগুলির জন্য আপনার যত সামান্য পরিমাণ প্রয়োজন)।

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


27
সুতরাং আপনি কি মূলত নেটওয়ার্কের বিলম্বকে উপকার করছেন এবং আপনার রাউটারকে এক ধরণের কাতারে পরিণত করছেন?
এরিক আর।

335
এই সমাধানটি বাক্সের ঠিক বাইরে নয়; মনে হচ্ছে এটি ঘরে বসে তার বাক্সটি ভুলে গেছে: ডি
ভ্লাদিস্লাভ জোরভ

28
দুর্দান্ত উত্তর ... আমি এই উত্তরগুলিকে ভালবাসি কারণ তারা সমস্যার
উদ্ভবের

33
আইসিএমপি নির্ভরযোগ্য নয়।
ঘুমন্তহীন

13
@ এমডিমাররা: আপনি ঠিক উপরে লক্ষ্য করবেন আমি বলছি "আপনার সমস্যার চারপাশের একটি উপায় নিম্নলিখিত ভয়াবহ কাজটি করা, যা কোনও পরিস্থিতিতে কোনও ব্যক্তির দ্বারা চেষ্টা করা উচিত নয়"। আমি এটি বলার একটি কারণ ছিল।
জো ফিটজসিমন্স

423

এখানে কিছু কার্যকারী সি ++ কোড যা সমস্যা সমাধান করে।

প্রমাণ মেমরির সীমাবদ্ধতা সন্তুষ্ট:

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

typedef unsigned int u32;

namespace WorkArea
{
    static const u32 circularSize = 253250;
    u32 circular[circularSize] = { 0 };         // consumes 1013000 bytes

    static const u32 stageSize = 8000;
    u32 stage[stageSize];                       // consumes 32000 bytes

    ...

একসাথে, এই দুটি অ্যারে স্টোরেজ 1045000 বাইট নেয়। এটি 1048576 - 1045000 - 2 × 1024 = 1528 বাইটগুলি ভেরিয়েবল এবং স্ট্যাক স্পেসের জন্য ছেড়ে যায়।

এটি আমার সিওন ডাব্লু 3520-তে প্রায় 23 সেকেন্ডে চলে। আপনি যাচাই করতে পারবেন যে প্রোগ্রামটি একটি প্রোগ্রামের নাম ধরে ধরে নীচের পাইথন স্ক্রিপ্টটি ব্যবহার করে কাজ করে sort1mb.exe

from subprocess import *
import random

sequence = [random.randint(0, 99999999) for i in xrange(1000000)]

sorter = Popen('sort1mb.exe', stdin=PIPE, stdout=PIPE)
for value in sequence:
    sorter.stdin.write('%08d\n' % value)
sorter.stdin.close()

result = [int(line) for line in sorter.stdout]
print('OK!' if result == sorted(sequence) else 'Error!')

নিম্নলিখিত সিরিজের পোস্টগুলিতে অ্যালগরিদমের বিস্তারিত ব্যাখ্যা পাওয়া যাবে:


8
হ্যাঁ, হ্যাঁ, আমরা খুব তাড়াতাড়ি এর বিস্তারিত ব্যাখ্যা চাই।
টি সুডস

25
আমি মনে করি মূল পর্যবেক্ষণটি হ'ল 8-সংখ্যার নম্বরে প্রায় 26.6 বিট তথ্য রয়েছে এবং এক মিলিয়ন 19.9 বিট। আপনি যদি তালিকাটি সংকুচিত করেন (সংলগ্ন মানের পার্থক্য সংরক্ষণ করুন) পার্থক্যগুলি 0 (0 বিট) থেকে শুরু করে 99999999 (26.6 বিট) পর্যন্ত হয় তবে আপনার প্রতিটি জোড়ের মধ্যে সর্বোচ্চ ব-দ্বীপ থাকতে পারে না । সবচেয়ে খারাপ ক্ষেত্রে আসলে এক মিলিয়ন সমানভাবে বিতরণকৃত মান হওয়া উচিত, যার জন্য ডেল্টা (26.6-19.9) বা ডেল্টায় প্রায় 7.7 বিট প্রয়োজন। এক মিলিয়ন মান 6..7 বিটের স্টোর করা সহজেই 1 এম তে ফিট করে। ডেল্টা সংকোচনের জন্য অবিচ্ছিন্ন মার্জ বাছাই করা দরকার যাতে আপনি এটি প্রায় বিনামূল্যে পান।
বেন জ্যাকসন

4
মিষ্টি সমাধান। আপনার সকলকে
ডেভেক

9
@ বেনজ্যাকসন: আপনার গণিতে কোথাও একটি ত্রুটি রয়েছে। এখানে 2.265 x 10 ^ 2436455 অনন্য সম্ভাব্য আউটপুট রয়েছে (10 ^ 6 8-সংখ্যার পূর্ণসংখ্যার অর্ডার সেট) যা 8.094 x 10 ^ 6 বিট সংরক্ষণ করতে লাগে (অর্থাত একটি মেগাবাইটের নীচে চুল)। কোনও চতুর স্কিম ক্ষতি ছাড়াই এই তথ্য তাত্ত্বিক সীমা ছাড়িয়ে সংকোচন করতে পারে। আপনার ব্যাখ্যাটি বোঝায় যে আপনাকে অনেক কম স্থানের প্রয়োজন, এবং তাই ভুল। প্রকৃতপক্ষে, উপরের সমাধানটির "বিজ্ঞপ্তি" প্রয়োজনীয় তথ্যগুলি ধারণ করার জন্য যথেষ্ট বড়, সুতরাং প্রেশিং মনে হচ্ছে এটি বিবেচনায় নিয়েছে তবে আপনি এটি অনুপস্থিত রয়েছেন।
জো ফিটজসিমনস

5
@ জোফিজসিমসনস: আমি পুনরাবৃত্তির কাজ করিনি (০.২ মিটার থেকে এন সংখ্যাগুলির অনন্য সাজানো সেট (n+m)!/(n!m!)) তাই আপনাকে অবশ্যই সঠিক হতে হবে। সম্ভবত এটি আমার অনুমান যে বি বিটগুলির একটি ডেল্টা বি বিটগুলি সঞ্চয় করতে নেয় - 0 এর ডেল্টাস 0 টি বিট সংরক্ষণ করার জন্য নেয় না।
বেন জ্যাকসন

371

দয়া করে পাটিগণিত এনকোডিং সহ প্রথম সঠিক উত্তর বা পরে উত্তরটি দেখুননীচে আপনি কিছু মজা পেতে পারেন, তবে 100% বুলেট-প্রমাণ সমাধান নয়।

এটি বেশ আকর্ষণীয় কাজ এবং এখানে একটি অন্য সমাধান রয়েছে। আমি আশা করি যে কেউ এই ফলাফলটি দরকারী (বা কমপক্ষে আকর্ষণীয়) খুঁজে পাবেন।

প্রথম পর্যায়: প্রাথমিক ডেটা স্ট্রাকচার, রুক্ষ সংকোচনের পদ্ধতি, প্রাথমিক ফলাফল

আসুন কিছু সাধারণ গণিত করা যাক: 10 ম ^ 6 8 ডিজিটের দশমিক সংখ্যা সংরক্ষণ করতে আমাদের প্রথম র‌্যামের 1M (1048576 বাইট) পাওয়া যায়। [0; 99999999]। সুতরাং এক নম্বর 27 টি বিট সংরক্ষণ করতে হবে (স্বাক্ষরযুক্ত স্বাক্ষরিত নম্বরগুলি ব্যবহার করা হবে তা গ্রহণ করে)। সুতরাং, একটি কাঁচা স্ট্রিম সঞ্চয় করতে RAM 3.5M র্যামের প্রয়োজন হবে। কেউ ইতিমধ্যে বলেছিল এটি সম্ভবপর বলে মনে হচ্ছে না, তবে আমি বলব ইনপুট "যথেষ্ট ভাল" হলে কাজটি সমাধান করা যায়। মূলত, ধারণাটি হ'ল সংকোচন ফ্যাক্টর 0.29 বা তার বেশি সংখ্যার ইনপুট ডেটা সংকুচিত করা এবং সঠিক পদ্ধতিতে বাছাই করা।

প্রথমে সংক্ষেপণের সমস্যাটি সমাধান করা যাক। ইতিমধ্যে কিছু প্রাসঙ্গিক পরীক্ষা পাওয়া যায়:

http://www.theeggeadventure.com/wikimedia/index.php/Java_Data_Compression

"আমি বিভিন্ন ধরণের সংকোচনের সাহায্যে এক মিলিয়ন টানা পূর্ণসংখ্যার সংকোচনের জন্য একটি পরীক্ষা চালিয়েছি The ফলাফলগুলি নিম্নরূপ:"

None     4000027
Deflate  2006803
Filtered 1391833
BZip2    427067
Lzma     255040

দেখে মনে হচ্ছে এলজেডএমএ ( লেম্পেল – জিভ – মার্কভ চেইন অ্যালগোরিদম ) চালিয়ে যাওয়া ভাল পছন্দ। আমি একটি সহজ পিসিও প্রস্তুত করেছি, তবে এখনও কিছু বিবরণ হাইলাইট করতে হবে:

  1. মেমরি সীমাবদ্ধ তাই ধারণাগুলি অস্থায়ী সঞ্চয়স্থান হিসাবে সংখ্যার প্রিন্ট করা এবং সংকুচিত বালতি (গতিশীল আকার) ব্যবহার করা
  2. পূর্বনির্ধারিত ডেটা সহ আরও ভাল কম্প্রেশন ফ্যাক্টর অর্জন করা সহজ, সুতরাং প্রতিটি বালতির জন্য একটি স্ট্যাটিক বাফার রয়েছে (বাফার থেকে সংখ্যাগুলি এলজেডএমএর আগে বাছাই করতে হবে)
  3. প্রতিটি বালতি একটি নির্দিষ্ট পরিসর ধারণ করে, তাই প্রতিটি বালতি পৃথকভাবে চূড়ান্ত বাছাই করা যায়
  4. বালতির আকার সঠিকভাবে সেট করা যেতে পারে, তাই সঞ্চিত ডেটা সংক্ষেপণ করতে এবং প্রতিটি বালতির জন্য পৃথকভাবে চূড়ান্ত বাছাই করার জন্য পর্যাপ্ত মেমরি থাকবে

ইন মেমরি বাছাই

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

নীচের পিওসি কোডটি দেখুন (দয়া করে এটি একটি ডেমো নোট করুন, এটি সংকলন করতে এলজেডএমএ-জাভা প্রয়োজন হবে):

public class MemorySortDemo {

static final int NUM_COUNT = 1000000;
static final int NUM_MAX   = 100000000;

static final int BUCKETS      = 5;
static final int DICT_SIZE    = 16 * 1024; // LZMA dictionary size
static final int BUCKET_SIZE  = 1024;
static final int BUFFER_SIZE  = 10 * 1024;
static final int BUCKET_RANGE = NUM_MAX / BUCKETS;

static class Producer {
    private Random random = new Random();
    public int produce() { return random.nextInt(NUM_MAX); }
}

static class Bucket {
    public int size, pointer;
    public int[] buffer = new int[BUFFER_SIZE];

    public ByteArrayOutputStream tempOut = new ByteArrayOutputStream();
    public DataOutputStream tempDataOut = new DataOutputStream(tempOut);
    public ByteArrayOutputStream compressedOut = new ByteArrayOutputStream();

    public void submitBuffer() throws IOException {
        Arrays.sort(buffer, 0, pointer);

        for (int j = 0; j < pointer; j++) {
            tempDataOut.writeInt(buffer[j]);
            size++;
        }            
        pointer = 0;
    }

    public void write(int value) throws IOException {
        if (isBufferFull()) {
            submitBuffer();
        }
        buffer[pointer++] = value;
    }

    public boolean isBufferFull() {
        return pointer == BUFFER_SIZE;
    }

    public byte[] compressData() throws IOException {
        tempDataOut.close();
        return compress(tempOut.toByteArray());
    }        

    private byte[] compress(byte[] input) throws IOException {
        final BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(input));
        final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(compressedOut));

        final Encoder encoder = new Encoder();
        encoder.setEndMarkerMode(true);
        encoder.setNumFastBytes(0x20);
        encoder.setDictionarySize(DICT_SIZE);
        encoder.setMatchFinder(Encoder.EMatchFinderTypeBT4);

        ByteArrayOutputStream encoderPrperties = new ByteArrayOutputStream();
        encoder.writeCoderProperties(encoderPrperties);
        encoderPrperties.flush();
        encoderPrperties.close();

        encoder.code(in, out, -1, -1, null);
        out.flush();
        out.close();
        in.close();

        return encoderPrperties.toByteArray();
    }

    public int[] decompress(byte[] properties) throws IOException {
        InputStream in = new ByteArrayInputStream(compressedOut.toByteArray());
        ByteArrayOutputStream data = new ByteArrayOutputStream(10 * 1024);
        BufferedOutputStream out = new BufferedOutputStream(data);

        Decoder decoder = new Decoder();
        decoder.setDecoderProperties(properties);
        decoder.code(in, out, 4 * size);

        out.flush();
        out.close();
        in.close();

        DataInputStream input = new DataInputStream(new ByteArrayInputStream(data.toByteArray()));
        int[] array = new int[size];
        for (int k = 0; k < size; k++) {
            array[k] = input.readInt();
        }

        return array;
    }
}

static class Sorter {
    private Bucket[] bucket = new Bucket[BUCKETS];

    public void doSort(Producer p, Consumer c) throws IOException {

        for (int i = 0; i < bucket.length; i++) {  // allocate buckets
            bucket[i] = new Bucket();
        }

        for(int i=0; i< NUM_COUNT; i++) {         // produce some data
            int value = p.produce();
            int bucketId = value/BUCKET_RANGE;
            bucket[bucketId].write(value);
            c.register(value);
        }

        for (int i = 0; i < bucket.length; i++) { // submit non-empty buffers
            bucket[i].submitBuffer();
        }

        byte[] compressProperties = null;
        for (int i = 0; i < bucket.length; i++) { // compress the data
            compressProperties = bucket[i].compressData();
        }

        printStatistics();

        for (int i = 0; i < bucket.length; i++) { // decode & sort buckets one by one
            int[] array = bucket[i].decompress(compressProperties);
            Arrays.sort(array);

            for(int v : array) {
                c.consume(v);
            }
        }
        c.finalCheck();
    }

    public void printStatistics() {
        int size = 0;
        int sizeCompressed = 0;

        for (int i = 0; i < BUCKETS; i++) {
            int bucketSize = 4*bucket[i].size;
            size += bucketSize;
            sizeCompressed += bucket[i].compressedOut.size();

            System.out.println("  bucket[" + i
                    + "] contains: " + bucket[i].size
                    + " numbers, compressed size: " + bucket[i].compressedOut.size()
                    + String.format(" compression factor: %.2f", ((double)bucket[i].compressedOut.size())/bucketSize));
        }

        System.out.println(String.format("Data size: %.2fM",(double)size/(1014*1024))
                + String.format(" compressed %.2fM",(double)sizeCompressed/(1014*1024))
                + String.format(" compression factor %.2f",(double)sizeCompressed/size));
    }
}

static class Consumer {
    private Set<Integer> values = new HashSet<>();

    int v = -1;
    public void consume(int value) {
        if(v < 0) v = value;

        if(v > value) {
            throw new IllegalArgumentException("Current value is greater than previous: " + v + " > " + value);
        }else{
            v = value;
            values.remove(value);
        }
    }

    public void register(int value) {
        values.add(value);
    }

    public void finalCheck() {
        System.out.println(values.size() > 0 ? "NOT OK: " + values.size() : "OK!");
    }
}

public static void main(String[] args) throws IOException {
    Producer p = new Producer();
    Consumer c = new Consumer();
    Sorter sorter = new Sorter();

    sorter.doSort(p, c);
}
}

এলোমেলো সংখ্যা সহ এটি নিম্নলিখিত উত্পাদন করে:

bucket[0] contains: 200357 numbers, compressed size: 353679 compression factor: 0.44
bucket[1] contains: 199465 numbers, compressed size: 352127 compression factor: 0.44
bucket[2] contains: 199682 numbers, compressed size: 352464 compression factor: 0.44
bucket[3] contains: 199949 numbers, compressed size: 352947 compression factor: 0.44
bucket[4] contains: 200547 numbers, compressed size: 353914 compression factor: 0.44
Data size: 3.85M compressed 1.70M compression factor 0.44

একটি সহজ আরোহী ক্রমের জন্য (একটি বালতি ব্যবহৃত হয়) এটি উত্পাদন করে:

bucket[0] contains: 1000000 numbers, compressed size: 256700 compression factor: 0.06
Data size: 3.85M compressed 0.25M compression factor 0.06

সম্পাদনা

উপসংহার:

  1. প্রকৃতি বোকা চেষ্টা করবেন না
  2. নিম্ন মেমরির পদচিহ্ন সহ সহজ সংক্ষেপণ ব্যবহার করুন
  3. কিছু অতিরিক্ত ক্লু সত্যই প্রয়োজন হয়। সাধারণ বুলেট-প্রুফ সমাধানটি সম্ভবপর বলে মনে হয় না।

দ্বিতীয় পর্যায়: বর্ধিত সংক্ষেপণ, চূড়ান্ত উপসংহার

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

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

এনকোডিং প্রকল্প

এলোমেলো ইনপুট পরীক্ষা কিছুটা ভাল ফলাফল দেখায়:

bucket[0] contains: 10103 numbers, compressed size: 13683 compression factor: 0.34
bucket[1] contains: 9885 numbers, compressed size: 13479 compression factor: 0.34
...
bucket[98] contains: 10026 numbers, compressed size: 13612 compression factor: 0.34
bucket[99] contains: 10058 numbers, compressed size: 13701 compression factor: 0.34
Data size: 3.85M compressed 1.31M compression factor 0.34

কোডের উদাহরণ

  public static void encode(int[] buffer, int length, BinaryOut output) {
    short size = (short)(length & 0x7FFF);

    output.write(size);
    output.write(buffer[0]);

    for(int i=1; i< size; i++) {
        int next = buffer[i] - buffer[i-1];
        int bits = getBinarySize(next);

        int len = bits;

        if(bits > 24) {
          output.write(3, 2);
          len = bits - 24;
        }else if(bits > 16) {
          output.write(2, 2);
          len = bits-16;
        }else if(bits > 8) {
          output.write(1, 2);
          len = bits - 8;
        }else{
          output.write(0, 2);
        }

        if (len > 0) {
            if ((len % 2) > 0) {
                len = len / 2;
                output.write(len, 2);
                output.write(false);
            } else {
                len = len / 2 - 1;
                output.write(len, 2);
            }

            output.write(next, bits);
        }
    }
}

public static short decode(BinaryIn input, int[] buffer, int offset) {
    short length = input.readShort();
    int value = input.readInt();
    buffer[offset] = value;

    for (int i = 1; i < length; i++) {
        int flag = input.readInt(2);

        int bits;
        int next = 0;
        switch (flag) {
            case 0:
                bits = 2 * input.readInt(2) + 2;
                next = input.readInt(bits);
                break;
            case 1:
                bits = 8 + 2 * input.readInt(2) +2;
                next = input.readInt(bits);
                break;
            case 2:
                bits = 16 + 2 * input.readInt(2) +2;
                next = input.readInt(bits);
                break;
            case 3:
                bits = 24 + 2 * input.readInt(2) +2;
                next = input.readInt(bits);
                break;
        }

        buffer[offset + i] = buffer[offset + i - 1] + next;
    }

   return length;
}

দয়া করে মনে রাখবেন, এই পদ্ধতির:

  1. প্রচুর স্মৃতি গ্রাস করে না
  2. স্রোতের সাথে কাজ করে
  3. এত খারাপ ফলাফল দেয় না

সম্পূর্ণ কোডটি এখানে পাওয়া যাবে , বাইনারিআউটপুট এবং বাইনারিআউটপুট বাস্তবায়নগুলি এখানে পাওয়া যাবে

চূড়ান্ত উপসংহার

কোনও চূড়ান্ত উপসংহার নয় :) কখনও কখনও মেটা-স্তরের দৃষ্টিকোণ থেকে এক স্তর উপরে সরিয়ে কাজটি পর্যালোচনা করা সত্যিই ভাল ধারণা ।

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


17
আমি ইনস্কেপ ব্যবহার করেছি । উপায় দ্বারা দুর্দান্ত সরঞ্জাম। আপনি উদাহরণ হিসাবে এই ডায়াগ্রাম উত্সটি ব্যবহার করতে পারেন ।
রেনাত গিলমানভ

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

67
এটি বাজে কথা ... 1 মিলিয়ন এলোমেলো 27 বিট পূর্ণসংখ্যা পান, তাদের বাছাই করুন, 7zip, xz দিয়ে সংক্ষেপ করুন, আপনি যা চান LZMA। ফলাফল 1MB এরও বেশি। উপরের ভিত্তিটি ক্রমিক সংখ্যাগুলির সংক্ষেপণ। এর সাথে ডেল্টার এনকোডিং 0 বিট হবে কেবল সংখ্যা হবে, উদাহরণস্বরূপ 1000000 (4 বাইটে বলুন)। অনুক্রমিক এবং সদৃশ (কোন ফাঁক নেই) সহ, 1000000 এবং 1000000 বিট = 128KB, ডুপ্লিকেট সংখ্যার জন্য 0 এবং পরবর্তী চিহ্নিত করার জন্য 1 দিয়ে with যখন আপনার এলোমেলো ফাঁক, এমনকি ছোট, এলজেডএমএ হাস্যকর। এটি এর জন্য ডিজাইন করা হয়নি।
আলেকো

30
এটি আসলে কাজ করবে না। আমি একটি সিমুলেশন চালিয়েছি এবং সংকুচিত ডেটা 1MB (প্রায় 1.5MB) এর বেশি হওয়ার পরেও এটি ডেটা সংকুচিত করতে 100MB এর বেশি র্যাম ব্যবহার করে। সুতরাং সংক্ষেপিত পূর্ণসংখ্যাগুলিও রান টাইম র‌্যাম ব্যবহারের উল্লেখ না করার ক্ষেত্রে সমস্যাটি ফিট করে না। আপনাকে বরকত প্রদান করা স্ট্যাকওভারফ্লোতে আমার বৃহত্তম ত্রুটি।
প্রিয় অনউইউমেন

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

185

শুধুমাত্র 1 মেগাবাইট এবং 1 মিলিয়ন বাইটের মধ্যে পার্থক্যের কারণে একটি সমাধান সম্ভব is ডাবলিকেট অনুমোদিত এবং অযৌক্তিক অর্ডার সহ 1 মিলিয়ন 8-সংখ্যা সংখ্যা নির্বাচন করার জন্য প্রায় 2 পাওয়ার 8093729.5 টির বিভিন্ন উপায় রয়েছে, সুতরাং র্যামের 1 মিলিয়ন বাইট সহ একটি মেশিনের সমস্ত সম্ভাবনার প্রতিনিধিত্ব করার মতো পর্যাপ্ত রাজ্য নেই। তবে 1 এম (টিসিপি / আইপির জন্য 2k কম) 1022 * 1024 * 8 = 8372224 বিট, সুতরাং একটি সমাধান সম্ভব।

পর্ব 1, প্রাথমিক সমাধান

এই পদ্ধতির জন্য 1M এর থেকে কিছুটা বেশি প্রয়োজন, আমি পরে 1 এম এর সাথে ফিট করার জন্য এটি পরিমার্জন করব।

আমি 7-বিট সংখ্যার সাবলিস্টের ক্রম হিসাবে 0 থেকে 99999999 পরিসরে একটি সংক্ষিপ্ত তালিকা অনুসারে তালিকা সঞ্চয় করব। প্রথম সাবলিস্টে 0 থেকে 127 পর্যন্ত সংখ্যা রয়েছে, দ্বিতীয় সাবলিস্টে 128 থেকে 255 পর্যন্ত সংখ্যা রয়েছে, 100000000/128 হ'ল 781250, সুতরাং এই জাতীয় সাবলিস্টের প্রয়োজন হবে।

প্রতিটি সাবলিস্টে একটি 2-বিট সাবলিস্ট শিরোনাম থাকে যার পরে একটি সাবলিস্ট বডি থাকে। সাবলিস্টের বডি সাবলিস্ট এন্ট্রি প্রতি 7 বিট নেয় সাবলিস্টগুলি সমস্ত একত্রে একত্রিত হয় এবং ফর্ম্যাটটি এটি বলতে সক্ষম করে যে কোন সাবলিস্টটি শেষ হয় এবং পরেরটি শুরু হয়। সম্পূর্ণ জনবহুল তালিকার জন্য প্রয়োজনীয় মোট স্টোরেজ 2 * 781250 + 7 * 1000000 = 8562500 বিট, যা প্রায় 1.021 এম-বাইট।

4 টি সাবস্টিস্ট শিরোনামের মানগুলি হ'ল:

00 খালি সাবলিস্ট, কিছুই অনুসরণ করে না।

01 সিঙ্গলটন, সাবলিস্টে কেবল একটি প্রবেশ রয়েছে এবং পরবর্তী 7 বিট এটি ধরে রাখবে।

10 সাবলিস্টটিতে কমপক্ষে 2 টি স্বতন্ত্র সংখ্যা রয়েছে। এন্ট্রিগুলি হ্রাস না করা ক্রমে সংরক্ষণ করা হয়, ব্যতীত শেষ এন্ট্রি প্রথমটির চেয়ে কম বা সমান হয়। এটি সাবলিস্টের শেষটি চিহ্নিত করার অনুমতি দেয়। উদাহরণস্বরূপ, 2,4,6 নম্বরগুলি (4,6,2) হিসাবে সংরক্ষণ করা হবে। 2,2,3,4,4 নম্বরগুলি (2,3,4,4,2) হিসাবে সংরক্ষণ করা হবে।

11 সাবলিস্টে একটি সংখ্যার 2 বা ততোধিক পুনরাবৃত্তি রয়েছে। পরবর্তী 7 বিট নম্বর দেয়। তারপরে শূন্য বা আরও বেশি 7-বিট এন্ট্রি 1 এর সাথে আসবে, তার পরে মান 0 সহ 7-বিট এন্ট্রি হবে the সাবলিস্ট বডিটির দৈর্ঘ্য পুনরাবৃত্তির সংখ্যা নির্দেশ করে। উদাহরণস্বরূপ, 12,12 নম্বর (12,0) হিসাবে সংরক্ষণ করা হবে, 12,12,12 নম্বর (12,1,0) হিসাবে সংরক্ষণ করা হবে, 12,12,12,12 হবে (12,1) , 1,0) এবং আরও অনেক কিছু।

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

নীচের লাইনটি তালিকা সংশ্লেষ ক্রিয়াকলাপ শুরুর ঠিক আগে স্মৃতি উপস্থাপন করে। "O" গুলি হ'ল এমন অঞ্চল যা বাছাই করা 32-বিট পূর্ণসংখ্যা রাখে। "এক্স" গুলি সেই অঞ্চল যা পুরাতন কমপ্যাক্টের তালিকাটি ধারণ করে। "=" চিহ্নগুলি হ'ল কমপ্যাক্ট তালিকার সম্প্রসারণ কক্ষ, "ও" এস এর প্রতিটি পূর্ণসংখ্যার জন্য 7 বিট। "জেড" গুলি অন্যান্য র্যান্ডম ওভারহেড।

ZZZOOOOOOOOOOOOOOOOOOOOOOOOOO==========XXXXXXXXXXXXXXXXXXXXXXXXXX

মার্জ রুটিনটি বামদিকে "O" এবং বামদিকে "X" এ পড়া শুরু করে এবং বাম পাশে "=" লেখা শুরু করে। নতুন ইন্টিজারগুলি একত্রিত না হওয়া পর্যন্ত রাইটিং পয়েন্টারটি কমপ্যাক্ট তালিকার পয়েন্ট পয়েন্টারটি ধরে না, কারণ উভয় পয়েন্টার প্রতিটি সাবলিস্টের জন্য 2 বিট এবং পুরানো কমপ্যাক্ট তালিকার প্রতিটি প্রবেশের জন্য 7 বিট অগ্রসর করে এবং এর জন্য পর্যাপ্ত অতিরিক্ত জায়গা রয়েছে নতুন সংখ্যাগুলির জন্য 7-বিট এন্ট্রি।

পার্ট 2, এটি 1 এম এ ক্র্যামিং

উপরের সমাধানটি 1 এম তে চেপে ধরার জন্য, আমার কমপ্যাক্ট তালিকার বিন্যাসটি আরও কিছুটা কমপ্যাক্ট করা দরকার। আমি সাবলিস্ট ধরণের একটি থেকে মুক্তি পাব, যাতে কেবলমাত্র 3 টি পৃথক সাবস্টিস্ট শিরোনামের মান হবে। তারপরে আমি সাবলিস্ট শিরোনামের মান হিসাবে "00", "01" এবং "1" ব্যবহার করতে পারি এবং কয়েকটি বিট সংরক্ষণ করতে পারি। সাবলিস্টের প্রকারগুলি হ'ল:

খালি সাবলিস্ট, কিছুই অনুসরণ করে না।

বি সিঙ্গেলটন, সাবলিস্টে কেবল একটি প্রবেশ আছে এবং পরবর্তী 7 বিট এটি ধারণ করে।

সি সাবলিস্টে কমপক্ষে 2 টি স্বতন্ত্র সংখ্যা ধারণ করে। এন্ট্রিগুলি হ্রাস না করা ক্রমে সংরক্ষণ করা হয়, ব্যতীত শেষ এন্ট্রি প্রথমটির চেয়ে কম বা সমান হয়। এটি সাবলিস্টের শেষটি চিহ্নিত করার অনুমতি দেয়। উদাহরণস্বরূপ, 2,4,6 নম্বরগুলি (4,6,2) হিসাবে সংরক্ষণ করা হবে। 2,2,3,4,4 নম্বরগুলি (2,3,4,4,2) হিসাবে সংরক্ষণ করা হবে।

ডি সাবলিস্টে একটি সংখ্যার 2 বা তার বেশি পুনরাবৃত্তি থাকে।

আমার 3 সাবলিস্টের শিরোনামের মানগুলি "এ", "বি" এবং "সি" হবে, সুতরাং আমার ডি-টাইপ সাবলিস্ট উপস্থাপনের জন্য একটি উপায় প্রয়োজন।

ধরুন আমার কাছে সি-টাইপ সাবলিস্ট শিরোনাম রয়েছে এবং তারপরে 3 টি এন্ট্রি রয়েছে, যেমন "সি [17] [101] [58]"। এটি উপরে বর্ণিত হিসাবে বৈধ সি-ধরণের সাবলিস্টের অংশ হতে পারে না, কারণ তৃতীয় এন্ট্রি দ্বিতীয়টির চেয়ে কম তবে প্রথমটির চেয়ে বেশি more আমি এই ধরণের কনস্ট্রাক্টটি ডি-টাইপ সাবলিস্ট উপস্থাপন করতে ব্যবহার করতে পারি। বিট কথায়, আমার কাছে যে কোনও জায়গায় "C {00 ?????} {1 ??????} {01 ?????}" একটি অসম্ভব সি-টাইপ সাবলিস্ট। আমি এটি একটি সংখ্যার 3 বা ততোধিক পুনরাবৃত্তি সমন্বিত সাবলিস্ট উপস্থাপন করতে ব্যবহার করব। প্রথম দুটি 7-বিট শব্দ নম্বরটি এনকোড করে (নীচে "এন" বিট) এবং তার পরে শূন্য বা আরও {0100001} শব্দ পরে একটি {0100000} শব্দটি আসে।

For example, 3 repetitions: "C{00NNNNN}{1NN0000}{0100000}", 4 repetitions: "C{00NNNNN}{1NN0000}{0100001}{0100000}", and so on.

এটি কেবলমাত্র একক সংখ্যার 2 পুনরাবৃত্তি ধারণ করে এমন তালিকা ছেড়ে দেয়। আমি অন্য একটি অসম্ভব সি-টাইপ সাবলিস্ট প্যাটার্ন সহ তাদের প্রতিনিধিত্ব করব: "সি {0 ??????} {11 ?????} {10 ?????}"। প্রথম 2 টি শব্দের সংখ্যার 7 বিটের জন্য প্রচুর জায়গা রয়েছে, তবে এই প্যাটার্নটি উপস্থাপন করা উপ-তালিকার চেয়ে দীর্ঘতর, যা কিছুটা জটিল করে তোলে। শেষে থাকা পাঁচটি প্রশ্ন-চিহ্নকে প্যাটার্নের অংশ হিসাবে বিবেচনা করা যাবে না, সুতরাং আমার কাছে রয়েছে: "সি {0NNNNNN} N 11N ????} 10" আমার প্যাটার্ন হিসাবে, "এন-এ পুনরাবৃত্তি করা সংখ্যাটি সহ "s। এটি 2 বিট খুব দীর্ঘ।

আমাকে 2 বিট ধার নিতে হবে এবং এই প্যাটার্নে 4 টি অব্যবহৃত বিট থেকে তাদের ফেরত দিতে হবে। "C {0NNNNNN} N 11N00AB} 10" এর মুখোমুখি পড়ার সময়, "N" s তে সংখ্যাটির 2 টি উদাহরণ আউটপুট, বি এবং এ বি দ্বারা শেষদিকে "10" ওভাররাইট করে, এবং পয়েন্ট পয়েন্টারটি 2 দিয়ে রিওয়াইন্ড করুন বিট। এই অ্যালগরিদমের জন্য ধ্বংসাত্মক পাঠগুলি ঠিক আছে, যেহেতু প্রতিটি কমপ্যাক্টের তালিকা কেবল একবারে পায়।

একটি একক সংখ্যার 2 পুনরাবৃত্তির একটি সাবলিস্ট লেখার সময়, "C {0NNNNNN} 11N00" লিখুন এবং ধার করা বিটগুলি 2 এর বিপরীতে সেট করুন যেখানে প্রতিটি লেখায় যেখানে ধার করা বিটের কাউন্টারটি শূন্য নয় সেখানে প্রতিটি বিট লিখিত জন্য এটি হ্রাস করা হয় এবং "10" লেখা হয় যখন কাউন্টার শূন্য হিট হয়। সুতরাং লিখিত পরবর্তী 2 বিটগুলি স্লট এ এবং বিতে যাবে এবং তারপরে "10" শেষের দিকে নামবে।

"00", "01" এবং "1" দ্বারা প্রতিনিধিত্ব করা 3 টি সাবলিস্ট শিরোনামের মান সহ, আমি "1" সর্বাধিক জনপ্রিয় সাবলিস্ট টাইপের জন্য নির্ধারণ করতে পারি। সাবলিস্টের ধরণের তালিকাতে শিরোনামের শিরোনামের মানগুলির মানচিত্রের জন্য আমার একটি ছোট টেবিলের প্রয়োজন হবে এবং প্রতিটি সাবলিস্টের ধরণের জন্য আমার একটি উপস্থিতি কাউন্টারের প্রয়োজন হবে যাতে আমি জানতে পারি যে সেরা সাবলিস্ট শিরোনাম ম্যাপিংটি কী।

সমস্ত সাবলিস্টের প্রকারগুলি সমানভাবে জনপ্রিয় হলে পুরোপুরি জনবহুল সংক্ষিপ্ত তালিকার সর্বনিম্ন প্রতিনিধিত্ব ঘটে। সেক্ষেত্রে আমি প্রতি 3 সাবলিস্ট শিরোনামের জন্য 1 বিট সংরক্ষণ করি, তাই তালিকার আকার 2 * 781250 + 7 * 1000000 - 781250/3 = 8302083.3 বিট। 32 বিট শব্দের বাউন্ডারি পর্যন্ত গোলাকার, 8302112 বিট বা 1037764 বাইটের গণ্ডি।

টিসিপি / আইপি রাজ্য এবং বাফারগুলির জন্য 1 এম বিয়োগ 2 কে 1022 * 1024 = 1046528 বাইট, আমাকে খেলতে 8764 বাইট রেখে।

তবে সাবলিস্ট শিরোনাম ম্যাপিং পরিবর্তন প্রক্রিয়া সম্পর্কে কি? নীচের স্মৃতি মানচিত্রে, "জেড" হল এলোমেলো ওভারহেড, "=" মুক্ত স্থান, "এক্স" কমপ্যাক্ট তালিকা list

ZZZ=====XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

বামতম "এক্স" থেকে পড়া শুরু করুন এবং বাম পাশে "=" এ লেখা শুরু করুন এবং ডানদিকে কাজ করুন। এটি সম্পন্ন হওয়ার পরে কমপ্যাক্টের তালিকাটি কিছুটা ছোট হবে এবং এটি মেমরির ভুল প্রান্তে থাকবে:

ZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=======

সুতরাং তখন আমার এটি ডানদিকে নামানো দরকার:

ZZZ=======XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

শিরোনাম ম্যাপিং পরিবর্তন প্রক্রিয়াতে, সাবলিস্ট শিরোনামগুলির 1/3 টি পর্যন্ত 1-বিট থেকে 2-বিটে পরিবর্তন হবে। সবচেয়ে খারাপ ক্ষেত্রে এগুলি সমস্ত তালিকার শীর্ষে থাকবে, সুতরাং আমি শুরুর আগে আমার কমপক্ষে 781250/3 বিট ফ্রি স্টোরেজ প্রয়োজন, যা আমাকে কমপ্যাক্ট তালিকার পূর্ববর্তী সংস্করণটির মেমরির প্রয়োজনীয়তাগুলিতে ফিরিয়ে নিয়ে যায়: (

এটি পেতে, আমি 781250 টি সাবলিস্টগুলিকে প্রতিটি 78125 সাবলিস্টের 10 টি সাবলিস্ট গ্রুপে বিভক্ত করব। প্রতিটি গ্রুপের নিজস্ব স্বতন্ত্র সাবলিস্ট শিরোনাম ম্যাপিং রয়েছে। দলগুলির জন্য A থেকে J অক্ষর ব্যবহার:

ZZZ=====AAAAAABBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ

প্রতিটি সাবলিস্ট গোষ্ঠী একটি সাবলিস্ট শিরোনাম ম্যাপিং পরিবর্তনের সময় সঙ্কুচিত বা একই থাকে:

ZZZ=====AAAAAABBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAA=====BBCCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABB=====CCCCDDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCC======DDDDDEEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDD======EEEFFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEE======FFFGGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFF======GGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGG=======HHIJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHH=======IJJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHI=======JJJJJJJJJJJJJJJJJJJJ
ZZZAAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ=======
ZZZ=======AAAAAABBCCCDDDDDEEEFFFGGGGGGGGGGHHIJJJJJJJJJJJJJJJJJJJJ

ম্যাপিং পরিবর্তনের সময় সাবলিস্ট গোষ্ঠীর অস্থায়ী প্রসারণটি 412-এর নীচে 78125/3 = 26042 বিট হয়। যদি আমি 4k প্লাস 1037764 বাইটগুলিকে সম্পূর্ণ জনবহুল কমপ্যাক্ট তালিকার জন্য অনুমতি দেয় তবে এটি আমাকে স্মৃতি মানচিত্রে "জেড" এর জন্য 8764 - 4096 = 4668 বাইট ছেড়ে যায়।

এটি 10 ​​সাবলিস্ট শিরোনাম ম্যাপিং টেবিল, 30 সাবলিস্ট শিরোলেখের উপস্থিতি গণনা এবং অন্যান্য কয়েকটি কাউন্টার, পয়েন্টার এবং ছোট বাফারগুলির জন্য প্রচুর পরিমাণে হওয়া উচিত, এবং ফাংশন কল রিটার্ন ঠিকানাগুলির জন্য স্ট্যাক স্পেসের মতো জায়গা আমি লক্ষ্য না করেই ব্যবহার করেছি and স্থানীয় পরিবর্তনশীল।

পার্ট 3, এটি চালাতে কত সময় লাগবে?

একটি খালি কমপ্যাক্ট তালিকার সাথে 1-বিট তালিকা শিরোনামটি খালি সাবলিস্টের জন্য ব্যবহার করা হবে এবং তালিকার প্রারম্ভিক আকারটি 781250 বিট হবে। সবচেয়ে খারাপ ক্ষেত্রে তালিকার প্রতিটি সংখ্যার জন্য 8 টি বিট বৃদ্ধি পায়, তাই 32 + 8 = 40 বিট খালি প্রতিটি জায়গার জন্য 32-বিট সংখ্যার প্রত্যেককে তালিকার বাফারের শীর্ষে স্থাপন করতে হবে এবং তারপরে বাছাই এবং একত্রিত করা হবে। সবচেয়ে খারাপ ক্ষেত্রে সাবলিস্ট শিরোনাম ম্যাপিংয়ের পরিবর্তনের ফলে 2 * 781250 + 7 * এন্ট্রি - 781250/3 বিটের স্থান ব্যবহার হয়।

তালিকায় কমপক্ষে 800000 নম্বর পাওয়া গেলে প্রতি পঞ্চম সংশ্লেষের পরে সাবলিস্ট শিরোনাম ম্যাপিং পরিবর্তন করার নীতিমালা সহ, সবচেয়ে খারাপ ক্ষেত্রে প্রায় কমপক্ষে প্রায় 30M কমপ্যাক্ট তালিকার পড়া এবং লেখার ক্রিয়াকলাপ জড়িত।

সূত্র:

http://nick.cleaton.net/ramsortsol.html


15
আমি মনে করি না এর চেয়ে আরও ভাল সমাধান সম্ভব (যদি আমাদের কোনও সংকোচনযোগ্য মানের সাথে কাজ করা প্রয়োজন)। তবে এটির কিছুটা উন্নতি হতে পারে। 1-বিট এবং 2-বিট উপস্থাপনার মধ্যে সাবলিস্ট শিরোনাম পরিবর্তন করার প্রয়োজন নেই। পরিবর্তে আপনি পাটিগণিত কোডিং ব্যবহার করতে পারেন যা অ্যালগরিদমকে সহজ করে তোলে এবং হিডার প্রতি বিটগুলির সংখ্যা সবচেয়ে কম হয় 1.67 থেকে 1.58 এ ases এবং আপনার মেমরিতে কমপ্যাক্ট তালিকাটি সরানোর প্রয়োজন হবে না; পরিবর্তে বিজ্ঞপ্তি বাফার ব্যবহার করুন এবং শুধুমাত্র পয়েন্টার পরিবর্তন করুন।
ইভজেনি ক্লুয়েভ

5
সুতরাং, অবশেষে, এটি একটি সাক্ষাত্কারের প্রশ্ন ছিল?
mlvljr

2
অন্যান্য সম্ভাব্য উন্নতি হ'ল 128-উপাদান সাবলিস্টগুলির পরিবর্তে 100-উপাদান সাবলিস্টগুলি ব্যবহার করা (কারণ যখন আমরা উপ-তালিকাগুলির সংখ্যা ডেটা সেটের উপাদানগুলির সংখ্যার সমান হয় তখন আমরা বেশিরভাগ কমপ্যাক্ট উপস্থাপনা পাই)। সাবলিস্টের প্রতিটি মান পাটিগণিত কোডিং (প্রতিটি মানের জন্য 1/100 সমান ফ্রিকোয়েন্সি সহ) সাথে এনকোড করা হবে। এটি প্রায় 10000 বিট সংরক্ষণ করতে পারে, সাবলিস্ট শিরোনামগুলির সংক্ষেপণের চেয়ে অনেক কম।
ইভজেনি ক্লুয়েভ

কেস সি এর জন্য, আপনি বলেছেন "এন্ট্রিগুলি অ-হ্রাসমান ক্রমে সংরক্ষণ করা হয়, ব্যতীত শেষ এন্ট্রি প্রথমটির চেয়ে কম বা সমান হয়" " তাহলে আপনি কীভাবে 2,2,2,3,5 এনকোড করবেন? 2 2,2,3,5,2 just ঠিক 2,2 এর মতো দেখাবে
রোলি

1
সাব-লিস্ট শিরোনাম এনকোডিংয়ের একটি সহজ সমাধান ম্যাপিংটিকে জটিল পরিবর্তন না করে সাব-হেডারের প্রতি একই কন্ট্রেশন অনুপাত 1.67 বিট দিয়ে সম্ভব। আপনি প্রতি 3 টি পরপর সাবহেডার একসাথে একত্রিত করতে পারেন, যা 5 টি বিটে সহজেই এনকোড করা যায় কারণ 3 * 3 * 3 = 27 < 32। আপনি তাদের একত্রিত করুন combined_subheader = subheader1 + 3 * subheader2 + 9 * subheader3
hynekcer

57

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

এটি নিজে চেষ্টা করো. 1 মিলিয়ন এলোমেলো বিট 27 বিট পূর্ণসংখ্যা পান, তাদের বাছাই করুন, 7-জিপ , এক্সজেড, আপনি যা চান এলজেডএমএ দিয়ে সংক্ষেপ করুন। ফলাফলটি 1.5 মেগাবাইটের বেশি। উপরের ভিত্তিটি ক্রমিক সংখ্যাগুলির সংক্ষেপণ। এমনকি ব-দ্বীপ এনকোডিং যে হয় 1.1 ওভার মেগাবাইট । এবং এটিকে সংকোচনের জন্য 100 এমবি র‌্যামের বেশি ব্যবহার করা উচিত মনে করবেন না। সুতরাং সংক্ষেপিত পূর্ণসংখ্যাগুলিও সমস্যার সাথে খাপ খায় না এবং রান টাইম র‌্যাম ব্যবহারের বিষয়টি মনে করে না

লোকেরা কীভাবে সুন্দর গ্রাফিক্স এবং যৌক্তিকরণকে উত্সাহ দেয় তা আমার দুঃখের বিষয়।

#include <stdint.h>
#include <stdlib.h>
#include <time.h>

int32_t ints[1000000]; // Random 27-bit integers

int cmpi32(const void *a, const void *b) {
    return ( *(int32_t *)a - *(int32_t *)b );
}

int main() {
    int32_t *pi = ints; // Pointer to input ints (REPLACE W/ read from net)

    // Fill pseudo-random integers of 27 bits
    srand(time(NULL));
    for (int i = 0; i < 1000000; i++)
        ints[i] = rand() & ((1<<27) - 1); // Random 32 bits masked to 27 bits

    qsort(ints, 1000000, sizeof (ints[0]), cmpi32); // Sort 1000000 int32s

    // Now delta encode, optional, store differences to previous int
    for (int i = 1, prev = ints[0]; i < 1000000; i++) {
        ints[i] -= prev;
        prev    += ints[i];
    }

    FILE *f = fopen("ints.bin", "w");
    fwrite(ints, 4, 1000000, f);
    fclose(f);
    exit(0);

}

এখন এলজেডএমএ এর সাথে ইনস.বিন সংক্ষেপ করুন ...

$ xz -f --keep ints.bin       # 100 MB RAM
$ 7z a ints.bin.7z ints.bin   # 130 MB RAM
$ ls -lh ints.bin*
    3.8M ints.bin
    1.1M ints.bin.7z
    1.2M ints.bin.xz

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

@ বেস্টেস হ্যাঁ! আমার শেষ অগ্রগতি উত্তর পরীক্ষা করে দেখুন। আমি মনে করি এটি সম্ভব হতে পারে।
alecco

3
দুঃখিত তবে এটি আসলে প্রশ্নের উত্তর দেবে বলে মনে হচ্ছে না ।
n611x007

@ ন্যাক্সা হ্যাঁ এর উত্তর দেয়: এটি মূল প্রশ্নের পরামিতিগুলির মধ্যে করা যায় না। এটি কেবল তখনই করা যেতে পারে যদি সংখ্যার বিতরণটির খুব কম এনট্রপি থাকে।
alecco

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

41

আমি মনে করি এটি সম্পর্কে চিন্তা করার একটি উপায় একটি সম্মিলক দৃষ্টিকোণ থেকে: বাছাই করা সংখ্যা ক্রমগুলির কতগুলি সংমিশ্রণ রয়েছে? যদি আমরা 0,0,0, ...., 0 কোড 0, এবং 0,0,0, ..., 1 কোড 1 এবং 99999999, 99999999, ... 99999999 কোড এন, এন কি? অন্য কথায়, ফলাফলের স্থানটি কত বড়?

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

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

এখানে চিত্র বর্ণনা লিখুন

সুতরাং যদি পথটি শেষের দিকে ডান দিকে সরানো থাকে তবে সমস্ত দিকে শীর্ষে উঠে যায়, এটি 0,0,0, ..., 0 অর্ডার করার সমান। পরিবর্তে যদি এটি সমস্ত দিকে শীর্ষে ঝাঁপ দিয়ে শুরু হয় এবং তারপরে ডান দিকে 1,000,000 বার চলে যায়, এটি 99999999,99999999, ..., 99999999 এর সমান হয় A এমন পথ যেখানে এটি একবারে ডানদিকে চলে যায়, তারপরে একবার উপরে, তারপরে ডানদিকে , তারপরে একবারে, একেবারে শেষ পর্যন্ত (তারপর অগত্যা সমস্ত দিকের উপরে উঠে যায়) 0,1,2,3, ..., 999999 এর সমান।

ভাগ্যক্রমে আমাদের জন্য এই সমস্যাটি ইতিমধ্যে সমাধান হয়ে গেছে, এই জাতীয় গ্রিডটি (এন + এম) বেছে নিন (এম) পাথগুলি:

(1,000,000 + 100,000,000) (100,000,000) চয়ন করুন ~ = 2.27 * 10 ^ 2436455

এন এভাবে সমান 2.27 * 10 ^ 2436455, এবং তাই কোড 0 0,0,0, ..., 0 এবং কোড 2.27 * 10 ^ 2436455 এবং কিছু পরিবর্তন 99999999,99999999, ..., 99999999 উপস্থাপন করে।

0 থেকে 2.27 * 10 ^ 2436455 পর্যন্ত সমস্ত সংখ্যা সঞ্চয় করতে আপনার lg2 (2.27 * 10 ^ 2436455) = 8.0937 * 10 ^ 6 বিট দরকার।

1 মেগাবাইট = 8388608 বিট> 8093700 বিট

সুতরাং দেখা যাচ্ছে যে আমাদের কমপক্ষে আসলে ফলাফল সংরক্ষণের জন্য পর্যাপ্ত জায়গা আছে! এখন অবশ্যই আকর্ষণীয় বিট সংখ্যাটি প্রবাহ হিসাবে বাছাই করছে sure নিশ্চিত না যে এটির সর্বোত্তম পন্থা দেওয়া হয়েছে আমাদের কাছে 294908 বিট বাকি রয়েছে। আমি কল্পনা করি যে প্রতিটি বিন্দুতে একটি আকর্ষণীয় কৌশল হ'ল এটি পুরো অর্ডারিং, সেই আদেশটির কোড খুঁজে পাওয়া এবং তারপরে আপনি একটি নতুন নম্বর পেয়ে যাবেন এবং পূর্ববর্তী কোডটি আপডেট করবেন। হাতের তরঙ্গ হাতের তরঙ্গ।


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

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

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

আপনি কাঁচা স্রোত সঞ্চয় করতে 3.5M উল্লেখ করছেন? (যদি তা না হয় তবে আমার ক্ষমা এবং এই প্রতিক্রিয়াটিকে উপেক্ষা করুন)। যদি তা হয় তবে তা সম্পূর্ণ অপ্রাসঙ্গিক নিম্ন সীমানা। আমার নিম্ন সীমাটি ফলাফলটি কতটা জায়গা নেবে তা হ'ল, নিম্ন সীমাটি হ'ল প্রয়োজনীয় স্থানগুলি রাখার জন্য ইনপুটগুলি কতটা জায়গা নেবে - এই প্রশ্নটি টিসিপি সংযোগ থেকে আসা একটি প্রবাহ হিসাবে প্রশ্নযুক্ত হয়েছিল given আপনার প্রকৃতপক্ষে কী করা দরকার কিনা তা পরিষ্কার নয়, আপনি একবারে একটি সংখ্যা পড়তে এবং আপনার রাষ্ট্র আপডেট করতে চলেছেন, সুতরাং 3.5M এর প্রয়োজন নেই - যে কোনও উপায়েই, 3.5 এই গণনাটির অরগানীয়।
ফ্রান্সিসকো রায়ান টলমাস্কি

আসল প্রশ্নকর্তার উত্তর থেকে "" প্রায় 2 পাওয়ার পাওয়ার জন্য 8093729.5 বিভিন্ন উপায় রয়েছে যা সদৃশ মুলুকগুলি সহ 1 মিলিয়ন 8-অঙ্কের সংখ্যা নির্বাচন করুন এবং গুরুত্বহীন অর্ডার করুন "<- মূল প্রশ্নকর্তার উত্তর থেকে। আমি কী বন্ধনের বিষয়ে কথা বলছি তা সম্পর্কে কীভাবে আরও স্পষ্ট হতে হবে তা জানেন না। আমি আমার শেষ মন্তব্যে এই বাক্যটির বিষয়ে বিশেষভাবে উল্লেখ করেছি।
ড্যানিয়েল ওয়াগনার

20

আমার পরামর্শগুলি এখানে ড্যানের সমাধানের অনেক .ণী

প্রথমে আমি ধরে নিই সমাধানটি অবশ্যই সমস্ত সম্ভাব্য ইনপুট তালিকা পরিচালনা করবে। আমি মনে করি জনপ্রিয় উত্তরগুলি এই অনুমানটি করে না (যা আইএমও একটি বিশাল ভুল)।

এটি জানা যায় যে কোনওরূপ ক্ষতিবিহীন সংকোচনের ফলে সমস্ত ইনপুটগুলির আকার হ্রাস পাবে না।

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

এই জাতীয় সমাধানের জন্য, যে কেউ তাদের সংক্ষেপণটি কীভাবে করবেন সে সম্পর্কে জ্ঞান সহ যে কেউ এই ইনপুট ডেটা ডিজাইন করতে সক্ষম হবেন যা এই স্কিমের জন্য ভালভাবে সংকোচিত হয় না এবং "সমাধান" সম্ভবত স্থান ছাড়িয়ে যাওয়ার কারণে সম্ভবত ভেঙে যায়।

পরিবর্তে আমি একটি গাণিতিক পদ্ধতির গ্রহণ করি। আমাদের সম্ভাব্য আউটপুটগুলি 0..MAX এর মধ্যে থাকা উপাদানগুলির সমন্বিত দৈর্ঘ্যের LEN এর সমস্ত তালিকা। এখানে LEN 1,000,000 এবং আমাদের MAX 100,000,000।

স্বেচ্ছাসেবী লেন এবং ম্যাক্সের জন্য, এই রাজ্যের এনকোড করার জন্য প্রয়োজনীয় পরিমাণ বিটের পরিমাণ হ'ল:

লগ 2 (ম্যাক্স মাল্টিচুজ লেন)

সুতরাং আমাদের সংখ্যার জন্য, একবার আমরা পুনরুদ্ধার এবং বাছাই সম্পন্ন করার পরে, আমাদের ফলাফলটি এমনভাবে সংরক্ষণ করতে কমপক্ষে লগ 2 (100,000,000 এমসি 1,000,000) বিটের দরকার হবে যা সমস্ত সম্ভাব্য আউটপুটগুলিকে আলাদাভাবে আলাদা করতে পারে।

এটি ~ = 988kb । সুতরাং আমাদের কাছে আমাদের রেজাল্ট ধরে রাখার জন্য পর্যাপ্ত জায়গা রয়েছে। এই দৃষ্টিকোণ থেকে, এটি সম্ভব।

[মুছে ফেলা অর্থহীন র‌্যাম্বিং এখন আরও ভাল উদাহরণ রয়েছে ...]

সেরা উত্তর এখানে

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


পরের দিন আপনার নিজের উত্তরটি পুনরায় পড়তে মজা করুন ... সুতরাং শীর্ষের উত্তরটি ভুল হওয়ার সময়ে, গৃহীত একটি স্ট্যাকওভারফ্লো . com/a/12978097/1763801 বেশ ভাল is তালিকাটি LEN-1 নিতে এবং LEN ফিরে আসার জন্য কার্যক্রমে সন্নিবেশ সাজানোর ব্যবহার করে। আপনি যদি একটি ছোট সেট প্রিন্ট করেন তবে দক্ষতা বাড়াতে আপনি একটি পাসে সেগুলি sertোকাতে পারেন। রাষ্ট্রের উপস্থাপনাটি আমার হাতের avyেউয়ের পরামর্শ এবং আরও স্বজ্ঞাত তুলনায় বেশ কমপ্যাক্ট (bit বিট সংখ্যার বালতি) better আমার
কমপ্লেক্স

1
আমি মনে করি আপনার পাটিগণিত কিছুটা দূরে আছে। আমি lg2 (100999999! / (99999999! * 1000000!)) পেয়েছি = 1011718.55
নোভাডেনিজেন

হ্যাঁ ধন্যবাদ এটি 988 কেবি 965 নয়। 1024 বনাম 1000 এর দিক থেকে আমি opালু ছিলাম 35 এখনও প্রায় 35 কেবি নিয়ে আমাদের খেলা বাকি রয়েছে। আমি উত্তরে গণিতের গণনার একটি লিঙ্ক যুক্ত করেছি।
ডেভেক

18

মনে করুন এই কাজটি সম্ভব হয়েছে। আউটপুট দেওয়ার ঠিক আগে, মিলিয়ন বাছাই করা সংখ্যার একটি ইন-মেমরি উপস্থাপনা থাকবে। এরকম কতগুলি উপস্থাপনা রয়েছে? যেহেতু এখানে পুনরাবৃত্তি সংখ্যা থাকতে পারে আমরা এনসিআর ব্যবহার করতে পারি না (চয়ন করুন), তবে মাল্টিচুজ নামে একটি অপারেশন রয়েছে যা মাল্টিসেটে কাজ করে ।

  • 0..99,999,999 পরিসরে একটি মিলিয়ন সংখ্যা চয়ন করার জন্য 2.2e2436455 উপায় রয়েছে।
  • প্রতিটি সম্ভাব্য সংমিশ্রণ বা 1,011,717 বাইট উপস্থাপনের জন্য এটি 8,093,730 বিট প্রয়োজন ।

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

তবে, যদি "1 এম র‌্যাম" এর অর্থ দশ মিলিয়ন বাইট হয়, তবে স্পষ্টতই যথেষ্ট স্থান নেই। আরও 5% মেমরি এটিকে তাত্ত্বিকভাবে সম্ভব করে তোলে তা আমার কাছে পরামর্শ দেয় যে উপস্থাপনাটি খুব দক্ষ হতে হবে এবং সম্ভবত বুদ্ধিমান নয়।


মিলিয়ন সংখ্যা (2.2e2436455) বাছাই করার উপায়গুলির সংখ্যা (256 ^ (1024 * 988)) এর কাছাকাছি হতে চলেছে, যা (2.0e2436445)। তবে, আপনি যদি 1M থেকে 32 কিলোমিটার মেমরি নিয়ে যান, সমস্যাটি সমাধান করা যাবে না। এছাড়াও মনে রাখবেন কমপক্ষে 3 কেবি মেমরি সংরক্ষিত ছিল।
johnwbyrd

এটি অবশ্যই ধরে নেয় যে ডেটা সম্পূর্ণ এলোমেলো। যতদূর আমরা জানি, এটি হ'ল, তবে আমি কেবল বলছি :)
থোররিন

সম্ভাব্য রাজ্যের এই সংখ্যার উপস্থাপনের প্রচলিত উপায় হ'ল লগ বেস 2 গ্রহণ এবং তাদের প্রতিনিধিত্ব করার জন্য প্রয়োজনীয় বিটের সংখ্যা রিপোর্ট করা reporting
নোভাডেনিজেন

@ থোররিন, হ্যাঁ, আমি "সমাধান" এর কোনও বিন্দু দেখতে পাচ্ছি না যা কেবলমাত্র কিছু ইনপুটগুলির জন্য কাজ করে।
ড্যান

12

(আমার মূল উত্তরটি ভুল ছিল, খারাপ গণিতের জন্য দুঃখিত, বিরতির নীচে দেখুন))

এ কেমন?

প্রথম 27 বিটগুলি আপনি দেখেছেন সর্বনিম্ন সংখ্যাটি সংরক্ষণ করুন, তারপরে পরবর্তী কোডটি এনকোড করা থেকে আলাদা হবে: পার্থক্যটি সংরক্ষণের জন্য ব্যবহৃত বিটের সংখ্যা সংরক্ষণ করার জন্য 5 বিট, তারপরে পার্থক্য। আপনি আবারও এই নম্বরটি দেখেছেন তা বোঝাতে 00000 ব্যবহার করুন।

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

সবচেয়ে খারাপ পরিস্থিতি আমি ভাবতে পারি সমস্ত সংখ্যা সমানভাবে ব্যবধানে (100 দ্বারা), উদাহরণস্বরূপ 0 টি প্রথম সংখ্যা হিসাবে ধরা হচ্ছে:

000000000000000000000000000 00111 1100100
                            ^^^^^^^^^^^^^
                            a million times

27 + 1,000,000 * (5+7) bits = ~ 427k

রেডডিট!

আপনার যা করতে হবে তা যদি তাদের বাছাই করা হত তবে এই সমস্যাটি সহজ হবে। আপনি কোন সংখ্যাটি দেখেছেন তা সংরক্ষণ করতে 122 কে (1 মিলিয়ন বিট) লাগে (0 টি দেখা গেলে 0 তম বিট, 2300 দেখা গেলে 2300 তম বিট ইত্যাদি) takes

আপনি সংখ্যাগুলি পড়েন, সেগুলি বিট ক্ষেত্রে সংরক্ষণ করুন এবং তারপরে একটি গণনা রাখার সময় বিটগুলি সরিয়ে ফেলুন।

তবে আপনাকে কতগুলি দেখেছেন তা মনে রাখতে হবে। এই স্কিমটি নিয়ে আসার জন্য আমি উপরের সাবলিস্টের উত্তরে অনুপ্রাণিত হয়েছি:

এক বিট ব্যবহারের পরিবর্তে, 2 বা 27 বিট ব্যবহার করুন:

  • 00 মানে আপনি নম্বরটি দেখেননি।
  • 01 এর অর্থ আপনি একবার দেখেছেন
  • 1 এর অর্থ হল আপনি এটি দেখেছেন এবং পরবর্তী 26 বিটগুলি কতবার গণনা করা হচ্ছে।

আমি মনে করি এটি কাজ করে: যদি কোনও সদৃশ না থাকে তবে আপনার 244k তালিকা রয়েছে। সবচেয়ে খারাপ ক্ষেত্রে আপনি প্রতিটি সংখ্যা দুটিবার দেখতে পান (যদি আপনি তিনবার এক নম্বর দেখতে পান তবে এটি আপনার জন্য বাকি তালিকাটি সংক্ষিপ্ত করে), এর অর্থ আপনি একবারের চেয়ে 50,000 বেশি দেখেছেন এবং আপনি 950,000 আইটেম 0 বা 1 বার দেখেছেন।

50,000 * 27 + 950,000 * 2 = 396.7 কে।

আপনি যদি নিম্নলিখিত এনকোডিংটি ব্যবহার করেন তবে আপনি আরও উন্নতি করতে পারেন:

0 এর অর্থ আপনি 10 নম্বরটি দেখেননি এর অর্থ 11 আপনি একবার এটি দেখেছিলেন কীভাবে আপনি গণনা রাখেন

যা গড়ে 280.7k স্টোরেজ তৈরি করবে।

সম্পাদনা: আমার রবিবার সকালে গণিতটি ভুল ছিল।

সবচেয়ে খারাপ পরিস্থিতি হ'ল আমরা দু'বার 500,000 নম্বর দেখতে পাচ্ছি, সুতরাং গণিতটি হয়ে যায়:

500,000 * 27 + 500,000 * 2 = 1.77M

বিকল্প এনকোডিংয়ের গড় স্টোরেজ হয়

500,000 * 27 + 500,000 = 1.70M

: (


1
ঠিক আছে, না, যেহেতু দ্বিতীয় সংখ্যাটি
500000

কিছু মধ্যবর্তী যুক্ত করুন, যেমন 11 এর অর্থ আপনি সংখ্যাটি 64 বার পর্যন্ত দেখেছেন (পরবর্তী 6 টি বিট ব্যবহার করে), এবং 11000000 এর অর্থ আপনি যে বার দেখেছেন তার সংখ্যা সংরক্ষণ করতে আরও 32 বিট ব্যবহার করুন।
τεκ

10
আপনি কোথায় "1 মিলিয়ন বিট" নম্বর পেয়েছেন? আপনি বলেছিলেন যে 2300 তম বিট 2300 দেখা গেছে কিনা তা উপস্থাপন করে। (আমি মনে করি আপনি প্রকৃতপক্ষে 2301st বোঝাতে চেয়েছিলেন 99) 99,999,999 দেখা গেছে কিনা (বৃহত্তম 8-সংখ্যা সংখ্যা) কোনটি উপস্থাপন করে? সম্ভবত, এটি হবে 100 মিলিয়ন বিট।
user94559

আপনি আপনার এক মিলিয়ন এবং আপনার শত মিলিয়ন পিছনে পেয়েছেন। সর্বাধিক বার কোনও মানটি দেখা দিতে পারে এটি 1 মিলিয়ন, এবং কোনও মানটির সংখ্যার প্রতিনিধিত্ব করতে আপনার কেবল 20 বিট প্রয়োজন। তেমনি আপনার প্রয়োজন 100,000,000 বিট ক্ষেত্র (1 মিলিয়ন নয়), প্রতিটি সম্ভাব্য মানের জন্য একটি।
টিম আর।

উহ, 27 + 1000000 * (5 + 7) = 12000027 বিট = 1.43 এম, 427 কে নয়।
ড্যানিয়েল ওয়াগনার

10

সমস্ত সম্ভাব্য ইনপুট জুড়ে এই সমস্যার একটি সমাধান রয়েছে। ঠকাই।

  1. টিসিপি-র উপর এম মানগুলি পড়ুন, যেখানে এম সর্বাধিকের নিকটে রয়েছে যা মেমরির অনুসারে বাছাই করা যায়, সম্ভবত এন / 4।
  2. 250,000 (বা তাই) সংখ্যাগুলি বাছাই করুন এবং তাদের আউটপুট করুন।
  3. অন্যান্য 3 কোয়ার্টারের জন্য পুনরাবৃত্তি করুন।
  4. প্রাপকটি এটির প্রক্রিয়া করার সাথে সাথে এটি প্রাপ্ত 4 টি সংখ্যার তালিকার একত্রীকরণ করতে দিন। (এটি একটি একক তালিকা ব্যবহারের চেয়ে বেশি ধীর নয় not)

7

আমি একটি Radix ট্রি চেষ্টা করবে । আপনি যদি কোনও গাছের মধ্যে ডেটা সঞ্চয় করতে পারেন, তবে আপনি ডেটা সংক্রমণ করার জন্য একটি অর্ডার ক্রস করতে পারেন।

আমি নিশ্চিত না যে আপনি এটি 1 এমবিতে ফিট করতে পারবেন তবে আমি মনে করি এটি চেষ্টা করার মতো।


7

আপনি কোন ধরণের কম্পিউটার ব্যবহার করছেন? এটিতে অন্য কোনও "সাধারণ" স্থানীয় স্টোরেজ নাও থাকতে পারে, তবে এর ভিডিও র‌্যাম রয়েছে, উদাহরণস্বরূপ? পিক্সেল প্রতি 1 মেগাপিক্সেল এক্স 32 বিট (বলুন) আপনার প্রয়োজনীয় ডেটা ইনপুট আকারের কাছাকাছি।

(আমি পুরানো অ্যাকর্ন আরআইএসসি পিসির স্মরণে জিজ্ঞাসা করি , যা আপনি যদি কম রেজোলিউশন বা কম রঙিন-গভীরতার স্ক্রিন মোড চয়ন করেন তবে উপলভ্য সিস্টেমের র‌্যামটি প্রসারিত করতে ভিআরএমকে 'ধার' নিতে পারে!)। এটি কেবলমাত্র কয়েকটি এমবি র‌্যামের মেশিনে উপকারী ছিল।


1
মন্তব্য করতে যত্নশীল, ডাউনভোটার? - আমি কেবল প্রশ্নের আপাত সংকোচগুলি প্রসারিত করার চেষ্টা করছি (অর্থাত্ সৃজনশীলভাবে প্রতারণা ;-)
ডিএনএ

কোনও কম্পিউটারই নাও থাকতে পারে, কারণ হ্যাকার সংবাদের প্রাসঙ্গিক থ্রেডটিতে এটি একবার গুগল সাক্ষাত্কারের প্রশ্ন ছিল।
mlvljr

1
হ্যাঁ - প্রশ্নটি সম্পাদনার আগে আমি উত্তর দিয়েছি যে এটি একটি সাক্ষাত্কারের প্রশ্ন!
ডিএনএ

6

একটি রেডিক্স ট্রি প্রতিনিধিত্বকারী এই সমস্যাটি পরিচালনা করার কাছাকাছি চলে আসবে, যেহেতু র‌্যাডিক্স ট্রি "উপসর্গ সংকোচনের" সুবিধা গ্রহণ করে। তবে একটি র‌্যাডিক্স ট্রি প্রতিনিধিত্বকে ধারণ করা কঠিন যা একটি বাইটে একটি নোডকে উপস্থাপন করতে পারে - দুটি সম্ভবত সীমা সম্পর্কে।

তবে, ডেটা কীভাবে উপস্থাপিত হয় তা নির্বিশেষে একবার এটি বাছাই করার পরে এটি উপসর্গ-সংক্ষেপিত আকারে সংরক্ষণ করা যেতে পারে, যেখানে 10, 11, এবং 12 সংখ্যাটি প্রতিনিধিত্ব করবে, বলুন 001 বি, 001 বি, 001 বি, 1 এর বর্ধিতকরণ নির্দেশ করে পূর্ববর্তী নম্বর থেকে সম্ভবত, তখন, 10101 বি 5, 1101001b 9, ইত্যাদি বৃদ্ধি বৃদ্ধি উপস্থাপন করবে etc.


6

10 ^ 8 এর পরিসীমাটিতে 10 ^ 6 মান রয়েছে, সুতরাং গড়ে প্রতি শত কোড পয়েন্টের একটি মান আছে। Nth পয়েন্ট থেকে (N + 1) th এর দূরত্ব সংরক্ষণ করুন। সদৃশ মানগুলি 0 এড়িয়ে যায় This এর অর্থ হ'ল এই স্কিপটি সংরক্ষণের জন্য গড়ে মাত্র 7 বিটের কম পরিমাণে আবশ্যক, সুতরাং তাদের এক মিলিয়ন আমাদের 8 মিলিয়ন বিট স্টোরেজে সুখে ফিট করবে fit

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

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


5

আমার কাছে 1M র্যামের কম্পিউটার রয়েছে এবং অন্য কোনও স্থানীয় স্টোরেজ নেই

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

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


5

আমি মনে করি সমাধানটি হ'ল ভিডিও এনকোডিং থেকে কৌশলগুলি একত্রিত করা, যথা পৃথক কোসাইন রূপান্তর। ডিজিটাল ভিডিওতে, পরিবর্তিত ভিডিওর উজ্জ্বলতা বা রঙের নিয়মিত মান যেমন 110 112 115 116 হিসাবে রেকর্ডিংয়ের প্রতিটিকে শেষ থেকে বিয়োগ করা হয় (দৈর্ঘ্যের এনকোডিং চালানোর অনুরূপ)। 110 112 115 116 110 2 3 1 হয়ে যায় 1.

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

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

যাইহোক, আমি কিছু পরীক্ষা করেছিলাম। আমি একটি এলোমেলো নম্বর জেনারেটর ব্যবহার করি এবং আমি এক মিলিয়ন বাছাই করা 8 ডিজিটের দশমিক সংখ্যাকে প্রায় 1279000 বাইটে ফিট করতে পারি। প্রতিটি সংখ্যার মধ্যে গড় স্থান নিয়মিতভাবে 99 ...

public class Test {
    public static void main(String[] args) throws IOException {
        // 1 million values
        int[] values = new int[1000000];

        // create random values up to 8 digits lrong
        Random random = new Random();
        for (int x=0;x<values.length;x++) {
            values[x] = random.nextInt(100000000);
        }
        Arrays.sort(values);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        int av = 0;    
        writeCompact(baos, values[0]);     // first value
        for (int x=1;x<values.length;x++) {
            int v = values[x] - values[x-1];  // difference
            av += v;
            System.out.println(values[x] + " diff " + v);
            writeCompact(baos, v);
        }

        System.out.println("Average offset " + (av/values.length));
        System.out.println("Fits in " + baos.toByteArray().length);
    }

    public static void writeCompact(OutputStream os, long value) throws IOException {
        do {
            int b = (int) value & 0x7f;
            value = (value & 0x7fffffffffffffffl) >> 7;
            os.write(value == 0 ? b : (b | 0x80));
        } while (value != 0);
    }
}

4

আমরা সমস্ত নম্বর থাকার আগে বাছাই ক্রমে নম্বর প্রেরণের জন্য আমরা নেটওয়ার্কিং স্ট্যাকের সাথে খেলতে পারি। আপনি যদি 1M ডেটা প্রেরণ করেন, টিসিপি / আইপি এটিকে 1500 বাইট প্যাকেটে বিভক্ত করে লক্ষ্য হিসাবে প্রবাহিত করবে। প্রতিটি প্যাকেট একটি ক্রম নম্বর দেওয়া হবে।

আমরা এটি হাত দিয়ে করতে পারি। আমাদের র‌্যামটি পূরণ করার ঠিক আগে আমরা আমাদের যা আছে তা বাছাই করতে পারি এবং আমাদের লক্ষ্যটিতে তালিকাটি প্রেরণ করতে পারি তবে প্রতিটি সংখ্যার চারপাশে আমাদের ক্রমের ছিদ্র রেখে দিতে পারি। তারপরে ক্রমের সেই ছিদ্রগুলি ব্যবহার করে একইভাবে দ্বিতীয় সংখ্যাটির ২ য় 1/2 প্রসেস করুন।

সুদূর প্রান্তে থাকা নেটওয়ার্কিং স্ট্যাকটি প্রয়োগের হাতে দেওয়ার আগে ক্রম অনুসারে ফলস্বরূপ তথ্য স্ট্রিমটি একত্রিত করবে।

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


4

গুগলের (খারাপ) পদ্ধতির, এইচএন থ্রেড থেকে। আরএলই-স্টাইল গণনা সঞ্চয় করুন।

আপনার প্রাথমিক ডেটা স্ট্রাকচারটি '99999999: 0' (সমস্ত শূন্য, কোনও সংখ্যা দেখেনি) এবং তারপরে আপনাকে বলতে হবে যে আপনি 3,866,344 সংখ্যাটি দেখেন তাই আপনার ডেটা স্ট্রাকচারটি আপনার হিসাবে '3866343: 0,1: 1,96133654: 0' হয়ে যায় সংখ্যাগুলি সর্বদা শূন্য বিটের সংখ্যার এবং '1' বিটের সংখ্যার মধ্যে বিকল্প হতে পারে যাতে আপনি কেবল বিজোড় সংখ্যাগুলি 0 বিট এবং সমান সংখ্যা 1 বিটকে উপস্থাপন করে ধরে নিতে পারেন। এটি হয়ে যায় (3866343,1,96133654)

তাদের সমস্যাটি সদৃশগুলি কভার করে বলে মনে হচ্ছে না, তবে ধরা যাক তারা সদৃশগুলির জন্য "0: 1" ব্যবহার করেন।

বড় সমস্যা # 1: 1 এম পূর্ণসংখ্যার সন্নিবেশে বয়স হতে হবে

বড় সমস্যা # 2: সমস্ত প্লেইন ডেল্টা এনকোডিং সমাধানগুলির মতো, কিছু বিতরণও এইভাবে কভার করা যায় না। উদাহরণস্বরূপ, দূরত্ব 0:99 সহ 1 মিটার পূর্ণসংখ্যা (উদাহরণস্বরূপ +99 প্রতিটি)। এখন 0:99 এর সীমার মধ্যে এলোমেলো দূরত্বের সাথে একই তবে ভাবুন । (দ্রষ্টব্য: 99999999/1000000 = 99.99)

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


3

বাছাই করা অ্যারে উপস্থাপন করতে কেউ কেবল প্রথম উপাদান এবং সংলগ্ন উপাদানগুলির মধ্যে পার্থক্য সংরক্ষণ করতে পারে। এইভাবে আমরা 10 ^ 6 টি উপাদান এনকোডিংয়ের সাথে সম্পর্কিত যা সর্বাধিক 10 ^ 8 পর্যন্ত যোগ করতে পারে। এই ডি কল । ডি এর উপাদানগুলিকে এনকোড করতে একটি হাফম্যান কোড ব্যবহার করতে পারে । হাফম্যান কোডের জন্য অভিধানটি তৈরির সময় তৈরি করা যেতে পারে এবং অ্যারে আপডেট করা হয় প্রতিবারই বাছাই করা অ্যারেটিতে একটি নতুন আইটেম isোকানো হয় (সন্নিবেশ সাজানোর)। মনে রাখবেন যে অভিধানটি যখন কোনও নতুন আইটেমটির কারণে পরিবর্তন হয় তখন নতুন এনকোডিংয়ের সাথে মেলে পুরো অ্যারে আপডেট করা উচিত।

ডি এর প্রতিটি উপাদানকে এনকোডিংয়ের জন্য বিটগুলির গড় সংখ্যা সর্বাধিক হয় যদি আমাদের প্রতিটি অনন্য উপাদানের সমান সংখ্যা থাকে। বলুন উপাদান D1 , D2 , ..., ডিএন মধ্যে ডি প্রতিটি প্রদর্শিত এফ বার। সেক্ষেত্রে (আমাদের সবচেয়ে খারাপ ক্ষেত্রে ইনপুট ক্রমটিতে 0 এবং 10 ^ 8 উভয়ই রয়েছে)

যোগফল (1 <= i <= N ) এফdi = 10 ^ 8

কোথায়

যোগফল (1 <= i <= N ) এফ = 10 ^ 6, বা এফ = 10 ^ 6 / এন এবং সাধারণীকৃত ফ্রিকোয়েন্সি পি = এফ / 10 ^ = 1 / এন হবে

বিটের গড় সংখ্যা -২২ (1 / পি ) = লগ 2 ( এন ) হবে। এই পরিস্থিতিতে আমাদের একটি কেস সন্ধান করতে হবে যা এনকে সর্বাধিক করে তোলে । যদি সেটা হয় আমরা জন্য পরপর নম্বর আছে দ্বি 0, বা থেকে শুরু, দ্বি = আমি -1, অতএব

10 ^ 8 = যোগ (1 <= i <= এন ) এফডি = যোগ (1 <= i <= এন ) (10 ^ 6 / এন ) (আই -1) = (10 ^ 6 / এন ) এন ( এন -1) / 2

অর্থাত

এন <= 201. এবং এই ক্ষেত্রে বিটগুলির গড় সংখ্যা লগ 2 (201) = 7.6511 যার অর্থ বাছাই করা অ্যারে সংরক্ষণের জন্য আমাদের প্রতি ইনপুট উপাদানটির প্রায় 1 বাইট লাগবে। নোট করুন যে এর অর্থ সাধারণত D এর সাথে 201 টিরও বেশি উপাদান থাকতে পারে না। এটি কেবল বপন করে যে ডি এর উপাদানগুলি সমানভাবে বিতরণ করা হলে এর 201 টিরও বেশি অনন্য মান থাকতে পারে না।


1
আমি মনে করি আপনি ভুলে গেছেন যে নম্বরটি নকল হতে পারে।
বেটসেস

সদৃশ সংখ্যার জন্য সংলগ্ন সংখ্যার মধ্যে পার্থক্য শূন্য হবে। কোনও সমস্যা তৈরি করে না। হাফম্যান কোডের ননজারো মান প্রয়োজন হয় না।
মোহসেন নসর্যাটিনিয়া

3

আমি টিসিপির পুনঃপ্রেরণ আচরণটি কাজে লাগাব would

  1. টিসিপি উপাদানটিকে একটি বড় রিসিভ উইন্ডো তৈরি করুন।
  2. তাদের জন্য একটি এসকে না প্রেরণে কিছু পরিমাণ প্যাকেট গ্রহণ করুন।
    • পাসগুলিতে কিছু সংবেদনশীল ডেটা স্ট্রাকচার তৈরি করার প্রক্রিয়া করুন
    • শেষ প্যাকেটের জন্য সদৃশ আক্ক পাঠান যা আর প্রয়োজন হয় না / পুনঃপ্রেরণ সময়সীমার জন্য অপেক্ষা করুন
    • গোটো 2
  3. সমস্ত প্যাকেট গ্রহণ করা হয়েছিল

এটি বালতি বা একাধিক পাসের একরকম উপকারের কথা ধরে।

সম্ভবত ব্যাচ / বালতি বাছাই করে এবং তাদের মার্জ করে। -> মূলা গাছ

প্রথম ৮০% গ্রহণ ও সাজানোর জন্য এই কৌশলটি ব্যবহার করুন তারপরে শেষ ২০% পড়ুন, যাচাই করুন যে শেষ ২০% এর মধ্যে এমন সংখ্যা নেই যা সর্বনিম্ন সংখ্যার প্রথম 20% এ অবতরণ করবে। তারপরে 20% সর্বনিম্ন সংখ্যা প্রেরণ করুন, মেমরি থেকে সরান, অবশিষ্ট 20% নতুন সংখ্যা গ্রহণ করুন এবং মার্জ করুন * **


3

এই ধরণের সমস্যার একটি সাধারণ সমাধান এখানে দেওয়া হল:

সাধারণ পদক্ষেপ

গৃহীত পন্থাটি নিম্নরূপ। অ্যালগরিদম 32-বিট শব্দের একক বাফারে কাজ করে। এটি একটি লুপে নিম্নলিখিত পদ্ধতিটি সম্পাদন করে:

  • আমরা শেষ পুনরাবৃত্তি থেকে সংকুচিত ডেটা ভরা বাফার দিয়ে শুরু করি। বাফারটি দেখতে এমন দেখাচ্ছে

    |compressed sorted|empty|

  • সংক্ষিপ্ত এবং সঙ্কুচিত উভয়ই এই বাফারটিতে সঞ্চিত হওয়া সর্বাধিক পরিমাণের গণনা করুন। সংক্ষেপিত ডেটা দিয়ে শেষ করে সংকুচিত ডেটার জন্য স্পেস দিয়ে শুরু করে এই দুটি বিভাগে বাফারটি বিভক্ত করুন। বাফারের মতো দেখতে

    |compressed sorted|empty|empty|

  • বাছাই করা সংখ্যার সাথে সঙ্কুচিত বিভাগটি পূরণ করুন। বাফারের মতো দেখতে

    |compressed sorted|empty|uncompressed unsorted|

  • নতুন নম্বরগুলিকে একটি ইন-প্লেস বাছাই করে বাছাই করুন। বাফারের মতো দেখতে

    |compressed sorted|empty|uncompressed sorted|

  • সংক্ষেপিত বিভাগে পূর্ববর্তী পুনরাবৃত্তি থেকে ইতিমধ্যে যে কোনও সংকুচিত ডেটা ডান-সারিবদ্ধ করুন। এই মুহুর্তে বাফারটি পার্টিশন করা হয়

    |empty|compressed sorted|uncompressed sorted|

  • সংকুচিত বিভাগে সাজানো ডেটাগুলিতে মার্জ করে সংকুচিত বিভাগে একটি স্ট্রিমিং ডিকম্প্রেশন-রিকম্প্রেশন করুন। নতুন সংকোচিত অংশটি বাড়ার সাথে সাথে পুরানো সংকোচিত অংশটি গ্রাস করা হয়। বাফারের মতো দেখতে

    |compressed sorted|empty|

সমস্ত নম্বর বাছাই না করা অবধি এই পদ্ধতিটি সম্পাদিত হয়।

সঙ্কোচন

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

ব্যবহৃত পদ্ধতির তিনটি পদক্ষেপ ব্যবহার করা হয়। প্রথমত, অ্যালগরিদম সর্বদা বাছাই করা ক্রমগুলি সংরক্ষণ করে রাখে, সুতরাং আমরা পরিবর্তে পরপর প্রবেশের মধ্যে পার্থক্যগুলি বিশুদ্ধভাবে সংরক্ষণ করতে পারি। প্রতিটি পার্থক্য [0, 99999999] এর মধ্যে রয়েছে।

এই পার্থক্যগুলি তখন অ্যানারি বিটস্ট্রিম হিসাবে এনকোড করা হয়। এই স্ট্রিমের A 1 এর অর্থ "সংগ্রহকারীর সাথে 1 যুক্ত করুন, এ 0 এর অর্থ" প্রবেশকারীর হিসাবে প্রবাহকে প্রেরণ করুন এবং পুনরায় সেট করুন "difference সুতরাং পার্থক্য N এন 1 এবং একটি 0 দ্বারা প্রতিনিধিত্ব করা হবে।

সমস্ত পার্থক্যের সমষ্টিটি আলগোরিদম সমর্থন করে এমন সর্বাধিক মানের কাছে পৌঁছাবে এবং সমস্ত পার্থক্যের গণনাটি অ্যালগরিদমে সন্নিবেশিত মানগুলির পরিমাণের সাথে যোগাযোগ করবে। এর অর্থ আমরা শেষ পর্যন্ত স্রোতটির সর্বাধিক মান 1 এবং গণনা 0 এর আশা করি। এটি আমাদের প্রবাহে 0 এবং 1 এর প্রত্যাশিত সম্ভাবনা গণনা করতে দেয়। যথা, 0 count/(count+maxval)এর সম্ভাব্যতা এবং 1 এর সম্ভাব্যতা maxval/(count+maxval)

আমরা এই সম্ভাব্যতাগুলি এই বিটস্ট্রিমের উপরে একটি গাণিতিক কোডিং মডেল সংজ্ঞায়িত করতে ব্যবহার করি। এই গাণিতিক কোডটি যথাযথ স্থানটিতে 1 এবং 0 এর পরিমাণটিকে সঠিকভাবে এনকোড করবে। আমরা যত কোন মধ্যবর্তী bitstream জন্য এই মডেল দ্বারা ব্যবহৃত স্থান নিরূপণ করতে পারেন: bits = encoded * log2(1 + amount / maxval) + maxval * log2(1 + maxval / amount)। অ্যালগরিদমের জন্য মোট প্রয়োজনীয় স্থান গণনা encodedকরতে, পরিমাণের সমান সেট করুন ।

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

তার পরেও, কিছু ওভারহেড বুককিপিং ডেটা সংরক্ষণ করার জন্য এবং পাটিগণিত কোডিং অ্যালগরিদমের নির্দিষ্ট পয়েন্টের সান্নিধ্যে সামান্য ভুলত্রুটিগুলি পরিচালনা করার জন্য প্রয়োজনীয়, তবে সামগ্রিকভাবে অ্যালগরিদম অতিরিক্ত বাফার সহ 1MiB স্পেসে ফিট করতে সক্ষম 8000 নম্বর, মোট স্থানের 1043916 বাইটের জন্য।

Optimality

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


2

যদি ইনপুট স্ট্রিমটি কয়েকবার পাওয়া যায় তবে এটি অনেক সহজ হবে (সে সম্পর্কে কোনও ধারণা, ধারণা এবং সময়-সম্পাদন সমস্যা নয়)।

তারপরে, আমরা দশমিক মানগুলি গণনা করতে পারি। গণিত মানগুলির সাথে আউটপুট স্ট্রিম করা সহজ হবে। মান গণনা করে সঙ্কুচিত করুন। এটি নির্ভর করে যে ইনপুট প্রবাহে কী হবে।


1

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


1

বাছাই করা এখানে একটি গৌণ সমস্যা। অন্যরা যেমন বলেছে, কেবল পূর্ণসংখ্যাগুলি সংরক্ষণ করা শক্ত, এবং সমস্ত ইনপুটগুলিতে কাজ করতে পারে না , যেহেতু সংখ্যার প্রতি 27 বিট প্রয়োজনীয় হবে।

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

00 -> 5 bits
01 -> 11 bits
10 -> 19 bits
11 -> 27 bits

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

আমি আশা করি এর উপর ভিত্তি করে ভাল পর্যাপ্ত সংখ্যার সংকোচনের স্কিমটি পেতে আপনি আপনার ইনপুটটির ডোমেন-নির্দিষ্ট জ্ঞানটি ব্যবহার করতে সক্ষম হতে পারেন ।

ওহ এবং তারপরে, আপনি ডেটা পাওয়ার সাথে সাথে আপনি সেই সাজানো তালিকায় একটি সন্নিবেশ বাছাই করেন।


1

এখন কেবল 1 এমবি র‌্যামের সাথে 8 ডিজিটের সীমার ইনপুটটির সমস্ত সম্ভাব্য কেসগুলি কভার করে, একটি আসল সমাধানের দিকে লক্ষ্য রেখে। দ্রষ্টব্য: কাজ চলছে, আগামীকালও চলবে। বাছাই করা ints এর ডেল্টাসের গাণিতিক কোডিং ব্যবহার করে, 1M বাছাই করা ints এর জন্য সবচেয়ে খারাপ ক্ষেত্রে প্রবেশের জন্য প্রায় 7 বিট পড়বে (যেহেতু 99999999/1000000 99, এবং লগ 2 (99) প্রায় 7 বিট)।

তবে আপনার 7 বা 8 টি বিট পেতে 1m পূর্ণসংখ্যার বাছাই করা দরকার! সংক্ষিপ্ত সিরিজের বড় ডেল্টাস হবে, সুতরাং উপাদান হিসাবে আরও বিট।

আমি যথাসম্ভব অনেকগুলি গ্রহণ এবং স্থানে (প্রায়) সংকোচনের বিষয়ে কাজ করছি। 250 কে ints এর কাছাকাছি প্রথম ব্যাচের জন্য সর্বোত্তমভাবে প্রায় 9 বিট লাগবে। সুতরাং ফলাফল প্রায় 275KB নিতে হবে। অবশিষ্ট বিনামূল্যে স্মৃতি কয়েকবার পুনরাবৃত্তি করুন। তারপরে comp সংকুচিত খণ্ডগুলি সংক্ষেপে-সংযুক্ত-স্থান-সংমিশ্রণ করুন। এটি বেশ শক্ত , তবে সম্ভব। আমি মনে করি.

একত্রীকরণ তালিকাগুলি প্রতি পূর্ণ সংখ্যার জন্য 7 বিটের আরও কাছাকাছি চলে আসবে। তবে আমি জানি না যে মার্জ লুপটি এটি গ্রহণ করতে পারে rations সম্ভবত 3।

তবে পাটিগণিত কোডিং বাস্তবায়নের অসম্পূর্ণতা এটি অসম্ভব করে দিতে পারে। এই সমস্যাটি যদি আদৌ সম্ভব হয় তবে এটি অত্যন্ত শক্ত হবে।

কোন স্বেচ্ছাসেবক?


পাটিগণিত কোডিং কার্যক্ষম। এটি লক্ষ্য করতে সহায়তা করতে পারে যে প্রতিটি ধারাবাহিক ব-দ্বীপ একটি নেতিবাচক দ্বিপদী বিতরণ থেকে আঁকা।
ভিড়

1

আপনার কেবল ক্রমানুসারে সংখ্যাগুলির মধ্যে পার্থক্যগুলি সংরক্ষণ করতে হবে এবং এই ক্রম সংখ্যাটি সংকুচিত করতে একটি এনকোডিং ব্যবহার করুন। আমাদের কাছে 2 ^ 23 বিট রয়েছে। আমরা এটিকে 6 বিট খণ্ডগুলিতে ভাগ করব এবং শেষ বিটটি সংখ্যাটি আরও 6 বিট পর্যন্ত প্রসারিত করবে কিনা তা বোঝাতে দিন (5 বিটস অতিরিক্ত বর্ধিত অংশ)।

সুতরাং, 000010 হ'ল 1, এবং 000100 হল 2.8000001100000 হল 128. এখন, আমরা 10,000,000 পর্যন্ত সংখ্যার ক্রমের মধ্যে পার্থক্য উপস্থাপনের মধ্যে সবচেয়ে খারাপ কাস্ট বিবেচনা করি। 2,000 than 5, 10,000,000 / 2 ^ 10 পার্থক্য 2 ^ 10 এর চেয়ে বেশি এবং 10,000 / / 2 ^ 15 পার্থক্য 2 ^ 15 এর চেয়ে বড় হতে পারে ইত্যাদি There

সুতরাং, আমরা আমাদের ক্রমটি উপস্থাপন করতে এটি কত বিট লাগবে তা যুক্ত করব। আমাদের 10,000,000 * 6 + রাউন্ডআপ (10,000,000 / 2 ^ 5) * 6 + রাউন্ডআপ (10,000,000 / 2 ^ 10) * 6 + রাউন্ডআপ (10,000,000 / 2 ^ 15) * 6 + রাউন্ডআপ (10,000,000 / 2 ^ 20) * 4 = 7935479।

2 ^ 24 = 8388608. যেহেতু 8388608> 7935479, আমাদের সহজেই যথেষ্ট স্মৃতি থাকা উচিত। আমরা নতুন সংখ্যা সন্নিবেশ করানোর সময় কোথায় রয়েছে তার যোগফল সংরক্ষণ করতে আমাদের সম্ভবত আরও কিছুটা মেমরির প্রয়োজন হবে। তারপরে আমরা ক্রমটি অতিক্রম করি এবং আমাদের নতুন নম্বরটি কোথায় সন্নিবেশ করানো যায়, প্রয়োজনে পরবর্তী পার্থক্যটি হ্রাস করতে পারি এবং তার ঠিক পরে সমস্ত কিছু স্থানান্তরিত করি।


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

@ ড্যানিয়েল ওয়াগনার - আপনাকে প্রতি অংশে বিট সংখ্যক অভিন্ন সংখ্যা ব্যবহার করতে হবে না, এবং আপনাকে প্রতি অংশে বিট সংখ্যার পূর্ণসংখ্যার সংখ্যাও ব্যবহার করতে হবে না।
ভিড় করছেন

@ ক্রাউডিং যদি আপনার কাছে কোনও কংক্রিট প্রস্তাব থাকে তবে আমি এটি শুনতে চাই। =)
ড্যানিয়েল ওয়াগনার

@ ক্রাউডিং গণিতটি কি অঙ্কিত গাণিতিক কোডিং লাগবে তা নিয়ে গণিত করুন। কিছুটা কেঁদে ফেলুন। তারপরে আরও কঠিন চিন্তা করুন।
ড্যানিয়েল ওয়াগনার

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

1

যদি আমরা এই সংখ্যাগুলির বিষয়ে কিছু না জানি তবে আমরা নিম্নলিখিত সীমাবদ্ধতার দ্বারা সীমাবদ্ধ:

  • সেগুলি বাছাই করার আগে আমাদের সমস্ত সংখ্যা লোড করতে হবে,
  • সংখ্যার সেট সংকোচযোগ্য নয়।

যদি এই অনুমানগুলি ধরে থাকে তবে আপনার কার্য সম্পাদনের কোনও উপায় নেই কারণ আপনার কমপক্ষে 26,575,425 বিট স্টোরেজ (3,321,929 বাইট) প্রয়োজন হবে need

আপনার ডেটা সম্পর্কে আমাদের কী বলতে পারেন?


1
আপনি সেগুলি পড়ুন এবং যাওয়ার পথে বাছাই করুন। এটি তাত্ত্বিকভাবে 100 এম বিশিষ্ট বাক্সগুলিতে 1 এম বিভেদযোগ্য আইটেম সংরক্ষণের জন্য বিগ 2 (100999999! / (99999999! * 1000000!)) বিটগুলির প্রয়োজন, যা 1MB এর 96.4% পর্যন্ত কাজ করে।
নোভাডেনিজেন

1

কৌশলটি হল "বর্ধিত কাউন্টার" = "+" এবং "আউটপুট কাউন্টার" = "এর সংকুচিত স্ট্রিম হিসাবে, একটি পূর্ণসংখ্যার বহু-সেট অ্যালগরিদম রাষ্ট্রকে উপস্থাপন করা!" চরিত্র. উদাহরণস্বরূপ, সেট {0,3,3,4} "+ +++ !! +!" হিসাবে উপস্থাপিত হবে, তারপরে "+" যে কোনও সংখ্যক অক্ষর থাকবে। মাল্টি-সেটটি পরিবর্তন করতে আপনি অক্ষরগুলি প্রবাহিত করে কেবল একবারে সংক্রমিত হয়ে যান এবং সংকোচযুক্ত আকারে ফিরে স্ট্রিম করার পূর্বে স্থান পরিবর্তন করেন।

বিস্তারিত

আমরা জানি চূড়ান্ত সেটে হুবহু 10 ^ 6 সংখ্যা রয়েছে, সুতরাং সেখানে বেশিরভাগ 10 ^ 6 রয়েছে! " চরিত্র. আমরা আরও জানি যে আমাদের পরিসীমাটির আকার 10 ^ 8 রয়েছে যার অর্থ সর্বাধিক 10 ^ 8 "+" অক্ষর রয়েছে। 10 ^ 8 "+" এর মধ্যে আমরা 10 ^ 6 "!" গুলি কীভাবে সাজিয়ে তুলতে পারি(10^8 + 10^6) choose 10^6 তার সংখ্যা , এবং তাই নির্দিষ্ট কিছু নির্দিষ্টকরণের জন্য ~ 0.965 মাইবি B ডেটা লাগে । এটি একটি টাইট ফিট হবে।

আমরা আমাদের কোটা অতিক্রম না করে প্রতিটি চরিত্রকে স্বাধীন হিসাবে বিবেচনা করতে পারি। "" "এর চেয়ে ঠিক 100 গুণ বেশি অক্ষর রয়েছে!" অক্ষরগুলি, যা প্রতিটি চরিত্রের "+" হয়ে ওঠার জন্য 100: 1 টির পক্ষে সহজতর হয় যদি আমরা ভুলে যাই যে তারা নির্ভরশীল। ১০০ এর মান: 101 এর চরিত্র প্রতি ~ 0.08 বিটের সাথে মিল রয়েছে, প্রায় একই পরিমাণে মোট ~ 0.965 মাইবি (নির্ভরতা উপেক্ষা করে এই ক্ষেত্রে কেবলমাত্র 12 ডলার বিট রয়েছে!)।

পূর্বের সম্ভাব্যতা সহ স্বতন্ত্র অক্ষরগুলি সংরক্ষণ করার সহজ কৌশল হফম্যান কোডিং । নোট করুন যে আমাদের একটি অবৈধভাবে বড় গাছ প্রয়োজন (10 টি অক্ষরের ব্লকের একটি হাফম্যান ট্রি মোট ব্লক প্রতি গড় 2.9 বিট প্রতি ব্যয় হয়, মোট ~ 2.9 Mib। 20 টি অক্ষরের ব্লকের একটি হাফম্যান গাছের প্রতি ব্লকের গড় ব্যয় হয় প্রায় ৩ টি বিট, যা মোট ১.৮ মিলিয়ন ডলার।আমরা সম্ভবত একশ ক্রমের আকারের একটি ব্লকের প্রয়োজন যা আমাদের গাছের মধ্যে থাকা সমস্ত কম্পিউটার সরঞ্জামের চেয়ে বেশি নোড বোঝাতে পারে যা সংরক্ষণ করতে পারে। )। তবে, সমস্যাটি অনুযায়ী আরওএম প্রযুক্তিগতভাবে "মুক্ত" এবং ব্যবহারিক সমাধান যা গাছের নিয়মিততার সুযোগ নেয় তা মূলত একই রকম দেখাবে।

সুডোকোড

  • ROM এ পর্যাপ্ত পরিমাণে হাফম্যান ট্রি (বা অনুরূপ ব্লক-বাই-ব্লক সংক্ষেপণ ডেটা) সঞ্চিত আছে
  • 10 ^ 8 "+" অক্ষরের সংকুচিত স্ট্রিং দিয়ে শুরু করুন।
  • N নম্বর সন্নিবেশ করতে, সংক্ষেপিত স্ট্রিংটি প্রবাহিত করুন যতক্ষণ না N "+" অক্ষর চলে না যায় তারপরে একটি "!" প্রবেশ করান। ওভার / অনূর্ধ্ব রানগুলি এড়াতে অবিচ্ছিন্ন পরিমাণে বাফার ব্লক রেখে আপনি আগের মতো আবার সংক্ষেপিত স্ট্রিংটি স্ট্রিম করুন।
  • এক মিলিয়ন বার পুনরাবৃত্তি করুন: [ইনপুট, স্ট্রিম ডিকম্প্রেস> সন্নিবেশ> সংক্ষেপণ], তারপরে আউটপুট থেকে ডেকম্প্রেস করুন

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

ইনপুট পূর্ণসংখ্যার বাছাই করা হয় না। আপনাকে প্রথমে বাছাই করতে হবে।
এলেকো

1
@ অ্যালেকো অ্যালগরিদম যেমন অগ্রগতি করে সেগুলি বাছাই করে। এগুলি কখনও বিনা বাছাই করা সঞ্চয় করা হয় না।
ক্রেগ গিডনি

1

আমাদের কাছে 1 এমবি - 3 কেবি র‌্যাম = 2 ^ 23 - 3 * 2 ^ 13 বিট = 8388608 - 24576 = 8364032 বিট উপলব্ধ।

আমাদের একটি 10 ​​^ 8 পরিসরে 10 ^ 6 নম্বর দেওয়া হয়। এটি গড়ে gap 100 <2 ^ 7 = 128 এর ব্যবধান দেয়

সমস্ত ফাঁক <128 হয় তখন প্রথমে মোটামুটি সমান ব্যবধানের সংখ্যাগুলির সরল সমস্যাটি বিবেচনা করি। এটি সহজ। কেবল প্রথম সংখ্যা এবং 7-বিট ফাঁকাগুলি সংরক্ষণ করুন:

(27 বিট) + 10 ^ 6 7-বিট ফাঁক সংখ্যা = 7000027 বিট প্রয়োজন

নোট পুনরাবৃত্তি সংখ্যা 0 ফাঁক আছে।

তবে আমাদের যদি 127 এর চেয়ে বড় ব্যবধান থাকে?

ঠিক আছে, ধরা যাক একটি ফাঁক আকার <127 সরাসরি উপস্থাপন করা হয়, তবে 127 এর ফাঁক আকারের পরে আসল ফাঁকের দৈর্ঘ্যের জন্য অবিচ্ছিন্ন 8-বিট এনকোডিং হয়:

 10xxxxxx xxxxxxxx                       = 127 .. 16,383
 110xxxxx xxxxxxxx xxxxxxxx              = 16384 .. 2,097,151

প্রভৃতি

নোট করুন এই সংখ্যার উপস্থাপনাটি তার নিজস্ব দৈর্ঘ্য বর্ণনা করে যাতে পরবর্তী গ্যাপ নম্বরটি কখন শুরু হয় তা আমরা জানি।

কেবলমাত্র ছোট ফাঁক দিয়ে <127, এর জন্য এখনও 7000027 বিট দরকার।

(10 ^ 8) / (2 ^ 7) = 781250 23-বিট ফাঁক সংখ্যা পর্যন্ত থাকতে পারে, অতিরিক্ত 16 * 781,250 = 12,500,000 বিট প্রয়োজন যা খুব বেশি। আমাদের আরও কমপ্যাক্ট এবং ধীরে ধীরে ব্যবধানগুলির প্রতিনিধিত্বের প্রয়োজন।

গড় ব্যবধানের আকার 100 হয় তাই যদি আমরা সেগুলিকে [100, 99, 101, 98, 102, ..., 2, 198, 1, 199, 0, 200, 201, 202, ...] হিসাবে পুনরায় অর্ডার করি এবং এটি সূচক হয় একটি ঘন বাইনারি ফিবোনাচি বেস এনকোডিং সহ কোনও জুড়ি নেই (উদাহরণস্বরূপ, 11011 = 8 + 5 + 2 + 1 = 16) '00' দ্বারা বিস্মৃত সংখ্যার সাথে তখন আমি মনে করি যে আমরা ব্যবধান উপস্থাপনাটি যথেষ্ট সংক্ষিপ্ত রাখতে পারি, তবে এটির প্রয়োজন আরও বিশ্লেষণ।


0

স্ট্রিম পাওয়ার সময় এই পদক্ষেপগুলি করুন।

1 ম কিছু যুক্তিসঙ্গত খণ্ড আকার সেট

সিউডো কোড ধারণা:

  1. প্রথম পদক্ষেপটি হ'ল সমস্ত অনুলিপিগুলি খুঁজে পেতে এবং এটির গণনা সহ একটি অভিধানে এগুলি আটকাতে এবং সেগুলি সরাতে।
  2. তৃতীয় পদক্ষেপটি হ'ল তাদের অ্যালগোরিদমিক পদক্ষেপের ক্রম অনুসারে যে সংখ্যাটি রয়েছে এবং সেগুলি প্রথম সংখ্যা এবং তাদের এন, এন + 1 ..., এন + 2, 2 এন, 2 এন + 1 এর মতো পদক্ষেপ সহ বিশেষ অভিধানে কাউন্টারে রাখে, 2n +2 ​​...
  3. প্রতি 1000 বা কখনও কখনও 10000 এর মতো সংখ্যার কিছু যুক্তিসঙ্গত পরিসরের অংশগুলিকে সঙ্কুচিত করা শুরু করুন যা পুনরাবৃত্তি করতে কম দেখা যায়।
  4. কোনও নম্বর পাওয়া গেলে সেই ব্যাপ্তিকে সঙ্কোচিত করুন এবং এটিকে পরিসরে যুক্ত করুন এবং আরও দীর্ঘ সময়ের জন্য সঙ্কুচিত রেখে দিন।
  5. অন্যথায় কেবল এই সংখ্যাটি একটি বাইটে যোগ করুন [চুঙ্কসাইজ]

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

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