একটি পূর্ণসংখ্যা তৈরি করুন যা প্রদত্ত চার বিলিয়ানের মধ্যে নয়


691

আমাকে এই সাক্ষাত্কারের প্রশ্ন দেওয়া হয়েছে:

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

আমার বিশ্লেষণ:

ফাইলটির আকার 4 × 10 9 × 4 বাইট = 16 জিবি।

আমরা বাহ্যিক বাছাই করতে পারি, এভাবে আমাদের পূর্ণসংখ্যার ব্যাপ্তিটি জানতে দেয়।

আমার প্রশ্নটি হল বাছাই করা বড় পূর্ণসংখ্যার সেটগুলিতে অনুপস্থিত পূর্ণসংখ্যা সনাক্ত করার সর্বোত্তম উপায় কোনটি?

আমার বোঝাপড়া (সমস্ত উত্তর পড়ার পরে):

ধরা যাক আমরা 32-বিট পূর্ণসংখ্যার কথা বলছি, 2 32 = 4 * 10 9 স্বতন্ত্র পূর্ণসংখ্যা রয়েছে।

কেস 1: আমাদের 1 জিবি = 1 * 10 9 * 8 বিট = 8 বিলিয়ন বিট মেমরি রয়েছে।

সমাধান:

আমরা যদি একটি স্বতন্ত্র পূর্ণসংখ্যার প্রতিনিধিত্ব করে একটি বিট ব্যবহার করি তবে এটি যথেষ্ট। আমাদের বাছাইয়ের দরকার নেই।

বাস্তবায়ন:

int radix = 8;
byte[] bitfield = new byte[0xffffffff/radix];
void F() throws FileNotFoundException{
    Scanner in = new Scanner(new FileReader("a.txt"));
    while(in.hasNextInt()){
        int n = in.nextInt();
        bitfield[n/radix] |= (1 << (n%radix));
    }

    for(int i = 0; i< bitfield.lenght; i++){
        for(int j =0; j<radix; j++){
            if( (bitfield[i] & (1<<j)) == 0) System.out.print(i*radix+j);
        }
    }
}

কেস 2: 10 এমবি মেমরি = 10 * 10 6 * 8 বিট = 80 মিলিয়ন বিট

সমাধান:

সমস্ত সম্ভাব্য 16-বিট উপসর্গের জন্য, 2 16 সংখ্যার পূর্ণসংখ্যা = 65536 রয়েছে, আমাদের 2 16 * 4 * 8 = 2 মিলিয়ন বিট প্রয়োজন। আমাদের 65536 বালতি তৈরি করতে হবে। প্রতিটি বালতিতে আমাদের 4 টি বাইটের সমস্ত সম্ভাবনা রয়েছে কারণ সবচেয়ে খারাপ পরিস্থিতি হ'ল 4 বিলিয়ন পূর্ণসংখ্যা একই বালতিতে।

  1. ফাইলের মাধ্যমে প্রথম পাসের মাধ্যমে প্রতিটি বালতির কাউন্টার তৈরি করুন।
  2. বালতিগুলি স্ক্যান করুন, প্রথমটি খুঁজে নিন যার 65536 কম হিট রয়েছে।
  3. নতুন বালতি তৈরি করুন যার উচ্চ 16 বিট উপসর্গগুলি আমরা ফাইলের দ্বিতীয় পাসের মাধ্যমে ধাপ 2 এ পেয়েছি
  4. স্টিপি 3 এ নির্মিত বালতিগুলি স্ক্যান করুন, প্রথম বালতিটি আবিষ্কার করুন যা হিট করতে পারে না।

কোডটি একের উপরে একটির মতোই।

উপসংহার: আমরা ফাইল পাসের মাধ্যমে স্মৃতিশক্তি হ্রাস করি decrease


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


32
@ ট্র্যাশগোড, ভুল 4294967295 অনন্য পূর্ণসংখ্যার জন্য আপনার 1 টি পূর্ণসংখ্যা বাকি থাকবে। এটির সন্ধানের জন্য, আপনাকে সমস্ত পূর্ণসংখ্যার সমষ্টি করতে হবে এবং এটি সম্ভাব্য পূর্ণসংখ্যার পূর্বাভাস সংকেত থেকে বিয়োগ করতে হবে।
নাকিলন

58
এটি "প্রোগ্রামিং পার্লস" এর দ্বিতীয় "মুক্তো", এবং আমি আপনাকে বইটিতে পুরো আলোচনাটি পড়ার পরামর্শ দিচ্ছি। দেখুন books.google.com/...
অলোক Singhal

8
@ রিচার্ড 64৪ বিট ইন্টের পরিমাণ যথেষ্ট বড় হবে।
সিফতার্নাস

79
int getMissingNumber(File inputFile) { return 4; }( রেফারেন্স )
জনি

14
আপনি 1 থেকে 2 ^ 32 পর্যন্ত সমস্ত সংখ্যার যোগফল সংরক্ষণ করতে পারবেন না এটি বিবেচ্য নয় কারণ সি / সি ++ এর মতো ভাষাতে পূর্ণসংখ্যার ধরন সর্বদা সাহচর্যতা এবং যোগাযোগের মতো বৈশিষ্ট্য সংরক্ষণ করে। এর অর্থ হ'ল যদিও যোগফলটি সঠিক উত্তর হতে পারে না, আপনি যদি ওভারফ্লো দিয়ে প্রত্যাশিত গণনা করেন, ওভারফ্লো সহ প্রকৃত যোগফল এবং বিয়োগ করেন তবে ফলাফলটি এখনও সঠিক হবে (শর্ত থাকে যে এটি নিজেই প্রবাহিত হবে না)।

উত্তর:


530

"পূর্ণসংখ্যা" মানে 32 টি বিট : 10 এমবি স্থানের জন্য আপনার প্রদত্ত 16-বিট উপসর্গের সাথে ইনপুট ফাইলে কতগুলি সংখ্যা রয়েছে তা গণনা করা যথেষ্ট, তারপরে এক পাসে সমস্ত সম্ভাব্য 16-বিট উপসর্গের জন্য ইনপুট ফাইল. কমপক্ষে বালতিগুলির মধ্যে একটিতে 16 বারেরও কম আঘাত হবে । ইতিমধ্যে ইতিমধ্যে যে বালতিটিতে সম্ভাব্য সংখ্যার ব্যবহার রয়েছে তা খুঁজে পেতে দ্বিতীয় পাস করুন।

যদি এর অর্থ 32 টিরও বেশি বিট হয় তবে তবুও আবদ্ধ আকারের : উপরের মতো করুন যা সমস্ত ইনপুট নম্বরগুলি (স্বাক্ষরিত বা স্বাক্ষরযুক্ত; আপনার পছন্দ) 32-বিটের সীমার বাইরে পড়ে।

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


24
পারফেক্ট। আপনার প্রথম উত্তরের জন্য ফাইলটি দিয়ে কেবল 2 পাস দরকার!
corsiKa

47
10 এমবি বিগনাম? এটা বেশ চরম।
মার্ক র্যানসোম

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

12
সলিউশন 1 সম্পর্কে ভাল জিনিসটি হ'ল পাস বাড়িয়ে আপনি স্মৃতিশক্তি হ্রাস করতে পারেন।
Yousf

11
@ ব্যারি: উপরের প্রশ্নটি ইঙ্গিত দেয় না যে ঠিক একটি নম্বর অনুপস্থিত রয়েছে। এটি ফাইলের সংখ্যাগুলি পুনরাবৃত্তি করবে না বলেও নয়। (আসলে জিজ্ঞাসিত প্রশ্ন অনুসরণ করা সম্ভবত একটি সাক্ষাত্কারে একটি ভাল ধারণা, ডান? ;-))
ক্রিস্টোফার ক্রিউটজিগ

197

পরিসংখ্যানগতভাবে অবহিত অ্যালগরিদমগুলি ডিস্ট্রিনিস্টিক পদ্ধতির চেয়ে কম পাস ব্যবহার করে এই সমস্যার সমাধান করে।

যদি খুব বড় পূর্ণসংখ্যার অনুমতি দেওয়া হয় তবে কেউ একটি সংখ্যা তৈরি করতে পারে যা ও (1) সময়ে অনন্য হওয়ার সম্ভাবনা রয়েছে। একটি মত একটি সিউডো-রেণ্ডম 128-বিট পূর্ণসংখ্যা GUID শুধুমাত্র সেটে বিদ্যমান চার বিলিয়ন পূর্ণসংখ্যার এক সঙ্গে ধাক্কা লাগা একের কম যে 64 বিলিয়ন বিলিয়ন বিলিয়ন মামলার আউট হবে।

