প্রদত্ত এলোমেলো সংখ্যা জেনারেটর ব্যবহার করে 1-100 মুদ্রণের জন্য সবচেয়ে দক্ষ অ্যালগরিদম


11

আমাদের একটি এলোমেলো সংখ্যার জেনারেটর দেওয়া হয় RandNum50যা 1-50 পরিসীমাতে অভিন্নভাবে একটি এলোমেলো পূর্ণসংখ্যার উত্পন্ন করে। আমরা কেবল একটি এলোমেলো নম্বর জেনারেটরটি এলোমেলো ক্রমে 1 থেকে 100 পর্যন্ত সমস্ত পূর্ণসংখ্যার উত্পাদন এবং মুদ্রণ করতে ব্যবহার করতে পারি। প্রতিটি সংখ্যা অবশ্যই একবারে আসবে এবং যে কোনও স্থানে যে কোনও সংখ্যক সংখ্যক হওয়ার সম্ভাবনা অবশ্যই সমান হবে।

এর জন্য সবচেয়ে দক্ষ অ্যালগরিদম কী?


1
ইতিমধ্যে দেখা সংখ্যাগুলি রেকর্ড করতে একটি অ্যারে / বা বিট ভেক্টর এবং দেখা অনন্য সংখ্যার সংখ্যা রেকর্ড করার জন্য একটি কাউন্টার ব্যবহার করুন।
ডেভ ক্লার্ক

@ ডেভ ক্লার্ক কিভাবে আমি এর সাথে 50 এর চেয়ে বড় একটি সংখ্যা তৈরি করতে পারি? যদি আমি এটি 1 টিরও বেশি বার ব্যবহার করি তবে আমি কীভাবে তাদের ব্যবহার করে 1 জেনারেট করব?
রাজ ওয়াধওয়া

1
অবশ্যই চ্যালেঞ্জটি নিশ্চিত করছে যে সমস্ত জায়গাগুলি সমান সম্ভাবনার সাথে ঘটবে। আপনি ব্যবহার করতে পারে RandNum100 = (RandNum50() * 2) - (RandNum50 > 25) ? 0 : 1)
ডেভ ক্লার্ক 9

2
@ ডেভ ক্লার্ক: সুতরাং আপনি পুনরাবৃত্তি প্রত্যাখ্যানের নমুনার প্রস্তাব দিচ্ছেন? এটি কেবল প্রত্যাশায় শেষ হবে।
রাফেল

আমি কেবল একটি ইঙ্গিত দিচ্ছিলাম।
ডেভ ক্লার্ক 11

উত্তর:


3

আমি ভেবেছিলাম (তাই এটা ভুল হতে পারে :-) এই ব্যবহার করে সমাধান ফিশার-ইয়েটস এলোমেলো । প্রতিটি পুনরাবৃত্তিতে ভাল অনুমানের সাথে অভিন্ন বিতরণ রাখতে (নীচের সম্পাদনা বিভাগটি দেখুন) আপনি 0 এবং কে - 1 এর মধ্যে একটি মান উত্পাদন করতে এই কৌশলটি ব্যবহার করতে পারেন :O(N2)krand0k1

 // return a random number in [0..k-1] with uniform distribution
 // using a uniform random generator in [1..50]
 funtion krand(k) {    
   sum = 0
   for i = 1 to k do sum = sum + RandNum50() - 1
   krand = sum mod k
 }

ফিশার-ইয়েটস অ্যালগরিদম হয়ে যায়:

arr : array[0..99]
for i = 0  to 99 do arr[i] = i+1; // store 1..100 in the array
for i = 99 downto 1 {
  r = krand(i+1)  // random value in [0..i]
  exchange the values of arr[i] and arr[r]
}
for i = 0 to 99 do print arr[i]

সম্পাদনা করুন:

এরিক দ্বারা নির্দেশিত হিসাবে krandউপরের ফাংশনটি সত্যই অভিন্ন বিতরণটি দেয় না। আরও একটি পদ্ধতি রয়েছে যা আরও ভাল (নির্বিচারে আরও ভাল) এবং দ্রুত সান্নিধ্য পেতে ব্যবহার করা যেতে পারে; কিন্তু (আপ আমার জ্ঞান) একটি সত্যিকারের সমবন্টন পেতে একমাত্র উপায় ব্যবহার করা প্রত্যাখ্যান স্যাম্পলিং বাছাই: র্যান্ডম বিট এবং যদি সংখ্যা প্রাপ্ত চেয়ে কম হয় এটা প্রত্যাবর্তন, অন্যথায় উৎপন্ন অন্য এলোমেলো সংখ্যা; একটি সম্ভাব্য বাস্তবায়ন:m=log2(k)rk

