1–5 থেকে 1–7 এ এলোমেলো পরিসীমা প্রসারিত করুন


692

একটি ফাংশন দেওয়া হয়েছে যা 1 থেকে 5 ব্যাপ্তির মধ্যে এলোমেলো পূর্ণসংখ্যার উত্পাদন করে, একটি ফাংশন লিখুন যা 1 থেকে 7 এর পরিসরে একটি এলোমেলো পূর্ণসংখ্যার উত্পাদন করে।

  1. একটি সহজ সমাধান কি?
  2. স্মৃতি ব্যবহার কমাতে বা ধীর সিপিইউতে চালানোর কার্যকর সমাধান কী?

এটি একটি অপ্রত্যাশিতভাবে আকর্ষণীয় সমস্যা হিসাবে প্রমাণিত, আমি এখনও মনে করি কীভাবে 1) এটি নির্ধারিত সময়ে করুন এবং 2) অভিন্ন বিতরণটি (যদি সেখানে থাকত না) নষ্ট করবেন না
ইউজেনস্ক

পাশা দিয়ে 5 জনের মধ্যে একজন খেলোয়াড় বেছে নেওয়ার সময় আমাদের একই সমস্যা ছিল। আমরা ঘুরিয়ে পাশা নিক্ষেপ করলাম, যিনি সর্বোচ্চ স্কোর পাবেন সে চয়েসেন। অভিন্নতা অর্জন করা হয়েছিল, তবে সময় স্থিরতা নয় :)
ইউজেনস্ক

আমি যদি উত্তরটি পোস্ট করে বলি যে সমস্যাটি আপনাকে প্রদত্ত ফাংশনটি ব্যবহার করতে হবে এবং কেবলমাত্র 1-7 এলোমেলোভাবে প্রত্যাবর্তন করে এমন একটি লিখতে হবে যে উত্তরটি পোস্ট করলে আমি কী অবনমিত হব?
ডাক্তার নীল

কি হবে 7 * rand5() / 5?
কিউইক্সজ

@ কিউইক্স, এটি "1 এবং 7 এর মধ্যে" উত্পাদন করবে তবে আপনি 3 বা 6 পাবেন না: {1: 19.96, 2: 20.02, 4: 20.01, 5: 19.99, 7: 20.02} মোটামুটি শতাংশ পরীক্ষা করে নিজেই testing 7 * .2, 7 * .4, 7 * .6, 7 * .8, 7 * 1।
পাইথোনালারি

উত্তর:


572

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

int rand7()
{
    int vals[5][5] = {
        { 1, 2, 3, 4, 5 },
        { 6, 7, 1, 2, 3 },
        { 4, 5, 6, 7, 1 },
        { 2, 3, 4, 5, 6 },
        { 7, 0, 0, 0, 0 }
    };

    int result = 0;
    while (result == 0)
    {
        int i = rand5();
        int j = rand5();
        result = vals[i-1][j-1];
    }
    return result;
}

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

অ্যাডাম যেমন বলেছিলেন, এটি সবচেয়ে খারাপ ক্ষেত্রে চিরকাল চলতে পারে তবে পরিসংখ্যানগত দিক থেকে সবচেয়ে খারাপ পরিস্থিতি কখনই ঘটে না। :)


5
আমি এই সমাধানের পিছনে যুক্তি বুঝতে পেরেছি কিন্তু বুঝতে পারি না যে এটির ফলে কীভাবে অভিন্ন সম্ভাবনা রয়েছে? কেউ কি গণিত ব্যাখ্যা করতে পারেন?
ব্যবহারকারী 1071840

6
@ ব্যবহারকারী 1071840 - যদি rand5অভিন্ন হয় তবে valsগ্রিডের প্রতিটি কক্ষের বাছাইয়ের সমান সম্ভাবনা থাকে। গ্রিডটিতে অন্তর [1, 7] এর মধ্যে প্রতিটি পূর্ণসংখ্যার ঠিক তিনটি অনুলিপি এবং আরও চারটি শূন্য থাকে। সুতরাং ফলাফলের "কাঁচা" স্ট্রিমটি [1, 7] মানের সমান মিশ্রণের দিকে ঝোঁকায়, পাশাপাশি কিছু শূন্য যা কোনও স্বতন্ত্র অনুমোদিত মানের চেয়ে বেশি বার ঘন ঘন হয়ে আসে। তবে এতে কিছু যায় আসে না কারণ শূন্যগুলি ছিটকে যায়, [1, 7] মানগুলির একটি সমান মিশ্রণ রেখে।
ড্যানিয়েল আরউইকার

3
সমস্যাটি উপলব্ধি করার শর্টকাট উপায়: আপনি যদি কেবল একবার র্যান্ড 5 () কল করেন তবে আপনার কেবলমাত্র 5 সম্ভাব্য ফলাফল রয়েছে। আরও এলোমেলো যোগ না করে এটিকে 5 টিরও বেশি সম্ভাব্য পরিণামে পরিণত করার স্পষ্টভাবে কোনও উপায় নেই।
ড্যানিয়েল আরউইকার

1
দীর্ঘতর সংস্করণ: র্যান্ড 5 () এর কেবল মান (1, 2, 3, 4, 5) থাকতে পারে। সুতরাং র্যান্ড 5 () * 5 এর কেবল মান (5, 10, 15, 20, 25) থাকতে পারে যা সম্পূর্ণ পরিসরের (1 ... 25) সমান নয়। যদি এটি হয়ে থাকে, 4 বিয়োগ করলে এটি (-3 ... 21) হয়ে যায়, তবে এই ক্ষেত্রে এটি হয়ে যায় (1, 6, 11, 16, 21), সুতরাং শেষ পয়েন্টগুলি সঠিক তবে চারটি বড় গর্ত রয়েছে: ( 2..5), (7..10), (12..15), (17..21)। অবশেষে আপনি মোড 7 করেন এবং 1 যোগ করুন, দিচ্ছেন (2, 7, 5, 3, 1)। সুতরাং 4 বা 6 কখনও হয় না। তবে (উপরের শর্টকাটটি দেখুন) আমরা জানতাম ফলস্বরূপ পরিসীমাটিতে কেবল 5 টি সংখ্যা থাকতে পারে, সুতরাং দুটি ফাঁক থাকতে হবে।
ড্যানিয়েল আরউইকার

1
আহা, কারণ আমাদের কেবল র্যান্ড 5 () রয়েছে, র্যান্ড 2 () :-) নয়
gzak

353

এর কোনও (ঠিক সঠিক) সমাধান নেই যা নিয়মিত পরিমাণে চলবে, যেহেতু ১/ 1/ বেসের একটি অসীম দশমিক 5. একটি সহজ সমাধান হ'ল প্রত্যাখ্যানের নমুনা ব্যবহার করা, যেমন:


int i;
do
{
  i = 5 * (rand5() - 1) + rand5();  // i is now uniformly random between 1 and 25
} while(i > 21);
// i is now uniformly random between 1 and 21
return i % 7 + 1;  // result is now uniformly random between 1 and 7

এটিতে লুপের 25/21 = 1.19 পুনরাবৃত্তির একটি প্রত্যাশিত রানটাইম রয়েছে তবে চিরকালের জন্য লুপিংয়ের অসীম ক্ষুদ্র সম্ভাবনা রয়েছে।


7
<21 টি <বি </ b> তে উল্টে গেলে -1 প্রয়োজন হয় না যেখানে আমি নীচে আবদ্ধ মানচিত্রগুলি কোথায় তা বিবেচনা করে না
বিসিএস 18

26
কেন এটি সঠিক তা ব্যাখ্যা করার ক্ষেত্রে আমার পদক্ষেপ: বলুন যে আমি এমন একটি প্রোগ্রাম লিখতে চাই যা ইউনিফর্ম র্যান্ডম সংখ্যার 1 থেকে 25 এর প্রবাহকে বহন করে; এর জন্য আমি উত্তরের কোড হিসাবে স্রেফ 5 * (র্যান্ড 5 () - 1) + র্যান্ড 5 () ফিরিয়ে দিয়েছি। এখন, আমি যদি 1 এবং 21 এর মধ্যে অভিন্ন র্যান্ডম সংখ্যার একটি স্ট্রিম তৈরি করতে চাই, আমি যদি প্রথম স্রোতটি ব্যবহার করি তবে এটি ফিল্টার করি যাতে [22, 25] এর সংখ্যাগুলি প্রত্যাখ্যান হয়, আমিও সেই স্ট্রিমটি তৈরি করতে পারি। পরবর্তী, আমি যদি এই স্ট্রিমটি নিয়ে যাই এবং এটি ফিল্টার করি যাতে প্রতিটি এলিমেন্টের জন্য আমি এক্স% 7 + 1 আউটপুট পাই, আমার কাছে 1 থেকে 7 পর্যন্ত অভিন্ন র্যান্ডম সংখ্যার স্ট্রিম রয়েছে! বেশ সহজ, তাই না? : ডি
প্যাগাস

6
এবং আপনি সঠিক যে আপনি আনবাউন্ডেড সবচেয়ে খারাপ ক্ষেত্রে রানটাইম সহ একটি নিখুঁত বন্টন চান, বা একটি বাউন্ডেড রানটাইম সহ একটি অসম্পূর্ণ বিতরণ চান কিনা তা এটিকে উত্সাহিত করে। এটি এই পরিণতির একটি ফলাফল যে সমস্ত শক্তি 5 দ্বারা 7 দ্বারা বিভাজ্য নয়, বা সমানভাবে যদি আপনার 5 ^ n সমানভাবে দৈর্ঘ্য n এর ক্রম থাকে তবে প্রতিটি অনুক্রমকে 1 থেকে 7 পর্যন্ত কোনও সংখ্যা নির্ধারণ করার কোনও উপায় নেই যেমন প্রতিটি প্রতিটি 1.7 সমানভাবে সম্ভবত।
অ্যাডাম রোজেনফিল্ড

5
@ জুলেস ওলোন: ধরুন যে ধ্রুবক সময়ে একটি সমাধান চলছিল যা সবচেয়ে খারাপ ক্ষেত্রে Nডাকা ছাড়া আর কিছু না করার গ্যারান্টিযুক্ত ছিল rand5()। তারপরে, কল করার ক্রমের 5 ^ N সম্ভাব্য ফলাফল rand5রয়েছে যার প্রতিটিরই 1-7 আউটপুট রয়েছে। সুতরাং, যদি আপনি কলগুলির সম্ভাব্য সমস্ত ক্রমগুলি যোগ করেন যার আউটপুট kপ্রতিটি 1≤k≤7 এর জন্য হয় তবে তার আউটপুটটি kএম / 5 ^ এন হয়, যেখানে এম এই ধরণের ক্রমগুলির সংখ্যা of সুতরাং, মি / 5 ^ এন = 1/7, তবে এই ==> বৈপরীত্যের কোনও সম্ভাব্য পূর্ণসংখ্যার সমাধান (এন, এম) নেই।
অ্যাডাম রোজেনফিল্ড

4
@ প্যাক্সিডিয়ালো: আপনি ভুল। সত্যিকারের আরএনজি 5 টির অসীম অনুক্রম তৈরি করার সুযোগটি ঠিক 0, একই সাথে এই যুক্তি ব্যবহার করে যে একটি মুদ্রাটিকে অসীম সংখ্যকবার উল্টানো এক অনন্ত সংখ্যক মাথা জড়ানোর নিশ্চয়তা নেই । এর অর্থ এই কোডটি চিরতরে লুপ করার সম্ভাবনাটি ঠিক 0 (যদিও কোনও ইতিবাচক সম্ভাবনা থাকলে এটি যেকোনও স্বতঃস্ফূর্ত সংখ্যার জন্য লুপ করবে)।
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

153

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