পূর্ণসংখ্যা যদি 32 বিটের মধ্যে সীমাবদ্ধ থাকে তবে একটি 10 ​​এমবি এর চেয়ে কম ব্যবহার করে একক পাসে অনন্য হতে পারে এমন একটি সংখ্যা তৈরি করতে পারে। একটি সিউডো-এলোমেলো 32-বিট পূর্ণসংখ্যার 4 বিলিয়ন বিদ্যমান পূর্ণসংখ্যার মধ্যে একটির সাথে সংঘর্ষ ঘটবে তা প্রায় 93% (4e9 / 2 ^ 32)। 1000 সিউডো-এলোমেলো পূর্ণসংখ্যার সংঘাতের যে পরিমাণ সংঘর্ষ ঘটবে তা 12,000 বিলিয়ন বিলিয়ন বিলিয়ন (বিজোড়-এক-সংঘর্ষ ^ 1000) এর মধ্যে একেরও কম। সুতরাং যদি কোনও প্রোগ্রাম 1000 সিউডো-এলোমেলো প্রার্থীদের সমন্বিত একটি ডেটা স্ট্রাকচার বজায় রাখে এবং পরিচিত প্রার্থীদের থেকে ম্যাচগুলি সরিয়ে, পরিচিত পূর্ণসংখ্যার মাধ্যমে পুনরাবৃত্তি করে, তবে ফাইলটিতে অন্তত একটি পূর্ণসংখ্যার সন্ধান করা তবে এটি নিশ্চিত।


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

12
আক্ষরিকভাবে একটি এলোমেলো আউটপুট অনুমান করা সম্ভবত আপনাকে একটি সাক্ষাত্কারে অনেক পয়েন্ট পাবেন না
ব্রায়ান গর্ডন

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

19
@ ব্রায়ান: আমি মনে করি এই সমাধানটি কল্পনা এবং বাস্তব উভয়ই। আমি এই উত্তরের জন্য একজনকে অনেক কুদো দিব।
রিচার্ড এইচ

6
আহ এখানে প্রকৌশলী এবং বিজ্ঞানীদের মধ্যে লাইন অবস্থিত। দুর্দান্ত উত্তর বেন!
ট্রোজান নাম

142

জোন বেন্টলে "কলাম 1 এ এই সমস্যা সম্পর্কিত একটি বিস্তৃত আলোচনা আলোচনা করা হয়েছে " ঝিনুক ক্র্যাকিং " প্রোগ্রামিং পার্লস অ্যাডিসন-ওয়েসলি পিপি 3-10

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

4 billion bits = (4000000000 / 8) bytes = about 0.466 GB

বিটসেট বাস্তবায়নের কোডটি সহজ: (থেকে নেওয়া হয়েছে) সমাধান পৃষ্ঠা )

#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1 + N/BITSPERWORD];

void set(int i) {        a[i>>SHIFT] |=  (1<<(i & MASK)); }
void clr(int i) {        a[i>>SHIFT] &= ~(1<<(i & MASK)); }
int  test(int i){ return a[i>>SHIFT] &   (1<<(i & MASK)); }

বেন্টলির অ্যালগরিদম setঅ্যারের মধ্যে যথাযথ বিটটি টাই করে ফাইলটির উপরে একটি একক পাস করে এবং তারপরে testনিখোঁজ নম্বরটি আবিষ্কার করতে উপরের ম্যাক্রো ব্যবহার করে এই অ্যারে পরীক্ষা করে ।

যদি উপলভ্য মেমরি 0.466 গিগাবাইটের কম হয় তবে বেন্টলে একটি কে-পাস অ্যালগরিদম প্রস্তাব করে যা উপলব্ধ মেমরির উপর নির্ভর করে ইনপুটটিকে রেঞ্জগুলিতে বিভক্ত করে। খুব সাধারণ উদাহরণ হিসাবে, যদি কেবলমাত্র 1 বাইট (8 টি সংখ্যা হ্যান্ডেল করার জন্য মেমরি) পাওয়া যায় এবং এর পরিসীমা 0 থেকে 31 অবধি থাকে তবে আমরা এটিকে 0 থেকে 7, 8-15, 16-22 এবং এর মধ্যে ভাগ করতে পারি এবং প্রতিটি 32/8 = 4পাসে এই ব্যাপ্তিটি পরিচালনা করে ।

আছে HTH।


12
আমি বইটি জানি না, তবে এটি "ওয়ান্ডার বাছাই" বলার কারণ নেই, কারণ এটি কেবল একটি বাল্টসোর্ট, 1 বিট কাউন্টার সহ।
ফ্লোলো

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

3
@ ব্রায়ান আমার মনে হয় না জোন বেন্টলি এই বিষয়গুলিকে অ্যালগরিদমের উপর তার বইতে প্রবেশ করিয়েছিলেন।
ডেভিড হেফারনান

8
@ ব্রায়ান গর্ডন, র‌্যামে ব্যয় করা সময়টি ফাইল পড়ার সময়টির তুলনায় নগণ্য হবে। এটি অনুকূলকরণ সম্পর্কে ভুলে যান
আয়ান

1
@ ব্রায়ান গর্ডন: না আপনি প্রথম আনসেট বিটটি খুঁজে পেতে শেষে লুপটি নিয়ে কথা বলছিলেন? হ্যাঁ, ভেক্টরগুলি এটির গতি বাড়িয়ে তুলবে, তবে 64 বিট পূর্ণসংখ্যার সাথে বিটফিল্ডের উপরে লুপিং != -1করবে , এমন একটি সন্ধান করবে যা এখনও মেমরি ব্যান্ডউইথকে একক কোরে চলমান পরিপূর্ণ করবে (এটি সিমডি-এর-এ-রেজিস্টার, এসওআর, উপাদান হিসাবে বিট সহ)। (সাম্প্রতিক ইন্টেল / এএমডি ডিজাইনের জন্য)। Bit৪ বিটের অবস্থানটি অন্তর্ভুক্ত করার পরে কোন বিটটি আনসেট করা হয়েছে তা কেবল আপনাকে খুঁজে বের করতে হবে। (এবং তার জন্য আপনি এটি করতে পারেন not / lzcntFair) ফর্সা পয়েন্ট যে একক বিট পরীক্ষায় লুপিং ভাল অনুকূলিত নাও হতে পারে।
পিটার কর্ডেস

120

যেহেতু সমস্যাটি সুনির্দিষ্ট করে না যে আমাদের ফাইলে নেই এমন ক্ষুদ্রতম সংখ্যার সন্ধান করতে হবে আমরা কেবল একটি সংখ্যা তৈরি করতে পারলাম যা ইনপুট ফাইলের চেয়ে বেশি দীর্ঘ। :)


6
ফাইলের বৃহত্তম সংখ্যাটি যদি সর্বোচ্চ
সীমা না থাকে

একটি আসল ওয়ার্ল্ড প্রোগ্রামে সেই ফাইলটির আকারটি কী হতে পারে যার জন্য একটি নতুন পূর্ণসংখ্যার উত্পাদন করতে এবং এটি "ব্যবহৃত পূর্ণসংখ্যার" ফাইলটিতে ১০০ বার সংযোজন করতে পারে?
মাইকেল 23

2
আমি এই চিন্তা ছিল। ধরে intনেওয়া 32বিট হয়, কেবল আউটপুট 2^64-1। সম্পন্ন.
আইলমেট

1
যদি প্রতি লাইনে একটি int- এ আছে: tr -d '\n' < nums.txt > new_num.txt: ডি
Shon

56

1 জিবি র‌্যাম ভেরিয়েন্টের জন্য আপনি কিছুটা ভেক্টর ব্যবহার করতে পারেন। আপনাকে 4 বিলিয়ন বিট == 500 এমবি বাইট অ্যারে বরাদ্দ করতে হবে। ইনপুট থেকে আপনি যে প্রতিটি সংখ্যা পড়েছেন তার জন্য সংশ্লিষ্ট বিটটি '1' তে সেট করুন। একবার সম্পন্ন করার পরে, বিটগুলির উপর পুনরাবৃত্তি করুন, প্রথমটি এখনও '0' খুঁজে পাবেন। এর সূচক উত্তর।


4
ইনপুটটিতে সংখ্যার ব্যাপ্তি নির্দিষ্ট করা হয়নি। কীভাবে এই অ্যালগরিদম কাজ করবে যদি ইনপুটটি 8 বিলিয়ন থেকে 16 বিলিয়ন এর মধ্যে সমস্ত সমান সংখ্যার সমন্বিত থাকে?
মার্ক র্যানসোম

27
@ মার্ক, কেবল 0..2 ^ 32 সীমার বাইরে থাকা ইনপুটগুলিকে উপেক্ষা করুন। আপনি যে কোনও উপায়ে আউটপুট যাচ্ছেন না, তাই তাদের মধ্যে কোনটি এড়াতে হবে তা মনে করার দরকার নেই।
hmakholm

@ বাস্তব সংখ্যাটিতে 32 বিট স্ট্রিং মানচিত্র কীভাবে আপনার উপর নির্ভর করে তা নির্ধারণ করতে আপনি যা কিছু অ্যালগরিদম ব্যবহার করেন তা মার্ক করুন প্রক্রিয়া এখনও একই। পার্থক্যটি হ'ল আপনি কীভাবে একে স্ক্রিনে আসল নম্বর হিসাবে মুদ্রণ করবেন।
কর্সিকা

4
নিজেকে পুনরাবৃত্তি করার পরিবর্তে আপনি ব্যবহার করতে পারেন bitSet.nextClearBit(0): download.oracle.com/javase/6/docs/api/java/util/…
স্টার ব্লু

