در این مطلب، برنامه بررسی وجود دور در گراف بدون جهت در زبانهای برنامهنویسی «سیپلاسپلاس» (++C)، «پایتون» (Python) و«جاوا» (Java) ارائه شده است. در ادامه، مساله تعریف و همراه با مثالی حل میشود. یک گراف بدون جهت داده شده است. هدف آن است که بررسی شود آیا دوری در گراف وجود دارد یا نه. برای مثال، گراف زیر دارای دور 1-2-۰-1 است.

پیش از این، در مطلبی با عنوان «برنامه تشخیص وجود دور در گراف جهت دار — راهنمای کاربردی»، روش پیدا کردن دور در گراف جهت دار مورد بررسی قرار گرفت. پیچیدگی زمانی الگوریتم مجموعههای مجزا برابر با (O(ELogV است. میتوان همچون گراف جهتدار، از «جستجوی اول عمق» (Depth First Search | DFS) برای شناسایی دور در گرافهای بدون جهت در زمان (O(V+E استفاده کرد. پیمایش گراف داده شده با استفاده از DFS انجام میشود. برای هر راس بازدید شده V، اگر راس همسایه u وجود دارد که پیش از این بازدید شده باشد و u والد v نباشد، دور در گراف وجود دارد. اگر چنین راس مجاوری برای هیچ راسی یافت نشود، گفته میشود که گراف فاقد دور است. فرض این رویکرد آن است که هیچ دو یال موازی بین دو راس وجود نداشته باشد.
Graph contains cycle Graph doesn't contain cycle
برنامه، یک پیمایش ساده DFS را در گراف انجام میدهد و گراف با استفاده از لیست همجواری نشان داده میشود. بنابراین، پیچیدگی زمانی از درجه (O(V+E است.
منبع: فرادرس
در این مطلب، الگوریتم جستجوی دودویی (Binary Search) مورد بررسی قرار گرفته و پیادهسازی آن در زبانهای برنامهنویسی گوناگون انجام شده است.
در جستجوی دودویی (Binary Search)، جستجو در یک آرایه مرتب شده، با تقسیم تکرار شونده بازه جستجو به نصف، انجام میشود. کار با بازهای که کل آرایه را پوشش میدهد، آغاز میشود. اگر مقدار کلید جستجو برابر با عنصر میانی باشد، اندیس آن بازگردانده میشود. در غیر این صورت، اگر مقدار کلید جستجو کمتر از عنصری باشد که در میانه بازه قرار دارد، بازه شکسته شده و جستجو در نیمه کمتر ادامه پیدا میکند. در صورتی که مقدار کلید جستجو بزرگتر از اندیس میانی آرایه باشد، جستجو در نیمه بیشتر (حاوی مقادیر بزرگتر) آرایه ادامه پیدا میکند. کار شکستن آرایه به دو نیم و انتخاب نیمهای که جستجو باید در آن انجام شود، مکررا و تا هنگامی که عنصر مورد نظر در آرایه یافته شود و یا مشخص شود که عنصر مورد نظر در آرایه وجود ندارد، ادامه خواهد داشت.
آرایه مرتب شده []arr شامل n عنصر موجود است. هدف، نوشتن تابعی است که یک عنصر داده شده x را در آرایه مذکور ([]arr) جستجو کند. یک رویکرد ساده برای انجام این کار، استفاده از «جستجوی خطی» (Linear Search) است. پیچیدگی زمانی الگوریتم جستجوی خطی، (O(n است. رویکرد دیگر، انجام کار مشابهی با استفاده از «جستجوی دودویی» (Binary Search) است. ایده اصلی نهفته در پس جستجوی دودویی، استفاده از اطلاعات موجود در آرایه مرتب شده و کاهش پیچیدگی زمانی به (O(Log n است. در جستجوی دودویی اساسا نیمی از عناصر تنها پس از یک مقایسه حذف میشوند. برای انجام جستجو، از الگوریتم زیر استفاده میشود.

در ادامه، پیادهسازی الگوریتم جستجوی دودویی به صورت بازگشتی، در زبانهای برنامهنویسی C++ ،C، «جاوا» (Java)، «پایتون» (Python)، «سیشارپ» (#C) و PHP ارائه شده است.
Element is present at index 3
در ادامه، کد مربوط به پیادهسازی الگوریتم جستجوی دودویی به صورت «تکرار شونده» (Iterative) ارائه شده است.
Element is present at index 3
پیچیدگی زمانی جستجوی دودویی را میتوان به صورت زیر نوشت:
T(n) = T(n/2) + c
رابطه بازگشتی بالا را میتوان با استفاده از روش «درخت بازگشتی» (Recursive tree) یا «قضیه اصلی واکاوی (تحلیل) الگوریتمها» (Master method) حل کرد. این رابطه، در حالت دوم قضیه اصلی تحلیل الگوریتمها صدق میکند و راهکار بازگشتی به صورت (Theta(Logn است.
«فضای کمکی» (Auxiliary Space)، اگر پیادهسازی به صورت تکرار شونده باشد برابر با (O(1 و در صورتی که بازگشتی باشد، از مرتبه (O(Logn فضای پشته فراخوانی بازگشتی است.
در این مطلب، روش نوشتن برنامه تجزیه عدد به عوامل اول آن مورد بررسی قرار گرفته است. فرض میشود که عدد n داده شده است. هدف، نوشتن برنامهای است که همه عوامل اول عدد n را پیدا کند. برای مثال، اگر عدد ورودی 12 است، خروجی باید «3 2 2» باشد و اگر ورودی 31۵ است، خروجی باید «۷ ۵ 3 3» باشد. در ادامه، گامهای لازم برای پیدا کردن کلیه عاملهای اول یک عدد ارائه شده است.
در ادامه، خروجیهای قطعه کد بالا برای n = 31۵ محاسبه شده است.
3 3 5 7
در گامهای 1 و 2 به اعداد مرکب و در گام 3 به اعداد اول پرداخته میشود. برای اثبات اینکه الگوریتم کامل کار میکند، نیاز به اثبات این است که گامهای 1 و 2 به اعداد مرکب میپردازند. واضح است که در گام 1، اعداد زوج مورد بررسی قرار میگیرند. پس از گام اول، همه فاکتورهای اول باقیمانده باید فرد باشند (تفاوت دو عامل اول حداقل باید دو باشد)، به همین دلیل است که i در هر گام، دو واحد افزایش پیدا میکند. اکنون، بخش اصلی مربوط به حلقهای است که تا ریشه دوم n ادامه پیدا میکند. برای اثبات اینکه این روش به درستی عمل میکند، خصوصیت زیر از اعداد مرکب در نظر گرفته میشود.
هر عدد مرکب، حداقل یک عامل اول کوچکتر یا مساوی ریشه دوم خود دارد.
این خصوصیت را میتوان با استفاده از عبارت نقیض اثبات کرد. فرض میشود a و b دو عامل n هستند، به طوریکه a*b = n. اگر هر دو این موارد بزرگتر از n√ باشند، a.b > √n و n√* که با عبارت a * b = n تناقض دارد. در گام 2 از الگوریتم، حلقه اجرا و اقدامات زیر در آن انجام میشود:
منبع: فرادرس
در این مقاله به بررسی قابلیت مدیریت پکیج در لاراول میپردازیم. در طی این مطلب، به بررسی یک مثل عملی نیز خواهیم پرداخت تا مقصود مقاله را به طور کامل نمایش دهیم.
مدیریت پکیج در لاراول قابلیت مهمی است که امکان بستهبندی یک کارکرد را به طوری فراهم میسازد که بتوان آن را به سهولت توزیع کرد. به علاوه میتوانید همواره پکیج خود را در ریپازیتوریهایی مانند Packagist و GitHub انتشار دهید. این ریپازیتوریها به توسعهدهندگان امکان استفاده از پکیجها را میدهند.
برای نمایش این مفهوم یک صفحه نمونه در لاراول میسازیم تا تصاویر را به کلود Amazon S3 آپلود کنیم. به این منظور به جای پیگیری گردش کار معمول آن را به صورت یک پکیج بستهبندی میکنیم که میتواند به سادگی توزیع یافته و نگهداری شود.
پیش از ادامه کار فرض ما بر این است که شما از قبل با فریمورک لاراول آشنا هستید، چون در این نوشته قرار است به بررسی جزییات مبانی مفاهیم لاراول بپردازیم.
ضمناً باید یک حساب معتبر AWS داشته باشید و از رمز عبور این حساب برای دسترسی به API آمازون استفاده کنید و به این ترتیب بتوانید مراحل این مقاله را عملاً پیگیری کنید. بنابراین ابتدا مطمئن شوید که این موضوع را تنظیم کردهاید. زمانی که همه چیز آماده شد، میتوانیم به مراحل توسعه عملی بپردازیم.
در ادامه فهرست خلاصهای از فایلهایی را که در طی این دوره آموزشی پیادهسازی خواهیم کرد مشاهده میکنید.
اگر از خواندن فهرست فوق چیز زیادی دستگیرتان نشد، نگران نباشید، چون در ادامه همه این موارد را به تفصیل بررسی خواهیم کرد.
چنان که پیشتر اشاره کردیم، پکیج ما، کاربرد آپلود فایل به کلود S3 آمازون را پیادهسازی میکند. در این بخش به بررسی پیشنیازهای لازم برای اجرای موفق پکیج میپردازیم.
شما به عنوان یک توسعهدهنده لاراول باید با Flysystem که یک لایه انتزاع زیبا برای تعامل با فایلسیستم ارائه میکند، آشنا باشید. این پکیج درایورهای با کاربری آسان ارائه میکند که به وسیله آنها میتوانید به راحتی با فایلسیستمهای مختلف کار کنید و مهم نیست که فایلسیستم روی یک دیسک محلی است و یا سیستم کلود S3 آمازون است.
برای فعالسازی پشتیبانی از فایلسیستم کلود S3 آمازون در Flysystem، شما باید پکیج کامپوزر آداپتر متناظر را نصب کنید. به این منظور دستور کامپوزر زیر را از ریشه پروژه اجرا کنید تا پکیج flysystem-aws-s3-v3 نصب شود:
composer require league/flysystem-aws-s3-v3
به محض اجرای موفق این دستور، میتوانید از Flysystem برای تعامل با فایلسیستم کلود S3 آمازون به همان روش که برای فایلسیستم لوکال استفاده میکردید، بهره بگیرید.
اکنون میتوانید فایل config/filesystems.php را به سرعت pull کرده و تنظیمات ارائه شده برای فایلسیستم S3 آمازون را مشاهده کنید.
چنان که میبینید، پیکربندی از قبل برای S3 آمازون تنظیم شده است و صرفاً کافی است که متغیرهای ENV مناسب را در فایل env. تنظیم کنیم. پا را فراتر گذارده و متغیرهای زیر را در فایل env. اضافه کنید.
AWS_KEY={AWS_KEY_VALUE}
AWS_SECRET={AWS_SECRET_VALUE}
AWS_REGION={AWS_REGION_VALUE}
AWS_BUCKET={AWS_BUCKET_VALUE}
AWS_CDN_URL={AWS_CDN_URL_VALUE}البته باید مقادیر placeholder را با مقادیر واقعیشان پر کنید. اکنون آماده هستید که از آداپتر Flysystem AWS S3 در اپلیکیشن لاراول خود استفاده کنید.
برای ایجاد پکیج لاراول، نخستین چیزی که باید ایجاد کنید یک ساختار دایرکتوری است که از قراردادهای سیستم لاراول تبعیت کند. فرض ما بر این است که یک اپلیکیشن لاراول ابتدایی را از قبل اجرا کردهاید. در واقع اپلیکیشن پیشفرض blog نیز به این منظور مناسب است.
در ادامه دایرکتوری Packages را در ریشه اپلیکیشن ایجاد میکنیم. با توجه به این که قصد داریم پکیج را با دیگران به اشتراک بگذاریم، ساختار ترجیحی پکیج باید به صورت {vendor_name}/{package_name} باشد.
با پیروی از همین قرارداد، میتوانیم یک دایرکتوری envato/aws زیر دایرکتوری packages ایجاد کنیم. چنان که احتمالاً حدس میزنید، envato نام ارائه دهنده است و aws اشاره به خود نام پکیج دارد. در نهایت یک دایرکتوری packages/envato/aws/src ایجاد میکنیم که فایلهای منبع پکیج را نگهداری میکند.
اکنون باید وجود پکیج جدید خود را به لاراول اطلاع دهیم. به این منظور فایل composer.json را در ریشه اپلیکیشن لاراول باز میکنیم و مدخل “Envato\\Aws\\”: “packages/envato/aws/src” را در بخش autoload به صورت زیر اضافه میکنیم:
چنان که میبینید، فضای نام Envato\Aws\ به دایرکتوری packages/envato/aws/src نگاشت شده است. اکنون باید دستور dump-autoload را اجرا کرده و نگاشتهای کامپوزر را باز تولید کنیم.
composer dump-autoload
در این مرحله میتوانیم با استفاده از فضای نام Envato\Aws\ در اپلیکیشن، فایلها را از مکان صحیحشان انتخاب کنیم.
در این مرحله یک فایل composer.json خاص پکیج اضافه میکنیم که میتوان به وسیله آن پکیج را روی ریپازیتوری packagist توزیع کنیم. به این منظور به دایرکتوری packages/envato/aws بروید و دستور زیر را برای تولید فایل composer.json برای پکیج خود اجرا کنید:
composer init
در این مرحله برخی سؤالات معمولی از شما پرسیده میشود که باید به آنها پاسخ دهید تا یک فایل composer.json ایجاد کنید. در کمترین حالت این فایل باید چیزی مانند زیر باشد:
در این پکیج یک صفحه نمونه میسازیم که وضعیت فایل آپلود شده را نمایش خواهد داد. بنابراین باید یک مسیر ایجاد کنیم که با آن صفحه متناظر باشد. در ادامه فایل مسیر را در آدرس packages/envato/aws/src/routes/web.php به صورت زیر ایجاد میکنیم:
این فایل به توضیح چندانی نیاز ندارد. گام بدیهی بعدی نیز این است که فایل کنترلر مربوطه را ایجاد کنیم.
در این زمان یک فایل کنترلر در مسیر packages/envato/aws/src/Controllers/AwsController.php با محتوای زیر ایجاد میکنیم:
در ادامه جزییات فایل فوق را به تفصیل بررسی میکنیم تا با کارکرد هر یک از خطوط کد آشنا شویم.
در آغاز یک فضای نام برای کنترلر به صورت فضای نام Envato\Aws\Controllers تنظیم میکنیم. به خاطر داشته باشید که باید در ریشه composer.json یک نگاشت از Envato\Aws به packages/envato/aws/src اضافه کنید تا بتواند فایلهای پکیج را پیدا کند.
سپس متد upload را تعریف میکنیم که برای همگامسازی فایلهای محلی با کلود S3 آمازون یک متد ضروری محسوب میشود. این نکته مهم را نیز به خاطر داشته باشید که آرگومان نخست متد upload نیازمند وابستگی \Illuminate\Contracts\Filesystem\Factory است. در طی اجرای این متد، قرارداد لاراول مناسب تزریق خواهد شد.
اکنون میتوانیم از وهلهای از filesystem factory برای ایجاد وهلههای دیسک بسته به نیاز استفاده کنیم. وهله دیسک در لاراول، درایوری است که امکان دسترسی آسان به فایلسیستمهای زیرین مانند دیسک محلی، کلود S3 آمازون و موارد مشابه را فراهم میسازد.
برای سادگی موضوع، فایل تصویر استاتیک را که از قبل در فضای ذخیرهسازی محلی پیشفرض لاراول موجود و مسیر آن به صورت storage/app/test.jpg است را انتقال میدهیم. به عنوان نخستین گام محتوای فایل منبع را انتخاب میکنیم.
زمانی که همه چیز مطابق انتظار راهاندازی شد، میتوانید فایلها را با استفاده از متد زیر با S3 آمازون همگامسازی کنید.
در صورتی که موردی به درستی کار نکرد، باید مطمئن شوید که متغیرهای محیطی AWS به درستی تنظیم شدهاند.
و آخرین کاری که باید انجام داد این است که یک فایل view را فراخوانی کنید تا تصویر همگامسازی شده و پیام مناسبی را نمایش دهد.
البته ما هنوز این فایل view را ایجاد نکردهایم و این همان کاری است که دقیقاً در بخش بعدی قرار است اجرا کنیم.
در این بخش یک فایل ویو در مسیر packages/envato/aws/src/views/upload.blade.php و با محتوای زیر میسازیم:
این یک فایل ویوی کاملاً استاندارد است که تصویر آپلود شده را به محض آپلود موفق نمایش میدهد همچنین در صورتی که آپلود عکس، موفق باشد، پیام خطای مناسبی نمایش خواهد داد.
ما کار خود را با پکیج تقریباً به پایان بردهایم، چون همه فایلهای لازم را با موفقیت ایجاد کردهایم. گام بعدی این است که یک ارائهدهنده سرویس بسازیم به طوری که بتوانیم مسیرها و ویوهای پکیج خود را بسازیم. در ادامه یک فایل ارائهدهنده سرویس در مسیر packages/envato/aws/src/Providers/AwsServiceProvider.php و با محتوای زیر ایجاد میکنیم:
بدیهی است که میتوانستیم فایل ارائهدهنده سرویس را با استفاده از دستور آرتیزان نیز بسازیم. اما این کار نیازمند گامهای اضافی انتقال فایل از app/Providers به پکیج بود.
در هر حال در ادامه به بررسی فایل ارائهدهنده سرویس که ایجاد کردیم، میپردازیم. در ابتدا مسیرها و ویوهای مرتبط با پکیج را بارگذاری میکنیم.
سپس پشتیبانی از انتشار ویوهای پکیج را ارائه میکنیم به طوری که توسعهدهندگانی که میخواهند ویوها را override کنند بتوانند این کار را انجام دهند. دفعه بعد که دستور php artisan vendor:publish اجرا شود، لاراول ویوها را از packages/envato/aws/src/views/ به resources/views/vendor/aws کپی میکند.
اکنون توسعهدهندگان دیگر میتوانند ویوها را زیر دایرکتوری resources/views/vendor/aws تغییر دهند و این فایلها به جای ویوهای زیر دایرکتوری packages/envato/aws/src/views/ به صورت خودکار از سوی لاراول انتخاب میشوند. در واقع، این روش صحیح ایجاد تغییر در ویوهای پکیج شخص ثالث به جای تغییر دادن مستقیم ویوهای پکیج محسوب میشود.
بدین ترتیب کار ما با فایل ارائهدهنده سرویس به پایان میرسد. چنان که انتظار دارید باید مدخل ارائهدهنده سرویس را در config/app.php اضافه کنیم. مدخل زیر را در آرایه providers وارد کنید.
بدین ترتیب کار ما به پایان میرسد. اینک همه چیز نظم خود را یافته است و از این رو میتوانیم در ادامه به تست پکیج خود بپردازیم.
در ادامه URL به صورت http://your-laravel-application/aws/s3/upload را در مرورگر خود وارد کنید. اگر همه چیز به درستی پیش برود باید تصویری را که از کلود S3 آمازون بارگذاری میشود ببینید. بدین ترتیب راهنمای ما نیز به پایان میرسد.
در این مقاله به بررسی یکی از مهمترین قابلیتهای فریمورک لاراول یعنی مدیریت پکیج پرداختیم. در فرایند راهاندازی پکیج سفارشی لاراول یک مثال عملی را بررسی کردیم که روش آپلود تصویر روی کلود S3 آمازون را نمایش میداد.
مدیریت پکیج قابلیت زیبایی در لاراول است که به وسیله آن میتوان مجموعهای از کارکردها را به صورت مجموع و کنار هم توزیع کرد. در واقع آن را میتوان به عنوان یک گزینه برای رویکرد توسعه ماژول سفارشی در لاراول نگریست.
چند قابلیت وجود دارند که به نسخه 3.8 پایتون اضافه شدهاند. برخی از این قابلیتها بسیار شگفتانگیز هستند. در این مقاله برخی از قابلیتهای جدید پایتون 3.8 را بررسی میکنیم که باید با آنها آشنا باشید.
این عملگر به نام عملگر walrus نیز شناخته میشود. در این عملگر مقدارها به عنوان بخشی از عبارت بدون مقداردهی اولیه قبلی آنها به متغیر انتساب مییابند.
در این قطعه کد، متغیر my_variable به یک مقدار انتساب مییابد. این قابلیت در خلاصه لیستها و دیگر ساختارهای عبارت وجود ندارد و تنها در فرمهای گزاره در دسترس ما است.
اگر میخواهید در پایتون به یک تابع اعلام کنید که پارامترهایی را بپذیرد، در این صورت میتوانید آرگومانها را از طریق موقعیت یا به وسیله کلیدواژه ارسال کنید. اما اگر بخواهیم فراخوانی کنندههای API خودمان را طوری محدود کنیم که تابع ما را صرفاً با ارسال پارامترها بر اساس موقعیت فراخوانی کنند چطور؟ کارکرد پارامتر صرفاً موقعیتی به همین منظور طراحی شده است:
در نتیجه (add(1,2,3 و (add(1,2,3,4 هر دو فراخوانیهای معتبری هستند، با این حال (add(a=1,b=2,c=3 یا (add(1,2,3,d=4 هر دو فراخوانیهای غیر معتبری هستند.
اکنون توصیفگر = میتواند به f-string–ها اضافه شود. f-string- ها به شکل {‘f'{expr= هستند، به ‘=’ دقت کنید. علامت تساوی میتواند به ارزیابی عبارت کمک کند.
کد فوق خروجی زیر را نمایش میدهد:
100-50=50
بدین ترتیب دیباگ کردن زمانی که تابع ارزیابی و خروجی پردازش میشود کار بسیار آسانی خواهد بود.
functools.lru_cache برای فراخوانیهای بازگشتی بسیار عالی است. از یک دیکشنری برای کش کردن نتایج استفاده میشود. میتوانیم دکوراتور functools.lru_cache را اضافه کنیم:
برخی اوقات لازم است که یک تکرارکننده را معکوس کنیم. خوشبختانه ورودیهای معکوس اینک به شیءهای Dict و dictviews اضافه شدهاند. آرگومان ورودی در تابع معکوس باید یک تابع ()__reversed__ داشته باشد یا باید متد ()__len__ و __()getitem__ را داشته باشد که آرگومانهایشان از 0 آغاز میشوند.
منبع: فرادرس