একটি এলোপাতাড়ি ভেরিয়েবলের এনট্রপি একটি ভাল-সংজ্ঞায়িত পরিমাণ। এলোমেলো পরিবর্তনশীলগুলির জন্য যা এন স্টেটগুলিতে সমান সম্ভাবনা (অভিন্ন বিতরণ) নিয়ে থাকে, এনট্রপিটি লগ 2 এন হয়। সুতরাং, rand5()প্রায় 2.32193 এনট্রপির বিট rand7()রয়েছে এবং এটিতে প্রায় 2.80735 বিট রয়েছে। আমরা যদি আমাদের এলোমেলো ব্যবহারের সর্বাধিক ব্যবহার আশা করি, আমাদের প্রতিটি কল থেকে এনট্রপির সমস্ত 2.32193 বিট ব্যবহার rand5()করতে হবে এবং প্রতিটি কলের জন্য প্রয়োজনীয় 2.80735 বিট তৈরি করতে হবে rand7()। তারপরে, মৌলিক সীমাটি হ'ল আমরা লগ (7) / লগ (5) = 1.20906 কল rand5()প্রতি কলের চেয়ে আরও ভাল কিছু করতে পারি নাrand7()

পার্শ্ব নোটস: অন্যথায় নির্দিষ্ট না করা থাকলে এই উত্তরে সমস্ত লগারিদম বেস 2 হবে base rand5()[0, 4], এবং এর মধ্যে পরিসরে নম্বরগুলি প্রত্যাবর্তন হিসাবে ধরে নেওয়া হবেrand7() পরিসীমাতে নম্বরগুলি প্রত্যাবর্তন হিসাবে ধরে নেওয়া হবে [0, 6] পরিসরে নম্বরগুলি প্রত্যাবর্তন হিসাবে ধরে নেওয়া হবে। যথাক্রমে [1, 5] এবং [1, 7] এর রেঞ্জগুলি সামঞ্জস্য করা তুচ্ছ।

সুতরাং আমরা এটা কিভাবে করব? আমরা 0 এবং 1 এর মধ্যে একটি অসীম সুনির্দিষ্ট এলোমেলো আসল সংখ্যা উত্পন্ন করি (এই মুহুর্তের জন্য ভান করি যে আমরা আসলে এইরকম একটি অসীম সুনির্দিষ্ট সংখ্যা গণনা করতে এবং সংরক্ষণ করতে পারি - আমরা এটি পরে ঠিক করব)। বেস 5 এ এর ​​অঙ্কগুলি তৈরি করে আমরা এই জাতীয় সংখ্যা উত্পন্ন করতে পারি: আমরা এলোমেলো নম্বর 0 বেছে নিই a1 1 a3 a3 ..., যেখানে প্রতিটি অঙ্ক iএকটি কল দ্বারা নির্বাচিত হয় rand5()। উদাহরণস্বরূপ, যদি আমাদের আরএনজি iসকলের জন্য একটি = 1 পছন্দ করে i, তবে এটি খুব এলোমেলো নয় এমন সত্যটি উপেক্ষা করে, এটি আসল সংখ্যার সাথে সামঞ্জস্য করবে 1/5 + 1/5 2 + 1/5 3 + + এর সাথে মিলে যায় ... = 1/4 (জ্যামিতিক সিরিজের সমষ্টি)।

ঠিক আছে, সুতরাং আমরা 0 এবং 1 এর মধ্যে একটি এলোমেলো আসল সংখ্যাটি বেছে নিয়েছি now এখন আমি দাবি করি যে এ জাতীয় এলোমেলো সংখ্যাটি সমানভাবে বিতরণ করা হয়েছে। স্বজ্ঞাতভাবে, এটি বুঝতে সহজ, যেহেতু প্রতিটি অঙ্কটি অভিন্নভাবে নেওয়া হয়েছিল, এবং সংখ্যাটি অসীমভাবে সুনির্দিষ্ট। তবে এর একটি আনুষ্ঠানিক প্রমাণ কিছুটা বেশি জড়িত, যেহেতু এখন আমরা একটি বিচ্ছিন্ন বিতরণের পরিবর্তে অবিচ্ছিন্ন বিতরণ নিয়ে কাজ করছি, সুতরাং আমাদের প্রমাণ করতে হবে যে আমাদের সংখ্যাটি একটি বিরতিতে [ a, b] রয়েছে তার দৈর্ঘ্যের সমান হয় যে বিরতি,b - a ,। প্রমাণটি পাঠকের জন্য অনুশীলন হিসাবে রেখে গেছে =)।

এখন যেহেতু [0, 1] রেঞ্জ থেকে আমাদের কাছে এলোমেলোভাবে আসল সংখ্যা নির্বাচন করা হয়েছে, এর আউটপুট উত্পন্ন করতে আমাদের এটিকে [0, 6] পরিসরে অভিন্ন র্যান্ডম সংখ্যার একটি সিরিজে রূপান্তর করতে হবে rand7()। আমরা এটা কিভাবে করব? আমরা কেবল যা করেছি তার বিপরীতে - আমরা এটিকে বেস 7 এ অসীম সুনির্দিষ্ট দশমিক হিসাবে রূপান্তর করি এবং তারপরে প্রতিটি বেস 7 ডিজিটের একটি আউটপুটের সাথে সামঞ্জস্য হয় rand7()

পূর্বের উদাহরণটি গ্রহণ করে, আমাদের যদি rand5()1 এর অসীম প্রবাহ উত্পাদন করে তবে আমাদের এলোমেলো আসল সংখ্যাটি 1/4 হবে। 1/4 কে বেস 7 এ রূপান্তর করা, আমরা অসীম দশমিক 0.15151515 পাই ... সুতরাং আমরা আউটপুট 1, 5, 1, 5, 1, 5 ইত্যাদি হিসাবে উত্পাদন করব

ঠিক আছে, সুতরাং আমরা মূল ধারণাটি পেয়েছি, তবে আমাদের দুটি সমস্যা রয়েছে: আমরা আসলে কোনও অসীম সুনির্দিষ্ট প্রকৃত সংখ্যা গণনা করতে বা সঞ্চয় করতে পারি না, সুতরাং আমরা কেবলমাত্র এর একটি সীমাবদ্ধ অংশটি কীভাবে व्यवहार করব? দ্বিতীয়ত, আমরা কীভাবে এটি এটিকে বেস 7 তে রূপান্তর করব?

একটি উপায় যা আমরা 0 এবং 1 এর মধ্যে একটি সংখ্যাটি বেস 7 তে রূপান্তর করতে পারি:

  1. 7 দ্বারা গুণ করুন
  2. ফলাফলের অবিচ্ছেদ্য অংশটি পরবর্তী বেস 7 ডিজিট
  3. কেবলমাত্র ভগ্নাংশের অংশ রেখে অবিচ্ছেদ্য অংশটি বিয়োগ করুন
  4. গোটো পদক্ষেপ 1

অসীম নির্ভুলতার সমস্যাটি মোকাবেলা করার জন্য আমরা একটি আংশিক ফলাফল গণনা করি এবং ফলাফল কী হতে পারে তার উপরও আমরা একটি উচ্চতর গণ্ডি সঞ্চয় করি। অর্থাৎ, ধরুন আমরা rand5()দুবার ফোন করেছি এবং এটি উভয় বার 1 টি ফিরে এসেছে। এখন পর্যন্ত আমরা যে সংখ্যাটি তৈরি করেছি তা 0.11 (বেস 5)। rand5()উত্পাদনের জন্য অসীম সিরিজের কলগুলির বাকি যতগুলিই হোক না কেন , আমরা যে এলোমেলো প্রকৃত সংখ্যাটি উত্পন্ন করি তা কখনই 0.12 এর চেয়ে বেশি হবে না: এটি সর্বদা সত্য যে 0.11 ≤ 0.11xyz ... <0.12।

সুতরাং, এখন পর্যন্ত বর্তমান সংখ্যার উপর নজর রাখা এবং এটি যে সর্বোচ্চ মান নিতে পারে, আমরা উভয় সংখ্যাকে বেস 7 এ রূপান্তর করি যদি তারা প্রথম kসংখ্যায় একমত হয় , তবে আমরা নিরাপদে পরবর্তী kঅঙ্কগুলি আউটপুট করতে পারি - যাই হোক না কেন বেস 5 সংখ্যার অসীম স্ট্রিমটি, তারা কখনই kবেস 7 এর উপস্থাপনের পরবর্তী অঙ্কগুলিকে প্রভাবিত করবে না !

এবং এটি আলগোরিদিম - এর পরবর্তী আউটপুট তৈরি করতে rand7(), আমরা কেবলমাত্র এতগুলি অঙ্ক তৈরি rand5()করি যেটি নিশ্চিত করতে হবে যে আমরা এলোমেলো আসল সংখ্যাকে বেস base এ রূপান্তর করতে পরবর্তী অঙ্কের মান নিশ্চিতভাবে জানি know একটি পরীক্ষার জোতা সহ পাইথন বাস্তবায়ন:

import random

rand5_calls = 0
def rand5():
    global rand5_calls
    rand5_calls += 1
    return random.randint(0, 4)

def rand7_gen():
    state = 0
    pow5 = 1
    pow7 = 7
    while True:
        if state / pow5 == (state + pow7) / pow5:
            result = state / pow5
            state = (state - result * pow5) * 7
            pow7 *= 7
            yield result
        else:
            state = 5 * state + pow7 * rand5()
            pow5 *= 5

if __name__ == '__main__':
    r7 = rand7_gen()
    N = 10000
    x = list(next(r7) for i in range(N))
    distr = [x.count(i) for i in range(7)]
    expmean = N / 7.0
    expstddev = math.sqrt(N * (1.0/7.0) * (6.0/7.0))

    print '%d TRIALS' % N
    print 'Expected mean: %.1f' % expmean
    print 'Expected standard deviation: %.1f' % expstddev
    print
    print 'DISTRIBUTION:'
    for i in range(7):
        print '%d: %d   (%+.3f stddevs)' % (i, distr[i], (distr[i] - expmean) / expstddev)
    print
    print 'Calls to rand5: %d (average of %f per call to rand7)' % (rand5_calls, float(rand5_calls) / N)

নোট করুন যে rand7_gen()একটি জেনারেটরকে ফেরত দেয়, যেহেতু এটির অভ্যন্তরীণ অবস্থাটি সংখ্যার সাথে বেস 7 তে রূপান্তর জড়িত থাকে পরীক্ষার জোনা next(r7)10000 বার কল করে 10000 এলোমেলো সংখ্যা তৈরি করে এবং তারপরে এটি তাদের বিতরণকে মাপ দেয়। শুধুমাত্র পূর্ণসংখ্যার গণিত ব্যবহৃত হয়, সুতরাং ফলাফলগুলি ঠিক সঠিক।

এছাড়াও নোট করুন যে এখানে নম্বরগুলি খুব বড়, খুব দ্রুত পান। 5 এবং 7 এর শক্তি দ্রুত বৃদ্ধি পায়। সুতরাং, বিগনাম পাটিগণিতের কারণে প্রচুর এলোমেলো সংখ্যা উত্পন্ন করার পরে কর্মক্ষমতা লক্ষণীয়ভাবে হ্রাস পেতে শুরু করবে। তবে এখানে মনে রাখবেন, আমার লক্ষ্যটি ছিল এলোমেলো বিটের ব্যবহার সর্বাধিক করে তোলা, সর্বাধিক কর্মক্ষমতা না করা (যদিও এটি গৌণ লক্ষ্য) secondary

এর এক দৌড়ে, আমি সর্বনিম্ন লগের (7) / লগ (5) কল করতে গড়ে 4 টি উল্লেখযোগ্য পরিসংখ্যান অর্জন করে rand5()10000 কল করার জন্য 12091 কল করেছি rand7()এবং ফলাফলটি আউটপুট অভিন্ন ছিল।

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


7
সত্যিই আকর্ষণীয় উত্তরের জন্য +1 একটি নির্দিষ্ট মান পুনরায় সেট করার পরিবর্তে, কেবল ব্যবহৃত বিটগুলি সরানো, এবং অন্যান্য বিটগুলি সরিয়ে নেওয়া এবং মূলত কেবল ব্যবহৃত বিটগুলি রাখা কি সম্ভব হবে? নাকি আমি কিছু মিস করছি?
ক্রিস লুটজ