3
এটি উল্লেখ করা কার্যকর হবে যে পূর্ণসংখ্যার ব্যাপ্তি নির্বিশেষে, পাসের শেষে কমপক্ষে একটি বিট 0 হওয়ার নিশ্চয়তা দেওয়া হয়। এটি কবুতরের নীতিটির কারণে।
রাফা ডগির্ড

46

তারা 32 বিট ইন্টিজার (বন্ধ 2 4 বিলিয়ন নম্বর ~ পছন্দমত থেকে সম্ভবত হন 32 ), 4 বিলিয়ন সংখ্যার আপনার তালিকা সম্ভব পূর্ণসংখ্যার (4 * 10 অধিকাংশ 93% এ নিতে হবে 9 / (2 32 ) )। সুতরাং আপনি যদি প্রতিটি বিট শূন্য থেকে শুরু করে 2 32 বিটের বিট-অ্যারে তৈরি করেন (যা 2 29 বাইট ~ 500 এমবি র‌্যাম গ্রহণ করতে পারে; একটি বাইট = 2 3 বিট = 8 বিট মনে রাখবেন ), আপনার পূর্ণসংখ্যা তালিকার মাধ্যমে পড়ুন এবং প্রতিটি int এর জন্য বিট-অ্যারে উপাদান 0 থেকে 1 সেট করে; এবং তারপরে আপনার বিট-অ্যারের মাধ্যমে পড়ুন এবং প্রথম বিটটি এখনও 0-এ ফিরে আসুন।

আপনার র‍্যাম কম (MB 10 এমবি) থাকার ক্ষেত্রে এই সমাধানটি কিছুটা সংশোধন করা দরকার। 10 এমবি ~ 83886080 বিট 0 এবং 83886079 এর মধ্যে সমস্ত সংখ্যার জন্য একটি বিট-অ্যারে করার জন্য এখনও যথেষ্ট So সুতরাং আপনি আপনার ints এর তালিকাটি পড়তে পারেন; এবং কেবল আপনার বিট অ্যারেতে 0 এবং 83886079 এর মধ্যে থাকা # টি রেকর্ড করুন। যদি নম্বরগুলি এলোমেলোভাবে বিতরণ করা হয়; অপ্রতিরোধ্য সম্ভাবনা সহ (এটি প্রায় 100% দ্বারা পৃথক হয়) 10 -2592069 ) আপনি একটি নিখোঁজ অন্তর্মুখী পাবেন)। প্রকৃতপক্ষে, আপনি যদি কেবল 1 থেকে 2048 নম্বর পছন্দ করেন (র‌্যামের কেবল 256 বাইট সহ) আপনি এখনও অনুপস্থিত সংখ্যাটি খুঁজে পান তবে সময়ের সময়ের অপ্রতিরোধ্য শতাংশ (99.999999999999999999999999999999999999999999999999999999999999%)।

তবে এর পরিবর্তে প্রায় 4 বিলিয়ন নম্বর থাকার কথা বলি; আপনার কাছে 2 32 - 1 নম্বর এবং 10 এমবি র‌্যামের মতো কিছু ছিল ; সুতরাং যে কোনও ছোট পরিসীমাতে কেবল সংখ্যাটি না রাখার একটি ছোট্ট সম্ভাবনা রয়েছে।

যদি আপনাকে গ্যারান্টী দেওয়া হয় যে তালিকার প্রতিটি অন্তর্নির্মিতটি অনন্য ছিল, আপনি নিখুঁত সংখ্যাটি খুঁজে পেতে এবং নিখোঁজটির সন্ধানের জন্য পুরো # ( 32 ) (2 32 ) (2 32 - 1) = 9223372034707292160 এ হারিয়ে একটি # দিয়ে যোগফল বিয়োগ করতে পারবেন । যাইহোক, যদি কোনও int দুটি বার ঘটে তবে এই পদ্ধতিটি ব্যর্থ হবে।

