diff --git a/Cargo.toml b/Cargo.toml index 17eec08..15bd75d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +itertools = "0.13.0" colored = "2.1.0" rand = "^0.8.5" # 0.8.5+, <0.9.0 time = "0.3.36" diff --git a/exam/0assesment.md b/exam/0assesment.md new file mode 100644 index 0000000..4a12a94 --- /dev/null +++ b/exam/0assesment.md @@ -0,0 +1,12 @@ +максимальна оцінка на екзамені - 100 балів + +5+ = 95-100 +5 = 90-95 +4 = 75-89 +3 = 60-74 + +1. теоретичне питання - макс 20 балів +2. практичне питання №1 - макс 30 балів +3. практичне питання №2 - макс 50 балів +4. наявність GitHub репозиторію з 16 практичними завданнями - макс 20 балів +5. наявність GitHub репозиторію з 20 задачами hackerrank - макс 20 балів \ No newline at end of file diff --git a/exam/q1theory.md b/exam/q1theory.md index c88f41a..d510eed 100644 --- a/exam/q1theory.md +++ b/exam/q1theory.md @@ -1,33 +1,190 @@ ### System Programming. Rust. I semester -1. Примітивні Типи. цілочисельні: u32/i32, розмір типів в байтах. -2. Примітивні Типи. кодування float. точність. Максимальне число без втрати точності. -3. Примітивні Типи. char, isize, usize, кодування від'ємних чисел. -4. Масиви. Декларація, використання, переваги, недоліки. -5. Масиви. Чи може масив зберігати різні дані. -6. Масиви. Slices. Синтаксис. Переваги використання. -7. String. Char. Encodings. Скільки байтів займає символ в String, чому. ASCII, UTF8. -8. String. Char. Encodings. Чи можна модифікувати String. mutable/immutable -9. String. Char. Encodings. Як зрозуміти чи можна різати String в місці який нам потрібно -10. Композитні типи. Tuple, Unit. Які значення має тип Unit -11. Композитні типи. Named Tuple (Tuple Struct), Unit. -12. Композитні типи. Struct, Unit. -13. Композитні типи. Enum. Для чого. Переваги, недоліки. -14. Композитні типи. Enum. Практичні приклади. -15. Композитні типи. Enum. Що таке exhaustiveness check. -16. Патерн матчінг. Для чого використовується, як виглядає else. -17. Патерн матчінг. Обмеження -18. Патерн матчінг. Практичні приклади. exhaustiveness check. -19. Управління виконанням. if, else, match, -20. Управління виконанням. Булева алгебра. Операції NOT, AND, OR, XOR, => -21. Управління виконанням. loop, while, for, break, continue -22. Функції, замакиння, різниця, плюси, мінуси, обмеження. -23. Функції, замакиння. Unit, implicit Unit, explicit Unit. Які значення має тип Unit -24. Функції, замакиння. -25. Impl блок. Функції, Асоційовані функції, self, &self, Self. -26. Traits. використання -27. Використання Traits для створення власного синтаксису -28. Iterators. Концепція, основні методи, переваги. Чи можна використовувати ітератор більш як 1 раз. -29. Iterators. Концепція, методи роботи з даними: map, filter, flat_map, zip, ... -30. Iterators. Концепція, методи для закінчення ітерації: for_each, collect, all, any, count, sum -31. Використання _ в мові програмування Rust. +1. Примітивні типи: Опишіть відмінності між типами u32 та i32 у контексті розміру в байтах і обробки цілих чисел. У яких + випадках слід використовувати беззнаковий тип, а коли — зі знаком? +2. Примітивні типи: Як відбувається кодування чисел з плаваючою точкою у форматі float? Яке максимальне значення можна + представити без втрати точності, і як це впливає на обчислення? +3. Примітивні типи: Як кодуються символи в типі char, і які особливості мають типи isize та usize? Опишіть, як кодуються + від'ємні числа і де можуть бути використані ці типи. +4. Масиви: Як оголошуються та використовуються масиви в Rust? Які переваги та недоліки мають масиви в порівнянні з + іншими структурами даних? +5. Масиви: Чи може масив містити елементи різних типів? Які обмеження накладає Rust на типи даних, що зберігаються в + масивах? +6. Масиви: Що таке зрізи (slices), і як вони працюють у Rust? У чому переваги використання зрізів замість масивів у + певних ситуаціях? +7. String. Char. Encodings: Скільки байтів займає символ у рядку типу String, і чому це залежить від кодування UTF-8? Як + відрізняється ASCII від UTF-8 у цьому контексті? +8. String. Char. Encodings: Чи є можливість модифікувати рядки в Rust, і як це залежить від того, чи рядок є змінним або + незмінним? Наведіть приклади використання mutable і immutable рядків. +9. String. Char. Encodings: Як визначити, чи можна розділити рядок у певній позиції, і чому це важливо для коректного + оброблення символів у UTF-8? +10. Композитні типи: Яку роль відіграють кортежі (tuple) та тип Unit у Rust? Як використовуються ці типи, і які значення + може приймати тип Unit? +11. Композитні типи: Що таке іменовані кортежі (named tuple або tuple struct) і тип Unit? Наведіть приклади їх + застосування у структурі програм на Rust. +12. Композитні типи: Як оголошуються структури (struct) у Rust? Яку роль відіграє тип Unit у контексті структур? +13. Композитні типи: Яка основна мета типу enum у Rust? Які переваги й недоліки використання цього типу в порівнянні з + іншими композитними типами? +14. Композитні типи: Наведіть практичні приклади використання типу enum у програмах на Rust. Як цей тип допомагає + моделювати складні структури даних? +15. Композитні типи: Що таке перевірка повноти (exhaustiveness check) для enum у Rust, і чому це важливо? Як це + допомагає уникнути помилок у коді? +16. Патерн матчінг: Для чого використовується патерн матчинг у Rust, і як виглядає вираз else у ньому? Чим відрізняється + від класичних умовних операторів? +17. Патерн матчінг: Які обмеження існують для патерн матчингу у Rust? Як це впливає на можливості використання цього + інструменту? +18. Патерн матчінг: Наведіть практичні приклади використання патерн матчингу у Rust, враховуючи перевірку повноти ( + exhaustiveness check). Як це полегшує роботу з різними варіантами даних? +19. Управління виконанням: Як працюють конструкції if, else та match у Rust? У чому полягають їхні особливості та + переваги в порівнянні з іншими мовами програмування? +20. Управління виконанням: Що таке булева алгебра, і як реалізовані операції NOT, AND, OR, XOR, та => в Rust? Які + завдання можна вирішувати за допомогою цих операцій? +21. Управління виконанням: Як працюють цикли loop, while, та for у Rust? Які особливості мають команди break та + continue, і в яких випадках вони використовуються? +22. Функції та замикання: Чим відрізняються функції від замикань у Rust? Які переваги та обмеження кожного з цих + підходів? +23. Функції та замикання: Що таке тип Unit у Rust, і як виглядає неявний та явний Unit у функціях? Які значення може + приймати цей тип? +24. Функції та замикання: Які основні властивості замикань у Rust? Як відрізняється поведінка замикань від класичних + функцій? +25. Impl блок: Як працюють impl блоки у Rust? Яка різниця між функціями і асоційованими функціями, і що таке self, + &self, і Self? +26. Traits: Яка мета використання traits у Rust? Як вони допомагають у реалізації поліморфізму та абстракцій? +27. Traits: Як за допомогою traits можна створювати власний синтаксис у Rust? Наведіть приклади кастомізації поведінки + через traits. +28. Ітератори: Що таке ітератори у Rust, і які основні методи вони мають? Чи можна використовувати ітератор більше ніж + один раз? +29. Ітератори: Які методи ітераторів у Rust допомагають працювати з даними, такі як map, filter, flat_map, zip? Як вони + спрощують обробку колекцій? +30. Ітератори: Які методи ітераторів дозволяють завершити ітерацію, такі як for_each, collect, all, any, count, sum? Як + ці методи використовуються для ефективного управління даними? +31. Використання _ у мові Rust: Які ситуації потребують використання символу _ у Rust? Наведіть приклади його + застосування для ігнорування значень або параметрів. + +### detailed + +- Примітивні типи: + +- Який розмір типу u32 в байтах? +- Чи зберігає i32 від'ємні значення? +- Яка різниця між беззнаковими (unsigned) і знаковими (signed) типами? + Примітивні типи: +- Який тип використовують для чисел з плаваючою точкою в Rust? +- Що таке точність числа з плаваючою точкою? +- Чи завжди можна зберегти число з плаваючою точкою без втрати точності? + Примітивні типи: +- Скільки байтів займає символ типу char? +- Що означає isize та usize в контексті архітектури? +- Як у Rust кодуються від'ємні числа? + Масиви: +- Як оголошується масив у Rust? +- Чи можуть масиви змінювати свій розмір після створення? +- Які елементи може містити масив одного типу? + Масиви: +- Чи можна змішувати різні типи даних у масиві? +- Як можна зберігати різні типи даних у структурі, схожій на масив? +- Що станеться, якщо спробувати додати різні типи до одного масиву? + Масиви: +- Що таке зріз (slice)? +- Чим відрізняється зріз від масиву? +- Чи можна змінювати довжину зрізу після створення? + String. Char. Encodings: +- Скільки байтів займає один символ у кодуванні ASCII? +- Яка різниця між кодуваннями ASCII та UTF-8? +- Як визначити, скільки байтів займає рядок у Rust? + String. Char. Encodings: +- Чи можна змінювати вміст рядка String у Rust? +- Чим відрізняються String та &str у Rust? +- Які методи використовуються для роботи з незмінними рядками? + String. Char. Encodings: +- Чому важливо перевіряти позицію різання рядка в кодуванні UTF-8? +- Що станеться, якщо неправильно "розрізати" рядок у UTF-8? +- Як дізнатися, скільки байтів займає певний символ у рядку? + Композитні типи: +- Що таке кортеж (tuple)? +- Скільки елементів може містити кортеж? +- Яке значення має тип Unit? + Композитні типи: +- Що таке іменований кортеж (tuple struct)? +- Як створити іменований кортеж у Rust? +- Яку користь дає використання типу Unit? + Композитні типи: +- Як створюється структура (struct) у Rust? +- Чим структура відрізняється від кортежу? +- Чи може структура містити поля з різними типами? + Композитні типи: +- Що таке enum у Rust? +- Які можливі значення може мати enum? +- Які переваги має використання enum? + Композитні типи: +- Наведіть приклад простого enum у Rust. +- Як оголошується enum у Rust? +- Як звертатися до конкретного варіанта enum? + Композитні типи: +- Що таке перевірка повноти (exhaustiveness check) у Rust? +- Чому важливо перевіряти всі можливі варіанти в enum? +- Що станеться, якщо пропустити варіант при перевірці enum? + Патерн матчінг: +- Що таке патерн матчинг у Rust? +- Який вигляд має вираз else у патерн матчінгу? +- У чому відмінність між if та match? + Патерн матчінг: +- Чи можна використовувати патерн матчинг для всіх типів? +- Які обмеження існують для патерн матчингу у Rust? +- Чи можна використовувати match для порівняння тільки одного варіанта? + Патерн матчінг: +- Як виглядає базовий приклад патерн матчингу? +- Що таке перевірка повноти у патерн матчінгу? +- Чому патерн матчинг краще підходить для роботи з enum? + Управління виконанням: +- Як працює оператор if у Rust? +- У чому різниця між if та match? +- Як записати кілька умов у if-else? + Управління виконанням: +- Що таке булева операція NOT? +- Як працює логічна операція AND? +- Що означає логічна операція OR? + Управління виконанням: +- Як працює цикл loop у Rust? +- У чому різниця між while та for циклами? +- Як використовуються break та continue? + Функції та замикання: +- Як визначається функція в Rust? +- Що таке замикання в Rust? +- Які обмеження мають замикання в порівнянні з функціями? + Функції та замикання: +- Що таке тип Unit у функціях? +- Як виглядає явний Unit у функції? +- Яка різниця між неявним та явним Unit? + Функції та замикання: +- Чи можна передавати функції як параметри у Rust? +- Які ключові особливості замикань? +- Чи можуть замикання зберігати змінні з навколишнього контексту? + Impl блок: +- Що таке impl блок у Rust? +- Як визначити асоційовану функцію у impl блоці? +- У чому різниця між self, &self, та Self? + Traits: +- Що таке trait у Rust? +- Як можна реалізувати trait для структури? +- Чим trait відрізняється від класу у інших мовах? + Traits: +- Як за допомогою trait можна створити новий синтаксис? +- Що таке синтаксичне розширення (syntactic sugar) у Rust? +- Як можна використовувати trait для перевантаження операторів? + Ітератори: +- Що таке ітератор у Rust? +- Які основні методи має ітератор? +- Чи можна використовувати ітератор більше одного разу? + Ітератори: +- Як працює метод map для ітераторів? +- Що робить метод filter у ітераторах? +- Яка різниця між map та flat_map? + Ітератори: +- Який метод ітератора дозволяє завершити ітерацію? +- Як працює метод collect? +- Що робить метод for_each? + Використання _: +- Для чого використовується символ _ у Rust? +- Як _ допомагає ігнорувати значення або параметри? +- У яких випадках використовують _ замість конкретного імені змінної? diff --git a/src/usecases/mod.rs b/src/homeworks/mod.rs similarity index 100% rename from src/usecases/mod.rs rename to src/homeworks/mod.rs diff --git a/src/usecases/p01/mod.rs b/src/homeworks/p01/mod.rs similarity index 100% rename from src/usecases/p01/mod.rs rename to src/homeworks/p01/mod.rs diff --git a/src/usecases/p02/mod.rs b/src/homeworks/p02/mod.rs similarity index 100% rename from src/usecases/p02/mod.rs rename to src/homeworks/p02/mod.rs diff --git a/src/usecases/p03/mod.rs b/src/homeworks/p03/mod.rs similarity index 100% rename from src/usecases/p03/mod.rs rename to src/homeworks/p03/mod.rs diff --git a/src/usecases/p04/mod.rs b/src/homeworks/p04/mod.rs similarity index 100% rename from src/usecases/p04/mod.rs rename to src/homeworks/p04/mod.rs diff --git a/src/usecases/p05/mod.rs b/src/homeworks/p05/mod.rs similarity index 100% rename from src/usecases/p05/mod.rs rename to src/homeworks/p05/mod.rs diff --git a/src/usecases/p06/mod.rs b/src/homeworks/p06/mod.rs similarity index 100% rename from src/usecases/p06/mod.rs rename to src/homeworks/p06/mod.rs diff --git a/src/usecases/p07/mod.rs b/src/homeworks/p07/mod.rs similarity index 100% rename from src/usecases/p07/mod.rs rename to src/homeworks/p07/mod.rs diff --git a/src/usecases/p08/mod.rs b/src/homeworks/p08/mod.rs similarity index 100% rename from src/usecases/p08/mod.rs rename to src/homeworks/p08/mod.rs diff --git a/src/usecases/p09/mod.rs b/src/homeworks/p09/mod.rs similarity index 100% rename from src/usecases/p09/mod.rs rename to src/homeworks/p09/mod.rs diff --git a/src/usecases/p10/mod.rs b/src/homeworks/p10/mod.rs similarity index 100% rename from src/usecases/p10/mod.rs rename to src/homeworks/p10/mod.rs diff --git a/src/usecases/p11/mod.rs b/src/homeworks/p11/mod.rs similarity index 100% rename from src/usecases/p11/mod.rs rename to src/homeworks/p11/mod.rs diff --git a/src/usecases/p12/mod.rs b/src/homeworks/p12/mod.rs similarity index 100% rename from src/usecases/p12/mod.rs rename to src/homeworks/p12/mod.rs diff --git a/src/usecases/p13/mod.rs b/src/homeworks/p13/mod.rs similarity index 100% rename from src/usecases/p13/mod.rs rename to src/homeworks/p13/mod.rs diff --git a/src/usecases/p14/mod.rs b/src/homeworks/p14/mod.rs similarity index 100% rename from src/usecases/p14/mod.rs rename to src/homeworks/p14/mod.rs diff --git a/src/usecases/p15/mod.rs b/src/homeworks/p15/mod.rs similarity index 100% rename from src/usecases/p15/mod.rs rename to src/homeworks/p15/mod.rs diff --git a/src/usecases/p16/mod.rs b/src/homeworks/p16/mod.rs similarity index 100% rename from src/usecases/p16/mod.rs rename to src/homeworks/p16/mod.rs diff --git a/src/lectures/lec04/a4case.rs b/src/lectures/lec04/a4case.rs index 4a24774..cfd4309 100644 --- a/src/lectures/lec04/a4case.rs +++ b/src/lectures/lec04/a4case.rs @@ -6,3 +6,16 @@ fn change_case() { println!("{}", upper); // ПРИВІТ println!("{}", lower); // привіт } + +#[test] +fn test1() { + // in some cases when letter becomes lowercase + // it has more than 1 symbol + let s = "ΣΣ"; + let c = 'Æ'; + + let cl = c.to_lowercase(); + let c2 = cl.collect::(); + println!("{}", s.to_lowercase()); + println!("{}", c2); +} diff --git a/src/main.rs b/src/main.rs index 01d26c8..742d6c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ +mod homeworks; mod lectures; mod practice; -mod usecases; fn main() { println!("Hello from \u{211D}u\x73\x74😀!"); diff --git a/src/practice/list.md b/src/practice/list.md new file mode 100644 index 0000000..1eb68f1 --- /dev/null +++ b/src/practice/list.md @@ -0,0 +1,18 @@ +### practical lessons + +1. github +2. project structure +3. TODO +4. envelope - console +5. apples_and_oranges +6. chess_board - console +7. rhombus - console +8. brackets_is_valid_simple - string/array +9. brackets_max_level - string/array +10. shoes_groups - string/array +11. counting_valleys - string/array +12. parking_dilemma - array/array +13. brackets_is_valid_full - string/array +14. char_indexes - data manipulation +15. pack-unpack - data manipulation +16. 5317^1000000000 diff --git a/src/practice/p05/envelope.rs b/src/practice/p04/envelope1.rs similarity index 100% rename from src/practice/p05/envelope.rs rename to src/practice/p04/envelope1.rs diff --git a/src/practice/p06/envelope.rs b/src/practice/p04/envelope2.rs similarity index 100% rename from src/practice/p06/envelope.rs rename to src/practice/p04/envelope2.rs diff --git a/src/practice/p04/mod.rs b/src/practice/p04/mod.rs index e69de29..97a70d5 100644 --- a/src/practice/p04/mod.rs +++ b/src/practice/p04/mod.rs @@ -0,0 +1,2 @@ +mod envelope1; +mod envelope2; diff --git a/src/practice/p04/slides1.pdf b/src/practice/p04/slides1.pdf new file mode 100644 index 0000000..4bd0718 Binary files /dev/null and b/src/practice/p04/slides1.pdf differ diff --git a/src/practice/p04/slides2.pdf b/src/practice/p04/slides2.pdf new file mode 100644 index 0000000..913b489 Binary files /dev/null and b/src/practice/p04/slides2.pdf differ diff --git a/src/practice/p07/apple_and_oranges.rs b/src/practice/p05/apple_and_oranges.rs similarity index 100% rename from src/practice/p07/apple_and_oranges.rs rename to src/practice/p05/apple_and_oranges.rs diff --git a/src/practice/p05/mod.rs b/src/practice/p05/mod.rs index 172ee72..57bcc44 100644 --- a/src/practice/p05/mod.rs +++ b/src/practice/p05/mod.rs @@ -1 +1 @@ -mod envelope; +mod apple_and_oranges; diff --git a/src/practice/p05/slides.pdf b/src/practice/p05/slides.pdf index 4bd0718..67b6b65 100644 Binary files a/src/practice/p05/slides.pdf and b/src/practice/p05/slides.pdf differ diff --git a/src/practice/p08/chessboard.rs b/src/practice/p06/chessboard.rs similarity index 100% rename from src/practice/p08/chessboard.rs rename to src/practice/p06/chessboard.rs diff --git a/src/practice/p06/mod.rs b/src/practice/p06/mod.rs index 172ee72..4e47f03 100644 --- a/src/practice/p06/mod.rs +++ b/src/practice/p06/mod.rs @@ -1 +1 @@ -mod envelope; +mod chessboard; diff --git a/src/practice/p06/slides.pdf b/src/practice/p06/slides.pdf index 913b489..6056f1b 100644 Binary files a/src/practice/p06/slides.pdf and b/src/practice/p06/slides.pdf differ diff --git a/src/practice/p07/mod.rs b/src/practice/p07/mod.rs index 57bcc44..febbd28 100644 --- a/src/practice/p07/mod.rs +++ b/src/practice/p07/mod.rs @@ -1 +1 @@ -mod apple_and_oranges; +mod rhombus; diff --git a/src/practice/p09/rhombus.rs b/src/practice/p07/rhombus.rs similarity index 100% rename from src/practice/p09/rhombus.rs rename to src/practice/p07/rhombus.rs diff --git a/src/practice/p07/slides.pdf b/src/practice/p07/slides.pdf index 67b6b65..baf8fa5 100644 Binary files a/src/practice/p07/slides.pdf and b/src/practice/p07/slides.pdf differ diff --git a/src/practice/p10/brackets_is_valid.rs b/src/practice/p08/brackets_is_valid.rs similarity index 100% rename from src/practice/p10/brackets_is_valid.rs rename to src/practice/p08/brackets_is_valid.rs diff --git a/src/practice/p08/mod.rs b/src/practice/p08/mod.rs index 4e47f03..437bcb5 100644 --- a/src/practice/p08/mod.rs +++ b/src/practice/p08/mod.rs @@ -1 +1 @@ -mod chessboard; +mod brackets_is_valid; diff --git a/src/practice/p08/slides.pdf b/src/practice/p08/slides.pdf deleted file mode 100644 index 6056f1b..0000000 Binary files a/src/practice/p08/slides.pdf and /dev/null differ diff --git a/src/practice/p11/brackets_max_level.pdf b/src/practice/p09/brackets_max_level.pdf similarity index 100% rename from src/practice/p11/brackets_max_level.pdf rename to src/practice/p09/brackets_max_level.pdf diff --git a/src/practice/p11/brackets_max_level.rs b/src/practice/p09/brackets_max_level.rs similarity index 100% rename from src/practice/p11/brackets_max_level.rs rename to src/practice/p09/brackets_max_level.rs diff --git a/src/practice/p09/mod.rs b/src/practice/p09/mod.rs index febbd28..23a8485 100644 --- a/src/practice/p09/mod.rs +++ b/src/practice/p09/mod.rs @@ -1 +1 @@ -mod rhombus; +mod brackets_max_level; diff --git a/src/practice/p09/slides.pdf b/src/practice/p09/slides.pdf deleted file mode 100644 index baf8fa5..0000000 Binary files a/src/practice/p09/slides.pdf and /dev/null differ diff --git a/src/practice/p10/mod.rs b/src/practice/p10/mod.rs index 437bcb5..0dca96e 100644 --- a/src/practice/p10/mod.rs +++ b/src/practice/p10/mod.rs @@ -1 +1 @@ -mod brackets_is_valid; +mod shoes_groups; diff --git a/src/practice/p11/shoes_groups.md b/src/practice/p10/shoes_groups.md similarity index 100% rename from src/practice/p11/shoes_groups.md rename to src/practice/p10/shoes_groups.md diff --git a/src/practice/p11/shoes_groups.pdf b/src/practice/p10/shoes_groups.pdf similarity index 100% rename from src/practice/p11/shoes_groups.pdf rename to src/practice/p10/shoes_groups.pdf diff --git a/src/practice/p11/shoes_groups.rs b/src/practice/p10/shoes_groups.rs similarity index 100% rename from src/practice/p11/shoes_groups.rs rename to src/practice/p10/shoes_groups.rs diff --git a/src/practice/p11/counting_valleys.rs b/src/practice/p11/counting_valleys.rs new file mode 100644 index 0000000..19a2086 --- /dev/null +++ b/src/practice/p11/counting_valleys.rs @@ -0,0 +1,65 @@ +/// https://www.hackerrank.com/challenges/counting-valleys/problem +fn countingValleys(steps: i32, path: &str) -> i32 { + let mut n = 0; + let mut p = 0; + + for c in path.chars() { + let l = match c { + 'U' => p + 1, + 'D' => p - 1, + _ => continue, + }; + if l == 0 && p < 0 { + n += 1; + } + p = l; + } + + n +} + +fn countingValleys2(steps: i32, path: &str) -> i32 { + struct State { + level: i32, + count: i32, + } + + fn is_crossed(prev_level: i32, curr_level: i32) -> bool { + prev_level < 0 && curr_level == 0 + } + + impl State { + fn new(level: i32, count: i32) -> State { + State { level, count } + } + fn fresh() -> State { + State::new(0, 0) + } + fn next(&self, cur_level: i32, crossed: bool) -> State { + let delta = if crossed { 1 } else { 0 }; + State::new(cur_level, self.count + delta) + } + fn up(&self) -> State { + let cur_level = self.level + 1; + self.next(cur_level, is_crossed(self.level, cur_level)) + } + fn down(&self) -> State { + let cur_level = self.level - 1; + self.next(cur_level, is_crossed(self.level, cur_level)) + } + } + + fn logic(st: State, c: char) -> State { + match c { + 'U' => st.up(), + 'D' => st.down(), + _ => st, + } + } + + let s = path + .chars() + .fold(State::fresh(), logic); + + s.count +} diff --git a/src/practice/p11/mod.rs b/src/practice/p11/mod.rs index 13af35c..f180a6f 100644 --- a/src/practice/p11/mod.rs +++ b/src/practice/p11/mod.rs @@ -1,2 +1 @@ -mod brackets_max_level; -mod shoes_groups; +mod counting_valleys; diff --git a/src/practice/p11/slides.pdf b/src/practice/p11/slides.pdf new file mode 100644 index 0000000..6ce8c62 Binary files /dev/null and b/src/practice/p11/slides.pdf differ diff --git a/src/practice/p12/counting_valleys.rs b/src/practice/p12/counting_valleys.rs deleted file mode 100644 index 8edde60..0000000 --- a/src/practice/p12/counting_valleys.rs +++ /dev/null @@ -1,50 +0,0 @@ -/// https://www.hackerrank.com/challenges/counting-valleys/problem -fn countingValleys1(steps: i32, path: &str) -> i32 { - struct State { - level: i32, - count: i32, - } - - impl State { - fn new() -> Self { - Self { level: 0, count: 0 } - } - } - - path.chars() - .fold(State::new(), |st, c| { - let curr_level = match c { - 'U' => st.level + 1, - 'D' => st.level - 1, - _ => panic!("wrong char"), - }; - let delta_count = match curr_level { - 0 if st.level < 0 => 1, - _ => 0, - }; - State { - level: curr_level, - count: st.count + delta_count, - } - }) - .count -} - -fn countingValleys2(steps: i32, path: &str) -> i32 { - let mut prev_level = 0; - let mut count = 0; - for c in path.chars() { - let curr_level = match c { - 'U' => prev_level + 1, - 'D' => prev_level - 1, - _ => prev_level, - }; - let delta = match curr_level { - 0 if prev_level < 0 => 1, - _ => 0, - }; - prev_level = curr_level; - count += delta; - } - count -} diff --git a/src/practice/p12/mod.rs b/src/practice/p12/mod.rs index 88795e8..8cf438a 100644 --- a/src/practice/p12/mod.rs +++ b/src/practice/p12/mod.rs @@ -1,2 +1 @@ -mod counting_valleys; mod parking_dilemma; diff --git a/src/practice/p12/parking_dilemma.pdf b/src/practice/p12/parking_dilemma.pdf new file mode 100644 index 0000000..be1659a Binary files /dev/null and b/src/practice/p12/parking_dilemma.pdf differ diff --git a/src/practice/p12/parking_dilemma.rs b/src/practice/p12/parking_dilemma.rs index 1239dbb..3d8e974 100644 --- a/src/practice/p12/parking_dilemma.rs +++ b/src/practice/p12/parking_dilemma.rs @@ -1,18 +1,60 @@ -fn car_parking_roof(cars: &[usize], k: usize) -> usize { +use std::cmp::min; + +fn car_parking_roof1(cars: &[u32], k: usize) -> u32 { + let mut cars = cars.to_vec(); + cars.sort(); + + let roof_size = |i1: usize, i2: usize| -> u32 { cars[i2] - cars[i1] + 1 }; + + let mut m = roof_size(0, k - 1); + + println!("{:?}", cars); + + for idx in 0..cars.len() - k + 1 { + let s = roof_size(idx, idx + (k - 1)); + m = min(m, s); + println!("i: {idx}, size: {s}, min:{m}"); + } + + m +} + +fn car_parking_roof2(cars: &[usize], k: usize) -> usize { let mut cars = cars.to_vec(); cars.sort_unstable(); - (0..(cars.len() - k)) - .map(|idx| cars[idx + k - 1] - cars[idx] + 1) + let roof_size = |idx: usize| cars[idx + k - 1] - cars[idx] + 1; + (0..(cars.len() - k + 1)) + .map(roof_size) + .min() + .unwrap() +} + +fn car_parking_roof3(cars: &[u32], k: usize) -> u32 { + let mut cars = cars.to_vec(); + cars.sort(); + let roof_size = |i: (usize, usize)| cars[i.0].abs_diff(cars[i.1]) + 1; + let it1 = 0..; + let it2 = (k - 1)..cars.len(); + it1.zip(it2) + .map(roof_size) .min() .unwrap() } #[test] -fn car_parking_roof_test() { +fn car_parking_roof_test1() { let cars = [6, 2, 12, 7]; let k = 3; + let roof_expected = 6; + let roof_real = car_parking_roof2(&cars, k); + assert_eq!(roof_expected, roof_real); +} - let roof_size = car_parking_roof(&cars, k); - let expected = 6; - assert_eq!(expected, roof_size); +#[test] +fn car_parking_roof_test2() { + let cars = [6, 2, 12, 7, 20, 25, 26, 28]; + let k = 3; + let roof_expected = 4; + let roof_real = car_parking_roof3(&cars, k); + assert_eq!(roof_expected, roof_real); } diff --git a/src/practice/p13/brackets_full.rs b/src/practice/p13/brackets_full.rs index e69de29..fa46ad8 100644 --- a/src/practice/p13/brackets_full.rs +++ b/src/practice/p13/brackets_full.rs @@ -0,0 +1,93 @@ +use std::collections::{HashMap, HashSet}; + +/// straightforward +fn brackets_is_valid_full(s: String) -> bool { + let pairs = HashMap::from([('}', '{'), (')', '('), (']', '['), ('>', '<')]); + let open = HashSet::::from_iter("{[(<".chars()); + let close = HashSet::::from_iter("}])>".chars()); + + let mut stack = Vec::new(); + for c in s.chars() { + match c { + c if open.contains(&c) => stack.push(c), + c if close.contains(&c) => match stack.pop() { + None => return false, + Some(top) => match pairs.get(&c) { + Some(&op) if op == top => (), + Some(_) | None => return false, + }, + }, + _ => continue, + } + } + + stack.is_empty() +} + +/// more functional +fn brackets_is_valid_full2(s: String) -> bool { + let pairs = HashMap::from([('}', '{'), (')', '('), (']', '['), ('>', '<')]); + let open = HashSet::::from_iter("{[(<".chars()); + let close = HashSet::::from_iter("}])>".chars()); + + enum State { + Valid(Vec), + Invalid, + } + + impl State { + fn new() -> Self { + State::Valid(Vec::new()) + } + } + + let process = |mut st: State, c: char| match st { + State::Valid(ref mut stack) => match c { + c if open.contains(&c) => { + stack.push(c); + st + } + c if close.contains(&c) => match stack.pop() { + Some(top) => match pairs.get(&c) { + Some(&op) if op == top => st, + _ => State::Invalid, + }, + _ => State::Invalid, + }, + _ => st, + }, + _ => State::Invalid, + }; + + let s = s + .chars() + .fold(State::new(), process); + + match s { + State::Valid(stack) => stack.is_empty(), + State::Invalid => false, + } +} + +#[test] +fn is_valid_test2() { + let test_data = [ + //input expected + ("{}", true), + ("[{(<>()[])}<>]", true), + ("{}{}", true), + ("{{}}", true), + ("{{}{}}", true), + ("{{}", false), + ("{}}", false), + ("}{", false), + ("{", false), + ("}", false), + ("<}", false), + ]; + + for (s, r) in test_data { + assert_eq!(brackets_is_valid_full(s.to_string()), r); + assert_eq!(brackets_is_valid_full2(s.to_string()), r); + } +} diff --git a/src/practice/p14/char_coordinates.rs b/src/practice/p14/char_coordinates.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/practice/p14/char_indexes.rs b/src/practice/p14/char_indexes.rs new file mode 100644 index 0000000..c39677b --- /dev/null +++ b/src/practice/p14/char_indexes.rs @@ -0,0 +1,41 @@ +use itertools::Itertools; +use std::collections::HashMap; + +fn char_indexes(text: &String) -> HashMap> { + let mut outcome: HashMap> = HashMap::new(); + text.chars() + .into_iter() + .zip(1..) + .filter(|&(c, _)| c.is_alphabetic()) + .for_each(|(c, idx)| { + outcome + .entry(c.to_ascii_lowercase()) + .or_insert_with(Vec::new) + .push(idx); + }); + + outcome +} + +// with help of https://docs.rs/itertools/latest/itertools/ +fn char_indexes2(text: &String) -> HashMap> { + text.chars() + .into_iter() + .zip(1..) + .filter(|&(c, _)| c.is_alphabetic()) + .map(|(c, idx)| (c.to_ascii_lowercase(), idx)) + .into_group_map() +} + +#[test] +fn char_indexes_test() { + let s = String::from("Hello, world!"); + + let indexes1 = char_indexes(&s); + println!("{:?}", indexes1); + + let indexes2 = char_indexes2(&s); + println!("{:?}", indexes2); + + assert_eq!(indexes1, indexes2); +} diff --git a/src/practice/p14/mod.rs b/src/practice/p14/mod.rs index c08a9c5..0dcc0b1 100644 --- a/src/practice/p14/mod.rs +++ b/src/practice/p14/mod.rs @@ -1 +1 @@ -mod char_coordinates; +mod char_indexes; diff --git a/src/practice/p15/mod.rs b/src/practice/p15/mod.rs index 9302bc0..ff4d02c 100644 --- a/src/practice/p15/mod.rs +++ b/src/practice/p15/mod.rs @@ -1 +1 @@ -mod permutations; +mod pack_unpack; diff --git a/src/practice/p15/pack_unpack.rs b/src/practice/p15/pack_unpack.rs new file mode 100644 index 0000000..113a922 --- /dev/null +++ b/src/practice/p15/pack_unpack.rs @@ -0,0 +1,95 @@ +// fold-left implementation +fn pack2(xs: &Vec) -> Vec<(A, usize)> { + let one = |a: &A| (a.clone(), 1); + + xs.iter() + .fold(Vec::<(A, usize)>::with_capacity(xs.len()), |mut acc, a| { + match acc.last() { + // start + None => vec![one(a)], + // continue with the same element + Some((aa, c)) if a == aa => { + acc.last_mut() + .unwrap() + .1 = c + 1; + acc + } + // continue with the different element + Some(_) => { + acc.push(one(a)); + acc + } + } + }) +} + +// iterator-based implementation +fn pack1(xs: &Vec) -> Vec<(A, usize)> { + let mut iter = xs.iter(); + let mut cur: Option<(A, usize)> = None; + let mut acc = Vec::<(A, usize)>::new(); + + loop { + match (iter.next(), &cur) { + // finish with empty current + (None, None) => break acc, + // finish with non-empty current + (None, Some((v, count))) => { + acc.push((v.clone(), *count)); + break acc; + } + // start + (Some(a), None) => cur = Some((a.clone(), 1)), + // continue with the same element + (Some(a), Some((v, count))) if a == v => cur = Some((a.clone(), count + 1)), + // continue with the different element + (Some(a), Some((v, count))) => { + acc.push((v.clone(), *count)); + cur = Some((a.clone(), 1)); + } + } + } +} + +fn unpack(xs: &Vec<(A, usize)>) -> Vec { + xs.iter() + .flat_map(|&(ref a, ref count)| vec![a.clone(); *count]) + .collect() +} + +#[test] +fn pack_test() { + let test_cases: Vec<(&str, Vec<(char, usize)>)> = vec![ + ("", vec![]), + ("a", vec![('a', 1)]), + ("aa", vec![('a', 2)]), + ("ab", vec![('a', 1), ('b', 1)]), + ("aab", vec![('a', 2), ('b', 1)]), + ("abb", vec![('a', 1), ('b', 2)]), + ("abba", vec![('a', 1), ('b', 2), ('a', 1)]), + ( + "abbcccaabc", + vec![('a', 1), ('b', 2), ('c', 3), ('a', 2), ('b', 1), ('c', 1)], + ), + ]; + + test_cases + .iter() + .for_each(|(s_unpacked, packed)| { + let unpacked = s_unpacked + .chars() + .collect::>(); + + // pack V1 + let packed2 = pack1(&unpacked); + assert_eq!(packed2, *packed); + + // pack V2 + let packed2 = pack2(&unpacked); + assert_eq!(packed2, *packed); + + // unpack + let unpacked2 = unpack(&packed); + assert_eq!(unpacked2, unpacked); + }); +} diff --git a/src/practice/p15/permutations.rs b/src/practice/p15/permutations.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/practice/p16/huge_power.rs b/src/practice/p16/huge_power.rs new file mode 100644 index 0000000..7f6e163 --- /dev/null +++ b/src/practice/p16/huge_power.rs @@ -0,0 +1,81 @@ +// the task is: +// to calculate the last digit of: 1234567^1000000000000000000 + +fn last_digit_bruteforce1(power: u64) -> u8 { + let x: u32 = 137; + let mut ld = x; + + for _ in 1..power { + ld = ld * x; + } + (ld % 10) as u8 +} + +fn last_digit_bruteforce2(power: u64) -> u8 { + match power { + 0 => 1, + power => { + let x: u32 = 137; + let mut ld = x; + + for _ in 1..power { + ld = (ld * x) % 10; + } + (ld % 10) as u8 + } + } +} + +#[ignore] +#[test] +fn test_bruteforce() { + /// never finishes ;) + let ld = last_digit_bruteforce2(1000000000000000000u64); + println!("last digit bruteforce way: {}", ld); +} + +#[test] +fn playground_bruteforce() { + (0..=12) + .into_iter() + .for_each(|x| println!("{:2} {}", x, last_digit_bruteforce2(x))); + // 0 1 + // 1 7 + // 2 9 + // 3 3 + + // 4 1 + // 5 7 + // 6 9 + // 7 3 + + // 8 1 + // 9 7 + // 10 9 + // 11 3 + + // .... +} + +fn last_digit_smart(power: u64) -> i32 { + match power % 4 { + 1 => 7, + 2 => 9, + 3 => 3, + _ => 1, + } +} + +#[test] +fn last_digit_smart_test() { + [(0, 1), (1, 7), (2, 9), (3, 3), (4, 1), (5, 7), (6, 9), (3, 3), (1000000000000000000u64, 1)] + .iter() + .for_each(|(n, last)| assert_eq!(last_digit_smart(*n), *last)); +} + +#[test] +fn playground_smart() { + (0..=12) + .into_iter() + .for_each(|x| println!("{:2} {}", x, last_digit_smart(x))); +} diff --git a/src/practice/p16/mod.rs b/src/practice/p16/mod.rs index 8b13789..8cb2029 100644 --- a/src/practice/p16/mod.rs +++ b/src/practice/p16/mod.rs @@ -1 +1 @@ - +mod huge_power;