1
আমি ১০০% নিশ্চিত নই, তবে আমি বিশ্বাস করি যদি আপনি এটি করেন তবে আপনি বিতরণটিকে এত সামান্য করে ফেলবেন (যদিও আমি সন্দেহ করি যে ট্রিলিয়ন ট্রায়াল ছাড়াই এই জাতীয় স্কিউ পরিমাপযোগ্য হবে)।
অ্যাডাম রোজেনফিল্ড

FTW এর! আমি বাইনগমগুলি আরও ছোট করার চেষ্টা করেছি তবে এটি করা যায় না কারণ 5 এর কোনও পাওয়ারের 7 টির শক্তির সাথে সাধারণ কারণ নেই! এছাড়াও, ফলন কীওয়ার্ডটির ভাল ব্যবহার। অনেক ভালো করেছ.
ইয়াল

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

@ অ্যাডাম আপনাকে অবশ্যই "নিজের নেটিভ ইন্টিগ্রাল টাইপের সর্বাধিক মানের জন্য পাও 5 এবং পাউ 7 এর মানগুলি ক্যাপ করুন"। আমি আপনার বিশ্বাসকে দ্বিতীয় বলেছি এটি কমপক্ষে নির্লজ্জভাবে করা গেলে, এই বিতরণটি স্কু হবে।
অনুঘটক

36

(আমি অ্যাডাম রোজেনফিল্ডের উত্তরটি চুরি করে প্রায় 7% দ্রুত চালিয়েছি))

ধরে নিন যে র‌্যান্ড 5 () সমান বন্টন সহ, 0,1,2,3,4 one এর মধ্যে একটি প্রদান করে এবং গোলটি সমান বন্টন সহ {0,1,2,3,4,5,6 return প্রত্যাবর্তন করবে।

int rand7() {
  i = 5 * rand5() + rand5();
  max = 25;
  //i is uniform among {0 ... max-1}
  while(i < max%7) {
    //i is uniform among {0 ... (max%7 - 1)}
    i *= 5;
    i += rand5(); //i is uniform {0 ... (((max%7)*5) - 1)}
    max %= 7;
    max *= 5; //once again, i is uniform among {0 ... max-1}
  }
  return(i%7);
}

লুপটি ভেরিয়েবলের মধ্যে তৈরি করতে পারে এমন বৃহত্তম মান আমরা ট্র্যাক করে রাখছি max। যদি এখনও পর্যন্ত ফলাফলগুলি সর্বোচ্চ% 7 এবং সর্বোচ্চ -1 এর মধ্যে হয় তবে ফলাফলটি এই পরিসরে অভিন্নভাবে বিভ্রান্ত হবে। যদি তা না হয় তবে আমরা অবশিষ্টটি ব্যবহার করি যা 0 থেকে সর্বোচ্চ% 7-1 এর মধ্যে এলোমেলো এবং একটি নতুন নম্বর এবং একটি নতুন সর্বোচ্চ তৈরি করতে র্যান্ড ()) এ অন্য কল। তারপরে আমরা আবার শুরু করি।

সম্পাদনা করুন: এই সমীকরণে র্যান্ড 5 () কল করার জন্য বারের সংখ্যাটি প্রত্যাশা করুন:

x =  2     * 21/25
   + 3     *  4/25 * 14/20
   + 4     *  4/25 *  6/20 * 28/30
   + 5     *  4/25 *  6/20 *  2/30 * 7/10
   + 6     *  4/25 *  6/20 *  2/30 * 3/10 * 14/15
   + (6+x) *  4/25 *  6/20 *  2/30 * 3/10 *  1/15
x = about 2.21 calls to rand5()

2
1,000,000 চেষ্টা করে ফলাফল ফলাফল: 1 = 47216; 2 = 127444; 3 = 141407; 4 = 221453; 5 = 127479; 6 = 167536; 7 = 167465। আপনি দেখতে পাচ্ছেন, বিতরণে একটি পাওয়ার
রবার্ট কে

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

5
অভিন্ন বিতরণ সংখ্যা যুক্ত করার ফলে অভিন্ন বিতরণ সংখ্যার ফলাফল হয় না। প্রকৃতপক্ষে, সাধারণ বিতরণে যুক্তিসঙ্গত সান্নিধ্য পেতে আপনার কেবল 6 টি সমানভাবে বিতরণযোগ্য ভেরিয়েবলগুলি যোগ করতে হবে।
মিচ গম

2
@ মিচওয়েট - দুটি সমানভাবে বিতরণকৃত পূর্ণসংখ্যার যোগ করার ফলে বাস্তবে অভিন্ন বিতরণ করা এলোমেলো পূর্ণসংখ্যা প্রদান করা হয় তবে প্রতিটি সম্ভাব্য পরিমাণ ঠিক এক উপায়ে তৈরি করা যায়। অভিব্যক্তিতে কেসটি ঘটে 5 * rand5() + rand5()
টেড হপ্প

28

অ্যালগরিদম:

7 টি 3 বিটের ক্রমতে উপস্থাপন করা যেতে পারে

প্রতিটি বিট 0 বা 1 দিয়ে এলোমেলোভাবে পূরণ করতে র্যান্ড (5) ব্যবহার করুন
উদাহরণস্বরূপ: কল র্যান্ড (5) এবং

ফলাফল যদি 1 বা 2 হয়
তবে ফলাফলটি 4 বা 5 হলে বিটটি পূরণ করুন
, ফলাফলটি 3 হলে 1 দিয়ে বিটটি পূরণ করুন , তারপরে উপেক্ষা করুন এবং আবার এটি করুন (প্রত্যাখ্যান)

এইভাবে আমরা 0/1 দিয়ে এলোমেলোভাবে 3 টি বিট পূরণ করতে পারি এবং এভাবে 1-7 থেকে একটি নম্বর পেতে পারি।

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

public static int random_7() {
    int returnValue = 0;
    while (returnValue == 0) {
        for (int i = 1; i <= 3; i++) {
            returnValue = (returnValue << 1) + random_5_output_2();
        }
    }
    return returnValue;
}

private static int random_5_output_2() {
    while (true) {
        int flip = random_5();

        if (flip < 3) {
            return 0;
        }
        else if (flip > 3) {
            return 1;
        }
    }
}

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

"ফলাফল যদি 1 বা 2 হয় তবে ফলাফলটি 4 বা 5 হলে বিটটি পূরণ করুন, 1 দিয়ে বিটটি পূরণ করুন" 1,2,4,5 গৃহীত হয়েছিল এবং 3 প্রত্যাখ্যান করা হয়েছিল এমন যুক্তিটি কী? আপনি এই ব্যাখ্যা করতে পারেন?
gkns

@gkns কোন যুক্তি নেই, আপনার 1 এবং 2 এর সাথে 0 বিট এবং 3 এবং 4 এর অর্থ পূরণ করতে হবে 1 পূরণ করতে হবে। গুরুত্বপূর্ণ বিষয়টি হ'ল প্রতিটি বিকল্পের 50% সম্ভাবনা থাকে, সুতরাং গ্যারান্টি দেয় যে আপনার ফাংশনের এলোমেলোতা রয়েছে is কমপক্ষে মূল র্যান্ড (5) ফাংশনের মতো এলোমেলো। এটি একটি দুর্দান্ত সমাধান!
মো বেইগি

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

1
কিছু মনে করবেন না, আমি "যখন returnValue == 0" অংশ মিস
NicholasFolk

19
int randbit( void )
{
    while( 1 )
    {
        int r = rand5();
        if( r <= 4 ) return(r & 1);
    }
}

int randint( int nbits )
{
    int result = 0;
    while( nbits-- )
    {
        result = (result<<1) | randbit();
    }
    return( result );
}

int rand7( void )
{
    while( 1 )
    {
        int r = randint( 3 ) + 1;
        if( r <= 7 ) return( r );
    }
}

2
একটি সঠিক সমাধান, র‌্যান্ড 7 () এ কল প্রতি র‌্যান্ড 5 () এ কল করুন গড় 30/7 = 4.29 making
অ্যাডাম রোজেনফিল্ড

17
rand7() = (rand5()+rand5()+rand5()+rand5()+rand5()+rand5()+rand5())%7+1

সম্পাদনা: এটি বেশিরভাগ কাজ করে না। এটি 1000 এ প্রায় 2 অংশ দ্বারা বন্ধ রয়েছে (নিখুঁত র্যান্ড 5 অনুমান করে)। বালতি পেতে:

value   Count  Error%
1       11158  -0.0035
2       11144  -0.0214
3       11144  -0.0214
4       11158  -0.0035
5       11172  +0.0144
6       11177  +0.0208
7       11172  +0.0144

একটি যোগফলে স্যুইচ করে

n   Error%
10  +/- 1e-3,
12  +/- 1e-4,
14  +/- 1e-5,
16  +/- 1e-6,
...
28  +/- 3e-11

যোগ করা প্রতিটি 2 জন্য প্রশস্ততার অর্ডার অর্জন বলে মনে হচ্ছে

বিটিডব্লিউ: উপরের ত্রুটিগুলির সারণি নমুনা তৈরির মাধ্যমে তৈরি করা হয়নি তবে নিম্নলিখিত পুনরাবৃত্তির সম্পর্কের মাধ্যমে:

p[x,n]কল output=xদেওয়া nফোন নম্বর ঘটতে পারে rand5

  p[1,1] ... p[5,1] = 1
  p[6,1] ... p[7,1] = 0

  p[1,n] = p[7,n-1] + p[6,n-1] + p[5,n-1] + p[4,n-1] + p[3,n-1]
  p[2,n] = p[1,n-1] + p[7,n-1] + p[6,n-1] + p[5,n-1] + p[4,n-1]
  p[3,n] = p[2,n-1] + p[1,n-1] + p[7,n-1] + p[6,n-1] + p[5,n-1]
  p[4,n] = p[3,n-1] + p[2,n-1] + p[1,n-1] + p[7,n-1] + p[6,n-1]
  p[5,n] = p[4,n-1] + p[3,n-1] + p[2,n-1] + p[1,n-1] + p[7,n-1]
  p[6,n] = p[5,n-1] + p[4,n-1] + p[3,n-1] + p[2,n-1] + p[1,n-1]
  p[7,n] = p[6,n-1] + p[5,n-1] + p[4,n-1] + p[3,n-1] + p[2,n-1]

8
এটি অভিন্ন বিতরণ নয়। এটি ইউনিফর্মের খুব কাছাকাছি , তবে পুরোপুরি অভিন্ন নয়।
অ্যাডাম রোজেনফিল্ড

আহ! পাশা এবং 7 এর। আপনি যদি ভুল বলতে চান তবে আপনার প্রমাণটি পাঠকের জন্য অনুশীলন হিসাবে ছেড়ে দেওয়া উচিত নয়।
বিসিএস 0

45
এটি অভিন্ন নয় এর প্রমাণটি সহজ: 5 ^ 7 সম্ভাব্য উপায় রয়েছে যা এলোমেলোভাবে যেতে পারে, এবং 5 ^ 7 যেমন 7 এর একক নয়, এটি সম্ভব নয় যে সমস্ত 7 টি পরিমাণ সমানভাবে সম্ভব। (মূলত, এটি 5 টি তুলনামূলকভাবে প্রাইম হিসাবে 5 এ নেমে যায় বা সমানভাবে 1/7 বেস 5 এ শেষ হওয়া দশমিক হয় না) বাস্তবে এটি এই সীমাবদ্ধতার অধীনেও "সর্বাধিক ইউনিফর্ম" নয়: প্রত্যক্ষ গণনা এটি দেখায় যে 5 ^ 7 = 78125 অঙ্কের পরিমাণ, আপনি 1 থেকে 7 এর মানগুলি পেয়েছেন তার সংখ্যা} 1: 11145, 2: 11120, 3: 11120, 4: 11145, 5: 11190, 6: 11215, 7: 11190}}}
শ্রীভাতসার আর

@ শ্রীভত্সআর তাই, তবে যদি র্যান্ড 5 () এর যোগফল সাতবার না নিয়ে, আমরা এটি 5 * 7 করে নিই - তবে কি এই কাজটি হবে না? 35 ^ 7% 7 = 35 ^ 5% 7 = 0.
কেবিএ