function trulyrand(k) {
    if (k <= 1) return 0
    while (true) { // ... if you're really unlucky ...
      m = ceil(log_2 (k) ) // calculate m such that k < 2^m
      r = 0  // will hold the random value
      while (m >= 0) {  // ... will add m bits        
        if ( rand50() > 25 ) then b = 1 else b = 0   // random bit
        r = r * 2 + b  // shift and add the random bit
        m = m - 1
      }      
      if (r < k) then return r  // we have 0<=r<2^m ; accept it, if r < k
    }
}

1
আপনি উইকিপিডিয়া পৃষ্ঠায় লিঙ্ক করেছেন যে একটি বৈকল্পিক আছে states O(n)
ডেভ ক্লার্ক 9

1
আমি মনে করি এখানে "শিফাল" হ'ল মূল শব্দটি।
রাফেল

4
ক্র্যান্ড (কে) এর ট্রিকটি সত্যই অভিন্ন বিতরণ তৈরি করে না, যদিও এটি একটি ভাল অনুমানের মতো: এমনকি কে = 3 এর জন্যও এটি আউটপুট দেওয়ার একটি 33.333328% সম্ভাবনা দেয় Is এখানে কে পর্যন্ত সমস্ত উপায় যোগ করার কোনও যৌক্তিকতা আছে কি? ? আমি যদি মনে করি আমরা কেবল একটি আনুমানিকতা চাই তবে একটি ছোট সীমাই যথেষ্ট।
এরিক ওয়াং

1
@ এরিকওয়ং: আপনি ঠিক বলেছেন; আমি মনে করি যে সত্যিকারের ইউনিফর্ম বিতরণটি কেবল প্রত্যাখ্যানকারী নমুনা পদ্ধতি ব্যবহার করে পৌঁছানো যেতে পারে যা ধ্রুবক সময়ে শেষ হওয়ার গ্যারান্টিযুক্ত নয়। অন্যান্য আনুমানিক স্কিম রয়েছে (এটি যে কোনও পছন্দসই আনুষঙ্গিকতায় পৌঁছাতে দেয়), আমি যে প্রস্তাব দিয়েছিলাম তা হ'ল প্রথমটি যা আমার মনে আসে।
মাস

2
@ ex0du5: আমি এটি জানি, তবে আপনি কীভাবে [১.১.০০] তে একটি অভিন্ন র্যান্ডম জেনারেটর ব্যবহার করে [১.১.০০] সংখ্যার অভিন্ন র্যান্ডম অনুমান উত্পাদন করতে পারেন? একমাত্র বিকল্প পদ্ধতি আমি জানি হল: 1 ম ধাপ) একটি র্যান্ডম মান বাছাই মধ্যে 1..100 ; পদক্ষেপ 2 ) যদি ইতিমধ্যে আর বেছে নেওয়া হয়েছে তবে তা ফেলে দিন এবং পদক্ষেপ 1; স্টিপি 3) প্রিন্ট r ; পদক্ষেপ 4) আমরা যদি 100 টি নম্বর গোটো স্টেপ 1 মুদ্রণ না করে থাকি। কিন্তু এই পদ্ধতিটি কেবল ইতিমধ্যে বাছাই করা উপাদানগুলির কাছে প্রত্যাখ্যানকে স্থানান্তরিত করে। r1..100RR
মাস

4

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

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

