نمایش نتایج: از 1 به 8 از 8
Like Tree4 لایک
  • 1 Post By Tiranoid
  • 1 Post By Tiranoid
  • 1 Post By AliRezaBeytari
  • 1 Post By Tiranoid

موضوع: انتخاب عضو تصادفی از درون آرایه (بدون تکرار)

  1. #1
    Junior Member
    تاریخ عضویت
    Jun 2016
    نوشته ها
    7

    انتخاب عضو تصادفی از درون آرایه (بدون تکرار)

    سلام دوستان.
    من یه آرایه از نوع int دارم که پین های LED هام توش ریخته شده. حالا میخوام طوری برنامه نویسیش کنم که به صورت رندوم یکی از اون پایه های داخل اون آرایه HIGH بشه ؛ اما میخوام اون رندوم تکراری نباشه. یعنی مثلا اگر پین های ما 13 و 12 و 11 و 10 باشن وقتی اولین رندوم مثلا 11 شد ، تا زمانی که بقیه ی پین های هم رندوم پیدا نشدن 11 دوباره انتخاب نشه. نمیخوام با while یا if چک کنم ببینم قبلا پین HIGH شده یا نه ، چون بعضی مواقع چندین بار رندوم تکراری میاد و یک وقفه ای میفته !!

    لطفا راهنمایی کنید.
    خیلی ممنونم.

  2. #2
    Member
    تاریخ عضویت
    Apr 2015
    محل سکونت
    ایران :|
    نوشته ها
    76
    این کار چند راه داره

    راه اول استفاده از list ه. من نمیدونم آردویینو بطور کامل از توابع C++ استفاده میکنه یا نه. ولی اگر بکنه با این میشه :

    list یه کلاسه که مثل آرایه ها، این امکان رو میده که یه لیست درست کنیم و هر عنصری میخوایم توش بذاریم. برعکس آرایه که نمیشه یه عضو رو حذف کرد، تو لیست میشه یه عضو رو چه بر اساس مقدارش یا چه بر اساس جاش توی لیست حذف کرد و لیست بصورت خودکار تغییر سایز میده.

    کد:
    std::list<int> mylist = {5,10,15,20};
    std::cout << "mylist contains:";
    for (auto it = mylist.cbegin(); it != mylist.cend(); ++it)
    کد مربوط به عملیات رندوم روی عنصر شماره it از لیستی به نام mylist
    حذف مورد it
    این یه کد نمونه هست. تو حلقه ی for ، بجای اینکه مشخص کنیم دقیقا 10 بار تکرار میشه، با کمک auto(بصورت اتوماتیک نوع متغییر رو انتخاب میکنه) بهش میگیم که از ابتدای لیست (list.cbegin) تا انتهای لیست (list.cend) اسکن کنه

    بعد با حذف کردن اون عنصر از لیست با کمک mylist.remove(مقدار عنصری که میخوایم حذفش کنیم. مثلا it یا مثلا 11)

    لیست بصورت خودکار تغییر سایز پیدا میکنه و تمام.

    البته قبل از کار باید یه پشتیبان از لیست تهیه بکنیم که برای بارهای بعد مقدار لیست رو داشته باشیم.
    مقدار دادن به لیست دقیقا مث مقدار دادن به آرایه س

    list - C++ Reference
    لایک کردن

  3. #3
    Member
    تاریخ عضویت
    Apr 2015
    محل سکونت
    ایران :|
    نوشته ها
    76
    راه دوم استفاده از یه آرایه س که خودتونم استفاده کردین به این صورت

    اول یه پشتیبان از آرایه تهیه میکنیم

    بعد آرایه ای رو که میخوایم باش کار کنیم اینطوری میکنیم

    1) یه عنصر از آرایه بصورت رندوم انتخاب کن
    2) اگر مقدارش -1 نبود، پین رو high کن
    3) وقتی پین رو high کردی، حالا تو آرایه، اون عنصر رو مقدارش رو برابر -1 قرار بده تا دفعه بعد انتخاب نشه

    به همین راحتی
    بار اول مثلا پین ها اینطوری هستن

    0 و 1 و 2 و 3 و 4 و 5 و 6 و ...

    بعد مثلا بصورت رندوم شماره 4 انتخاب میشه. پین شماره 4 های میشه و بعد عدد 4 میشه -1. میشه

    0 و 1 و 2 و 3 و -1 و 5 و 6 و ...

    دیگه در بار بعدی که حلقه اجرا میشه، اگر عنصر 5 امی (عنصری که مقدار 4 داشت و الان شده -1) انتخاب بشه، انتخاب اجرا نمیشه


    عدد -1 رو همینطوری گذاشتم .
    توجه کنید که بسته به نوع کدنویسیتون ممکنه مجبور باشید از foreach بجای for معمولی استفاده کنید.
    ویرایش توسط Tiranoid : 03-09-2017 در ساعت 06:35 PM
    لایک کردن

  4. #4
    Junior Member
    تاریخ عضویت
    Jun 2016
    نوشته ها
    7
    نقل قول نوشته اصلی توسط Tiranoid نمایش پست ها
    این کار چند راه داره

    راه اول استفاده از list ه. من نمیدونم آردویینو بطور کامل از توابع C++ استفاده میکنه یا نه. ولی اگر بکنه با این میشه :

    list یه کلاسه که مثل آرایه ها، این امکان رو میده که یه لیست درست کنیم و هر عنصری میخوایم توش بذاریم. برعکس آرایه که نمیشه یه عضو رو حذف کرد، تو لیست میشه یه عضو رو چه بر اساس مقدارش یا چه بر اساس جاش توی لیست حذف کرد و لیست بصورت خودکار تغییر سایز میده.

    کد:
    std::list<int> mylist = {5,10,15,20};
    std::cout << "mylist contains:";
    for (auto it = mylist.cbegin(); it != mylist.cend(); ++it)
    کد مربوط به عملیات رندوم روی عنصر شماره it از لیستی به نام mylist
    حذف مورد it
    این یه کد نمونه هست. تو حلقه ی for ، بجای اینکه مشخص کنیم دقیقا 10 بار تکرار میشه، با کمک auto(بصورت اتوماتیک نوع متغییر رو انتخاب میکنه) بهش میگیم که از ابتدای لیست (list.cbegin) تا انتهای لیست (list.cend) اسکن کنه

    بعد با حذف کردن اون عنصر از لیست با کمک mylist.remove(مقدار عنصری که میخوایم حذفش کنیم. مثلا it یا مثلا 11)

    لیست بصورت خودکار تغییر سایز پیدا میکنه و تمام.

    البته قبل از کار باید یه پشتیبان از لیست تهیه بکنیم که برای بارهای بعد مقدار لیست رو داشته باشیم.
    مقدار دادن به لیست دقیقا مث مقدار دادن به آرایه س

    list - C++ Reference
    سلام. خیلی ممنونم از پاسختون.
    متاسفانه Arduino از توابع list پشتیبانی نمیکنه !!

  5. #5
    Junior Member
    تاریخ عضویت
    Jun 2016
    نوشته ها
    7
    نقل قول نوشته اصلی توسط Tiranoid نمایش پست ها
    راه دوم استفاده از یه آرایه س که خودتونم استفاده کردین به این صورت

    اول یه پشتیبان از آرایه تهیه میکنیم

    بعد آرایه ای رو که میخوایم باش کار کنیم اینطوری میکنیم

    1) یه عنصر از آرایه بصورت رندوم انتخاب کن
    2) اگر مقدارش -1 نبود، پین رو high کن
    3) وقتی پین رو high کردی، حالا تو آرایه، اون عنصر رو مقدارش رو برابر -1 قرار بده تا دفعه بعد انتخاب نشه

    به همین راحتی
    بار اول مثلا پین ها اینطوری هستن

    0 و 1 و 2 و 3 و 4 و 5 و 6 و ...

    بعد مثلا بصورت رندوم شماره 4 انتخاب میشه. پین شماره 4 های میشه و بعد عدد 4 میشه -1. میشه

    0 و 1 و 2 و 3 و -1 و 5 و 6 و ...

    دیگه در بار بعدی که حلقه اجرا میشه، اگر عنصر 5 امی (عنصری که مقدار 4 داشت و الان شده -1) انتخاب بشه، انتخاب اجرا نمیشه


    عدد -1 رو همینطوری گذاشتم .
    توجه کنید که بسته به نوع کدنویسیتون ممکنه مجبور باشید از foreach بجای for معمولی استفاده کنید.

    بله ، بنده هم همین فکر رو کرده بودم ؛ اما همونطور که در پست اول این تاپیک عرض کردم ، این کار (استفاده از if برای چک کردن -1) در بعضی مواقع (زمان هایی که چندین رندوم پشت سرهم تکراری می افتند) وقفه ایجاد میکنه و راه خوبی به نظر نمیرسه !!
    لایک کردن

  6. #6
    Member
    تاریخ عضویت
    Apr 2015
    محل سکونت
    ایران :|
    نوشته ها
    76
    این که چجوری از if استفاده شده خب بسته به کد داره و قطعا خودتون بهتر میدونین.

    ولی if (دستور برنچ) ساده ترین و پایه ترین دستورالعمل شرطی برای میکروکنترلره. سرعت اجراش تقریبا با سرعت مثلا جمع کردن یه متغییر با 1 برابره. جزو بنیادی ترین دستورالعمل های یه کامپیوتره. پس اگر سرعت if کم باشه، هیچ چیز دیگه ای نیست که سریعترش باشه. مگر اینکه اصلا بیخیال میکروکنترلر بشین و از FPGA استفاده کنید.

    عیب روشی که بالا گفتیم که از if استفاده میکرد، این بود که ممکنه حلقه بیش از تعداد متغییرها اجرا بشه.
    مثلا اگر ما 5 تا متغییر تو آرایه مون داریم، ممکنه حلقه 10 بار مثلا اجرا بشه (از نظر تئوری ممکنه بینهایت بار اجرا بشه !!)
    چون بصورت رندوم انتخاب میکنه، ممکنه مثلا بار سوم، عددیو انتخاب کنه که -1 شده و درسته اجراش نمیکنه، ولی بالاخره حلقه انجام شده.

    مثلا زمانی که آخرین بار داره حلقه اجرا میشه، یکی از متغییرها مقدار داره و بقیه -1 شدن. حالا هی تابع رندوم، اون -1 ها رو میده و این متغییر باقی مونده ممکنه هیچوقت توسط تابع رندوم اجرا نشه (احتمال اجراش 20 درصده اگر 5 متغییر داشته باشیم)
    و اگه تعداد متغییرها زیاد باشه، عملا به نتیجه نمیرسه

    این هم باز یه راه حل دیگه داره که خیلی عملی نیست تو این موقعیت
    کافیه هر بار متغییری که انتخاب شده رو بجای اینکه مقدار -1 بهش بدیم، از تو آرایه حذفش کنیم. بجای آرایه باید از vector استفاده کنیم که اونم باز داستانیه.

    بنظر من در کل بهتره برای اینکار از آردویینو استفاده نکنید.
    یه میکروکنترلر AVR به انتخاب خودتون بگیرین و با اتمل استودیو یا کدویژن کدنویسی کنید و از توابع C استفاده کنید و همون روش لیست رو اجرا کنید.
    لایک کردن

  7. #7
    Junior Member
    تاریخ عضویت
    Jun 2016
    نوشته ها
    7
    نقل قول نوشته اصلی توسط Tiranoid نمایش پست ها
    این که چجوری از if استفاده شده خب بسته به کد داره و قطعا خودتون بهتر میدونین.

    ولی if (دستور برنچ) ساده ترین و پایه ترین دستورالعمل شرطی برای میکروکنترلره. سرعت اجراش تقریبا با سرعت مثلا جمع کردن یه متغییر با 1 برابره. جزو بنیادی ترین دستورالعمل های یه کامپیوتره. پس اگر سرعت if کم باشه، هیچ چیز دیگه ای نیست که سریعترش باشه. مگر اینکه اصلا بیخیال میکروکنترلر بشین و از FPGA استفاده کنید.

    عیب روشی که بالا گفتیم که از if استفاده میکرد، این بود که ممکنه حلقه بیش از تعداد متغییرها اجرا بشه.
    مثلا اگر ما 5 تا متغییر تو آرایه مون داریم، ممکنه حلقه 10 بار مثلا اجرا بشه (از نظر تئوری ممکنه بینهایت بار اجرا بشه !!)
    چون بصورت رندوم انتخاب میکنه، ممکنه مثلا بار سوم، عددیو انتخاب کنه که -1 شده و درسته اجراش نمیکنه، ولی بالاخره حلقه انجام شده.

    مثلا زمانی که آخرین بار داره حلقه اجرا میشه، یکی از متغییرها مقدار داره و بقیه -1 شدن. حالا هی تابع رندوم، اون -1 ها رو میده و این متغییر باقی مونده ممکنه هیچوقت توسط تابع رندوم اجرا نشه (احتمال اجراش 20 درصده اگر 5 متغییر داشته باشیم)
    و اگه تعداد متغییرها زیاد باشه، عملا به نتیجه نمیرسه

    این هم باز یه راه حل دیگه داره که خیلی عملی نیست تو این موقعیت
    کافیه هر بار متغییری که انتخاب شده رو بجای اینکه مقدار -1 بهش بدیم، از تو آرایه حذفش کنیم. بجای آرایه باید از vector استفاده کنیم که اونم باز داستانیه.

    بنظر من در کل بهتره برای اینکار از آردویینو استفاده نکنید.
    یه میکروکنترلر AVR به انتخاب خودتون بگیرین و با اتمل استودیو یا کدویژن کدنویسی کنید و از توابع C استفاده کنید و همون روش لیست رو اجرا کنید.
    مشکل دستور if ، سرعتش نیست ؛ بلکه احتمال تکراری بودن هر رندوم پشت سر هم هست که باعث میشه وقفه ایجاد بشه.

    متاسفانه آردوینو vector رو هم پشتیبانی نمیکنه.

    شما مطمئنید که اگر از خود میکروکنترلر AVR در محیط کدویژن استفاده کنم میتونم از همه ی دستورات C استفاده کنم ؟!

  8. #8
    Member
    تاریخ عضویت
    Apr 2015
    محل سکونت
    ایران :|
    نوشته ها
    76
    نه لیست رو تا کنون امتحان نکردم. اجازه بدید تا فردا شب امتحان میکنم و براتون اینجا مینویسم که میشه لیست رو کامپایل کرد یانه

    =====
    نه اصلا std::list ازش مشخصه نمیشه !!
    ویرایش توسط Tiranoid : 03-12-2017 در ساعت 06:42 AM

مجوز های ارسال و ویرایش

  • شما نمیتوانید موضوع جدیدی ارسال کنید
  • شما امکان ارسال پاسخ را ندارید
  • شما نمیتوانید فایل پیوست کنید.
  • شما نمیتوانید پست های خود را ویرایش کنید
  •  

SEO by vBSEO