4
@ ক্রিশ্চিয়্যান্টনসনসন: আপনি কতবার র্যান্ড 5 () করেছেন, আপনি অভিন্ন বিতরণ পাবেন না। যদি আপনি এটি এন বার করেন তবে 5 ^ N সম্ভাব্য আউটপুট রয়েছে, যা div দ্বারা বিভাজ্য নয় you (আপনি যদি এটি 35 বার করেন তবে 5 ^ 35 থাকে, 35 ^ 7 হয় না)) আপনি আরও কাছাকাছি পৌঁছে যাবেন আপনি যে বৃহত সংখ্যক কল ব্যবহার করেন তা সমান করুন (এবং এটি কোনও নম্বর হতে পারে, by দ্বারা বিভাজ্য হতে হবে না), তবে আইএমএইচও খুব বেশি সংখ্যক কলকে র‌্যান্ড () ব্যবহার করার পরিবর্তে, আপনি সম্ভাব্যতাও ব্যবহার করতে পারেন শীর্ষগুলির উত্তরে অ্যালগরিদম, যা সঠিক ইউনিফর্ম বিতরণ দেয় এবং যার প্রত্যাশিত সংখ্যার নামটি র‍্যান্ড () এ ছোট হয়।
শ্রীভাতসার

15
int ans = 0;
while (ans == 0) 
{
     for (int i=0; i<3; i++) 
     {
          while ((r = rand5()) == 3){};
          ans += (r < 3) >> i
     }
}

2
একটি সঠিক সমাধান, র‌্যান্ড 7 () এ কল প্রতি র‌্যান্ড 5 () এ কল করুন গড় 30/7 = 4.29 making
অ্যাডাম রোজেনফিল্ড

3
অ্যালগরিদমকে কাজ করতে রেখে যেতে হবে :ans += (r < 3) << i
উলফি

13

নিম্নলিখিতটি rand 1, 2, 3, 4, 5 on এ অভিন্ন বিতরণ উত্পাদন করে একটি এলোমেলো সংখ্যা জেনারেটর ব্যবহার করে 1 2, 2, 3, 4, 5, 6, 7 on এ অভিন্ন বিতরণ তৈরি করে} কোডটি অগোছালো তবে যুক্তিটি পরিষ্কার।

public static int random_7(Random rg) {
    int returnValue = 0;
    while (returnValue == 0) {
        for (int i = 1; i <= 3; i++) {
            returnValue = (returnValue << 1) + SimulateFairCoin(rg);
        }
    }
    return returnValue;
}

private static int SimulateFairCoin(Random rg) {
    while (true) {
        int flipOne = random_5_mod_2(rg);
        int flipTwo = random_5_mod_2(rg);

        if (flipOne == 0 && flipTwo == 1) {
            return 0;
        }
        else if (flipOne == 1 && flipTwo == 0) {
            return 1;
        }
    }
}

private static int random_5_mod_2(Random rg) {
    return random_5(rg) % 2;
}

private static int random_5(Random rg) {
    return rg.Next(5) + 1;
}    

2
একটি সঠিক সমাধান (যা আপনাকে বক্ররেখার আগে ফেলেছে), যদিও খুব দক্ষ নয়। এটি রেন্ডম_7 () এ কল প্রতি 100/7 = 14.3 কল প্রতি রেন্ডম_5 () এ মোট গড় হিসাবে, ন্যায্য মুদ্রা ফ্লিপ প্রতি র্যান্ডম_5_mod_2 এ গড়ে 25/6 = 4.17 কল করে।
অ্যাডাম রোজেনফিল্ড

অন্যদের চেয়ে এই সমাধানটির সুবিধাটি হ'ল এটি যে কোনও অন্যরকম বিতরণ করা পরিসীমা উত্পাদন করতে সহজেই প্রসারিত হতে পারে। কেবল এলোমেলোভাবে প্রতিটি বিট নির্বাচন করুন, অবৈধ মানগুলিতে পুনরায় ঘূর্ণায়মান (আমাদের বর্তমান সমাধানে 0 মান যা 8 সংখ্যা উত্পন্ন করে)।
DenTheMan 16'11

1
সম্ভব অসীম loops, ইত্যাদি
robermorales

1
@robermorales: অত্যন্ত সম্ভাবনা নেই।
জেসন

13
int rand7() {
    int value = rand5()
              + rand5() * 2
              + rand5() * 3
              + rand5() * 4
              + rand5() * 5
              + rand5() * 6;
    return value%7;
}

নির্বাচিত সমাধানের বিপরীতে, অ্যালগরিদম স্থির সময়ে চলবে। তবে এটি নির্বাচিত সমাধানের গড় রান সময়ের চেয়ে র্যান্ড 5 এ আরও 2 টি কল করে।

মনে রাখবেন যে এই জেনারেটরটি নিখুঁত নয় (সংখ্যাটিতে 0 অন্যান্য সংখ্যাগুলির তুলনায় 0.0064% বেশি সুযোগ রয়েছে), তবে বেশিরভাগ ব্যবহারিক উদ্দেশ্যে ধ্রুবক সময়ের গ্যারান্টি সম্ভবত এই ত্রুটিটিকে ছাড়িয়ে যায়।

ব্যাখ্যা

এই সমাধানটি 15,624 নম্বরটি 7 দ্বারা বিভাজ্য এই সত্য থেকে উদ্ভূত হয়েছে এবং আমরা যদি এলোমেলোভাবে এবং অভিন্নভাবে 0 থেকে 15,624 পর্যন্ত সংখ্যা তৈরি করতে পারি এবং তারপরে 7 মড নিতে পারি আমরা একটি অভিন্ন ইউনিফর্ম র্যান্ড 7 জেনারেটর পেতে পারি। 0 থেকে 15,624 পর্যন্ত নম্বরগুলি র‍্যান্ড 55 রোল করে এবং বেস 5 সংখ্যার অঙ্কগুলি নিম্নলিখিত রূপে ব্যবহার করে অভিন্নভাবে তৈরি করা যেতে পারে:

rand5 * 5^5 + rand5 * 5^4 + rand5 * 5^3 + rand5 * 5^2 + rand5 * 5 + rand5

Mod 7 এর বৈশিষ্ট্যগুলি তবে আমাদের সমীকরণটি কিছুটা সহজ করার অনুমতি দেয়:

5^5 = 3 mod 7
5^4 = 2 mod 7
5^3 = 6 mod 7
5^2 = 4 mod 7
5^1 = 5 mod 7

সুতরাং

rand5 * 5^5 + rand5 * 5^4 + rand5 * 5^3 + rand5 * 5^2 + rand5 * 5 + rand5

হয়ে

rand5 * 3 + rand5 * 2 + rand5 * 6 + rand5 * 4 + rand5 * 5 + rand5

তত্ত্ব

15,624 নম্বরটি এলোমেলোভাবে বেছে নেওয়া হয়নি, তবে ফেরমেটের সামান্য উপপাদ্যটি ব্যবহার করে এটি আবিষ্কার করা যেতে পারে, যা বলে যে পি যদি প্রধান সংখ্যা হয় তবে

a^(p-1) = 1 mod p

সুতরাং এটি আমাদের দেয়,

(5^6)-1 = 0 mod 7

(5 ^ 6) -1 এর সমান

4 * 5^5 + 4 * 5^4 + 4 * 5^3 + 4 * 5^2 + 4 * 5 + 4

এটি বেস 5 ফর্মের একটি সংখ্যা এবং সুতরাং আমরা দেখতে পারি যে এই পদ্ধতিটি যেকোন র্যান্ডম নম্বর জেনারেটর থেকে অন্য কোনও এলোমেলো নম্বর জেনারেটরে যেতে ব্যবহার করা যেতে পারে। যদিও 0-এর দিকে একটি ছোট পক্ষপাত সর্বদা চালু করা হয় যখন প্রকাশক p-1 ব্যবহার করে।

এই পদ্ধতির সাধারণীকরণ করতে এবং আরও নির্ভুল হওয়ার জন্য আমাদের এর মতো ফাংশন থাকতে পারে:

def getRandomconverted(frm, to):
    s = 0
    for i in range(to):
        s += getRandomUniform(frm)*frm**i
    mx = 0
    for i in range(to):
        mx = (to-1)*frm**i 
    mx = int(mx/to)*to # maximum value till which we can take mod
    if s < mx:
        return s%to
    else:
        return getRandomconverted(frm, to)

1
এই জেনারেটর সঠিক, কিন্তু না পুরোপুরি অভিন্ন। এটি দেখতে, বিবেচনা করুন যে [0,15624] এ অভিন্ন জেনারেটরের 15625 সম্ভাব্য ফলাফল রয়েছে, যা by দ্বারা বিভাজ্য নয় This এটি 0 সংখ্যার পক্ষপাতদুটির পরিচয় দেয় (যার 2233/15625 সুযোগ রয়েছে, এবং অন্যরা কেবলমাত্র 2232/15625)। সর্বোপরি, ফারম্যাট এর সামান্য উপপাদ্যটি প্রথম নজরে সঠিক মনে হতে পারে, তবে এটি বলে যে (5 ^ 6)% 7 = 1, এবং (5 ^ 6)% 7 = 0 নয়। দ্বিতীয়টি কোনও উদ্দিষ্টের পক্ষে স্পষ্টতই অসম্ভব কারণ 5 এবং 7 উভয়ই প্রধান সংখ্যা। আমি মনে করি এটি এখনও একটি গ্রহণযোগ্য সমাধান এবং এটি প্রতিফলিত করার জন্য আমি আপনার পোস্ট সম্পাদনা করেছি।
এভিয়েটর

12

হোমওয়ার্ক সমস্যা এখানে অনুমোদিত?

এই ফাংশনটি 0 থেকে 6 এর মধ্যে একটি সংখ্যা তৈরি করতে অশোধিত "বেস 5" গণিত করে।

function rnd7() {
    do {
        r1 = rnd5() - 1;
        do {
            r2=rnd5() - 1;
        } while (r2 > 1);
        result = r2 * 5 + r1;
    } while (result > 6);
    return result + 1;
}

3
একটি সঠিক সমাধান (যা আপনাকে বক্ররেখার আগে ফেলেছে), যদিও খুব দক্ষ নয়। Rnd7 () এ প্রতিটি কলের জন্য এটি rnd5 () এ গড়ে 5 টি কল করে।
অ্যাডাম রোজেনফিল্ড

আরও কিছু ব্যাখ্যা প্লিজ দরকার
ব্যারি

1
@ ব্যারি - প্রথমত, আপনি কেবল দুটি এলোমেলো সংখ্যা একসাথে যোগ করতে পারবেন না, আপনি একটি রৈখিক সমাধান পাবেন না (একজোড়া পাশা বিবেচনা করুন)। এখন "বেস 5" বিবেচনা করুন: 00, 01, 02, 03, 04, 10, 11. বেস 5 এ 0-6 তাই, আমাদের কেবল বেস 5 সংখ্যার 2 ডিজিট উত্পন্ন করতে হবে এবং আমাদের অবধি এগুলি যুক্ত করা দরকার সীমা মধ্যে যে একটি পেতে। আর 2 * 5 + আর 1 এটি করে। R2> 1 লুপ আছে কারণ আমরা> 1. একটি উচ্চ অঙ্ক কখনোই চাইবেন
উইল Hartung

এই সমাধানটি অভিন্ন বিতরণ উত্পন্ন করে না। 1 এবং 7 সংখ্যাটি কেবল একটি উপায়ে তৈরি করা যায় তবে প্রতিটি বিয়োগ 1 এবং r2 সমান 0 এর সাথে সমান r1 সহ বা বিয়োগ সংখ্যার 2 এবং r2 সমান r1 সমান 2 টির মাধ্যমে 2 টি 6 টির মাধ্যমে দুটি উপায়ে উত্পন্ন করা যায় ১. সুতরাং ২ থেকে জন গড়ে ১ বা 7. বার হিসাবে গড় দ্বিগুণ ফিরে আসবে
টেড হপ

12