কিন্তু আমরা যদি জানতাম যে আমাদের এলগরিদম সর্বাধিক ব্যবহৃত কল কিছু , তাহলে আমরা তর্ক হতে পারে নিম্নরূপ: প্রথমত, বাইরে সেই গণনার পাথ যে কম করা প্যাড কল অতিরিক্ত ডামি কল করার জন্য (যেমন, কল যেখানে ফিরে মান অপ্রাসঙ্গিক), যাতে সব গণনার পাথ অবিকল করা কল। আমাদের কল থেকে কে ফলাফলের কোনও প্রদত্ত ক্রম অবশ্যই কিছু আউটপুট ক্রিয়াকলাপের ফলস্বরূপ হবে, এবং তাই আমরা একটি 'ফলাফল টেবিল' তৈরি করতে পারি যা প্রদত্ত যে কোনও অনুক্রমকে মানচিত্র করে ( আর 1 , আর 2 , , আর কে )RandNum50RandNum50RandNum50(R1,R2,...,R)আমাদের কলগুলি থেকে ফলাফলকে একটি নির্দিষ্ট আউটপুট অনুক্রমের ফলাফল যেহেতু এই প্রতিটি ফলাফলের সমান সম্ভাবনা রয়েছে (তাদের প্রত্যেকেরই সম্ভাবনা ), তারপরে আমাদের অ্যালগরিদম থেকে কোনও নির্দিষ্ট ক্রম ছাড়ার সম্ভাবনা অবশ্যই ফর্মের হতে হবেসি150 কিছু। তবে50এই ফর্ম হতে পারে না, কারণ100! ভাগ না50কোন(উদাহরণস্বরূপ, 3 ভাগ100!কিন্তু ফর্ম যে কোন সংখ্যার বিভক্ত করা যাবে না50)। এর অর্থ হল যে এলোমেলো-নম্বর কলগুলিতে ফলাফলের কোনও সম্ভাব্য বিতরণ অভিন্ন ক্রম ছাড়তে পারে না।1100!100!50100!50


2

এনলগএন+ +হে(1)

if ( rand50() > 25 ) then b = 1 else b = 0   // random bit

1এন!123এন

আপনি যদি এলোমেলোভাবে কিছু থেকে এই পোস্টে প্রস্তাবিত ইউনিফর্মটি কীভাবে তৈরি করবেন তা জানেন না, আপনি সরাসরি এইভাবে ইউনিফর্মটির একটি আনুমানিক উত্পন্ন করতে পারেন (যা ভোরের "সত্যিকারের" সমান, তবে দ্রুত):

P = (RandNum50()-1) + (RandNum50()-1)*50^1 + (RandNum50()-1)*50^2 + ...

পি50পিপ্রশ্নঃ=পিগেলিক ভাষারএনএন=100!পি>এন


1

আমি নিশ্চিত করতে বিশ্লেষণ না করে কিভাবে অভিন্ন (অথবা না) এই হবে, এবং এটি একটি সত্য এলোমেলো হতে স্থায়ী করা যেতে পারে, কিন্তু আপনি শুধু শুরুর অ্যারে থেকে, চয়ন করতে পারেন iতম সূচক = i + 1, (k + RandNum50() + RandNum50() - 1) mod (100 - k)সূচক, সঙ্গে অপসারণ, k= 0..99 এর জন্য?

এটি RandNum50() + RandNum50()সমানভাবে বিতরণে শীর্ষে "ধাক্কা দেয়" ।

আমি দৃ sure়ভাবে নিশ্চিত যে এটি ঠিক মত নয় যেহেতু আমি এটি বলেছি কারণ 0 সূচক (1) প্রথম পছন্দ থেকে প্রাপ্ত নয় এবং আমি দ্রুত বিকল্প 1..50 + 1..50 সমন্বয় দেখতে পাচ্ছি না যা 0 উত্পাদন করে ..99।

হালনাগাদ

আমি যে বিষয়টি উল্লেখ করেছি, তা সমাধান করার জন্য, আমি RandNum100প্রথম kঅফসেটটি এলোমেলোভাবে শুরু করার জন্য প্রশ্ন মন্তব্যে উল্লিখিতভাবে কার্যকরভাবে ব্যবহার করেছি ।

এটি সামনে একটি উল্লেখযোগ্য তরঙ্গ সহ একটি বিতরণ উত্পাদন করে।

1 দ্বারা অগ্রসর হওয়ার পরিবর্তে আমি আরও RandNum50প্রথমটি বাড়ানোর জন্য ব্যবহার করেছি k। এটি এমন একটি ফলাফল তৈরি করে যা আমার জন্য যথেষ্ট এলোমেলো, তবে এটি এখনও "সত্যিকারের" এলোমেলো নয়, আপনি কে-কে 2 এ পরিবর্তন করেন তবে সহজেই দেখা যায়।

ভিবি.এনইটি কোডের পরীক্ষার জন্য যেখানে আমি যে কোনও কে কে তৈরি করেছি Note নোট করুন এটি ও (কে), আসলে 6 কে + 2।

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