যাইহোক, আপনি সর্বদা বিভক্ত এবং বিজয় করতে পারেন। একটি নিষ্পাপ পদ্ধতি, অ্যারের মাধ্যমে পড়তে হবে এবং প্রথমার্ধে (0 থেকে 2 31 -1) এবং দ্বিতীয়ার্ধে (2 31 , 2 32 ) সংখ্যাটি গণনা করা হবে । তারপরে কম সংখ্যার সাথে ব্যাপ্তিটি চয়ন করুন এবং সেই ব্যাপ্তিটিকে অর্ধেক করে ভাগ করে নিন repeat (বলুন (2 31 , 2 32 এ যদি দু'জন কম সংখ্যক থাকে তবে আপনার পরবর্তী অনুসন্ধানে পরিসংখ্যানগুলিতে সংখ্যাগুলি গণনা করা হবে (২ 31 , 3 * 2 30 -1), (3 * 2 30 , 2 32 ) যতক্ষণ না আপনি শূন্য সংখ্যার সাথে একটি পরিসীমা খুঁজে পান এবং আপনার উত্তর থাকে ~

সেই পদ্ধতিটি অদক্ষ ছিল। আমরা প্রতিটি ধাপে কেবল দুটি পূর্ণসংখ্যা ব্যবহার করছি (বা 4 বাইট (32-বিট) পূর্ণসংখ্যার সাথে রমের প্রায় 8 বাইট)। আরও ভাল পদ্ধতি হবে স্কয়ারটি (2 32 ) = 2 16 = 65536 বিনগুলিতে বিভক্ত করা , যার প্রত্যেকটিতে একটি বাক্সে 65536 সংখ্যা রয়েছে। প্রতিটি বিনের তার গণনা সংরক্ষণের জন্য 4 বাইট প্রয়োজন, তাই আপনার প্রয়োজন 2 18 বাইট = 256 কেবি। সুতরাং বিন 0 হ'ল (0 থেকে 65535 = 2 16 -1), বিন 1 হ'ল (2 16 = 65536 থেকে 2 * 2 16 -1 = 131071), বিন 2 হ'ল (2 * 2 16 = 131072 থেকে 3 * 2 16 - 1 = 196607)। পাইথনে আপনার মতো কিছু ছিল:

import numpy as np
nums_in_bin = np.zeros(65536, dtype=np.uint32)
for N in four_billion_int_array:
    nums_in_bin[N // 65536] += 1
for bin_num, bin_count in enumerate(nums_in_bin):
    if bin_count < 65536:
        break # we have found an incomplete bin with missing ints (bin_num)

4 বিলিয়ন ডলার পূর্ণসংখ্যা তালিকার মাধ্যমে পড়ুন; এবং 2 16 টি বিনের প্রত্যেকটিতে কয়টি ints পড়ে তা গণনা করুন এবং এমন একটি অসম্পূর্ণ_বিন সন্ধান করুন যার সমস্ত 65536 নম্বর নেই। তারপরে আপনি আবার 4 বিলিয়ন পূর্ণসংখ্যার তালিকার মাধ্যমে পড়েন; তবে এবার কেবল লক্ষ্য করুন যখন পূর্ণসংখ্যাগুলি এই ব্যাপ্তিতে থাকে; আপনি এগুলি খুঁজে পেলে কিছুটা উল্টে যাচ্ছেন।

del nums_in_bin # allow gc to free old 256kB array
from bitarray import bitarray
my_bit_array = bitarray(65536) # 32 kB
my_bit_array.setall(0)
for N in four_billion_int_array:
    if N // 65536 == bin_num:
        my_bit_array[N % 65536] = 1
for i, bit in enumerate(my_bit_array):
    if not bit:
        print bin_num*65536 + i
        break

3
এমন দুর্দান্ত উত্তর এটি আসলে কাজ করবে; এবং এর গ্যারান্টিযুক্ত ফলাফল রয়েছে।
জোনাথন ডিকিনসন

@ ডিআর জিম্বোব, যদি একটি বাক্সে কেবল একটি সংখ্যা থাকে এবং সেই একক সংখ্যায় 65535 নকল থাকে? যদি তা হয় তবে বিনটি এখনও 65536 গণনা করা হবে, তবে 65536 সংখ্যাগুলির মধ্যে একটি একই।
অ্যালকোট

@ অ্যালকোট - আমি ধরে নিয়েছিলাম যে আপনার কাছে 2 ^ 32-1 (বা তার চেয়ে কম) সংখ্যা রয়েছে, তাই কবুতরের নীতি অনুসারে আপনাকে আরও বিশদ পরীক্ষা করার জন্য 65536 এরও কম সংখ্যক একটি বিনের নিশ্চয়তা দেওয়া হচ্ছে। আমরা কেবল একটি অনুপস্থিত পূর্ণসংখ্যার সন্ধান করার চেষ্টা করছি, সেগুলি সব নয়। আপনার যদি 2 ^ 32 বা ততোধিক সংখ্যা থাকে তবে আপনি অনুপস্থিত পূর্ণসংখ্যার গ্যারান্টি দিতে পারবেন না এবং এই পদ্ধতিটি ব্যবহার করতে সক্ষম হবেন না (বা গোপন সংখ্যার শুরুতে গ্যারান্টি রয়েছে)। আপনার সেরা বাজিটি হবে নিদারুণ বল (উদাহরণস্বরূপ, অ্যারের মাধ্যমে 32 বার পড়ুন; প্রথমবার 65536 # সেকেন্ড প্রথমবার পরীক্ষা করা; এবং একবার উত্তর পাওয়া গেলে থামানো)।
ডাঃ জিম্বব

চতুর উপরের -16 / নিম্ন -16 পদ্ধতিটি আগে হেনিং পোস্ট করেছিলেন: স্ট্যাকওভারফ্লো . com / a / 7153822 / 224132 । যদিও ঠিক একটি সদস্য নিখোঁজ হওয়া অনন্য সংখ্যার পূর্ণসংখ্যার জন্য আমি অ্যাড-টু-আপ আইডিয়াটি পছন্দ করি।
পিটার কর্ডেস

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

37

কেন এত জটিল? আপনি একটি পূর্ণসংখ্যার জন্য জিজ্ঞাসা ফাইলটিতে না?

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

ম্যাক্সিন্ট বা কোনও কিছুতে আঘাত করার ঝুঁকি নেই, কারণ নিয়ম অনুসারে, অ্যালগরিদমের দ্বারা পূর্ণসংখ্যার আকার বা সংখ্যার উপর কোনও সীমাবদ্ধতা নেই।


4
এই ফাইলটি সর্বাধিক সম্ভাব্য ফাইলটিতে না থাকলে এটি কাজ করবে ... যা সম্পূর্ণ সম্ভব ...
পিয়ারসন আর্টফোটো

13
নিয়মগুলি নির্দিষ্ট করে না যে এটি 32 বিট বা bit৪ বিট বা অন্য কোনও কিছু, তাই নির্দিষ্ট বিধি অনুসারে কোনও সর্বাধিক কোনও ইন্ট্রিজ নেই। পূর্ণসংখ্যা একটি কম্পিউটার শব্দ নয়, এটি একটি গণিত শব্দ যা ইতিবাচক বা নেতিবাচক পুরো সংখ্যা চিহ্নিত করে।
পিট

যথেষ্ট সত্য, তবে কেউ এটি ধরে নিতে পারে না যে এটি একটি bit৪ বিট সংখ্যা, বা কেউ এ জাতীয় অ্যালগরিদমকে বিভ্রান্ত করার জন্য সর্বাধিক সংখ্যায় স্নিগ্ধ করবে না।
পিয়ারসন আর্টফোটো

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

32

বাইনারি অনুসন্ধানের বৈকল্পিক ব্যবহার করে এটি খুব অল্প জায়গায় সমাধান করা যেতে পারে।

  1. সংখ্যার অনুমোদিত পরিসীমার সঙ্গে বন্ধ শুরু করুন, 0করতে 4294967295

  2. মিডপয়েন্টটি গণনা করুন।

  3. মিডপয়েন্টের মানের চেয়ে কম বা সমান কত নম্বর ছিল তা গণনা করে ফাইলটির মধ্য দিয়ে লুপ করুন।

  4. যদি সংখ্যা সমান না হয়, আপনি সম্পন্ন করেছেন। মিডপয়েন্ট নম্বরটি উত্তর।

  5. অন্যথায়, সর্বাধিক সংখ্যাযুক্ত ব্যাপ্তিটি নির্বাচন করুন এবং এই নতুন ব্যাপ্তির সাথে দ্বিতীয় ধাপে পুনরাবৃত্তি করুন।

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

এটি মূলত হেনিংয়ের সমাধান হিসাবে একই , এটি 16 কে এর পরিবর্তে দুটি বাইন ব্যবহার করে।


2
প্রদত্ত প্যারামিটারগুলির জন্য অনুকূলকরণ শুরু করার আগে এটিই আমি শুরু করেছি।
hmakholm

@ হেনিং: দুর্দান্ত এটি একটি অ্যালগরিদমের একটি দুর্দান্ত উদাহরণ যেখানে স্থান-কাল ট্রেডঅফকে টুইঙ্ক করা সহজ।
হামার

@ হ্যামার, তবে সেই সংখ্যাগুলি যদি একাধিকবার প্রদর্শিত হয় তবে কী হবে?
অ্যালকোট

@ অ্যালকোট: তারপরে অ্যালগরিদম স্পার্সার বিনের পরিবর্তে ডেনসার বিনটি বেছে নেবে, তবে কবুতরের নীতি অনুসারে এটি কখনও সম্পূর্ণ পূর্ণ বাক্স বাছাই করতে পারে না। (দুইটি সংখ্যার মধ্যে ছোটটি সর্বদা বিন পরিসরের তুলনায় কম থাকবে
পিটার কর্ডেস

27

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


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

((2³²-1) / 2³²) ⁴ ⁰⁰⁰ ⁰⁰⁰ ⁰⁰⁰ ≈ .4

শ্যানন এন্ট্রপি যত কম হবে, এই সম্ভাবনাটি গড়ের তুলনায় তত বেশি হয়, তবে এমনকি এই নিকৃষ্টতম পরিস্থিতির জন্যও আমরা এলোমেলোনা পূর্ণসংখ্যার সাথে 5 অনুমানের পরে একটি ননক্রাক্রিং নম্বর খুঁজে পাওয়ার 90% সম্ভাবনা রয়েছে। একটি সিউডোর্যান্ডম জেনারেটর দিয়ে কেবল এই জাতীয় সংখ্যা তৈরি করুন, তাদের একটি তালিকাতে সঞ্চয় করুন। তারপরে ইনট পড়ুন এবং এটিকে আপনার সমস্ত অনুমানের সাথে তুলনা করুন। কোনও মিল থাকলে এই তালিকার এন্ট্রিটি সরিয়ে দিন। সমস্ত ফাইলের মধ্যে দিয়ে যাওয়ার পরে, আপনার একাধিক অনুমানের সম্ভাবনা রয়েছে। এগুলির যে কোনও একটি ব্যবহার করুন। বিরল (10% এমনকি সবচেয়ে খারাপ ক্ষেত্রে) কোনও অনুমান باقی না থাকার ক্ষেত্রে, এলোমেলো পূর্ণসংখ্যার একটি নতুন সেট পান, সম্ভবত এবার আরও বেশি (10-> 99%)।

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


প্রকৃত নিকৃষ্টতম পরিস্থিতি, যখন আমরা স্থির বন্টন ধরে নিই না , তখন প্রতিটি পূর্ণসংখ্যার সর্বাধিক ঘটে। একবার, কারণ তখন কেবল 1 - 4000000000 / 2³² all 6% সমস্ত পূর্ণসংখ্যার ফাইলটি ঘটে না। সুতরাং আপনার আরও কিছু অনুমানের প্রয়োজন হবে তবে এটির জন্য এখনও ক্ষতিকারক পরিমাণে মেমরির দাম পড়বে না।


5
আমি অন্য কাউকে এ সম্পর্কে ভাবতে দেখে আনন্দিত, তবে কেন এখানে নীচে রয়েছে? এটি 1-পাস অ্যালগো ... 2.5 এমবি অনুমানের জন্য 10 এমবি যথেষ্ট এবং 93% ^ 2.5M ≈ 10 ^ -79000 সত্যিই দ্বিতীয় স্ক্যানের প্রয়োজনের একটি নগণ্য সুযোগ। বাইনারি অনুসন্ধানের ওভারহেডের কারণে, আপনি যদি কম অনুমান ব্যবহার করেন তবে এটি দ্রুত হয়! এটি সময় এবং স্থান উভয় ক্ষেত্রেই অনুকূল।
পোটোটোভটার

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

1
@ পোটাটোসওয়াতর বেন হ্যালের সমতুল্য উত্তর শীর্ষে পৌঁছেছে
ব্রায়ান গর্ডন

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

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

25

[0, 2 ^ x - 1] এর ব্যাপ্তি থেকে যদি আপনার একটি পূর্ণসংখ্যার অনুপস্থিত থাকে তবে কেবলমাত্র তাদের সকলকে একসাথে জোর করুন। উদাহরণ স্বরূপ:

>>> 0 ^ 1 ^ 3
2
>>> 0 ^ 1 ^ 2 ^ 3 ^ 4 ^ 6 ^ 7
5

(আমি জানি এটি প্রশ্নের সঠিক উত্তর দেয় না , তবে এটি একটি খুব অনুরূপ প্রশ্নের উত্তরের উত্তর))


1
হ্যাঁ, এটি প্রমাণ করা সহজ [ ] যা যখন কোনও পূর্ণসংখ্য অনুপস্থিত তখন কাজ করে তবে একাধিকটি নিখোঁজ থাকলে এটি প্রায়শই ব্যর্থ হয়। উদাহরণস্বরূপ, 0 ^ 1 ^ 3 ^ 4 ^ 6 ^ 70 হয়। [ 2 থেকে x'th পাওয়ারের জন্য 2 x লিখছেন, এবং একটি xor খের জন্য a ^ b, সমস্ত কে <2 x এর xor শূন্য - কে ^ ~ কে = (2 ^ x) - কে <2 ^ (এক্স -1) এর জন্য 1, এবং কে ^ ~ কে ^ জে ^ ~ জে = 0 যখন জে = কে + ২ ** (এক্স -২) - সুতরাং এক সংখ্যার ব্যতীত সকলের জোর মান নিখোঁজ হওয়া একজনের]
জেমস ওয়াল্ডবি - jwpat7

2
আমি যেমন আর্কমেক্সেলের জবাবে একটি মন্তব্যে উল্লেখ করেছি: সমস্যাটি "একটি সংখ্যা অনুপস্থিত" বলে না, এটি ফাইলের 4 বিলিয়ন সংখ্যার অন্তর্ভুক্ত নয় এমন একটি সংখ্যা খুঁজে বের করার জন্য বলেছে। আমরা যদি 32-বিট পূর্ণসংখ্যা ধরে নিই, তবে প্রায় 300 মিলিয়ন নম্বর ফাইলটি থেকে হারিয়ে যেতে পারে। অনুপস্থিত সংখ্যার সাথে মেলে উপস্থিত সংখ্যার জোরের সম্ভাবনা প্রায় 7%।
জেমস ওয়াল্ডবি - jwpat7

আমি প্রথমদিকে প্রশ্নটি পড়ার সময় আমি এই উত্তরটিই ভাবছিলাম, তবে কাছাকাছি পরিদর্শন করার সময় আমি মনে করি যে প্রশ্নটি এর চেয়ে আরও স্পষ্ট। এফওয়াইআই, এই প্রশ্নটিই আমি ভাবছিলাম: স্ট্যাকওভারফ্লো.com
লি নেদারটন

18

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


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

@ ক্রিস্টোফার ব্লুম ফিল্টারগুলির সম্পর্কে আমার বোঝা হল যে আপনি 100% না পৌঁছানো পর্যন্ত আপনি একটি পূর্ণ বিট্রেই পাবেন না
পল

... অন্যথায় আপনি মিথ্যা নেতিবাচক পেতে চাইবেন।
পল

@ পল একটি ভরাট বিট অ্যারে আপনাকে মিথ্যা ধনাত্মক মান দেয়, যা অনুমোদিত। এক্ষেত্রে ব্লুম ফিল্টারটি সম্ভবত সেই ক্ষেত্রে অধঃপতিত হবে যেখানে সমাধানটি, যা নেতিবাচক হবে, একটি মিথ্যা ইতিবাচক প্রত্যাবর্তন করে।
ataylor

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

17

মূল প্রশ্নের বর্তমান শব্দের উপর ভিত্তি করে, সহজ সমাধানটি হ'ল:

ফাইলটিতে সর্বাধিক মান সন্ধান করুন, তারপরে এটিতে 1 যুক্ত করুন।


5
MAXINT যদি ফাইলটিতে অন্তর্ভুক্ত থাকে তবে কী হবে?
পেট্র পেলার

@ পেটার পেলার: একটি বড় লাইব্রেরি মূলত পূর্ণসংখ্যার আকারের সীমাবদ্ধতাগুলি সরিয়ে ফেলবে।
অস্টারওয়াল

2
@ ওস্টারওয়াল, যদি এই উত্তরটির অনুমতি দেওয়া হয় তবে তার চেয়ে আপনার ফাইলটি পড়ার দরকার নেই - কেবল যতটা সম্ভব প্রিন্ট করুন।
নাকিলন

1
@ ওস্টারওয়াল, যদি আপনার এলোমেলো বিশাল সংখ্যা আপনি মুদ্রণ করতে পারেন এবং এটি ফাইলের মধ্যে থাকে তবে এই কাজটি সমাধান করা যায় না।
নাকিলন

3
@ নকিলন: +1 আপনার পয়েন্টটি নেওয়া হয়েছে। এটি মোটামুটি ফাইলের অঙ্কের সংখ্যা নির্ধারণ এবং সেই বহু অঙ্ক সহ একটি সংখ্যা মুদ্রণের সমান।
ওস্টারওয়াল

14

ব্যবহার করা BitSet । 4 বিলিয়ন পূর্ণসংখ্যা (2 ^ 32 পূর্ণসংখ্যার মান ধরে নেওয়া) 8 প্রতি বাইটে বিটসেটে প্যাক করা 2 ^ 32/2 ^ 3 = 2 ^ 29 = প্রায় 0.5 গিগাবাইট।

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

আসলে বিটসেট.নেক্সটক্রিয়াবিট (0) আপনাকে প্রথম অ-সেট বিট বলবে।

বিটসেট এপিআইয়ের দিকে তাকালে এটি কেবল 0..MAX_INT সমর্থন করে বলে মনে হয়, সুতরাং আপনার কাছে 2 বিটসেটের প্রয়োজন হতে পারে - একটির জন্য + 'নম্বর এবং একটির জন্য আছে - তবে মেমরির প্রয়োজনীয়তা পরিবর্তন হয় না।


1
অথবা আপনি যদি BitSet... ব্যবহার করতে না চান তবে বিটের একটি অ্যারে ব্যবহার করে দেখুন। একই জিনিস;)
jcolebrand

12

যদি কোনও আকারের সীমা না থাকে, দ্রুততম উপায় হ'ল ফাইলটির দৈর্ঘ্য নেওয়া এবং এলোমেলো অঙ্কের ফাইলের দৈর্ঘ্য +1 সংখ্যার উত্পন্ন করা (বা কেবল "11111 ..." গুলি)। সুবিধা: আপনার এমনকি ফাইলটি পড়ার দরকার নেই এবং আপনি মেমরির ব্যবহার প্রায় শূন্য করতে পারেন im অসুবিধা: আপনি কোটি কোটি অঙ্ক মুদ্রণ করবেন।

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


11

যদি আমরা ধরে নিই যে সংখ্যার ব্যাপ্তি সর্বদা 2 ^ n (2 এর সমান শক্তি) হবে তবে এক্সক্লুসিভ-বা কাজ করবে (অন্য পোস্টার হিসাবে দেখানো হয়েছে)। যতদূর কেন, আসুন এটি প্রমাণ করুন:

তত্ত্বটি

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

প্রমাণ

আসুন এন = ২ দেখুন n

  • 0 - 00
  • 1 - 01
  • 2 - 10
  • 3 - 11

এখন, আমরা যদি দেখি, প্রতিটি বিট ঠিক দু'বার সেট করা আছে। সুতরাং, যেহেতু এটি একটি বহু সংখ্যক সময় নির্ধারণ করা হয়েছে, এবং একচেটিয়া-বা সংখ্যার থেকে ০ ফলবে a ০. সুতরাং, অনুপস্থিত সংখ্যা এবং ফলাফলটি একচেটিয়া-আকৃতির সংখ্যা হুবহু একই। আমরা যদি 2 টি সরিয়ে ফেলি, তবে ফলাফলটি Xor হবে10 (বা 2) হবে।

এখন, এন + 1 দেখুন। আসুন বার প্রতিটি বিট সেট করা হয় এর নম্বরে কল n, xএবং বার প্রতিটি বিট সেট করা হয় সংখ্যা n+1 y। এর মান yসমান হবে y = x * 2কারণ আছে xউপাদানের n+10 বিট সেট করুন এবং xউপাদানের n+11. বিট সেট যেহেতু 2xসবসময় এমনকি হবে, n+1সবসময় একে বিট সময়ের একটি এমনকি সংখ্যা নির্ধারণ করে দিতে হবে।

সুতরাং, যেহেতু n=2কাজ করে, এবং n+1কাজ করে, xor পদ্ধতিটি সমস্ত মানের জন্য কাজ করবে n>=2

0 ভিত্তিক ব্যাপ্তির জন্য অ্যালগরিদম

এটি বেশ সহজ। এটি মেমরির 2 * n বিট ব্যবহার করে, সুতরাং যে কোনও ব্যাপ্তির জন্য <= 32, 2 32 বিট পূর্ণসংখ্যা কাজ করবে (ফাইল বর্ণনাকারীর দ্বারা গ্রাহিত কোনও স্মৃতি উপেক্ষা করে)। এবং এটি ফাইলটির একক পাস করে।

long supplied = 0;
long result = 0;
while (supplied = read_int_from_file()) {
    result = result ^ supplied;
}
return result;

সালিশ ভিত্তিক রেঞ্জের জন্য অ্যালগরিদম

এই অ্যালগরিদম যে কোনও প্রারম্ভিক সংখ্যার যে কোনও শেষের সংখ্যার রেঞ্জের জন্য কাজ করবে, যতক্ষণ না মোট ব্যাপ্তি 2 ^ n এর সমান হয় ... এটি মূলত সর্বনিম্ন 0 এ রেঞ্জটিকে বেস করে দেয় তবে এটিতে 2 পাসের প্রয়োজন হয় না ফাইলের মাধ্যমে (সর্বনিম্ন হ'ল প্রথমটি, দ্বিতীয়টি নিখোঁজ হওয়া গণনা করা)

long supplied = 0;
long result = 0;
long offset = INT_MAX;
while (supplied = read_int_from_file()) {
    if (supplied < offset) {
        offset = supplied;
    }
}
reset_file_pointer();
while (supplied = read_int_from_file()) {
    result = result ^ (supplied - offset);
}
return result + offset;

স্বেচ্ছাসেবী রেঞ্জ

আমরা এই পরিবর্তিত পদ্ধতিটি স্বেচ্ছাচারী রেঞ্জের সেটগুলিতে প্রয়োগ করতে পারি, যেহেতু সমস্ত ব্যাপ্তি কমপক্ষে একবারে 2 ^ n এর শক্তি অতিক্রম করবে। এটি কেবলমাত্র একটিমাত্র অনুপস্থিত বিট থাকলে কাজ করে। এটি একটি অপ্রচলিত ফাইলের 2 পাস লাগে, তবে এটি প্রতিবারই একক অনুপস্থিত নম্বরটি খুঁজে পাবে:

long supplied = 0;
long result = 0;
long offset = INT_MAX;
long n = 0;
double temp;
while (supplied = read_int_from_file()) {
    if (supplied < offset) {
        offset = supplied;
    }
}
reset_file_pointer();
while (supplied = read_int_from_file()) {
    n++;
    result = result ^ (supplied - offset);
}
// We need to increment n one value so that we take care of the missing 
// int value
n++
while (n == 1 || 0 != (n & (n - 1))) {
    result = result ^ (n++);
}
return result + offset;

মূলত, 0 এর কাছাকাছি ব্যাপ্তিকে পুনরায় বেস করে Then তারপরে, এটি একচেটিয়া-বা গণনা করার সাথে সাথে সংযুক্ত থাকা মানযুক্ত সংখ্যাকে গণনা করে। তারপরে, এটি অনুপস্থিত মানটির যত্ন নিতে নিরবচ্ছিন্ন মানগুলিতে 1 যোগ করে (নিখোঁজটিকে গণনা করুন)। তারপরে, এন মানকে জোরে রাখুন, প্রতি বার 1 দ্বারা বাড়িয়ে এন এর 2 পাওয়ার হয় যতক্ষণ না ফলাফলটি মূল ভিত্তিতে পুনরায় ভিত্তি করা হয়। সম্পন্ন.

আমি পিএইচপিতে পরীক্ষিত অ্যালগরিদম এখানে (কোনও ফাইলের পরিবর্তে অ্যারে ব্যবহার করে, তবে একই ধারণাটি):

function find($array) {
    $offset = min($array);
    $n = 0;
    $result = 0;
    foreach ($array as $value) {
        $result = $result ^ ($value - $offset);
        $n++;
    }
    $n++; // This takes care of the missing value
    while ($n == 1 || 0 != ($n & ($n - 1))) {
        $result = $result ^ ($n++);
    }
    return $result + $offset;
}

যে হারটি অনুপস্থিত রয়েছে তার সাথে কোনও মানের পরিসর (আমি নেতিবাচকগুলি সহ পরীক্ষা করেছি) দিয়ে একটি অ্যারেতে খাওয়ানো হয়েছিল, এটি প্রতিবার সঠিক মান খুঁজে পেয়েছে।

আরেকটি পন্থা

যেহেতু আমরা বাহ্যিক বাছাই করতে পারি, তাই কেন কেবল একটি ফাঁক পরীক্ষা করা যায় না? যদি আমরা ধরে নিই যে এই অ্যালগরিদমটি চালানোর আগে ফাইলটি সাজানো হয়েছে:

long supplied = 0;
long last = read_int_from_file();
while (supplied = read_int_from_file()) {
    if (supplied != last + 1) {
        return last + 1;
    }
    last = supplied;
}
// The range is contiguous, so what do we do here?  Let's return last + 1:
return last + 1;

3
সমস্যাটি "একটি সংখ্যা অনুপস্থিত" বলে না, এটি ফাইলের 4 বিলিয়ন সংখ্যার অন্তর্ভুক্ত নয় এমন একটি সংখ্যা খুঁজে বের করার জন্য বলেছে। আমরা যদি 32-বিট পূর্ণসংখ্যা ধরে নিই, তবে প্রায় 300 মিলিয়ন নম্বর ফাইলটি থেকে হারিয়ে যেতে পারে। অনুপস্থিত সংখ্যার সাথে মেলে উপস্থিত সংখ্যার জোরের সম্ভাবনা প্রায় 7%।
জেমস ওয়াল্ডবি - jwpat7

যদি আপনার কাছে একটি সংক্ষিপ্ত-তবে-মিসিং-ওপেন থাকে যা শূন্য-ভিত্তিক নয়, তবে জোরের পরিবর্তে যুক্ত করুন। sum(0..n) = n*(n+1)/2। তাই missing = nmax*(nmax+1)/2 - nmin*(nmin+1)/2 - sum(input[])। (@ হামার উত্তর থেকে সংক্ষিপ্ত ধারণা।)
পিটার

9

কৌতুক প্রশ্ন, যদি না এটি যথাযথভাবে উদ্ধৃত করা হয়। সর্বাধিক পূর্ণসংখ্যার জন্য একবার ফাইলটি পড়ুন nএবং ফিরে যান n+1

n+1কোনও পূর্ণসংখ্যার অতিরিক্ত প্রবাহের ক্ষেত্রে অবশ্যই আপনার একটি ব্যাকআপ পরিকল্পনা প্রয়োজন ।


3
এখানে এমন একটি সমাধান রয়েছে যা কার্যকর হয় ... যখন তা না করে। দরকারী! :-)
dty

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

9

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

void maxNum(ulong filesize)
{
    ulong bitcount = filesize * 8; //number of bits in file

    for (ulong i = 0; i < bitcount; i++)
    {
        Console.Write(9);
    }
}

10 টি বিটকাউন্ট - 1 মুদ্রণ করা উচিত , যা সর্বদা 2 বিটক্টের বেশি হবে । প্রযুক্তিগতভাবে, আপনার যে সংখ্যাটি হারাতে হবে তা 2 বিটকাউন্ট - (4 * 10 9 - 1) , যেহেতু আপনি জানেন যে ফাইলটিতে (4 বিলিয়ন - 1) অন্যান্য পূর্ণসংখ্যা রয়েছে, এবং এমনকি নিখুঁত সংকোচনের সাথে তারা কমপক্ষে গ্রহণ করবে এক বিট প্রতিটি।


শুধু Console.Write( 1 << bitcount )লুপের পরিবর্তে কেন নয় ? যদি ফাইলটিতে এন বিট থাকে তবে শীর্ষস্থানীয় 1 সহ যে কোনও (_n_ + 1) -বিট নম্বর একেবারে বড় হওয়ার গ্যারান্টিযুক্ত।
এমমেট

@ এমমেট - ফাইলটি কোনও ইন্টির আকারের চেয়ে ছোট (সি # তে 4 বাইট) না হলে এটি কেবল পূর্ণসংখ্যার উপচে পড়বে। সি ++ আপনাকে আরও বড় কিছু ব্যবহার করতে দেয়, তবে সি # <<অপারেটরের সাথে 32-বিট ইন্টস ছাড়া আর কিছু করার অনুমতি দেয় বলে মনে হচ্ছে না । যে কোনও উপায়ে, আপনি যদি নিজের বিশালাকার পূর্ণসংখ্যার প্রকারটি রোল না করেন তবে এটি একটি খুব ছোট ফাইলের আকার হতে চলেছে। ডেমো: rextester.com/BLETJ59067
জাস্টিন মরগান

8
  • সবচেয়ে সহজ পদ্ধতির মধ্যে রয়েছে ফাইলটিতে ন্যূনতম সংখ্যাটি খুঁজে পাওয়া এবং এর চেয়ে কম 1 ফিরে আসা। এটি ও (1) স্টোরেজ এবং এন সংখ্যার একটি ফাইলের জন্য ও (এন) সময় ব্যবহার করে। তবে এটির সংখ্যা ব্যর্থতা সীমিত থাকলে ব্যর্থ হবে, যা ন্যূনতম -1-নন-এ-সংখ্যা তৈরি করতে পারে।

  • বিটম্যাপ ব্যবহারের সহজ ও সরল পদ্ধতি ইতিমধ্যে উল্লেখ করা হয়েছে। এই পদ্ধতিতে ও (এন) সময় এবং স্টোরেজ ব্যবহার করা হয়।

  • 2 ^ 16 গণনা-বালতি সহ একটি 2-পাস পদ্ধতিও উল্লেখ করা হয়েছে। এটি 2 * n পূর্ণসংখ্যা পড়ায় তাই ও (এন) সময় এবং ও (1) স্টোরেজটি ব্যবহার করে তবে এটি 2 ^ 16 টির বেশি সংখ্যার সাথে ডেটাসেটগুলি পরিচালনা করতে পারে না। তবে এটি সহজেই 2 এর পরিবর্তে 4 পাস চালিয়ে 2 ^ 60 64-বিট পূর্ণসংখ্যায় প্রসারিত হয় এবং সহজেই মেমরির উপযুক্ত ফিট হিসাবে অনেকগুলি বিন ব্যবহার করে এবং পাসের সংখ্যাকে যথাযথভাবে বৃদ্ধি করে ক্ষুদ্র মেমরিটি সহজেই মানিয়ে নেওয়া হয় কোন ক্ষেত্রে রান সময় আর ও (এন) নয় বরং পরিবর্তে ও (এন * লগ এন)।

  • Ltn100 দ্বারা নির্দেশিত হিসাবে স্ট্রোকভারফ্লো # 35185-এ জিজ্ঞাসা করা প্রশ্নের উত্তর দেয় যেহেতু এখন পর্যন্ত rfrankel দ্বারা এবং দৈর্ঘ্যে আইক্রমেক্সেল দ্বারা উল্লিখিত সমস্ত সংখ্যার একসাথে XOR'ing করার পদ্ধতি । এটি ও (1) স্টোরেজ এবং ও (এন) রান সময় ব্যবহার করে। এই মুহুর্তের জন্য যদি আমরা 32-বিট পূর্ণসংখ্যা ধরে নিই তবে এক্সওরটির একটি স্বতন্ত্র সংখ্যা উত্পাদন করার 7% সম্ভাবনা রয়েছে। যৌক্তিক: প্রদত্ত ~ 4G স্বতন্ত্র সংখ্যাগুলি একসাথে এবং সিএ প্রদান করেছে। 300 এম ফাইল এ নয়, প্রতিটি বিট পজিশনে সেট বিটের সংখ্যার বিজোড় বা এমনকি হওয়ার সমান সম্ভাবনা রয়েছে। সুতরাং, 2 ^ 32 সংখ্যার এক্সওআর ফলাফল হিসাবে উত্থানের সমান সম্ভাবনা রয়েছে, যার মধ্যে 93% ইতিমধ্যে ফাইলটিতে রয়েছে। মনে রাখবেন যে যদি ফাইলের নম্বরগুলি পৃথক না হয় তবে এক্সওআর পদ্ধতির সাফল্যের সম্ভাবনা বেড়ে যায়।


7

কিছু কারণে, এই সমস্যাটি পড়ার সাথে সাথে আমি তির্যককরণের কথা ভাবি। আমি নির্বিচারে বড় পূর্ণসংখ্যা ধরে নিচ্ছি।

প্রথম নম্বর পড়ুন। আপনার 4 বিলিয়ন বিট না হওয়া পর্যন্ত এটি শূন্য বিট সহ বাম-প্যাড করুন। প্রথম (উচ্চ-অর্ডার) বিট যদি 0 হয়, আউটপুট 1; অন্য আউটপুট ০। এই ভাবে ফাইলের মাধ্যমে চালিয়ে যান। আপনি একবারে 4 বিলিয়ন বিট সংখ্যা এক বিট আউটপুট পাবেন এবং সেই সংখ্যাটি ফাইলের মতো হবে না। প্রুফ: এটি নবম সংখ্যার সমান ছিল, তারপরে তারা নবম বিটে একমত হবেন, তবে তারা নির্মাণের মাধ্যমে তা করেন না।


সৃজনশীলতার জন্য +1 (এবং একক পাসের সমাধানের জন্য এখনও সর্বকালের সবচেয়ে খারাপতম কেস আউটপুট)।
হামাখোলম

তবে 4 টি বিলিয়ন বিটগুলি তির্যক করার জন্য নেই, কেবল 32 টি রয়েছে You 32 বিট সংখ্যাটি আপনি শেষ করতে পারবেন যা তালিকার প্রথম 32 নম্বর থেকে আলাদা।
ব্রায়ান গর্ডন

@ হেনিং এটি একটিই পাস খুব কমই; আপনাকে এখনও আনারি থেকে বাইনারি রূপান্তর করতে হবে। সম্পাদনা: ভাল আমি অনুমান করি এটি ফাইলের এক পাস। কিছু মনে করো না.
ব্রায়ান গর্ডন

@ ব্রায়ান, এখানে "আনরি" কিছু আছে? উত্তরটি একবারে বাইনারি উত্তর তৈরি করছে এবং এটি কেবল একবার ইনপুট ফাইলটি পড়ে, একে একক পাস করে। (যদি দশমিক আউটপুট প্রয়োজন হয় তবে জিনিসগুলি সমস্যাযুক্ত হয়ে উঠবে - তবে আপনি সম্ভবত তিনটি ইনপুট সংখ্যায় এক দশমিক অঙ্ক তৈরির চেয়ে ভাল এবং আউটপুট সংখ্যার লগতে 10% বৃদ্ধি গ্রহণ করবেন)।
এইচএমখোলম

2
@ হেনিং সমস্যাটি নির্বিচারে বড় পূর্ণসংখ্যার জন্য অর্থবোধ করে না কারণ অনেক লোক উল্লেখ করেছেন যে, সর্বাধিক সংখ্যক সন্ধান করা এবং একটি সংযুক্ত করা, বা ফাইলের বাইরে খুব দীর্ঘ সংখ্যক নির্মাণ করা তুচ্ছ। এই তির্যক সমাধানটি বিশেষত অনুপযুক্ত কারণ iআপনি কেবলমাত্র 1 বিট 4 বিলিয়ন বার আউটপুট পেতে পারেন এবং শেষে আরও 1 নিক্ষেপ করতে পারেন the আমি অ্যালগোরিদমে নির্বিচারে বড় পূর্ণসংখ্যার সাথে ঠিক আছি তবে আমি মনে করি যে সমস্যাটি অনুপস্থিত 32-বিট পূর্ণসংখ্যাকে আউটপুট করা। এটি অন্য কোনও উপায়ে বোঝায় না।
ব্রায়ান গর্ডন

6

কোনও পূর্ণসংখ্যা উপস্থিত রয়েছে কিনা তা চিহ্নিত করতে আপনি বিট পতাকা ব্যবহার করতে পারেন।

পুরো ফাইলটি ট্র্যাভার করার পরে, নম্বরটি উপস্থিত রয়েছে কিনা তা নির্ধারণ করতে প্রতিটি বিট স্ক্যান করুন।

প্রতিটি পূর্ণসংখ্যা 32 বিট হিসাবে ধরে নেওয়া, বিট ফ্ল্যাগিং করা গেলে এগুলি 1 জিবি র‌্যামে সুবিধামত ফিট হবে।


0.5 গিগাবাইট, যদি না আপনি 4 বিট ;-) হিসাবে বাইটকে নতুন সংজ্ঞা দিয়ে থাকেন
dty

2
@ ডিটি আমি মনে করি তার অর্থ "স্বাচ্ছন্দ্যে", যেমন 1 জিবিতে প্রচুর জায়গা থাকবে।
কর্সিকা

6

ফাইল থেকে সাদা স্থান এবং অ-সংখ্যাযুক্ত অক্ষরগুলি স্ট্রিপ করুন এবং সংযোজন ১। আপনার ফাইলটিতে এখন মূল ফাইলটিতে তালিকাভুক্ত নয় এমন একক সংখ্যা রয়েছে।

কার্বনেটেক দ্বারা রেডডিট থেকে।


এটা ভালবাসা! যদিও এটি তিনি যে উত্তরটি সন্ধান করছিলেন তা পুরোপুরি না হলেও ...: ডি
জোহান ডু টোইট

6

কেবলমাত্র সম্পূর্ণতার জন্য, এখানে আরও একটি সহজ সমাধান রয়েছে, যা সম্ভবত চালাতে খুব দীর্ঘ সময় নিবে, তবে খুব কম স্মৃতি ব্যবহার করে।

সমস্ত সম্ভাব্য পূর্ণসংখ্যার পরিসীমা হতে int_minপারে int_maxএবং bool isNotInFile(integer)একটি ফাংশন যা সত্যটি প্রত্যাবর্তন করে যদি ফাইলটিতে একটি নির্দিষ্ট পূর্ণসংখ্যা এবং অন্য কোনও মিথ্যা থাকে না (ফাইলের প্রতিটি পূর্ণসংখ্যার সাথে সেই নির্দিষ্ট পূর্ণসংখ্যার তুলনা করে)

for (integer i = int_min; i <= int_max; ++i)
{
    if (isNotInFile(i)) {
        return i;
    }
}

প্রশ্নটি ঠিক isNotInFileফাংশনের জন্য অ্যালগরিদম সম্পর্কে ছিল । উত্তর দেওয়ার আগে দয়া করে প্রশ্নটি বুঝতে পেরেছেন তা নিশ্চিত করুন।
আলেকস জি

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

আমি মনে করি এটি একটি বৈধ উত্তর। I / O ব্যতীত আপনার কেবল একটি পূর্ণসংখ্যার এবং বুল পতাকা দরকার।
ব্রায়ান গর্ডন

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

1
@ আলেক্স জি - ঠিক আছে। আমি কখনও বলিনি যে আপনি এটিও বলেছেন। আমরা কেবলমাত্র বলি যে ইসনটআইনফাইলে তুচ্ছভাবে ফাইলের একটি লুপ ব্যবহার করে প্রয়োগ করা যেতে পারে: খুলুন; ইওফ না থাকাকালীন পড়ুন; পূর্ণসংখ্যক পড়ুন; মিথ্যা ফিরিয়ে দিন যদি পূর্ণসংখ্যা = i; অন্য চালিয়ে যান; Continue। এটির স্মৃতি মাত্র 4 বাইট প্রয়োজন।
সাইমন মউরিয়ার

5

10 এমবি মেমরির সীমাবদ্ধতার জন্য:

  1. সংখ্যাটিকে তার বাইনারি উপস্থাপনায় রূপান্তর করুন।
  2. বাইনারি ট্রি তৈরি করুন যেখানে বাম = 0 এবং ডান = 1।
  3. গাছের প্রতিটি বাইনারি উপস্থাপনা ব্যবহার করে প্রতিটি সংখ্যা োকান।
  4. যদি একটি নম্বর ইতিমধ্যে sertedোকানো হয় তবে পাতাগুলি ইতিমধ্যে তৈরি করা হবে।

শেষ হয়ে গেলে, অনুরোধ করা নম্বরটি তৈরি করার জন্য আগে তৈরি করা হয়নি এমন কোনও পথ ধরুন।

4 বিলিয়ন সংখ্যা = 2 ^ 32, যার অর্থ 10 এমবি পর্যাপ্ত নাও হতে পারে।

সম্পাদনা

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

দ্বিতীয় সম্পাদনা

পুরোপুরি গাছটিও তৈরি করার দরকার নেই। সংখ্যাগুলি সমান হলে আপনার কেবল গভীর শাখা তৈরি করতে হবে। আমরা যদি শাখাগুলিও কাটা করি, তবে এই সমাধানটি বাস্তবে কার্যকর হতে পারে।


6
... এবং এটি কীভাবে 10 এমবিতে ফিট করবে?
hmakholm

কীভাবে: বিটিরির গভীরতা এমন কিছুতে সীমাবদ্ধ করুন যা 10 এমবিতে মাপসই হয়; এর অর্থ হ'ল সেটটিতে ফল পাবেন {মিথ্যা পজিটিভ | ধনাত্মক} এবং আপনি এটির মাধ্যমে পুনরাবৃত্তি করতে পারেন এবং অন্যান্য কৌশলগুলি মান সন্ধান করতে পারেন।
জোনাথন ডিকিনসন

5

আমি 1 জিবি সংস্করণটির উত্তর দেব:

প্রশ্নে পর্যাপ্ত তথ্য নেই, তাই আমি প্রথমে কিছু অনুমানগুলি বর্ণনা করব:

পূর্ণসংখ্যা -2,147,483,648 থেকে 2,147,483,647 পরিসীমা সহ 32 বিট।

সুডোকোড:

var bitArray = new bit[4294967296];  // 0.5 GB, initialized to all 0s.

foreach (var number in file) {
    bitArray[number + 2147483648] = 1;   // Shift all numbers so they start at 0.
}

for (var i = 0; i < 4294967296; i++) {
    if (bitArray[i] == 0) {
        return i - 2147483648;
    }
}

4

যতক্ষণ আমরা সৃজনশীল উত্তরগুলি করছি, এখানে অন্য একটি রয়েছে।

সংখ্যায় ইনপুট ফাইলটি বাছাই করতে বাহ্যিক সাজানোর প্রোগ্রামটি ব্যবহার করুন। এটি আপনার যে কোনও পরিমাণ মেমরির জন্য কাজ করবে (এটি প্রয়োজনে ফাইল স্টোরেজ ব্যবহার করবে)। বাছাই করা ফাইলটি পড়ুন এবং অনুপস্থিত যে প্রথম সংখ্যাটি আউটপুট করুন।


3

বিট নির্মূল

একটি উপায় হ'ল বিটগুলি মুছে ফেলা, তবে এটি সম্ভবত কোনও ফল দিতে পারে না (সম্ভাবনাগুলি এটি হয় না)। Psuedocode:

long val = 0xFFFFFFFFFFFFFFFF; // (all bits set)
foreach long fileVal in file
{
    val = val & ~fileVal;
    if (val == 0) error;
}

বিট গণনা

বিট গুনে রাখুন; এবং মান উত্পন্ন করতে কমপক্ষে পরিমাণে বিট ব্যবহার করুন। আবার এর সঠিক মান উৎপন্ন করার কোনও গ্যারান্টি নেই।

ব্যাপ্তি যুক্তি

অর্ডার করা রেঞ্জের একটি তালিকা (শুরু করে অর্ডার করা) ট্র্যাক রাখুন। কাঠামো দ্বারা একটি পরিসীমা সংজ্ঞায়িত করা হয়:

struct Range
{
  long Start, End; // Inclusive.
}
Range startRange = new Range { Start = 0x0, End = 0xFFFFFFFFFFFFFFFF };

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


3

2 128 * 10 18 + 1 (যা (2 8 ) 16 * 10 18 + 1) - এটি কি আজকের সার্বজনীন উত্তর হতে পারে না? এটি এমন একটি সংখ্যার প্রতিনিধিত্ব করে যা 16 টি EB ফাইলে ধরে রাখা যায় না যা কোনও বর্তমান ফাইল সিস্টেমে সর্বাধিক ফাইলের আকার।


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

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

3

আমি মনে করি এটি একটি সমাধান সমস্যা (উপরে দেখুন), তবে মনে রাখার জন্য একটি আকর্ষণীয় দিক রয়েছে কারণ এটি জিজ্ঞাসা করা হতে পারে:

যদি ঠিক 4,294,967,295 (2 ^ 32 - 1) কোনও পুনরাবৃত্তি না করে 32-বিট পূর্ণসংখ্যা থাকে এবং তাই কেবলমাত্র একটি অনুপস্থিত থাকে, তবে একটি সহজ সমাধান রয়েছে।

মোট রানিং শূন্যে শুরু করুন এবং ফাইলের প্রতিটি পূর্ণসংখ্যার জন্য, inte২-বিট ওভারফ্লো (কার্যকরভাবে, রানটোটাল = (রানটোটাল + নেক্সটইন্টিজার)% 4294967296) দিয়ে সেই পূর্ণসংখ্যাটি যুক্ত করুন। একবার সম্পূর্ণ হয়ে গেলে, চলমান মোটে 4294967296/2 যোগ করুন, আবার 32-বিট ওভারফ্লো দিয়ে। এটি 4294967296 থেকে বিয়োগ করুন, এবং ফলাফলটি অনুপস্থিত পূর্ণসংখ্যা।

"শুধুমাত্র একটি অনুপস্থিত পূর্ণসংখ্যার" সমস্যাটি কেবলমাত্র একটি রান দিয়ে সমাধানযোগ্য এবং কেবলমাত্র 64 টি বিট র‌্যাম ডেটাকে উত্সর্গীকৃত (চলমান মোটের জন্য 32, পরবর্তী সংখ্যায় পড়ার জন্য 32))

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

# Grab the file size
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
# Print a '2' for every bit of the file.
for (c=0; c<sz; c++) {
  for (b=0; b<4; b++) {
    print "2";
  }
}

@ নাকিলন এবং দ্যডি টর্নস মূল প্রশ্নের মন্তব্যে এটি উল্লেখ করেছেন
ব্রায়ান গর্ডন

3

রায়ান যেমনটি এটি বলেছে, ফাইলটি বাছাই করুন এবং তারপরে পূর্ণসংখ্যার উপর দিয়ে যান এবং সেখানে কোনও মান বাদ দেওয়া হয় যখন আপনার কাছে থাকে :)

ডাউনভোটারদের এডিট করুন : ওপি উল্লেখ করেছে যে ফাইলটি বাছাই করা যেতে পারে তাই এটি একটি বৈধ পদ্ধতি।


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

@ আরিয়ান বাহ্যিক বাছাই বেশিরভাগ ক্ষেত্রেই একত্রিতকরণের ধরণ তাই শেষ মার্জটিতে আপনি চেকটি করতে পারেন :)
রাচেট ফ্রিক

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

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

4
@ ক্লাস মার্জ বাছাই এর জন্য ডিজাইন করা হয়েছে
র‌্যাচেট ফ্রিক

2

যদি আপনি 32-বিট প্রতিবন্ধকতা না ধরে থাকেন তবে কেবল এলোমেলোভাবে উত্পন্ন 64-বিট নম্বরটি (বা আপনি যদি হতাশবাদী হন তবে 128-বিট) ফিরিয়ে দিন। সংঘর্ষের সম্ভাবনা 1 in 2^64/(4*10^9) = 4611686018.4(মোটামুটি ৪ বিলিয়নতে 1)। আপনি বেশিরভাগ সময় ঠিক থাকবেন!

(জকিং ... ধরণের।)


আমি দেখতে পাচ্ছি যে ইতিমধ্যে এটির জন্য পরামর্শ দেওয়া হয়েছে :) এই সমস্ত ব্যক্তির জন্য আপগ্রেসগুলি
পিটার গিবসন

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

@ পিটারকর্ডস এলোমেলোভাবে উত্পাদিত 128 বিট সংখ্যা হ'ল ইউআইডিগুলি কীভাবে কাজ করে - এমনকি উইকিপিডিয়া ইউইউডি পৃষ্ঠায়
পিটার গিবসন

বৈকল্পিক: সেটটিতে সর্বাধিক সন্ধান করুন, ১ যোগ করুন
ফিলি

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