যদি আমরা সর্বাধিক দক্ষ উত্তর দেওয়ার চেষ্টা করার অতিরিক্ত বাধা বিবেচনা করি যেমন একটি ইনপুট স্ট্রিম দিয়েছে, 1-5 থেকে Iদৈর্ঘ্যের সমানভাবে বিতরণকৃত পূর্ণসংখ্যার mএকটি প্রবাহকে আউটপুট Oদেয়, দীর্ঘতম দৈর্ঘের আপেক্ষিকের 1-7 থেকে সমানভাবে বিতরণকৃত পূর্ণসংখ্যাগুলি বলতে m, বলতে L(m)

এটি বিশ্লেষণের সহজতম উপায় হ'ল স্ট্রিমগুলি I এবং Oযথাক্রমে 5-অ্যারি এবং 7-অ্যারি সংখ্যার হিসাবে আচরণ করা। এটি স্ট্রিমটি গ্রহণের মূল উত্তরটির ধারণা a1, a2, a3,... -> a1+5*a2+5^2*a3+..এবং একইভাবে স্রোতের জন্য অর্জন করেছে O

তারপরে যদি আমরা দৈর্ঘ্যের ইনপুট স্ট্রিমের একটি অংশ নিই m choose n s.t. 5^m-7^n=cযেখানে c>0এবং যতটা সম্ভব ছোট। তারপর সেখান থেকে একটি অভিন্ন মানচিত্র পূর্ণসংখ্যার থেকে দৈর্ঘ্য মিটার ইনপুট স্ট্রিম থেকে 1থেকে 5^mএবং অন্য অভিন্ন 1 থেকে মানচিত্র পূর্ণসংখ্যার থেকে 7^nদৈর্ঘ্য আউটপুট প্রবাহে এন আমরা যখন ম্যাপ করা পূর্ণসংখ্যা ইনপুট স্ট্রিম থেকে কিছু ক্ষেত্রে হারান করতে হতে পারে যেখানে অতিক্রম করে 7^n

তাই এই জন্য একটি মান দেয় L(m)চারপাশে m (log5/log7)যা আনুমানিক হয় .82m

উপরে বিশ্লেষণের সঙ্গে অসুবিধা সমীকরণ হয় 5^m-7^n=cযা সহজ ঠিক সমাধানের জন্য নয় এবং ক্ষেত্রে কোথা থেকে অভিন্ন মান 1থেকে 5^mছাড়িয়ে গেছে 7^nএবং আমরা দক্ষতা হারান।

এম এর সর্বোত্তম সম্ভাব্য মান (লগ 5 / লগ 7) কতটা কাছাকাছি পাওয়া যায় তা প্রশ্ন। উদাহরণস্বরূপ, যখন এই সংখ্যাটি একটি পূর্ণসংখ্যার কাছাকাছি আসে আমরা আউটপুট মানগুলির এই নিখুঁত অবিচ্ছেদ্য সংখ্যা অর্জনের জন্য কোনও উপায় খুঁজে পেতে পারি?

তাহলে 5^m-7^n=cতারপর ইনপুট স্ট্রিম থেকে আমরা কার্যকরভাবে থেকে একটি অভিন্ন র্যান্ডম সংখ্যা উৎপন্ন 0করতে (5^m)-1এবং বেশী কোন মান ব্যবহার করবেন না 7^n। তবে এই মানগুলি উদ্ধার করে আবার ব্যবহার করা যেতে পারে। তারা কার্যকরভাবে 1 থেকে সংখ্যার অভিন্ন ক্রম তৈরি করে 5^m-7^n। সুতরাং আমরা এগুলি ব্যবহার করার চেষ্টা করতে পারি এবং তাদের 7-অ্যারি সংখ্যায় রূপান্তর করতে পারি যাতে আমরা আরও আউটপুট মান তৈরি করতে পারি।

আমরা দিন যদি T7(X)আউটপুট ক্রম গড় দৈর্ঘ্য হতে random(1-7)আকারের একটি অভিন্ন ইনপুট থেকে উদ্ভূত পূর্ণসংখ্যার X, এবং যে অভিমানী 5^m=7^n0+7^n1+7^n2+...+7^nr+s, s<7

তারপরে সম্ভাব্যতার সাথে T7(5^m)=n0x7^n0/5^m + ((5^m-7^n0)/5^m) T7(5^m-7^n0)দৈর্ঘ্যের অবশিষ্টাংশের সাথে আমাদের সম্ভাব্যতা 7 ^ n0 / 5 we মিটারের দৈর্ঘ্যের কোনও অনুক্রম নেই ।5^m-7^n0(5^m-7^n0)/5^m)

যদি আমরা কেবল স্থিতি রাখি তবে আমরা পাই:

T7(5^m) = n0x7^n0/5^m + n1x7^n1/5^m + ... + nrx7^nr/5^m  = (n0x7^n0 + n1x7^n1 + ... + nrx7^nr)/5^m

অত: পর

L(m)=T7(5^m)=(n0x7^n0 + n1x7^n1 + ... + nrx7^nr)/(7^n0+7^n1+7^n2+...+7^nr+s)

এটি দেওয়ার আরেকটি উপায় হ'ল:

