Strashivskyi / algo_lab_2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Завдання:

Довгий покер

Ви граєте в альтернативний варіант покеру, де кожен гравець має в руках N карт, і метою гри є набрати якомога довшу гpyny послідовних карт. Колода складається з карт, які мають числову величину. Також, в колоді присутні джокери. Якщо в руці гравця є джокери, він може присвоїти кожному будь-яку величину на власний розсуд. Вам роздали карти. Визначте довжину найдовшої послідовності карт, яку ви можете скласти.
Вхідні дані:
Вхідний файл ingpok.in складається з одного рядка. Він містить перелік цілих чисел від 0 до 1000000 включно, розділених пробілом - величини окремих карт в руці. Загальна кількість карт в руці не перевищує 10000. Джокери позначаються величиною 0. «Перехід через верхню межу не дозволяється - [999999, 1000000, 1, 2] не вважається коректною послідовністю.
Вихідні дані:
Вихідний файл ingpok.out повинен містити одне число - довжина найдовшої послідовності.

Логіка рішення:

В файлі long_poker_algo спершу приймаємо всі значення з послідовності, заданої у вхідному файлі. Якщо довжина вхідної послідовності більша за 10000 або будь-яке значення з послідовності не входить в проміжок від 0 до 1000000, то вхідний файл неправильний, викидаємо exception i виходимо з виконання програми. Якщо вхідний файл правильний, то рахуємо кількість джокерів(нулів) jokers_number. Числа, відмінні від нуля, додаємо в ліст cards. Якщо чисел відмінних від нуля не більше одиниці, то довжину максимальної послідовності можна визначити одразу - jokers_number + довжина ліста cards. Якщо таких чисел більше ніж одне, то сортуємо ліст cards. Тепер ліст cards містить посортовані числа(дублікати також може містити).
!!!!!!!Основна логіка!!!!!!!!!
Щоб знайти максимальну послідовність, будемо ввважати, що кожен елемент ліста cards може стати першим елементом(head) такої послідовності. Зовнішній цикл буде перебирати кожен елемент з ліста cards і задавати його першим елементом поточної послідовністі. Внутрішній цикл буде формувати з кожного head максимальну можливу послідовність, використовуючи джокери.

Задаємо початкову довжину послідовності 1, оскільки в нас точно є один елемент - head. Внутрішній цикл працює наступним чином: порінюємо поточний елемент з наступним:

-Якщо їх різниця = 1, тобто між ними нема проміжку, space_size=0, то довжина послідовності збільшується на 1;
-Якщо різниця > 1, то використовуємо джокери: якщо число джокерів більше-рівне проміжку, то заповнюємо джокерами проміжок, кількість джокерів зменшується на довжину проміжку, ліст збільшується на довжину проміжку + 1 елемент, до якого ми дойшли з допомогою джокерів; якщо довжина проміжку більша за кількість наявних джокерів, то ми не можемо заповнити такий проміжок. Залишається тільки додати значення кількості усіх невикористаних джокерів до значення довжини поточної послідовності і вийти з внутрішнього циклу;
-Якщо їх різниця = 0, а довжина проміжку відповідно вирахується, як -1, то порівнювані числа - дублікати. Такий випадок наша програмка просто проігнорує і виконання програми дійде одразу до кінця внутрішньгго циклу.

Вкінці внутрішнього циклу міняємо поточний елемент(prev_element) на наступний(next_element), а next_element тепер дорівнює його наступному елементу по списку(next_element.next). Знову виконується внутрішній цикл. Він виконуватиметься доти, доки в нас буде 2 числа для порівняння, тобто доки існує next_element. Також він міг завершитись коли в нас не було достатньо джокерів, щоб заповнити проміжок Коли ми вийшли з виконання внутрішнього циклу, в нас є значення довжини поточної послідовності, яке ми знайшли в внутршіньому циклі, беручи певний елемент з cards за перший. Але ця довжина може бути неправильною, оскільки виконання внутрішнього ціклу завершується коли не існує наступного елемента, а можливий такий варіант, що кінець максимальної послідовності - це останній елемент з cards, ми дойшли до нього, і при цьому в нас залишились джокери, тоді кількість цих джокерів слід додати до значення довжини ліста.В умові сказано, що переходити верхню межу не можна. Припустімо послідовність, створена внутрішнім циклом закінчується на числі 1000000 і залишаються ще джокери. Щоб обійти це обмеження(заборона на перехід через вехню межу) ми додаєм саме значення довжини послідовності і кількості джокерів, а не values лістів, які можна було утворити. Джокери просто можуть збільшити довжину послідовності. У випадку з мільйоном, будемо вважати, що джокери додаються на початок послідовності, а не на кінець. Порівнюємо довжину поточної послідовності з довжиною максимальної послідовності, якщо поточна послідовність більша за максимальну, яку ми знайшли в котромусь з попередніх циклів, то прирінвюєм довжину максимальної послідовністі до довжини поточної. Вкінці зовнішнього циклу змінюємо поточний елемент(current_element) на наступний по лісту cards(current_element.next). Зовнішній цикл працюєватиме поки ми не пройдемось по всіх елементах cards. Кінцевий результат max_sequence_length записуємо в вихідний файл.

!!!!!!!!!! В алгоритмі я працюю з кастомним лінкед лістом, який я створив в файлі linked_list.py

Складність алгоритму

Оскільки у алгоритмі використовується цикл у циклі, то складність цього алгоритму - O(n^2). Складність алгоритму сортування елементів(mergeSort)- O(nlogn). Оскільки алгоритм сортування міститься на одному рівні з основним алгоритмом, то він не додає йому складності.

Як запустити програму

To start the program, please, do the same steps in your console:

git clone https://github.com/Strashivskyi/algo_lab_2
cd algo_lab_2
long_poker_algo.py

or to run tests:

git clone https://github.com/Strashivskyi/algo_lab_2
cd algo_lab_2
unittests.py

If you decided to download and extract it. For example, into D:/projects, then do this in your console:

D:
cd projects/algo_lab_2
long_poker_algo.py

About


Languages

Language:Python 100.0%