If 5^m has 7-ary representation `a0+a1*7 + a2*7^2 + a3*7^3+...+ar*7^r
Then L(m) = (a1*7 + 2a2*7^2 + 3a3*7^3+...+rar*7^r)/(a0+a1*7 + a2*7^2 + a3*7^3+...+ar*7^r)

সর্বোত্তম সম্ভাব্য কেসটি আমার মূলটি উপরে যেখানে কোথায় 5^m=7^n+s, কোথায় s<7

তারপরে T7(5^m) = nx(7^n)/(7^n+s) = n+o(1) = m (Log5/Log7)+o(1)আগের মতোই।

সবচেয়ে খারাপ অবস্থাটি তখন হয় যখন আমরা কেবলমাত্র k এবং st 5 ^ m = kx7 + s খুঁজে পাই।

Then T7(5^m) = 1x(k.7)/(k.7+s) = 1+o(1)

অন্য মামলাগুলি কোথাও অন্তর্দ্বন্দ্বী। এটি দেখতে খুব আকর্ষণীয় হবে যে আমরা খুব বড় মিটারের জন্য কতটা ভাল করতে পারি, অর্থাৎ ত্রুটির শব্দটি আমরা কীভাবে পেতে পারি:

T7(5^m) = m (Log5/Log7)+e(m)

এটি e(m) = o(1)সাধারণভাবে অর্জন করা অসম্ভব বলে মনে হচ্ছে তবে আশা করি আমরা প্রমাণ করতে পারব e(m)=o(m)

পুরো জিনিসটি তখন 5^mবিভিন্ন মানের জন্য 7-অ্যারি ডিজিটের বিতরণের উপর নির্ভর করে m

আমি নিশ্চিত যে সেখানে প্রচুর তত্ত্ব আছে যা এটি কভার করে আমার কোনও চেহারা থাকতে পারে এবং কোনও সময়ে ফিরে রিপোর্ট করতে পারে।


+2 (যদি আমি পারতাম) - এটি ছিল একমাত্র ভাল উত্তর (কেবল পর্যাপ্ত পর্যায়ে বিপরীতে)। আপনি দ্বিতীয় সেরা উত্তর পেয়েছেন যা 32 বিট পূর্ণসংখ্যায় ফিট করবে।
রেক্স কের

10

এখানে অ্যাডামের উত্তরের একটি কার্যকরী পাইথন প্রয়োগ রয়েছে ।

import random

def rand5():
    return random.randint(1, 5)

def rand7():
    while True:
        r = 5 * (rand5() - 1) + rand5()
        #r is now uniformly random between 1 and 25
        if (r <= 21):
            break
    #result is now uniformly random between 1 and 7
    return r % 7 + 1

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


না, এটি আমার উত্তর থেকে সম্পূর্ণ ভিন্ন। আপনি 21 বার লুপ করছেন এবং প্রথম 20 পুনরাবৃত্তির ফলাফলগুলি বাতিল করছেন। আপনি ইনপুট হিসাবে একটি র্যান্ড 4 () এবং একটি র্যান্ড 5 () ব্যবহার করছেন, যা কেবল স্পষ্টতই কেবল55 () ব্যবহারের নিয়মগুলিকে ভঙ্গ করে। অবশেষে, আপনি একটি অ-অভিন্ন বিতরণ উত্পাদন করেন।
অ্যাডাম রোজনফিল্ড 13

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

@ আরবারমোরালস - অ্যাডাম রোজেনফিল্ড তার উত্তরে যেমন ব্যাখ্যা করেছেন , [১,]] এ প্রকৃত অভিন্ন বন্টন দেওয়ার প্রতিটি সমাধানের মধ্যে কিছুটা গ্রহণযোগ্য-প্রত্যাখ্যানকারী লুপ যুক্ত হবে যা সম্ভাব্য অসীম। (তবে, যদি rand5()কোনও শালীন পিআরএনজি হয় তবে লুপটি অসীম হবে না কারণ শেষ পর্যন্ত 5*(rand5() - 1) + rand5()অবশ্যই <= 21. হবে)
টেড হপ ৩

10

কেন এটি সহজ না?

int random7() {
  return random5() + (random5() % 3);
}

এই দ্রবণটিতে 1 এবং 7 পাওয়ার সম্ভাবনাগুলি মডিউলগুলির কারণে কম, তবে, আপনি যদি কেবল একটি দ্রুত এবং পঠনযোগ্য সমাধান চান তবে এটি এই পথ।


13
এটি অভিন্ন বিতরণ উত্পাদন করে না। এটি সম্ভাব্যতা 2/25, 4/25, 5/25, 5/25, 5/25, 3/25, 1/25 সহ 0-6 নম্বর উত্পন্ন করে, যতগুলি 25 সম্ভাব্য ফলাফল গণনা করে যাচাই করা যেতে পারে।
অ্যাডাম রোজেনফিল্ড

8

ধরে নিই যে র‌্যাণ্ড (এন) এর অর্থ এখানে " 0 থেকে n-1 থেকে অভিন্ন বিতরণে এলোমেলো পূর্ণসংখ্যা ", পাইথনের র্যান্ডিন্ট ব্যবহার করে এখানে একটি কোড নমুনা দেওয়া হয়েছে, যা এর প্রভাব ফেলে। এটি র্যান্ডেন্ট (7) এর প্রভাব তৈরি করতে কেবল র্যান্ডেন্ট (5) এবং ধ্রুবক ব্যবহার করে । একটু নির্বোধ, আসলে

from random import randint
sum = 7
while sum >= 7:
    first = randint(0,5)   
    toadd = 9999
    while toadd>1:
        toadd = randint(0,5)
    if toadd:
        sum = first+5
    else:
        sum = first

assert 7>sum>=0 
print sum

1
@robermorales- এর কাছে পাইথন নেই do ... while। এটি 1337, বা 12345, বা যে কোনও সংখ্যা> 1. থাকতে পারে
tckmn

8

অ্যাডাম রোজেনফিল্ডের সঠিক উত্তরের পিছনে ভিত্তিটি হ'ল:

  • x = 5 ^ n (তার ক্ষেত্রে: এন = 2)
  • এন rand5 কল নিপূণভাবে একটি নম্বর পেতে Y পরিসীমা [1, x এর] এর মধ্যে
  • z = ((অন্তঃ) (এক্স / 7)) * 7
  • যদি y> z, আবার চেষ্টা করুন। অন্যথায় y% 7 + 1 প্রদান করুন

যখন এন 2 এর সমান হয় তখন আপনার 4 টি ফেলে দেওয়ার সম্ভাবনা থাকে: y = {22, 23, 24, 25}} আপনি যদি n এর সমান 6 ব্যবহার করেন তবে আপনার কেবল 1 টি ফেলে দেওয়া হবে: y = {15625}}

5 ^ 6 = 15625
7 * 2232 = 15624

আপনি র্যান্ড 5 আরও বার কল করুন। তবে, আপনার কাছে থ্রো-অ্যাওয়ে মান (বা অসীম লুপ) পাওয়ার খুব কম সুযোগ রয়েছে। যদি আপনার জন্য কোনও সম্ভাব্য থ্রো-অ্যাভ মান পাওয়ার উপায় থাকে তবে আমি এটি এখনও পাইনি।


1
থ্রোওয়ে মান ব্যতীত কোনও ক্ষেত্রেই সম্ভবত নেই - যদি কোনও নিক্ষিপ্ত না হয়, তবে 5 and n এবং 7 in মিটারের মধ্যে একটি কারণ রয়েছে। তবে তারা প্রাইমস, তাই তারা না।
রেকর্ড কের

8

আমার উত্তর এখানে:

static struct rand_buffer {
  unsigned v, count;
} buf2, buf3;

void push (struct rand_buffer *buf, unsigned n, unsigned v)
{
  buf->v = buf->v * n + v;
  ++buf->count;
}

#define PUSH(n, v)  push (&buf##n, n, v)

int rand16 (void)
{
  int v = buf2.v & 0xf;
  buf2.v >>= 4;
  buf2.count -= 4;
  return v;
}

int rand9 (void)
{
  int v = buf3.v % 9;
  buf3.v /= 9;
  buf3.count -= 2;
  return v;
}

int rand7 (void)
{
  if (buf3.count >= 2) {
    int v = rand9 ();

    if (v < 7)
      return v % 7 + 1;

    PUSH (2, v - 7);
  }

  for (;;) {
    if (buf2.count >= 4) {
      int v = rand16 ();

      if (v < 14) {
        PUSH (2, v / 7);
        return v % 7 + 1;
      }

      PUSH (2, v - 14);
    }

    // Get a number between 0 & 25
    int v = 5 * (rand5 () - 1) + rand5 () - 1;

    if (v < 21) {
      PUSH (3, v / 7);
      return v % 7 + 1;
    }

    v -= 21;
    PUSH (2, v & 1);
    PUSH (2, v >> 1);
  }
}

এটি অন্যদের তুলনায় কিছুটা জটিল, তবে আমি বিশ্বাস করি এটি র্যান্ড 5 এ কলগুলি হ্রাস করে। অন্যান্য সমাধানগুলির মতো, একটি ছোট্ট সম্ভাবনা রয়েছে যা এটি দীর্ঘ সময়ের জন্য লুপ করতে পারে।


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

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


6

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

$num = 0;
$possibilities = 1;

sub rand7
{
  while( $possibilities < 7 )
  {
    $num = $num * 5 + int(rand(5));
    $possibilities *= 5;
  }
  my $result = $num % 7;
  $num = int( $num / 7 );
  $possibilities /= 7;
  return $result;
}

কমপক্ষে প্রথম কলটিতে আপনার বিতরণ অভিন্ন নয়। $possibilitiesলুপটি থেকে বেরিয়ে আসার জন্য প্রকৃতপক্ষে সর্বদা 25-এ বৃদ্ধি পেতে হবে। সুতরাং, আপনার প্রথম ফলাফলটি [0-124] % 7, যা অভিন্নভাবে বিতরণ করা হয়নি কারণ 125 % 7 != 0(এটি আসলে 6 is
বার্নার্ড পলুস

6

আমি 1 থেকে শুরু করে রেঞ্জ পছন্দ করি না, তাই আমি 0 :-) থেকে শুরু করব

unsigned rand5()
{
    return rand() % 5;
}

unsigned rand7()
{
    int r;

    do
    {
        r =         rand5();
        r = r * 5 + rand5();
        r = r * 5 + rand5();
        r = r * 5 + rand5();
        r = r * 5 + rand5();
        r = r * 5 + rand5();
    } while (r > 15623);

    return r / 2232;
}

এটি একটি বিজয়ী। এটি সমান সম্ভাবনা সহ সমস্ত 7 টি ফলাফল উত্পন্ন করে। from collections import defaultdict def r7(n): if not n: yield [] else: for i in range(1, 6): for j in r7(n-1): yield [i] + j def test_r7(): d = defaultdict(int) for x in r7(6): s = (((((((((x[5] * 5) + x[4]) * 5) + x[3]) * 5) + x[2]) * 5) + x[1]) * 5) + x[0] if s <= 15623: d[s % 7] += 1 print d
হিউডব্রাউন

5

সেখানে আপনি যান, অভিন্ন বিতরণ এবং শূন্য র্যান্ড 5 কল।

def rand7:
    seed += 1
    if seed >= 7:
        seed = 0
    yield seed

আগে থেকেই বীজ স্থাপন করা দরকার।


5

আমি জানি যে এটির উত্তর দেওয়া হয়েছে, তবে এটি কি ঠিক কাজ করে বলে মনে হচ্ছে তবে এর পক্ষপাতিত্ব আছে কিনা তা আমি আপনাকে বলতে পারি না। আমার 'পরীক্ষার' পরামর্শ দেয় এটি কমপক্ষে, যুক্তিসঙ্গত।

সম্ভবত অ্যাডাম রোজেনফিল্ড মন্তব্য করার যথেষ্ট সদয় হতে হবে?

আমার (নিষ্পাপ?) ধারণাটি হ'ল:

একটি র‌্যান্ড 7 তৈরি করার জন্য পর্যাপ্ত এলোমেলো বিট না পাওয়া পর্যন্ত র‌্যান্ড 5 এর জমে থাকা। এটি সর্বাধিক 2 র্যান্ড 5 এর লাগে। র্যান্ড 7 নম্বর পেতে আমি জমে থাকা মান 7 ব্যবহার করি।

জমে থাকা উপচে পড়া এড়ানোর জন্য, এবং যেহেতু সঞ্চালকটি 7 তম মডেল হয় তাই আমি সঞ্চয়ের মডেল 7 গ্রহণ করি:

(5a + rand5) % 7 = (k*7 + (5a%7) + rand5) % 7 = ( (5a%7) + rand5) % 7

র্যান্ড 7 () ফাংশনটি নিম্নলিখিত:

(আমি র্যান্ড 5 এর ব্যাপ্তি 0-4 হতে পারি এবং র্যান্ড 7 একইভাবে 0-6 হতে পারে))

int rand7(){
  static int    a=0;
  static int    e=0;
  int       r;
  a = a * 5 + rand5();
  e = e + 5;        // added 5/7ths of a rand7 number
  if ( e<7 ){
    a = a * 5 + rand5();
    e = e + 5;  // another 5/7ths
  }
  r = a % 7;
  e = e - 7;        // removed a rand7 number
  a = a % 7;
  return r;
}

সম্পাদনা: 100 মিলিয়ন পরীক্ষার জন্য ফলাফল যুক্ত করা হয়েছে।

'রিয়েল' র্যান্ড ফাংশনগুলি 5 বা 7 mod

র্যান্ড 5: গড় = 1.999802 0: 20003944 1: 19999889 2: 20003690 3: 19996938 4: 19995539 র্যান্ড 7: গড় = 3.000111 0: 14282851 1: 14282879 2: 14284554 3: 14288546 4: 14292388 5: 14288736 6: 14280046

আমার র্যান্ড 7

গড়পড়তা ঠিকঠাক দেখাচ্ছে এবং সংখ্যা বিতরণও ঠিক আছে।

র‌্যাণ্ড: গড় = 3.000080 0: 14288793 1: 14280135 2: 14287848 3: 14285277 4: 14286341 5: 14278663 6: 14292943


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

ধারাবাহিক সম্পর্ক কি এই সমাধানগুলির অনেকের জন্য প্রযোজ্য?
ফিলাকলবর্ন

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

4

উপরে বর্ণিত মার্জিত অ্যালগরিদম রয়েছে, তবে এটির কাছে যাওয়ার একটি উপায় এখানে রয়েছে, যদিও এটি চক্রাকার হতে পারে। আমি 0 থেকে উত্পন্ন মান ধরে নিচ্ছি।

আর 2 = এলোমেলো সংখ্যা জেনারেটর 2 টির চেয়ে কম মান দেয় (নমুনা স্পেস = = 0, 1}) আর
8 = এলোমেলো নম্বর জেনারেটর 8 এর চেয়ে কম মান দেয় (নমুনা স্পেস = {0, 1, 2, 3, 4, 5, 6, 7 })

আর 2 থেকে আর 8 উত্পন্ন করার জন্য, আপনি তিনবার আর 2 চালাবেন এবং 3 টি সংখ্যার সাথে বাইনারি সংখ্যা হিসাবে সমস্ত 3 রানের সম্মিলিত ফলাফলটি ব্যবহার করবেন। R2 তিনবার চালিত হলে মানগুলির পরিসীমা এখানে রয়েছে:

0 0 0 -> 0


1 1 1 -> 7

এখন আর 8 থেকে আর 7 জেনারেট করার জন্য, আমরা কেবল আবার আর 7 চালিয়ে দিই যদি এটি 7:

int R7() {
  do {
    x = R8();
  } while (x > 6)
  return x;
}

চতুর্দিকে সমাধানটি হ'ল আর 5 থেকে আর 2 উত্পন্ন করা (ঠিক যেমন আমরা আর 8 থেকে আর 7 উত্পন্ন করেছি), তারপরে আর 2 থেকে আর 8 এবং আর 8 থেকে আর 7 তৈরি করা।


অন্যান্য সংখ্যার মতো, এই পদ্ধতির জন্য R7 কল প্রতি নির্বিচারে দীর্ঘ সময় নিতে পারে, যেহেতু আপনি আর 8 থেকে সপ্তরের দীর্ঘ স্ট্রিং পেতে পারেন।
অ্যালেক্স উত্তর-কীগুলি

4

এখানে একটি সমাধান রয়েছে যা পুরোপুরি পূর্ণসংখ্যার সাথে ফিট করে এবং প্রায় 4% এর মধ্যে থাকে (অর্থাত্ {0..6} এর প্রতিটির জন্য 26 0..4 in এ 1.26 র্যান্ডম সংখ্যার ব্যবহার করে)। কোডটি স্কালায় রয়েছে তবে গণিতটি যে কোনও ভাষায় যুক্তিযুক্তভাবে পরিষ্কার হওয়া উচিত: আপনি 7 ^ 9 + 7 ^ 8 এর 5 ^ 11 এর খুব কাছাকাছি যে বিষয়টি গ্রহণ করেন। সুতরাং আপনি বেস 5 এ 11 ডিজিটের নম্বরটি বেছে নিন এবং তারপরে এটি 9 সেকেন্ডের সংখ্যা হিসাবে ব্যাখ্য করুন যদি এটি সীমার মধ্যে থাকে (9 বেস 7 নম্বর দিচ্ছে), বা এটি যদি 8 ডিজিটের সংখ্যার চেয়ে বেশি হয় তবে এটি 8 সংখ্যা হিসাবে ।

abstract class RNG {
  def apply(): Int
}

class Random5 extends RNG {
  val rng = new scala.util.Random
  var count = 0
  def apply() = { count += 1 ; rng.nextInt(5) }
}

class FiveSevener(five: RNG) {
  val sevens = new Array[Int](9)
  var nsevens = 0
  val to9 = 40353607;
  val to8 = 5764801;
  val to7 = 823543;
  def loadSevens(value: Int, count: Int) {
    nsevens = 0;
    var remaining = value;
    while (nsevens < count) {
      sevens(nsevens) = remaining % 7
      remaining /= 7
      nsevens += 1
    }
  }
  def loadSevens {
    var fivepow11 = 0;
    var i=0
    while (i<11) { i+=1 ; fivepow11 = five() + fivepow11*5 }
    if (fivepow11 < to9) { loadSevens(fivepow11 , 9) ; return }
    fivepow11 -= to9
    if (fivepow11 < to8) { loadSevens(fivepow11 , 8) ; return }
    fivepow11 -= to8
    if (fivepow11 < 3*to7) loadSevens(fivepow11 % to7 , 7)
    else loadSevens
  }
  def apply() = {
    if (nsevens==0) loadSevens
    nsevens -= 1
    sevens(nsevens)
  }
}

আপনি যদি দোভাষীর (সত্যিকার অর্থে) পরীক্ষায় পেস্ট করেন তবে আপনি পাবেন:

scala> val five = new Random5
five: Random5 = Random5@e9c592

scala> val seven = new FiveSevener(five)
seven: FiveSevener = FiveSevener@143c423

scala> val counts = new Array[Int](7)
counts: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0)

scala> var i=0 ; while (i < 100000000) { counts( seven() ) += 1 ; i += 1 }
i: Int = 100000000

scala> counts
res0: Array[Int] = Array(14280662, 14293012, 14281286, 14284836, 14287188,
14289332, 14283684)

scala> five.count
res1: Int = 125902876

বিতরণটি দুর্দান্ত এবং সমতল (প্রায় প্রতিটি গায়ে 10 ^ 8 এর 1/7 এর প্রায় 10k এর মধ্যে, প্রায়-গাউসীয় বিতরণ থেকে প্রত্যাশিত)।


3

ঘূর্ণায়মান মোট ব্যবহার করে , আপনি উভয়ই করতে পারেন

  • সমান বন্টন বজায় রাখা; এবং
  • এলোমেলো ক্রমের কোনও উপাদানকে ত্যাগ করতে হবে না।

এই উভয় rand(5)+rand(5)...সমস্যাই সরল- টাইপ সমাধানগুলির সাথে একটি সমস্যা । নিম্নলিখিত পাইথন কোডটি কীভাবে এটি প্রয়োগ করতে হবে তা দেখায় (এর বেশিরভাগই বিতরণ প্রমাণ করছে)।

import random
x = []
for i in range (0,7):
    x.append (0)
t = 0
tt = 0
for i in range (0,700000):
    ########################################
    #####            qq.py             #####
    r = int (random.random () * 5)
    t = (t + r) % 7
    ########################################
    #####       qq_notsogood.py        #####
    #r = 20
    #while r > 6:
        #r =     int (random.random () * 5)
        #r = r + int (random.random () * 5)
    #t = r
    ########################################
    x[t] = x[t] + 1
    tt = tt + 1
high = x[0]
low = x[0]
for i in range (0,7):
    print "%d: %7d %.5f" % (i, x[i], 100.0 * x[i] / tt)
    if x[i] < low:
        low = x[i]
    if x[i] > high:
        high = x[i]
diff = high - low
print "Variation = %d (%.5f%%)" % (diff, 100.0 * diff / tt)

এবং এই আউটপুট ফলাফলগুলি দেখায়:

pax$ python qq.py
0:   99908 14.27257
1:  100029 14.28986
2:  100327 14.33243
3:  100395 14.34214
4:   99104 14.15771
5:   99829 14.26129
6:  100408 14.34400
Variation = 1304 (0.18629%)

pax$ python qq.py
0:   99547 14.22100
1:  100229 14.31843
2:  100078 14.29686
3:   99451 14.20729
4:  100284 14.32629
5:  100038 14.29114
6:  100373 14.33900
Variation = 922 (0.13171%)

pax$ python qq.py
0:  100481 14.35443
1:   99188 14.16971
2:  100284 14.32629
3:  100222 14.31743
4:   99960 14.28000
5:   99426 14.20371
6:  100439 14.34843
Variation = 1293 (0.18471%)

একটি সরল rand(5)+rand(5), যারা ক্ষেত্রে যেখানে চেয়ে বেশি 6 এই আয় 18%, একটি আদর্শ প্রকরণ রয়েছে উপেক্ষা 100 বার পদ্ধতির যে উপরে দেখানো:

pax$ python qq_notsogood.py
0:   31756 4.53657
1:   63304 9.04343
2:   95507 13.64386
3:  127825 18.26071
4:  158851 22.69300
5:  127567 18.22386
6:   95190 13.59857
Variation = 127095 (18.15643%)

pax$ python qq_notsogood.py
0:   31792 4.54171
1:   63637 9.09100
2:   95641 13.66300
3:  127627 18.23243
4:  158751 22.67871
5:  126782 18.11171
6:   95770 13.68143
Variation = 126959 (18.13700%)

pax$ python qq_notsogood.py
0:   31955 4.56500
1:   63485 9.06929
2:   94849 13.54986
3:  127737 18.24814
4:  159687 22.81243
5:  127391 18.19871
6:   94896 13.55657
Variation = 127732 (18.24743%)

এবং, নিক্সুজের পরামর্শে, আমি স্ক্রিপ্টটি সাফ করে দিয়েছি যাতে আপনি খালি rand7...জিনিস বের করতে এবং ব্যবহার করতে পারেন:

import random

# rand5() returns 0 through 4 inclusive.

def rand5():
    return int (random.random () * 5)

# rand7() generator returns 0 through 6 inclusive (using rand5()).

def rand7():
    rand7ret = 0
    while True:
        rand7ret = (rand7ret + rand5()) % 7
        yield rand7ret

# Number of test runs.

count = 700000

# Work out distribution.

distrib = [0,0,0,0,0,0,0]
rgen =rand7()
for i in range (0,count):
    r = rgen.next()
    distrib[r] = distrib[r] + 1

# Print distributions and calculate variation.

high = distrib[0]
low = distrib[0]
for i in range (0,7):
    print "%d: %7d %.5f" % (i, distrib[i], 100.0 * distrib[i] / count)
    if distrib[i] < low:
        low = distrib[i]
    if distrib[i] > high:
        high = distrib[i]
diff = high - low
print "Variation = %d (%.5f%%)" % (diff, 100.0 * diff / count)

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

3
এটি সত্য যে ইনপুট এবং আউটপুট ফাংশনগুলি স্বতন্ত্র এবং অভিন্ন-বিতরণকৃত (আইআইডি) নমুনা উত্পন্ন করে তবে মূল প্রশ্নটি নির্দিষ্ট করে না তবে আমি মনে করি এটি যুক্তিসঙ্গত প্রত্যাশা যে যদি ইনপুট র্যান্ড 5 () আইড হয় তবে আউটপুট র্যান্ড 7 () আইআইডি হওয়া উচিত। যদি আপনি এটি যুক্তিসঙ্গত মনে না করেন তবে আপনার নন-আইড আরএনজি ব্যবহার করে মজা করুন।
অ্যাডাম রোজেনফিল্ড

1
তো, বিশ্ববিদ্যালয়ের গণিতবিদদের কাছ থেকে শব্দটি কী?
অ্যাডাম রোজেনফিল্ড

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

1
@ প্যাক্স আপনার ফাংশনটির প্রতিটি পুনরাবৃত্তিতে, এটি কেবল পাঁচটি পৃথক মানের মধ্যে একটি (যেটি ০--6 এর মধ্যে থাকা সত্ত্বেও) ফিরিয়ে দিতে পারে। খুব প্রথম পুনরাবৃত্তি কেবল 0-4-এর মধ্যে একটি নম্বর দিতে পারে। সুতরাং, এটি পরিষ্কার হওয়া উচিত যে আপনার ফাংশনটিতে অভিন্ন বন্টন থাকতে পারে, নমুনাগুলি স্বতন্ত্র নয় they এগুলি পরস্পর সম্পর্কযুক্ত যা আপনি এলোমেলো সংখ্যার জেনারেটরে চান এমন কিছু নয়।
ক্রিস সুটার

3

এই উত্তরটি র‌্যান্ড 5 ফাংশন থেকে সর্বাধিক এনট্রপি প্রাপ্তিতে আরও একটি পরীক্ষা experiment টি তাই কিছুটা অস্পষ্ট এবং অন্যান্য বাস্তবায়নগুলির তুলনায় প্রায় অবশ্যই অনেক ধীর।

0-4 থেকে অভিন্ন বিতরণ এবং 0-6 থেকে অভিন্ন বিতরণ হিসাবে ধরে নেওয়া:

public class SevenFromFive
{
  public SevenFromFive()
  {
    // this outputs a uniform ditribution but for some reason including it 
    // screws up the output distribution
    // open question Why?
    this.fifth = new ProbabilityCondensor(5, b => {});
    this.eigth = new ProbabilityCondensor(8, AddEntropy);
  } 

  private static Random r = new Random();
  private static uint Rand5()
  {
    return (uint)r.Next(0,5);
  }

  private class ProbabilityCondensor
  {
    private readonly int samples;
    private int counter;
    private int store;
    private readonly Action<bool> output;

    public ProbabilityCondensor(int chanceOfTrueReciprocal,
      Action<bool> output)
    {
      this.output = output;
      this.samples = chanceOfTrueReciprocal - 1;  
    }

    public void Add(bool bit)
    {
      this.counter++;
      if (bit)
        this.store++;   
      if (counter == samples)
      {
        bool? e;
        if (store == 0)
          e = false;
        else if (store == 1)
          e = true;
        else
          e = null;// discard for now       
        counter = 0;
        store = 0;
        if (e.HasValue)
          output(e.Value);
      }
    }
  }

  ulong buffer = 0;
  const ulong Mask = 7UL;
  int bitsAvail = 0;
  private readonly ProbabilityCondensor fifth;
  private readonly ProbabilityCondensor eigth;

  private void AddEntropy(bool bit)
  {
    buffer <<= 1;
    if (bit)
      buffer |= 1;      
    bitsAvail++;
  }

  private void AddTwoBitsEntropy(uint u)
  {
    buffer <<= 2;
    buffer |= (u & 3UL);    
    bitsAvail += 2;
  }

  public uint Rand7()
  {
    uint selection;   
    do
    {
      while (bitsAvail < 3)
      {
        var x = Rand5();
        if (x < 4)
        {
          // put the two low order bits straight in
          AddTwoBitsEntropy(x);
          fifth.Add(false);
        }
        else
        { 
          fifth.Add(true);
        }
      }
      // read 3 bits
      selection = (uint)((buffer & Mask));
      bitsAvail -= 3;     
      buffer >>= 3;
      if (selection == 7)
        eigth.Add(true);
      else
        eigth.Add(false);
    }
    while (selection == 7);   
    return selection;
  }
}

র্যান্ড 5 এ কল প্রতি বাফারে যুক্ত বিটের সংখ্যা বর্তমানে 4/5 * 2 তাই 1.6। যদি 1/5 সম্ভাব্যতার মানটি অন্তর্ভুক্ত করা হয় যা 0.05 সুতরাং 1.65 দ্বারা বৃদ্ধি পায় তবে কোডটি যেখানে আমাকে এটি অক্ষম করতে হয়েছে তাতে মন্তব্যটি দেখুন।

র‌্যান্ড 7 = 3 + 1/8 * (3 + 1/8 * (3 + 1/8 * (...
এটি 3 + 3/8 + 3/64 + 3/512 এ কল করুন প্রায় 3.42

সাতটি থেকে তথ্য আহরণ করে আমি কল প্রতি 1/8 * 1/7 বিট পুনরায় দাবি করি তাই প্রায় 0.018

এটি কল প্রতি নেট ব্যবহারের জন্য 3.4 বিট দেয় যার মানে অনুপাতটি প্রতিটি র‌্যান্ড 7 এর জন্য র‌্যান্ড 5 এ 2.125 কল। সর্বোত্তম হতে হবে 2.1।

আমি ভাবতে পারি যে এই পদ্ধতিটি এখানে অন্যান্য অনেকের তুলনায় উল্লেখযোগ্যভাবে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে হয়ে যায় যতক্ষণ না র‌্যান্ড 5 এ কল করার ব্যয়টি অত্যন্ত ব্যয়বহুল (এন্ট্রপির কোনও বাহ্যিক উত্সকে কল করে বলুন)।


কিছু সাধারণ ত্রুটি বাদ দিয়ে আপনার সমাধানটি সঠিক দেখা যাচ্ছে: "যদি (গণনা> 1)" হওয়া উচিত "যদি (গণনা <= 1)", এবং এরপরে ঘটে যাওয়া "i ++" হওয়া উচিত এটির পূর্ববর্তী কোঁকড়ানো ধনুর্বন্ধনীগুলির মধ্যে। আমি বিটসেট () সঠিক কিনা তা নিশ্চিত নই, তবে এটি কিছুটা অপ্রাসঙ্গিক।
অ্যাডাম রোজেনফিল্ড

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

আমি সংশোধন করলাম <= ধন্যবাদ, আমি ++ সত্যই সেখানে থাকা উচিত। এটি শূন্য এবং 1 কেসে ঘটতে হবে (বাফারে যথাক্রমে 1 বা শূন্য যোগ করা)। এটি হ'ল আমি যা ব্যবহার করার পরামর্শ দেব তা একেবারেই জটিল নয়, এটি মারাত্মক জটিল। আমি কেবল আগ্রহী ছিলাম যে সমস্যার মধ্যে অন্তর্নিহিত তাত্ত্বিক এনট্রোপি সীমাতে আমি কতটা কাছাকাছি যেতে পারি ... প্রতিক্রিয়াটির জন্য ধন্যবাদ। হাস্যকরভাবে প্রথম কলটিতে বাফারটি পূরণ করা ছিল এটি আরও সহজ লেখার জন্য :)
ShuggyCoUk

আমি এটি বুঝতে (সহজ গতিতে) আরও সহজ হতে পুনরায় কাজ করেছি তবে এটিকেও সঠিক করে তুলেছি। এটি এখনও সর্বোত্তম নয়, কোনও কারণে 1/5 বিটগুলি গণনায় অভিন্ন হলেও সমস্যা সৃষ্টি করে।
ShuggyCoUk

3

পিএইচপি

function rand1to7() {
    do {
        $output_value = 0;
        for ($i = 0; $i < 28; $i++) {
            $output_value += rand1to5();
        }
    while ($output_value != 140);
    $output_value -= 12;
    return floor($output_value / 16);
}

16 এবং 127 এর মধ্যে একটি এলোমেলো সংখ্যা তৈরি করতে লুপগুলি 1 এবং 7.9375 এর মধ্যে একটি ফ্লোট তৈরি করতে ষোলটি দ্বারা বিভক্ত হয়, তারপরে 1 এবং 7 এর মধ্যে একটি ইন্টিটি পেতে গোলাকার হয়ে যায়, যদি আমার ভুল না হয় তবে 16/112 পাওয়ার সম্ভাবনা রয়েছে 7 ফলাফলের যে কোনও একটি।


যদিও এটির মতো সম্ভবত আরও সহজ উত্তর নেই শর্তাধীন লুপ এবং মেঝে পরিবর্তে মডুলো ব্যবহার করে। আমি এখনই সংখ্যাগুলি ক্রাঙ্ক করতে পারি না।
dqhendrick


3

আমার মনে হয় আমার চারটি উত্তর রয়েছে, দু'টি @ অ্যাডাম রোজেনফিল্ডের মতো নির্ভুল সমাধান দিচ্ছেন তবে অসীম লুপ সমস্যা ছাড়াই এবং অন্য দুটি প্রায় নিখুঁত সমাধানের সাথে তবে প্রথমটির চেয়ে দ্রুত বাস্তবায়ন রয়েছে।

সেরা সঠিক সমাধানটির জন্য 7 টি কল প্রয়োজন rand5, তবে বোঝার জন্য এগিয়ে যেতে দিন।

পদ্ধতি 1 - সঠিক

অ্যাডামের উত্তরের শক্তি হ'ল এটি একটি নিখুঁত অভিন্ন বিতরণ দেয় এবং খুব উচ্চ সম্ভাবনা রয়েছে (21/25) যা র্যান্ড 5 () এ কেবলমাত্র দুটি কল প্রয়োজন হবে। তবে সবচেয়ে খারাপ ক্ষেত্রে অসীম লুপ।

নীচের প্রথম সমাধানটিতে একটি নিখুঁত ইউনিফর্ম বিতরণও দেওয়া হয় তবে এর জন্য মোট ৪২ টি কল প্রয়োজন rand5। অসীম লুপ নেই।

এখানে একটি আর বাস্তবায়ন:

rand5 <- function() sample(1:5,1)

rand7 <- function()  (sum(sapply(0:6, function(i) i + rand5() + rand5()*2 + rand5()*3 + rand5()*4 + rand5()*5 + rand5()*6)) %% 7) + 1

আর এর সাথে পরিচিত না লোকদের জন্য, এখানে একটি সরলীকৃত সংস্করণ দেওয়া হয়েছে:

rand7 = function(){
  r = 0 
  for(i in 0:6){
    r = r + i + rand5() + rand5()*2 + rand5()*3 + rand5()*4 + rand5()*5 + rand5()*6
  }
  return r %% 7 + 1
}

বিতরণ rand5সংরক্ষণ করা হবে। আমরা যদি গণিত করি, লুপের 7 টি পুনরাবৃত্তের প্রত্যেকটিতে 5 ^ 6 টি সম্ভাব্য সংমিশ্রণ রয়েছে, সুতরাং সম্ভাব্য সংমিশ্রণের মোট সংখ্যা (7 * 5^6) %% 7 = 0। সুতরাং আমরা equal টি সমান গ্রুপে উত্পন্ন এলোমেলো সংখ্যাগুলি ভাগ করতে পারি। এ সম্পর্কে আরও আলোচনার জন্য দুটি পদ্ধতি দেখুন।

এখানে সমস্ত সম্ভাব্য সংমিশ্রণ রয়েছে:

table(apply(expand.grid(c(outer(1:5,0:6,"+")),(1:5)*2,(1:5)*3,(1:5)*4,(1:5)*5,(1:5)*6),1,sum) %% 7 + 1)

    1     2     3     4     5     6     7 
15625 15625 15625 15625 15625 15625 15625 

আমার মনে হয় অ্যাডামের পদ্ধতিটি আরও দ্রুত চালিত হবে তা দেখানোর জন্য এটি সরাসরি এগিয়ে। rand5অ্যাডামের সমাধানটিতে 42 বা তার বেশি কল করার সম্ভাবনা খুব কম ( (4/25)^21 ~ 10^(-17))।

পদ্ধতি 2 - সঠিক নয়

এখন দ্বিতীয় পদ্ধতি, যা প্রায় অভিন্ন, তবে এতে 6 টি কল প্রয়োজন rand5:

rand7 <- function() (sum(sapply(1:6,function(i) i*rand5())) %% 7) + 1

এখানে একটি সরলীকৃত সংস্করণ দেওয়া হয়েছে:

rand7 = function(){
  r = 0 
  for(i in 1:6){
    r = r + i*rand5()
  }
  return r %% 7 + 1
}

এটি মূলত 1 পদ্ধতির এক পুনরাবৃত্তি we

table(apply(expand.grid(1:5,(1:5)*2,(1:5)*3,(1:5)*4,(1:5)*5,(1:5)*6),1,sum) %% 7 + 1)

   1    2    3    4    5    6    7 
2233 2232 2232 2232 2232 2232 2232

এক নম্বর আরও একবার 5^6 = 15625বিচারে উপস্থিত হবে ।

এখন, পদ্ধতি 1 এ, 1 থেকে 6 যোগ করে আমরা একের পর এক বিন্দুতে 2233 নম্বরটি সরিয়েছি। এইভাবে সংমিশ্রণের মোট সংখ্যা মিলবে। এটি 5 ^ 6 %% 7 = 1 এর কারণ হিসাবে কাজ করে এবং তারপরে আমরা 7 উপযুক্ত প্রকরণগুলি করি, সুতরাং (7 * 5 ^ 6 %% 7 = 0)।

পদ্ধতি 3 - সঠিক

যদি পদ্ধতি 1 এবং 2 টির যুক্তি বোঝা যায়, পদ্ধতি 3 অনুসরণ করে এবং কেবলমাত্র 7 টি কল করতে হবে rand5। এই মুহুর্তে, আমি অনুভব করি যে এটি সঠিক সমাধানের জন্য প্রয়োজনীয় ন্যূনতম সংখ্যা।

এখানে একটি আর বাস্তবায়ন:

rand5 <- function() sample(1:5,1)

rand7 <- function()  (sum(sapply(1:7, function(i) i * rand5())) %% 7) + 1

আর এর সাথে পরিচিত না লোকদের জন্য, এখানে একটি সরলীকৃত সংস্করণ দেওয়া হয়েছে:

rand7 = function(){
  r = 0 
  for(i in 1:7){
    r = r + i * rand5()
  }
  return r %% 7 + 1
}

বিতরণ rand5সংরক্ষণ করা হবে। আমরা যদি গণিত করি, লুপের 7 টি পুনরাবৃত্তের প্রতিটিটির 5 টি সম্ভাব্য ফলাফল রয়েছে, সুতরাং সম্ভাব্য সংমিশ্রণের মোট সংখ্যা (7 * 5) %% 7 = 0। সুতরাং আমরা equal টি সমান গ্রুপে উত্পন্ন এলোমেলো সংখ্যাগুলিকে ভাগ করতে পারি। এ সম্পর্কে আরও আলোচনার জন্য পদ্ধতি এক এবং দুটি দেখুন।

এখানে সমস্ত সম্ভাব্য সংমিশ্রণ রয়েছে:

table(apply(expand.grid(0:6,(1:5)),1,sum) %% 7 + 1)

1 2 3 4 5 6 7  
5 5 5 5 5 5 5 

আমার মনে হয় অ্যাডামের পদ্ধতিটি আরও দ্রুত চলবে তা দেখানোর জন্য এটি সরাসরি এগিয়ে। rand5অ্যাডামের সমাধানটিতে 7 বা তার বেশি কল করার সম্ভাবনা এখনও ছোট ( (4/25)^3 ~ 0.004)।

পদ্ধতি 4 - সঠিক নয়

এটি দ্বিতীয় পদ্ধতির একটি সামান্য প্রকরণ। এটি প্রায় অভিন্ন, তবে এটির জন্য 7 টি কল প্রয়োজন rand5, এটি পদ্ধতি 2-তে একটি অতিরিক্ত:

rand7 <- function() (rand5() + sum(sapply(1:6,function(i) i*rand5())) %% 7) + 1

এখানে একটি সরলীকৃত সংস্করণ দেওয়া হয়েছে:

rand7 = function(){
  r = 0 
  for(i in 1:6){
    r = r + i*rand5()
  }
  return (r+rand5()) %% 7 + 1
}

যদি আমরা সমস্ত সম্ভাব্য সংমিশ্রণ তৈরি করি, তবে এখানে ফলাফলগুলি গণনা করা হবে:

table(apply(expand.grid(1:5,(1:5)*2,(1:5)*3,(1:5)*4,(1:5)*5,(1:5)*6,1:5),1,sum) %% 7 + 1)

    1     2     3     4     5     6     7 
11160 11161 11161 11161 11161 11161 11160

দুটি সংখ্যা একবার 5^7 = 78125ট্রায়ালে কম দেখাবে । বেশিরভাগ উদ্দেশ্যে, আমি এটি নিয়ে বেঁচে থাকতে পারি।


1
আমি আর এর সাথে পরিচিত নই, তবে যতক্ষণ না আমি এই কাজগুলি সম্পর্কে ভুল বোঝাবুঝি না করি, ততক্ষণ পদ্ধতি 1 সঠিক নয়। এটির (5 ^ 6) ^ 7 = 5 ^ 42 সম্ভাব্য ফলাফল রয়েছে (5 ^ 6) * 7; 5 ^ 42 দ্বারা বিভাজ্য নয় 7 অনুরূপ পদ্ধতি 3 সঠিক নয়। এটির 5 7 7 এর সম্ভাব্য ফলাফল রয়েছে, 5 * 7 নয়। (পদ্ধতি 3 এর সাথে শেষ লুপের পুনরাবৃত্তির i=7কোনও প্রভাব নেই, যেহেতু যোগ 7*rand5()করার rপরিবর্তে r7 এর মান পরিবর্তন হয় না ))
অ্যাডাম রোজেনফিল্ড

2

আপনার যে ক্রিয়াকলাপটি প্রয়োজন তা হল র্যান্ড 1_7 () , আমি র্যান্ড 1_5 () লিখেছি যাতে আপনি এটি পরীক্ষা করে এটি প্লট করতে পারেন।

import numpy
def rand1_5():
    return numpy.random.randint(5)+1

def rand1_7():
    q = 0
    for i in xrange(7):  q+= rand1_5()
    return q%7 + 1
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.