├── .gitignore ├── .idea ├── Algorithmic Toolbox.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── README.md └── algorithmic_toolbox ├── week_1 └── maximum_pairwise_product │ ├── max_pairwise_product.cpp │ ├── max_pairwise_product.java │ └── max_pairwise_product.py ├── week_2 ├── 01_introduction_problems.pdf └── 01_introduction_starter_files │ ├── fibonacci │ ├── Fibonacci.java │ ├── fibonacci.cpp │ └── fibonacci.py │ ├── fibonacci_huge │ ├── FibonacciHuge.java │ ├── fibonacci_huge.cpp │ └── fibonacci_huge.py │ ├── fibonacci_last_digit │ ├── FibonacciLastDigit.java │ ├── fibonacci_last_digit.cpp │ └── fibonacci_last_digit.py │ ├── fibonacci_partial_sum │ ├── FibonacciPartialSum.java │ ├── fibonacci_partial_sum.cpp │ └── fibonacci_partial_sum.py │ ├── fibonacci_sum_last_digit │ ├── FibonacciSumLastDigit.java │ ├── fibonacci_sum_last_digit.cpp │ └── fibonacci_sum_last_digit.py │ ├── gcd │ ├── GCD.java │ ├── gcd.cpp │ └── gcd.py │ └── lcm │ ├── LCM.java │ ├── lcm.cpp │ └── lcm.py ├── week_3 ├── 02_greedy_algorithms_problems.pdf └── 02_greedy_algorithms_starter_files │ ├── change │ ├── Change.java │ ├── change.cpp │ └── change.py │ ├── covering_segments │ ├── CoveringSegments.java │ ├── covering_segments.cpp │ └── covering_segments.py │ ├── different_summands │ ├── DifferentSummands.java │ ├── different_summands.cpp │ └── different_summands.py │ ├── dot_product │ ├── DotProduct.java │ ├── dot_product.cpp │ └── dot_product.py │ ├── fractional_knapsack │ ├── FractionalKnapsack.java │ ├── fractional_knapsack.cpp │ └── fractional_knapsack.py │ └── largest_number │ ├── LargestNumber.java │ ├── by_learners │ └── largest_number.rb │ ├── largest_number.cpp │ ├── largest_number.hs │ └── largest_number.py ├── week_4 ├── 03_divide_and_conquer_problems.pdf └── 03_divide_and_conquer_starter_files_20160804 │ ├── binary_search │ ├── BinarySearch.java │ ├── binary_search.cpp │ └── binary_search.py │ ├── closest │ ├── Closest.java │ ├── closest.cpp │ └── closest.py │ ├── inversions │ ├── Inversions.java │ ├── inversions.cpp │ └── inversions.py │ ├── majority_element │ ├── MajorityElement.java │ ├── majority_element.cpp │ └── majority_element.py │ ├── points_and_segments │ ├── PointsAndSegments.java │ ├── points_and_segments.cpp │ └── points_and_segments.py │ └── sorting │ ├── Sorting.java │ ├── sorting.cpp │ └── sorting.py └── week_5 ├── 04_dynamic_programming_problems.pdf └── 04_dynamic_programming_starter_files ├── edit_distance ├── EditDistance.java ├── edit_distance.cpp └── edit_distance.py ├── knapsack ├── Knapsack.java ├── knapsack.cpp └── knapsack.py ├── lcs3 ├── LCS3.java ├── lcs3.cpp └── lcs3.py ├── placing_parentheses ├── PlacingParentheses.java ├── placing_parentheses.cpp └── placing_parentheses.py └── primitive_calculator ├── PrimitiveCalculator.java ├── primitive_calculator.cpp ├── primitive_calculator.py ├── primitive_calculator2.cpp └── primitive_calculator3.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /.buildpath 2 | /build/ 3 | */archive/ 4 | 5 | __MACOSX 6 | .DS_Store 7 | 8 | .project 9 | .settings 10 | .classpath 11 | .sass-cache/ 12 | .hs 13 | 14 | # OS generated files # 15 | ###################### 16 | */.DS_Store 17 | .DS_Store 18 | .DS_Store? 19 | ._* 20 | .Spotlight-V100 21 | .Trashes 22 | Icon? 23 | ehthumbs.db 24 | Thumbs.db 25 | 26 | # Packages # 27 | ############ 28 | # it's better to unpack these files and commit the raw source 29 | # git has its own built in compression methods 30 | *.7z 31 | *.dmg 32 | *.gz 33 | *.iso 34 | *.jar 35 | *.rar 36 | *.tar 37 | *.zip -------------------------------------------------------------------------------- /.idea/Algorithmic Toolbox.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | 53 | 79 | 80 | 81 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 108 | 109 | 112 | 113 | 114 | 115 | 118 | 119 | 122 | 123 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 139 | 140 | 141 | 142 | 1484392836471 143 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data Structures and Algorithms 2 | 3 | This repository will contain my work from the [Master Algorithmic Programming Techniques Specialization](https://www.coursera.org/specializations/data-structures-algorithms) that was created by UC San Diego and delivered through Coursera. I will be implementing solutions in Python3, Java, and C++. 4 | 5 | ## About This Specialization 6 | 7 | The Specialization covers algorithmic techniques for solving problems arising in computer science applications. It is a mix of theory and practice: you will not only design algorithms and estimate their complexity, but you will get a deeper understanding of algorithms by implementing them in the programming language of your choice (C, C++, C#, Haskell, Java, JavaScript, Python2, Python3, Ruby, and Scala). 8 | 9 | This Specialization is unique, because it offers two real-world projects. Advanced Shortest Paths project is offered in the end of the Algorithms on Graphs course. In this project, you'll deal with road network analysis and social network analysis. You'll learn how to compute the fastest route between New York and Mountain View thousands of times faster than classic algorithms and close to those used in Google Maps. Through Genome Assembly culminating project at the end of the Specialization, you'll learn how to assemble genomes from millions of short pieces and how algorithms fuel recent developments in personalized medicine. 10 | 11 | # Algorithmic Toolbox 12 | Assignments for Algorithmic Toolbox on Coursera with time and memory results from grader
13 | 14 | ## Week 1 15 | ### Solving a Simple Code Problem 16 | Problem: [Maximum Pairwise Product](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_1/maximum_pairwise_product) 17 | 18 | * Python: Max time used: 0.14/5.00, max memory used: 26456064/536870912 19 | * Java: Max time used: 0.07/1.00, max memory used: 21037056/536870912 20 | * C++: Max time used: 0.12/1.00, max memory used: 21045248/536870912 21 | 22 | ## Week 2 23 | ### Prgramming Assignment: [Introduction](https://github.com/mablatnik/Data-Structures-And-Algorithms/blob/master/algorithmic_toolbox/week_2/01_introduction_problems.pdf) 24 | Problem: [Small Fibonacci Number](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci)
25 | 26 | * Python: Max time used: 0.02/5.00, max memory used: 8740864/536870912 27 | * Java: Max time used: 0.21/1.50, max memory used: 24145920/536870912 28 | * C++: Max time used: 0.00/1.00, max memory used: 8744960/536870912 29 | 30 | Problem: [The Last Digit of a Large Fibonacci Number](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_last_digit)
31 | 32 | * Python: Max time used: 0.17/5.00, max memory used: 8699904/536870912 33 | * Java: Max time used: 0.19/1.50, max memory used: 28651520/536870912 34 | * C++: Max time used: 0.00/1.00, max memory used: 8699904/536870912 35 | 36 | Problem: [Greatest Common Divisor](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_2/01_introduction_starter_files/gcd)
37 | 38 | * Python: Max time used: 0.05/5.00, max memory used: 9568256/536870912 39 | * Java: Max time used: 0.21/1.50, max memory used: 24121344/536870912 40 | * C++: Max time used: 0.00/1.00, max memory used: 9560064/536870912 41 | 42 | Problem: [Least Common Multiple](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_2/01_introduction_starter_files/lcm)
43 | 44 | * Python: Max time used: 0.09/5.00, max memory used: 9601024/536870912 45 | * Java: Max time used: 0.17/1.50, max memory used: 24133632/536870912 46 | * C++: Max time used: 0.00/1.00, max memory used: 9580544/536870912 47 | 48 | Advanced Problem: [Huge Fibonacci Number modulo m](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_huge)
49 | 50 | * Python: Max time used: 0.21/5.00, max memory used: 30359552/536870912 51 | * Java: Max time used: 0.17/1.50, max memory used: 30363648/536870912 52 | * C++: Max time used: 0.00/1.00, max memory used: 30363648/536870912 53 | 54 | Advanced Problem: [Last Digit of a Sum of Fibonacci Numbers](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_sum_last_digit)
55 | 56 | * Python: Max time used: 0.06/5.00, max memory used: 9564160/536870912 57 | * Java: Max time used: 0.21/1.50, max memory used: 24285184/536870912 58 | * C++: Max time used: 0.00/1.00, max memory used: 8720384/536870912 59 | 60 | Advanced Problem: [Last Digit of a Partial Sum of Fibonacci Numbers](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_partial_sum)
61 | 62 | * Python: Max time used: 0.05/5.00, max memory used: 8720384/536870912 63 | 64 | ## Week 3 65 | ### Programming Assignment: [Greedy Algorithms](https://github.com/mablatnik/Data-Structures-And-Algorithms/blob/master/algorithmic_toolbox/week_3/02_greedy_algorithms_problems.pdf) 66 | Problem: [Changing Money](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/change)
67 | 68 | * Python: Max time used: 0.05/5.00, max memory used: 8716288/536870912 69 | * Java: Max time used: 0.17/1.50, max memory used: 24166400/536870912 70 | * C++: Max time used: 0.00/1.00, max memory used: 8716288/536870912 71 | 72 | Problem: [Fractional Knapsack](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/fractional_knapsack)
73 | 74 | * Python: Max time used: 0.05/5.00, max memory used: 8761344/671088640 75 | * Java: Max time used: 0.36/1.50, max memory used: 33243136/671088640 76 | * C++: Max time used: 0.00/1.00, max memory used: 8769536/671088640 77 | 78 | Problem: [Minimum Dot Product](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/dot_product)
79 | 80 | * Python: Max time used: 0.02/5.00, max memory used: 8945664/536870912 81 | * Java: Max time used: 0.31/1.50, max memory used: 32632832/536870912 82 | * C++: Max time used: 0.00/1.00, max memory used: 8957952/536870912 83 | 84 | Problem: [Covering Segments by Points](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/covering_segments)
85 | 86 | * Python: Max time used: 0.03/5.00, max memory used: 9023488/536870912 87 | * Java: Max time used: 0.20/1.50, max memory used: 24457216/536870912 88 | * C++: Max time used: 0.00/1.00, max memory used: 9019392/536870912 89 | 90 | Problem: [Pairwise Distinct Summands](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/different_summands)
91 | 92 | * Python: Max time used: 0.07/5.00, max memory used: 9617408/536870912 93 | * Java: Max time used: 0.69/1.50, max memory used: 47325184/536870912 94 | * C++: Max time used: 0.00/1.00, max memory used: 9613312/536870912 95 | 96 | ## Week 4 97 | ### Programming Assignment: [Divide and Conquer](https://github.com/mablatnik/Data-Structures-And-Algorithms/blob/master/algorithmic_toolbox/week_4/03_divide_and_conquer_problems.pdf) 98 | Problem: [Binary Search](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/binary_search)
99 | 100 | * Python: Max time used: 0.82/10.00, max memory used: 37974016/536870912 101 | * Java: Max time used: 1.13/3.00, max memory used: 74174464/536870912 102 | * C++: Max time used: 0.10/2.00, max memory used: 37974016/536870912 103 | 104 | Problem: [Majority Element](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/majority_element)
105 | 106 | * Python: Max time used: 0.66/5.00, max memory used: 21393408/536870912 107 | * Java: Max time used: 0.36/1.50, max memory used: 42090496/536870912 108 | * C++: Max time used: 0.05/1.00, max memory used: 21393408/536870912 109 | 110 | Problem: [3-Way Partition](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/sorting)
111 | 112 | * Python: Max time used: 1.02/11.00, max memory used: 28880896/536870912 113 | * Java: Max time used: 1.16/5.50, max memory used: 70074368/536870912 114 | * C++: Max time used: 0.08/2.20, max memory used: 29736960/536870912 115 | 116 | Advanced Problem: [Number of Inversions](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/inversions)
117 | 118 | * Python: Max time used: 0.77/15.00, max memory used: 21364736/536870912 119 | * Java: Max time used: 0.87/4.50, max memory used: 112693248/536870912 120 | * C++: Max time used: 0.05/3.00, max memory used: 21360640/536870912 121 | 122 | Advanced Problem: [Points and Segments](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/points_and_segments)
123 | 124 | * Python: Max time used: 0.41/20.00, max memory used: 44896256/536870912 125 | 126 | ## Week 5 127 | ### Programming Assignment: [Dynamic Programming](https://github.com/mablatnik/Data-Structures-And-Algorithms/blob/master/algorithmic_toolbox/week_5/04_dynamic_programming_problems.pdf) 128 | Problem: [Primitive Calculator](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/primitive_calculator)
129 | 130 | * Python: Max time used: 1.08/7.50, max memory used: 13688832/536870912 131 | * Java: Max time used: 0.19/2.25, max memory used: 32600064/536870912 132 | * C++: Max time used: 0.01/1.50, max memory used: 9396224/536870912 133 | 134 | Problem: [Take as Much Gold as Possible](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/knapsack)
135 | 136 | * Python: Max time used: 0.61/10.00, max memory used: 20611072/536870912 137 | * Java: 138 | * C++: 139 | 140 | Problem: [Compute the Edit Distance Between Two Strings](https://github.com/mablatnik/Data-Structures-And-Algorithms/tree/master/algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/edit_distance)
141 | 142 | * Python: 143 | * Java: 144 | * C++: 145 | 146 | Problem: [Maximize the Value of an Arithmetic Expression]()
147 | 148 | * Python: 149 | * Java: 150 | * C++: 151 | 152 | Advanced Problem: [Longest Common Subsequence of Three Sequences]()
153 | 154 | * Python: 155 | * Java: 156 | * C++: -------------------------------------------------------------------------------- /algorithmic_toolbox/week_1/maximum_pairwise_product/max_pairwise_product.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::cin; 7 | using std::cout; 8 | 9 | long long MaxPairwiseProduct(const vector &numbers) { 10 | long long result = 0; 11 | int n = numbers.size(); 12 | for (int i = 0; i < n; ++i) { 13 | for (int j = i + 1; j < n; ++j) { 14 | if (((long long) (numbers[i])) * numbers[j] > result) { 15 | result = ((long long) (numbers[i])) * numbers[j]; 16 | } 17 | } 18 | } 19 | return result; 20 | } 21 | 22 | long long MaxPairwiseProductFast(const vector &numbers) { 23 | int n = numbers.size(); 24 | 25 | int max_index1 = -1; 26 | for (int i = 0; i < n; ++i) 27 | if ((max_index1 == -1) || (numbers[i] > numbers[max_index1])) 28 | max_index1 = i; 29 | 30 | int max_index2 = -1; 31 | for (int j = 0; j < n; ++j) 32 | if ((j != max_index1) && ((max_index2 == -1) || (numbers[j] > numbers[max_index2]))) 33 | max_index2 = j; 34 | 35 | //cout << max_index1 << ' ' << max_index2 << "\n"; 36 | 37 | return ((long long) (numbers[max_index1])) * numbers[max_index2]; 38 | } 39 | 40 | int main() { 41 | // while (true) { 42 | // int n = rand() % 1000 + 2; 43 | // cout << n << "\n"; 44 | // vector a; 45 | // for (int i = 0; i < n; ++i) { 46 | // a.push_back(rand() % 100000); 47 | // } 48 | // for (int i = 0; i < n; ++i) { 49 | // cout << a[i] << ' '; 50 | // } 51 | // cout << "\n"; 52 | // long long res1 = MaxPairwiseProduct(a); 53 | // long long res2 = MaxPairwiseProductFast(a); 54 | // if (res1 != res2) { 55 | // cout << "Wrong answer: " << res1 << ' ' << res2 << "\n"; 56 | // break; 57 | // } 58 | // else { 59 | // cout << "OK\n"; 60 | // } 61 | // } 62 | int n; 63 | cin >> n; 64 | vector numbers(n); 65 | for (int i = 0; i < n; ++i) { 66 | cin >> numbers[i]; 67 | } 68 | 69 | long long result = MaxPairwiseProductFast(numbers); 70 | cout << result << "\n"; 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_1/maximum_pairwise_product/max_pairwise_product.java: -------------------------------------------------------------------------------- 1 | 2 | import java.util.*; 3 | import java.io.*; 4 | 5 | public class MaxPairwiseProduct { 6 | 7 | // slower methon O(n^2) 8 | static long getMaxPairwiseProduct(int[] numbers) { 9 | long result = 0; 10 | int n = numbers.length; 11 | for (int i = 0; i < n; ++i) { 12 | for (int j = i + 1; j < n; ++j) { 13 | if ((long)numbers[i] * numbers[j] > result) { 14 | result = (long)numbers[i] * numbers[j]; 15 | } 16 | } 17 | } 18 | return result; 19 | } 20 | 21 | // faster method 22 | static long getMaxPairwiseProductFast(int[] numbers) { 23 | int nSize = numbers.length; 24 | 25 | int max_index1 = -1; 26 | for (int i = 0; i < nSize; i++) { 27 | if ((max_index1 == -1) || (numbers[i] > numbers[max_index1])) 28 | max_index1 = i; 29 | } 30 | 31 | int max_index2 = -1; 32 | for (int j = 0; j < nSize; j++) { 33 | if ((j != max_index1) && ((max_index2 == -1) || (numbers[j] > numbers[max_index2]))) 34 | max_index2 = j; 35 | } 36 | 37 | return (long)numbers[max_index1] * numbers[max_index2]; 38 | } 39 | 40 | // main method 41 | public static void main(String[] args) { 42 | 43 | FastScanner scanner = new FastScanner(System.in); 44 | int n = scanner.nextInt(); 45 | int[] numbers = new int[n]; 46 | for (int i = 0; i < n; i++) { 47 | numbers[i] = scanner.nextInt(); 48 | } 49 | 50 | System.out.println(getMaxPairwiseProductFast(numbers)); 51 | 52 | 53 | /* 54 | // stress test 55 | while (true) { 56 | 57 | Random ran = new Random(); 58 | int max = 5; 59 | int min = 2; 60 | int randomNum = ran.nextInt((max - min) + 1) + min; 61 | 62 | System.out.println("Random number: " + randomNum); 63 | 64 | int[] list = new int[randomNum]; 65 | 66 | for (int i = 0; i < randomNum; i++) { 67 | list[i] = ran.nextInt((10) + 1); 68 | System.out.println(list[i]); 69 | } 70 | System.out.println(""); 71 | 72 | double result1 = getMaxPairwiseProduct(list); 73 | double result2 = getMaxPairwiseProductFast(list); 74 | 75 | if (result1 != result2) { 76 | System.out.println("Error! slow: " + result1 + " fast: " + result2); 77 | break; 78 | } else { 79 | System.out.println("OK"); 80 | } 81 | } 82 | */ 83 | } 84 | // scanning code 85 | static class FastScanner { 86 | BufferedReader br; 87 | StringTokenizer st; 88 | 89 | FastScanner(InputStream stream) { 90 | try { 91 | br = new BufferedReader(new InputStreamReader(stream)); 92 | } catch (Exception e) { 93 | e.printStackTrace(); 94 | } 95 | } 96 | 97 | String next() { 98 | while (st == null || !st.hasMoreTokens()) { 99 | try { 100 | st = new StringTokenizer(br.readLine()); 101 | } catch (IOException e) { 102 | e.printStackTrace(); 103 | } 104 | } 105 | return st.nextToken(); 106 | } 107 | 108 | int nextInt() { 109 | return Integer.parseInt(next()); 110 | } 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_1/maximum_pairwise_product/max_pairwise_product.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | result = 0 3 | 4 | 5 | def max_pairwise_product(n, a): 6 | for i in range(0, n): 7 | for j in range(i + 1, n): 8 | if a[i] * a[j] > result: 9 | result = a[i] * a[j] 10 | return result 11 | 12 | 13 | def max_pairwise_product_fast(n, numbers): 14 | max_index1 = -1 15 | for i in range(n): 16 | if max_index1 == -1 or numbers[i] > numbers[max_index1]: 17 | max_index1 = i 18 | 19 | max_index2 = -1 20 | for i in range(n): 21 | if i != max_index1 and (max_index2 == -1 or numbers[i] > numbers[max_index2]): 22 | max_index2 = i 23 | 24 | return numbers[max_index1] * numbers[max_index2] 25 | 26 | 27 | if __name__ == '__main__': 28 | n = int(input()) 29 | a = [int(x) for x in input().split()] 30 | assert (len(a) == n) 31 | 32 | print(max_pairwise_product_fast(n, a)) 33 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_problems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mablatnik/Algorithmic-Toolbox/5d79938e2f2d97f2100f4555e2ac2f2b79f8f36f/algorithmic_toolbox/week_2/01_introduction_problems.pdf -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci/Fibonacci.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class Fibonacci { 4 | 5 | private static long calc_fib(int n) { 6 | if (n <= 1) 7 | return n; 8 | 9 | int[] result = new int[n + 1]; 10 | result[0] = 0; 11 | result[1] = 1; 12 | for (int i = 2; i < n + 1; i++) { 13 | result[i] = result[i - 1] + result[i - 2]; 14 | } 15 | return result[n]; 16 | } 17 | 18 | public static void main(String args[]) { 19 | Scanner in = new Scanner(System.in); 20 | int n = in.nextInt(); 21 | 22 | System.out.println(calc_fib(n)); 23 | } 24 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci/fibonacci.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // The following code calls a naive algorithm for computing a Fibonacci number. 5 | // 6 | // What to do: 7 | // 1. Compile the following code and run it on an input "40" to check that it is slow. 8 | // You may also want to submit it to the grader to ensure that it gets the "time limit exceeded" message. 9 | // 2. Implement the fibonacci_fast procedure. 10 | // 3. Remove the line that prints the result of the naive algorithm, comment the lines reading the input, 11 | // uncomment the line with a call to test_solution, compile the program, and run it. 12 | // This will ensure that your efficient algorithm returns the same as the naive one for small values of n. 13 | // 4. If test_solution() reveals a bug in your implementation, debug it, fix it, and repeat step 3. 14 | // 5. Remove the call to test_solution, uncomment the line with a call to fibonacci_fast (and the lines reading the input), 15 | // and submit it to the grader. 16 | 17 | int fibonacci_naive(int n) { 18 | if (n <= 1) 19 | return n; 20 | 21 | return fibonacci_naive(n - 1) + fibonacci_naive(n - 2); 22 | } 23 | 24 | int fibonacci_fast(int n) { 25 | if (n <= 1) 26 | return n; 27 | 28 | int F1, F2, F; 29 | F1 = 0; 30 | F2 = 1; 31 | for (int i = 2; i <= n; i++) { 32 | F = F1 + F2; 33 | F1 = F2; 34 | F2 = F; 35 | } 36 | return F; 37 | } 38 | 39 | void test_solution() { 40 | assert(fibonacci_fast(3) == 2); 41 | assert(fibonacci_fast(10) == 55); 42 | for (int n = 0; n < 20; ++n) 43 | assert(fibonacci_fast(n) == fibonacci_naive(n)); 44 | } 45 | 46 | int main() { 47 | int n = 0; 48 | std::cin >> n; 49 | 50 | // test_solution(); 51 | std::cout << fibonacci_fast(n) << '\n'; 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci/fibonacci.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | 3 | 4 | def calc_fib(n): 5 | if n <= 1: 6 | return n 7 | 8 | previous = 0 9 | current = 1 10 | 11 | for _ in range(n - 1): 12 | previous, current = current, previous + current 13 | 14 | return current 15 | 16 | 17 | n = int(input()) 18 | print(calc_fib(n)) 19 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_huge/FibonacciHuge.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class FibonacciHuge { 4 | private static long getFibonacciHugeNaive(long n, long m) { 5 | if (n <= 1) 6 | return n; 7 | 8 | long previous = 0; 9 | long current = 1; 10 | 11 | for (long i = 0; i < n - 1; ++i) { 12 | long tmp_previous = previous; 13 | previous = current; 14 | current = tmp_previous + current; 15 | } 16 | 17 | return current % m; 18 | } 19 | 20 | private static long pisanoPeriodLength(long m) { 21 | long F1 = 0, F2 = 1, F = F1 + F2, length = 0; 22 | for (int i = 0; i < m * m; i++) { 23 | F = (F1 + F2) % m; 24 | F1 = F2; 25 | F2 = F; 26 | if (F1 == 0 && F2 == 1) { 27 | length = i + 1; 28 | break; 29 | } 30 | } 31 | return length; 32 | } 33 | 34 | private static long getFibonacciHugeFast(long n, long m) { 35 | long remainder = n % pisanoPeriodLength(m); 36 | 37 | long F1 = 0, F2 = 1, F = remainder; 38 | for (int i = 1; i < remainder; i++) { 39 | F = (F1 + F2) % m; 40 | F1 = F2; 41 | F2 = F; 42 | } 43 | return F % m; 44 | } 45 | 46 | public static void main(String[] args) { 47 | Scanner scanner = new Scanner(System.in); 48 | long n = scanner.nextLong(); 49 | long m = scanner.nextLong(); 50 | System.out.println(getFibonacciHugeFast(n, m)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_huge/fibonacci_huge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using std::cin; 4 | using std::cout; 5 | 6 | long long get_fibonacci_huge_naive(long long n, long long m) { 7 | if (n <= 1) 8 | return n; 9 | 10 | long long previous = 0; 11 | long long current = 1; 12 | 13 | for (long long i = 0; i < n - 1; ++i) { 14 | long long tmp_previous = previous; 15 | previous = current; 16 | current = tmp_previous + current; 17 | } 18 | 19 | return current % m; 20 | } 21 | 22 | long long get_pisano_period_length(long long m) { 23 | long long F1 = 0, F2 = 1, F = F1 + F2; 24 | for (int i = 0; i < m * m; i++) { 25 | F = (F1 + F2) % m; 26 | F1 = F2; 27 | F2 = F; 28 | if (F1 == 0 && F2 == 1) return i + 1; 29 | } 30 | } 31 | 32 | long long get_fibonacci_huge_fast(long long n, long long m) { 33 | long long remainder = n % get_pisano_period_length(m); 34 | 35 | long long F1 = 0, F2 = 1, F = remainder; 36 | for (int i = 1; i < remainder; i++) { 37 | F = (F1 + F2) % m; 38 | F1 = F2; 39 | F2 = F; 40 | } 41 | return F % m; 42 | } 43 | 44 | int main() { 45 | long long n, m; 46 | 47 | std::cin >> n >> m; 48 | std::cout << get_fibonacci_huge_fast(n, m) << '\n'; 49 | } 50 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_huge/fibonacci_huge.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import unittest 4 | 5 | 6 | def get_fibonacci_huge_naive(n, m): 7 | if n <= 1: 8 | return n 9 | 10 | previous = 0 11 | current = 1 12 | 13 | for _ in range(n - 1): 14 | previous, current = current, previous + current 15 | 16 | return current % m 17 | 18 | 19 | def get_fibonacci(n): 20 | if n <= 1: 21 | return n 22 | 23 | previous = 0 24 | current = 1 25 | 26 | for _ in range(n - 1): 27 | previous, current = current, previous + current 28 | 29 | return current 30 | 31 | 32 | def fib_period_length(m): 33 | previous = 0 34 | current = 1 35 | for i in range(m * m + 1): 36 | previous, current = current, (previous + current) % m 37 | if previous == 0 and current == 1: 38 | return i + 1 39 | 40 | 41 | def get_fibonacci_huge_fast(n, m): 42 | remainder = n % fib_period_length(m) 43 | return get_fibonacci(remainder) % m 44 | 45 | 46 | class MyTest(unittest.TestCase): 47 | def test_naive(self): 48 | self.assertEqual(get_fibonacci_huge_naive(1, 239), 1) 49 | self.assertEqual(get_fibonacci_huge_naive(239, 1000), 161) 50 | 51 | def test_fast(self): 52 | self.assertEqual(get_fibonacci_huge_fast(1, 239), 1) 53 | self.assertEqual(get_fibonacci_huge_fast(239, 1000), 161) 54 | self.assertEqual(get_fibonacci_huge_fast(2816213588, 30524), 10249) 55 | 56 | 57 | if __name__ == '__main__': 58 | # unittest.main() 59 | 60 | # while(True): 61 | # a = random.randint(1, 1000) 62 | # b = random.randint(2, 100) 63 | 64 | # res1 = get_fibonacci_huge_naive(a, b) 65 | # res2 = get_fibonacci_huge_fast(a, b) 66 | # if (res1 != res2): 67 | # print('Wrond answer: {} {}'.format(res1, res2)) 68 | # break 69 | # else: 70 | # print('OK: {} {}'.format(res1, res2)) 71 | 72 | input = sys.stdin.read() 73 | n, m = map(int, input.split()) 74 | print(get_fibonacci_huge_fast(n, m)) 75 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_last_digit/FibonacciLastDigit.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class FibonacciLastDigit { 4 | private static int getFibonacciLastDigitNaive(int n) { 5 | if (n <= 1) 6 | return n; 7 | 8 | int previous = 0; 9 | int current = 1; 10 | 11 | for (int i = 0; i < n - 1; ++i) { 12 | int tmp_previous = previous; 13 | previous = current; 14 | current = tmp_previous + current; 15 | } 16 | 17 | return current % 10; 18 | } 19 | 20 | public static int getFibonacciLastDigitFast(int n) { 21 | if (n <= 1) 22 | return n; 23 | 24 | int[] result = new int[n + 1]; 25 | result[0] = 0; 26 | result[1] = 1; 27 | for (int i = 2; i < n + 1; i++) { 28 | result[i] = (result[i - 1] + result[i - 2]) % 10; 29 | } 30 | return result[n]; 31 | } 32 | 33 | public static void main(String[] args) { 34 | Scanner scanner = new Scanner(System.in); 35 | int n = scanner.nextInt(); 36 | int c = getFibonacciLastDigitFast(n); 37 | System.out.println(c); 38 | } 39 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_last_digit/fibonacci_last_digit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int get_fibonacci_last_digit_naive(long long n) { 5 | if (n <= 1) 6 | return n; 7 | 8 | int previous = 0; 9 | int current = 1; 10 | 11 | for (int i = 0; i < n - 1; ++i) { 12 | int tmp_previous = previous; 13 | previous = current; 14 | current = tmp_previous + current; 15 | } 16 | 17 | return current % 10; 18 | } 19 | 20 | int get_fibonacci_last_digit_fast(long long n) { 21 | if (n <= 1) 22 | return n; 23 | 24 | int previous = 0; 25 | int current = 1; 26 | 27 | for (int i = 0; i < n - 1; ++i) { 28 | int tmp_previous = previous % 10; 29 | previous = current % 10; 30 | current = tmp_previous + current % 10; 31 | } 32 | return current % 10; 33 | } 34 | 35 | // void test_solution() { 36 | // assert(get_fibonacci_last_digit_fast(3), 2); 37 | // assert(get_fibonacci_last_digit_fast(3), 2); 38 | // for (int n = 0; n < 20; ++n) 39 | // assert(get_fibonacci_last_digit_fast(n) == get_fibonacci_last_digit_naive(n)); 40 | // } 41 | 42 | int main() { 43 | int n; 44 | std::cin >> n; 45 | 46 | // test_solution(); 47 | int c = get_fibonacci_last_digit_fast(n); 48 | std::cout << c << '\n'; 49 | } 50 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_last_digit/fibonacci_last_digit.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import unittest 4 | 5 | 6 | def get_fibonacci_last_digit_naive(n): 7 | if n <= 1: 8 | return n 9 | 10 | previous = 0 11 | current = 1 12 | 13 | for _ in range(n - 1): 14 | previous, current = current, previous + current 15 | 16 | return current % 10 17 | 18 | 19 | def get_fibonacci_last_digit_fast(n): 20 | if n <= 1: 21 | return n 22 | 23 | previous = 0 24 | current = 1 25 | 26 | for _ in range(n - 1): 27 | previous, current = current % 10, (previous + current) % 10 28 | 29 | return current 30 | 31 | 32 | class MyTest(unittest.TestCase): 33 | def test_naive(self): 34 | self.assertEqual(get_fibonacci_last_digit_naive(3), 2) 35 | self.assertEqual(get_fibonacci_last_digit_naive(331), 9) 36 | self.assertEqual(get_fibonacci_last_digit_naive(327305), 5) 37 | 38 | def test_fast(self): 39 | self.assertEqual(get_fibonacci_last_digit_fast(3), 2) 40 | self.assertEqual(get_fibonacci_last_digit_fast(331), 9) 41 | self.assertEqual(get_fibonacci_last_digit_fast(327305), 5) 42 | 43 | 44 | if __name__ == '__main__': 45 | # unittest.main() 46 | input = sys.stdin.read() 47 | n = int(input) 48 | print(get_fibonacci_last_digit_fast(n)) 49 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_partial_sum/FibonacciPartialSum.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class FibonacciPartialSum { 4 | private static long getFibonacciPartialSumNaive(long from, long to) { 5 | if (to <= 1) 6 | return to; 7 | 8 | long previous = 0; 9 | long current = 1; 10 | 11 | for (long i = 0; i < from - 1; ++i) { 12 | long tmp_previous = previous; 13 | previous = current; 14 | current = tmp_previous + current; 15 | } 16 | 17 | long sum = current; 18 | 19 | for (long i = 0; i < to - from; ++i) { 20 | long tmp_previous = previous; 21 | previous = current; 22 | current = tmp_previous + current; 23 | sum += current; 24 | } 25 | 26 | return sum % 10; 27 | } 28 | 29 | public static void main(String[] args) { 30 | Scanner scanner = new Scanner(System.in); 31 | long from = scanner.nextLong(); 32 | long to = scanner.nextLong(); 33 | System.out.println(getFibonacciPartialSumNaive(from, to)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_partial_sum/fibonacci_partial_sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | long long get_fibonacci_partial_sum_naive(long long from, long long to) { 7 | if (to <= 1) 8 | return to; 9 | 10 | long long previous = 0; 11 | long long current = 1; 12 | 13 | for (long long i = 0; i < from - 1; ++i) { 14 | long long tmp_previous = previous; 15 | previous = current; 16 | current = tmp_previous + current; 17 | } 18 | 19 | long long sum = current; 20 | 21 | for (long long i = 0; i < to - from; ++i) { 22 | long long tmp_previous = previous; 23 | previous = current; 24 | current = tmp_previous + current; 25 | sum += current; 26 | } 27 | 28 | return sum % 10; 29 | } 30 | 31 | long long fibonacci_fast(long long n) { 32 | if (n <= 1) 33 | return n; 34 | 35 | long long F1, F2, F; 36 | F1 = 0; 37 | F2 = 1; 38 | for (int i = 2; i <= n; i++) { 39 | F = F1 + F2; 40 | F1 = F2; 41 | F2 = F; 42 | } 43 | return F; 44 | } 45 | 46 | int get_pisano_period_length(long long m) { 47 | long long F1 = 0, F2 = 1, F = F1 + F2; 48 | for (int i = 0; i < m * m; i++) { 49 | F = (F1 + F2) % m; 50 | F1 = F2; 51 | F2 = F; 52 | if (F1 == 0 && F2 == 1) return i + 1; 53 | } 54 | } 55 | 56 | int get_fibonacci_huge_fast(long long n, long long m) { 57 | long long remainder = n % get_pisano_period_length(m); 58 | 59 | return fibonacci_fast(remainder) % m; 60 | } 61 | 62 | int get_fibonacci_last_digit_fast(long long n) { 63 | if (n <= 1) 64 | return n; 65 | 66 | int previous = 0; 67 | int current = 1; 68 | 69 | for (int i = 0; i < n - 1; ++i) { 70 | int tmp_previous = previous % 10; 71 | previous = current % 10; 72 | current = tmp_previous + current % 10; 73 | } 74 | return current % 10; 75 | } 76 | 77 | long long fibonacci_partial_sum_fast(long long from_, long long to) { 78 | long long from_last, to_last; 79 | if (from_ == to) { 80 | return get_fibonacci_last_digit_fast(from_ % 60); 81 | } else { 82 | from_ = from_ % 60; 83 | to = to % 60; 84 | 85 | from_last = get_fibonacci_huge_fast(from_ + 1, 10) - 1; 86 | to_last = get_fibonacci_huge_fast(to + 2, 10) - 1; 87 | } 88 | return (to_last - from_last) % 10; 89 | } 90 | 91 | int main() { 92 | long long from, to; 93 | std::cin >> from >> to; 94 | std::cout << fibonacci_partial_sum_fast(from, to) << '\n'; 95 | } 96 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_partial_sum/fibonacci_partial_sum.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import unittest 4 | 5 | 6 | def fibonacci_partial_sum_naive(from_, to): 7 | if to <= 1: 8 | return to 9 | 10 | previous = 0 11 | current = 1 12 | 13 | for _ in range(from_ - 1): 14 | previous, current = current, previous + current 15 | 16 | sum = current 17 | 18 | for _ in range(to - from_): 19 | previous, current = current, previous + current 20 | sum += current 21 | 22 | return sum % 10 23 | 24 | 25 | def get_fibonacci(n): 26 | if n <= 1: 27 | return n 28 | 29 | previous = 0 30 | current = 1 31 | 32 | for _ in range(n - 1): 33 | previous, current = current, previous + current 34 | 35 | return current 36 | 37 | 38 | def fib_period_length(m): 39 | previous = 0 40 | current = 1 41 | for i in range(m * m + 1): 42 | previous, current = current, (previous + current) % m 43 | if previous == 0 and current == 1: 44 | return i + 1 45 | 46 | 47 | def get_fibonacci_huge_fast(n, m): 48 | remainder = n % fib_period_length(m) 49 | return get_fibonacci(remainder) % m 50 | 51 | 52 | def get_fibonacci_last_digit_fast(n): 53 | if n <= 1: 54 | return n 55 | 56 | previous = 0 57 | current = 1 58 | 59 | for _ in range(n - 1): 60 | previous, current = current % 10, (previous + current) % 10 61 | 62 | return current 63 | 64 | 65 | def fibonacci_partial_sum_fast(from_, to): 66 | if from_ == to: 67 | return get_fibonacci_last_digit_fast(from_ % 60) 68 | else: 69 | from_ %= 60 70 | to %= 60 71 | 72 | from_last = get_fibonacci_huge_fast(from_ + 1, 10) - 1 73 | to_last = get_fibonacci_huge_fast(to + 2, 10) - 1 74 | 75 | return (to_last - from_last) % 10 76 | 77 | 78 | class MyTest(unittest.TestCase): 79 | def test_naive(self): 80 | self.assertEqual(fibonacci_partial_sum_naive(3, 7), 1) 81 | self.assertEqual(fibonacci_partial_sum_naive(10, 10), 5) 82 | 83 | def test_fast(self): 84 | self.assertEqual(fibonacci_partial_sum_fast(3, 7), 1) 85 | self.assertEqual(fibonacci_partial_sum_fast(10, 10), 5) 86 | self.assertEqual(fibonacci_partial_sum_fast(10, 200), 2) 87 | 88 | 89 | if __name__ == '__main__': 90 | # unittest.main() 91 | 92 | input = sys.stdin.read() 93 | from_, to = map(int, input.split()) 94 | print(fibonacci_partial_sum_fast(from_, to)) 95 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_sum_last_digit/FibonacciSumLastDigit.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class FibonacciSumLastDigit { 4 | private static long getFibonacciSumNaive(long n) { 5 | if (n <= 1) 6 | return n; 7 | 8 | long previous = 0; 9 | long current = 1; 10 | long sum = 1; 11 | 12 | for (long i = 0; i < n - 1; ++i) { 13 | long tmp_previous = previous; 14 | previous = current; 15 | current = tmp_previous + current; 16 | sum += current; 17 | } 18 | 19 | return sum % 10; 20 | } 21 | 22 | public static int getFibonacciLastDigitFast(int n) { 23 | if (n <= 1) 24 | return n; 25 | 26 | int[] result = new int[n + 1]; 27 | result[0] = 0; 28 | result[1] = 1; 29 | for (int i = 2; i < n + 1; i++) { 30 | result[i] = (result[i - 1] + result[i - 2]) % 10; 31 | } 32 | return result[n]; 33 | } 34 | 35 | public static int getFibonacciSumFast(long n) { 36 | int new_n = (int) ((n + 2) % 60); 37 | int new_last = getFibonacciLastDigitFast(new_n); 38 | if (new_last == 0) { 39 | return 9; 40 | } else { 41 | return new_last - 1; 42 | } 43 | 44 | } 45 | 46 | public static void main(String[] args) { 47 | Scanner scanner = new Scanner(System.in); 48 | long n = scanner.nextLong(); 49 | long s = getFibonacciSumFast(n); 50 | System.out.println(s); 51 | } 52 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_sum_last_digit/fibonacci_sum_last_digit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fibonacci_sum_naive(long long n) { 4 | if (n <= 1) 5 | return n; 6 | 7 | long long previous = 0; 8 | long long current = 1; 9 | long long sum = 1; 10 | 11 | for (long long i = 0; i < n - 1; ++i) { 12 | long long tmp_previous = previous; 13 | previous = current; 14 | current = tmp_previous + current; 15 | sum += current; 16 | } 17 | 18 | return sum % 10; 19 | } 20 | 21 | int get_fibonacci_last_digit_fast(long long n) { 22 | if (n <= 1) 23 | return n; 24 | 25 | int previous = 0; 26 | int current = 1; 27 | 28 | for (int i = 0; i < n - 1; ++i) { 29 | int tmp_previous = previous % 10; 30 | previous = current % 10; 31 | current = tmp_previous + current % 10; 32 | } 33 | return current % 10; 34 | } 35 | 36 | int fibonacci_sum_fast(long long n) { 37 | int new_n = (n + 2) % 60; 38 | int new_last = get_fibonacci_last_digit_fast(new_n); 39 | if (new_last == 0) { 40 | return 9; 41 | } else { 42 | return new_last - 1; 43 | } 44 | } 45 | 46 | int main() { 47 | long long n = 0; 48 | std::cin >> n; 49 | std::cout << fibonacci_sum_fast(n); 50 | } 51 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/fibonacci_sum_last_digit/fibonacci_sum_last_digit.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import unittest 4 | 5 | 6 | def fibonacci_sum_naive(n): 7 | if n <= 1: 8 | return n 9 | 10 | previous = 0 11 | current = 1 12 | sum = 1 13 | 14 | for _ in range(n - 1): 15 | previous, current = current, previous + current 16 | sum += current 17 | 18 | return sum % 10 19 | 20 | 21 | def get_fibonacci_last_digit_fast(n): 22 | if n <= 1: 23 | return n 24 | 25 | previous = 0 26 | current = 1 27 | 28 | for _ in range(n - 1): 29 | previous, current = current % 10, (previous + current) % 10 30 | 31 | return current 32 | 33 | 34 | def fibonacci_sum_fast(n): 35 | new_n = (n + 2) % 60 36 | new_last = get_fibonacci_last_digit_fast(new_n) 37 | if new_last == 0: 38 | return 9 39 | else: 40 | return new_last - 1 41 | 42 | 43 | class MyTest(unittest.TestCase): 44 | def test_naive(self): 45 | self.assertEqual(fibonacci_sum_naive(3), 4) 46 | self.assertEqual(fibonacci_sum_naive(100), 5) 47 | 48 | def test_fast(self): 49 | self.assertEqual(fibonacci_sum_fast(3), 4) 50 | self.assertEqual(fibonacci_sum_fast(100), 5) 51 | 52 | 53 | if __name__ == '__main__': 54 | # unittest.main() 55 | 56 | # while(True): 57 | # a = random.randint(1, 100) 58 | 59 | # res1 = fibonacci_sum_naive(a) 60 | # res2 = fibonacci_sum_fast(a) 61 | # if (res1 != res2): 62 | # print('Generated: {}'.format(a)) 63 | # print('Wrond answer: {} {}'.format(res1, res2)) 64 | # break 65 | # else: 66 | # print('OK: {} {}'.format(res1, res2)) 67 | 68 | input = sys.stdin.read() 69 | n = int(input) 70 | print(fibonacci_sum_fast(n)) 71 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/gcd/GCD.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class GCD { 4 | private static int gcd_naive(int a, int b) { 5 | int current_gcd = 1; 6 | for (int d = 2; d <= a && d <= b; ++d) { 7 | if (a % d == 0 && b % d == 0) { 8 | if (d > current_gcd) { 9 | current_gcd = d; 10 | } 11 | } 12 | } 13 | 14 | return current_gcd; 15 | } 16 | 17 | private static int euclid_gcd(int a, int b) { 18 | int divisor = a >= b ? a : b; 19 | int dividend = a <= b ? a : b; 20 | while (divisor != 0) { 21 | int remainder = dividend % divisor; 22 | dividend = divisor; 23 | divisor = remainder; 24 | } 25 | return dividend; 26 | } 27 | 28 | public static void main(String args[]) { 29 | Scanner scanner = new Scanner(System.in); 30 | int a = scanner.nextInt(); 31 | int b = scanner.nextInt(); 32 | 33 | System.out.println(euclid_gcd(a, b)); 34 | } 35 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/gcd/gcd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using std::cin; 4 | using std::cout; 5 | 6 | int gcd_naive(int a, int b) { 7 | int current_gcd = 1; 8 | for (int d = 2; d <= a && d <= b; d++) { 9 | if (a % d == 0 && b % d == 0) { 10 | if (d > current_gcd) { 11 | current_gcd = d; 12 | } 13 | } 14 | } 15 | return current_gcd; 16 | } 17 | 18 | int euclid_gcd(int a, int b) { 19 | int divisor = a >= b ? a : b; 20 | int dividend = a <= b ? a : b; 21 | while (divisor != 0) { 22 | int remainder = dividend % divisor; 23 | dividend = divisor; 24 | divisor = remainder; 25 | } 26 | return dividend; 27 | } 28 | 29 | int main() { 30 | int a, b; 31 | // while (true) { 32 | // a = rand() % 1000 + 2; 33 | // b = rand() % 1000 + 2; 34 | // cout << "Numbers: " << a << ' ' << b << "\n"; 35 | 36 | // long res1 = gcd_naive(a, b); 37 | // long res2 = euclid_gcd(a, b); 38 | // if (res1 != res2) { 39 | // cout << "Wrong answer: " << res1 << ' ' << res2 << "\n"; 40 | // break; 41 | // } 42 | // else { 43 | // cout << "OK\n"; 44 | // } 45 | // } 46 | std::cin >> a >> b; 47 | std::cout << euclid_gcd(a, b) << std::endl; 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/gcd/gcd.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import unittest 4 | 5 | 6 | def gcd_naive(a, b): 7 | current_gcd = 1 8 | for d in range(2, min(a, b) + 1): 9 | if a % d == 0 and b % d == 0: 10 | if d > current_gcd: 11 | current_gcd = d 12 | 13 | return current_gcd 14 | 15 | 16 | def gcd_euclid(a, b): 17 | dividend = a if (a >= b) else b 18 | divisor = a if (a <= b) else b 19 | 20 | while divisor != 0: 21 | remainder = dividend % divisor 22 | dividend = divisor 23 | divisor = remainder 24 | 25 | return dividend 26 | 27 | 28 | class MyTest(unittest.TestCase): 29 | def test_naive(self): 30 | self.assertEqual(gcd_naive(18, 35), 1) 31 | self.assertEqual(gcd_naive(28851538, 1183019), 17657) 32 | 33 | def test_fast(self): 34 | self.assertEqual(gcd_euclid(18, 35), 1) 35 | self.assertEqual(gcd_euclid(28851538, 1183019), 17657) 36 | 37 | 38 | if __name__ == '__main__': 39 | # unittest.main() 40 | 41 | # while(True): 42 | # a = random.randint(1, 10000) 43 | # b = random.randint(2, 10000) 44 | 45 | # res1 = gcd_naive(a, b) 46 | # res2 = gcd_euclid(a, b) 47 | # if (res1 != res2): 48 | # print('Wrond answer: {} {}'.format(res1, res2)) 49 | # break 50 | # else: 51 | # print('OK: {} {}'.format(res1, res2)) 52 | 53 | input = sys.stdin.read() 54 | a, b = map(int, input.split()) 55 | print(gcd_euclid(a, b)) 56 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/lcm/LCM.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class LCM { 4 | private static long lcm_naive(int a, int b) { 5 | for (long l = 1; l <= (long) a * b; ++l) 6 | if (l % a == 0 && l % b == 0) 7 | return l; 8 | 9 | return (long) a * b; 10 | } 11 | 12 | private static long euclid_gcd(long a, long b) { 13 | long divisor = a >= b ? a : b; 14 | long dividend = a <= b ? a : b; 15 | while (divisor != 0) { 16 | long remainder = dividend % divisor; 17 | dividend = divisor; 18 | divisor = remainder; 19 | } 20 | return dividend; 21 | } 22 | 23 | private static long lmc_fast(long a, long b) { 24 | return (a * b) / euclid_gcd(a, b); 25 | } 26 | 27 | public static void main(String args[]) { 28 | Scanner scanner = new Scanner(System.in); 29 | int a = scanner.nextInt(); 30 | int b = scanner.nextInt(); 31 | 32 | System.out.println(lmc_fast(a, b)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/lcm/lcm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | long long lcm_naive(int a, int b) { 4 | for (long l = 1; l <= (long long) a * b; ++l) 5 | if (l % a == 0 && l % b == 0) 6 | return l; 7 | 8 | return (long long) a * b; 9 | } 10 | 11 | int euclid_gcd(long a, long b) { 12 | int divisor = a >= b ? a : b; 13 | int dividend = a <= b ? a : b; 14 | while (divisor != 0) { 15 | int remainder = dividend % divisor; 16 | dividend = divisor; 17 | divisor = remainder; 18 | } 19 | return dividend; 20 | } 21 | 22 | long long lcm_fast(long long a, long long b) { 23 | return (a * b) / euclid_gcd(a, b); 24 | } 25 | 26 | int main() { 27 | long long a, b; 28 | std::cin >> a >> b; 29 | std::cout << lcm_fast(a, b) << std::endl; 30 | return 0; 31 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_2/01_introduction_starter_files/lcm/lcm.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import unittest 4 | 5 | 6 | def lcm_naive(a, b): 7 | for l in range(1, a * b + 1): 8 | if l % a == 0 and l % b == 0: 9 | return l 10 | 11 | return a * b 12 | 13 | 14 | def gcd_euclid(a, b): 15 | dividend = a if (a >= b) else b 16 | divisor = a if (a <= b) else b 17 | 18 | while divisor != 0: 19 | remainder = dividend % divisor 20 | dividend = divisor 21 | divisor = remainder 22 | 23 | return dividend 24 | 25 | 26 | def lcm_fast(a, b): 27 | return (a * b) // gcd_euclid(a, b) 28 | 29 | 30 | class MyTest(unittest.TestCase): 31 | def test_naive(self): 32 | self.assertEqual(lcm_naive(6, 8), 24) 33 | 34 | # self.assertEqual( lcm_naive(28851538, 1183019), 1933053046) 35 | 36 | def test_fast(self): 37 | self.assertEqual(lcm_fast(6, 8), 24) 38 | self.assertEqual(lcm_fast(28851538, 1183019), 1933053046) 39 | 40 | 41 | if __name__ == '__main__': 42 | # unittest.main() 43 | 44 | # while(True): 45 | # a = random.randint(1, 1000) 46 | # b = random.randint(2, 1000) 47 | 48 | # res1 = lcm_naive(a, b) 49 | # res2 = lcm_fast(a, b) 50 | # if (res1 != res2): 51 | # print('Wrond answer: {} {}'.format(res1, res2)) 52 | # break 53 | # else: 54 | # print('OK: {} {}'.format(res1, res2)) 55 | 56 | input = sys.stdin.read() 57 | a, b = map(int, input.split()) 58 | print(lcm_fast(a, b)) 59 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_problems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mablatnik/Algorithmic-Toolbox/5d79938e2f2d97f2100f4555e2ac2f2b79f8f36f/algorithmic_toolbox/week_3/02_greedy_algorithms_problems.pdf -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/change/Change.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class Change { 4 | private static int getChange(int m) { 5 | int[] coins = { 10, 5, 1 }; 6 | int count = 0; 7 | 8 | for (int i = 0; m > 0; i++) { 9 | count += m / coins[i]; 10 | m %= coins[i]; 11 | } 12 | return count; 13 | } 14 | 15 | public static void main(String[] args) { 16 | Scanner scanner = new Scanner(System.in); 17 | int m = scanner.nextInt(); 18 | System.out.println(getChange(m)); 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/change/change.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int get_change(int m) { 4 | int coins[] = {10, 5, 1}; 5 | int count = 0; 6 | for (int i = 0; m > 0; i++) { 7 | count += m / coins[i]; 8 | m %= coins[i]; 9 | } 10 | return count; 11 | } 12 | 13 | int main() { 14 | int m; 15 | std::cin >> m; 16 | std::cout << get_change(m) << '\n'; 17 | } 18 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/change/change.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import unittest 4 | 5 | 6 | def get_change_specific(value): 7 | p, n, d = 1, 5, 10 8 | count = 0 9 | while value > 0: 10 | if value >= d: 11 | count += value // d 12 | value %= d 13 | elif value >= n: 14 | count += value // n 15 | value %= n 16 | else: 17 | count += value // p 18 | break 19 | return count 20 | 21 | 22 | def get_change_abstract(value, *coins): 23 | count = 0 24 | i = 0 25 | while value > 0: 26 | count += value // coins[i] 27 | value %= coins[i] 28 | i += 1 29 | return count 30 | 31 | 32 | class MyTest(unittest.TestCase): 33 | def test_naive(self): 34 | self.assertEqual(get_change_specific(2), 2) 35 | self.assertEqual(get_change_specific(28), 6) 36 | 37 | def test_naive(self): 38 | self.assertEqual(get_change_abstract(2, 10, 5, 1), 2) 39 | self.assertEqual(get_change_abstract(28, 10, 5, 1), 6) 40 | 41 | 42 | if __name__ == '__main__': 43 | # unittest.main() 44 | 45 | value = int(sys.stdin.read()) 46 | print(get_change_specific(value)) 47 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/covering_segments/CoveringSegments.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class CoveringSegments { 4 | 5 | private static int[] optimalPoints(Segment[] segments) { 6 | int[] points = new int[2 * segments.length]; 7 | 8 | Arrays.sort(segments, new Comparator() { 9 | public int compare(Segment s1, Segment s2) { 10 | return Integer.compare(s1.end, s2.end); 11 | } 12 | }); 13 | int point = segments[0].end; 14 | points[0] = point; 15 | 16 | int j = 1; 17 | for (int i = 1; i < segments.length; i++) { 18 | if (point < segments[i].start || point > segments[i].end) { 19 | point = segments[i].end; 20 | points[j] = point; 21 | j++; 22 | } 23 | } 24 | int[] pointsFinal = new int[j]; 25 | for (int i = 0; i < j; i++) { 26 | pointsFinal[i] = points[i]; 27 | } 28 | return pointsFinal; 29 | } 30 | 31 | private static class Segment { 32 | int start, end; 33 | 34 | Segment(int start, int end) { 35 | this.start = start; 36 | this.end = end; 37 | } 38 | } 39 | 40 | public static void main(String[] args) { 41 | Scanner scanner = new Scanner(System.in); 42 | int n = scanner.nextInt(); 43 | Segment[] segments = new Segment[n]; 44 | for (int i = 0; i < n; i++) { 45 | int start, end; 46 | start = scanner.nextInt(); 47 | end = scanner.nextInt(); 48 | segments[i] = new Segment(start, end); 49 | } 50 | int[] points = optimalPoints(segments); 51 | System.out.println(points.length); 52 | for (int point : points) { 53 | System.out.print(point + " "); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/covering_segments/covering_segments.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::vector; 7 | 8 | struct Segment { 9 | int start, end; 10 | }; 11 | 12 | bool sortFunction(Segment i, Segment j) { return (i.end < j.end); } 13 | 14 | vector optimal_points(vector &segments) { 15 | 16 | std::sort(segments.begin(), segments.end(), sortFunction); 17 | 18 | vector points; 19 | int point = segments[0].end; 20 | points.push_back(point); 21 | 22 | for (size_t i = 1; i < segments.size(); ++i) { 23 | if (point < segments[i].start || point > segments[i].end) { 24 | point = segments[i].end; 25 | points.push_back(point); 26 | } 27 | } 28 | return points; 29 | } 30 | 31 | int main() { 32 | int n; 33 | std::cin >> n; 34 | vector segments(n); 35 | for (size_t i = 0; i < segments.size(); ++i) { 36 | std::cin >> segments[i].start >> segments[i].end; 37 | } 38 | vector points = optimal_points(segments); 39 | std::cout << points.size() << "\n"; 40 | for (size_t i = 0; i < points.size(); ++i) { 41 | std::cout << points[i] << " "; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/covering_segments/covering_segments.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | from operator import attrgetter 4 | from collections import namedtuple 5 | 6 | Segment = namedtuple('Segment', 'start end') 7 | 8 | 9 | def optimal_points(segments): 10 | points = [] 11 | segments = sorted(segments, key=attrgetter('end')) 12 | max_right = segments[0].end 13 | points.append(max_right) 14 | i = 1 15 | while i < len(segments): 16 | if max_right < segments[i].start: 17 | max_right = segments[i].end 18 | points.append(max_right) 19 | i += 1 20 | 21 | return points 22 | 23 | 24 | if __name__ == '__main__': 25 | input = sys.stdin.read() 26 | n, *data = map(int, input.split()) 27 | segments = list(map(lambda x: Segment(x[0], x[1]), zip(data[::2], data[1::2]))) 28 | points = optimal_points(segments) 29 | print(len(points)) 30 | for p in points: 31 | print(p, end=' ') 32 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/different_summands/DifferentSummands.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class DifferentSummands { 4 | private static List optimalSummands(int n) { 5 | List summands = new ArrayList(); 6 | for (int i = 1; i <= n; i++) { 7 | n -= i; 8 | if (n <= i) { 9 | summands.add(n + i); 10 | } else if (n == 0) { 11 | summands.add(i); 12 | break; 13 | } else { 14 | summands.add(i); 15 | } 16 | } 17 | return summands; 18 | } 19 | 20 | public static void main(String[] args) { 21 | Scanner scanner = new Scanner(System.in); 22 | int n = scanner.nextInt(); 23 | List summands = optimalSummands(n); 24 | System.out.println(summands.size()); 25 | for (Integer summand : summands) { 26 | System.out.print(summand + " "); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/different_summands/different_summands.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | vector optimal_summands(int n) { 7 | vector summands; 8 | for (int i = 1; i <= n; i++) { 9 | n -= i; 10 | if (n <= i) { 11 | summands.push_back(n + i); 12 | } else if (n == 0) { 13 | summands.push_back(i); 14 | break; 15 | } else { 16 | summands.push_back(i); 17 | } 18 | } 19 | return summands; 20 | } 21 | 22 | int main() { 23 | int n; 24 | std::cin >> n; 25 | vector summands = optimal_summands(n); 26 | std::cout << summands.size() << '\n'; 27 | for (size_t i = 0; i < summands.size(); ++i) { 28 | std::cout << summands[i] << ' '; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/different_summands/different_summands.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | 4 | 5 | def optimal_summands(n): 6 | summands = [] 7 | for i in range(1, n + 1): 8 | n -= i 9 | if n <= i: 10 | summands.append(n + i) 11 | break 12 | elif n == 0: 13 | summands.append(i) 14 | break 15 | else: 16 | summands.append(i) 17 | return summands 18 | 19 | 20 | if __name__ == '__main__': 21 | input = sys.stdin.read() 22 | n = int(input) 23 | summands = optimal_summands(n) 24 | print(len(summands)) 25 | for x in summands: 26 | print(x, end=' ') 27 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/dot_product/DotProduct.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class DotProduct { 4 | private static long maxDotProduct(int[] a, int[] b) { 5 | Arrays.sort(a); 6 | Arrays.sort(b); 7 | long result = 0; 8 | for (int i = 0; i < a.length; i++) { 9 | result += (long) a[i] * b[i]; 10 | } 11 | return result; 12 | } 13 | 14 | public static void main(String[] args) { 15 | Scanner scanner = new Scanner(System.in); 16 | int n = scanner.nextInt(); 17 | int[] a = new int[n]; 18 | for (int i = 0; i < n; i++) { 19 | a[i] = scanner.nextInt(); 20 | } 21 | int[] b = new int[n]; 22 | for (int i = 0; i < n; i++) { 23 | b[i] = scanner.nextInt(); 24 | } 25 | System.out.println(maxDotProduct(a, b)); 26 | } 27 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/dot_product/dot_product.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | 7 | long long max_dot_product(vector a, vector b) { 8 | std::sort(begin(a), end(a)); 9 | std::sort(begin(b), end(b)); 10 | long long result = 0; 11 | for (int i = 0; i < a.size(); i++) { 12 | result += (long long) a[i] * b[i]; 13 | } 14 | return result; 15 | } 16 | 17 | int main() { 18 | size_t n; 19 | std::cin >> n; 20 | vector a(n), b(n); 21 | for (size_t i = 0; i < n; i++) { 22 | std::cin >> a[i]; 23 | } 24 | for (size_t i = 0; i < n; i++) { 25 | std::cin >> b[i]; 26 | } 27 | std::cout << max_dot_product(a, b) << std::endl; 28 | } 29 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/dot_product/dot_product.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | 3 | import sys 4 | 5 | 6 | def max_dot_product(a, b): 7 | a.sort() 8 | b.sort() 9 | 10 | res = 0 11 | for i in range(len(a)): 12 | res += a[i] * b[i] 13 | return res 14 | 15 | 16 | if __name__ == '__main__': 17 | input = sys.stdin.read() 18 | data = list(map(int, input.split())) 19 | n = data[0] 20 | a = data[1:(n + 1)] 21 | b = data[(n + 1):] 22 | print(max_dot_product(a, b)) 23 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/fractional_knapsack/FractionalKnapsack.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class FractionalKnapsack { 4 | 5 | private static int getMaxIndex(int[] weights, int[] values) { 6 | int max_i = 0; 7 | double max = 0; 8 | 9 | for (int i = 0; i < weights.length; i++) { 10 | if (weights[i] != 0 && (double) values[i] / weights[i] > max) { 11 | max = (double) values[i] / weights[i]; 12 | max_i = i; 13 | } 14 | } 15 | return max_i; 16 | } 17 | 18 | private static double getOptimalValue(int capacity, int[] values, int[] weights) { 19 | double value = 0.0; 20 | 21 | for (int i = 0; i < weights.length; i++) { 22 | if (capacity == 0) 23 | return value; 24 | int index = getMaxIndex(weights, values); 25 | int a = Math.min(capacity, weights[index]); 26 | value += a * (double) values[index] / weights[index]; 27 | weights[index] -= a; 28 | capacity -= a; 29 | } 30 | return value; 31 | } 32 | 33 | public static void main(String args[]) { 34 | Scanner scanner = new Scanner(System.in); 35 | int n = scanner.nextInt(); 36 | int capacity = scanner.nextInt(); 37 | int[] values = new int[n]; 38 | int[] weights = new int[n]; 39 | for (int i = 0; i < n; i++) { 40 | values[i] = scanner.nextInt(); 41 | weights[i] = scanner.nextInt(); 42 | } 43 | System.out.println(getOptimalValue(capacity, values, weights)); 44 | } 45 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/fractional_knapsack/fractional_knapsack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | int get_max_index(vector weights, vector values) { 7 | int max_i = 0; 8 | double max = 0; 9 | 10 | for (int i = 0; i < weights.size(); i++) { 11 | if (weights[i] != 0 && (double) values[i] / weights[i] > max) { 12 | max = (double) values[i] / weights[i]; 13 | max_i = i; 14 | } 15 | } 16 | return max_i; 17 | } 18 | 19 | double get_optimal_value(int capacity, vector weights, vector values) { 20 | double value = 0.0; 21 | 22 | for (int i = 0; i < weights.size(); i++) { 23 | if (capacity == 0) return value; 24 | int index = get_max_index(weights, values); 25 | int a = std::min(capacity, weights[index]); 26 | value += a * (double) values[index] / weights[index]; 27 | weights[index] -= a; 28 | capacity -= a; 29 | } 30 | 31 | return value; 32 | } 33 | 34 | int main() { 35 | int n; 36 | int capacity; 37 | std::cin >> n >> capacity; 38 | vector values(n); 39 | vector weights(n); 40 | for (int i = 0; i < n; i++) { 41 | std::cin >> values[i] >> weights[i]; 42 | } 43 | 44 | double optimal_value = get_optimal_value(capacity, weights, values); 45 | 46 | std::cout.precision(10); 47 | std::cout << optimal_value << std::endl; 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/fractional_knapsack/fractional_knapsack.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import unittest 4 | 5 | 6 | def get_optimal_value(capacity, weights, values): 7 | value = 0. 8 | proportion = [float(v) / float(w) for v, w in zip(values, weights)] 9 | for _ in range(len(weights) + 1): 10 | if capacity == 0: 11 | return value 12 | break 13 | max_weight = max(proportion) 14 | index = proportion.index(max_weight) 15 | proportion[index] = -1 16 | add_capacity = min(capacity, weights[index]) 17 | value += add_capacity * max_weight 18 | weights[index] -= add_capacity 19 | capacity -= add_capacity 20 | return value 21 | 22 | 23 | if __name__ == "__main__": 24 | data = list(map(int, sys.stdin.read().split())) 25 | n, capacity = data[0:2] 26 | values = data[2:(2 * n + 2):2] 27 | weights = data[3:(2 * n + 2):2] 28 | opt_value = get_optimal_value(capacity, weights, values) 29 | print("{:.10f}".format(opt_value)) 30 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/largest_number/LargestNumber.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class LargestNumber { 4 | private static String largestNumber(String[] a) { 5 | // write your code here 6 | String result = ""; 7 | for (int i = 0; i < a.length; i++) { 8 | result += a[i]; 9 | } 10 | return result; 11 | } 12 | 13 | public static void main(String[] args) { 14 | Scanner scanner = new Scanner(System.in); 15 | int n = scanner.nextInt(); 16 | String[] a = new String[n]; 17 | for (int i = 0; i < n; i++) { 18 | a[i] = scanner.next(); 19 | } 20 | System.out.println(largestNumber(a)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/largest_number/by_learners/largest_number.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def largest_number(a) 5 | # write your code here 6 | a.join('') 7 | end 8 | 9 | if __FILE__ == $0 10 | a = STDIN.read.split().drop(1) 11 | puts largest_number(a) 12 | end -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/largest_number/largest_number.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using std::vector; 8 | using std::string; 9 | 10 | string largest_number(vector a) { 11 | //write your code here 12 | std::stringstream ret; 13 | for (size_t i = 0; i < a.size(); i++) { 14 | ret << a[i]; 15 | } 16 | string result; 17 | ret >> result; 18 | return result; 19 | } 20 | 21 | int main() { 22 | int n; 23 | std::cin >> n; 24 | vector a(n); 25 | for (size_t i = 0; i < a.size(); i++) { 26 | std::cin >> a[i]; 27 | } 28 | std::cout << largest_number(a); 29 | } 30 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/largest_number/largest_number.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | largest_number :: [Int] -> String 4 | largest_number as = concat (map show as) -- write your code here 5 | 6 | main :: IO () 7 | main = do 8 | _ <- getLine 9 | as <- fmap (map read . words) getLine 10 | putStrLn $ largest_number as 11 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_3/02_greedy_algorithms_starter_files/largest_number/largest_number.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | 3 | import sys 4 | 5 | 6 | def largest_number(a): 7 | nums = map(str, a) 8 | nums.sort() 9 | 10 | return res 11 | 12 | 13 | if __name__ == '__main__': 14 | input = sys.stdin.read() 15 | data = input.split() 16 | a = data[1:] 17 | print(largest_number(a)) 18 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_problems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mablatnik/Algorithmic-Toolbox/5d79938e2f2d97f2100f4555e2ac2f2b79f8f36f/algorithmic_toolbox/week_4/03_divide_and_conquer_problems.pdf -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/binary_search/BinarySearch.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | 4 | public class BinarySearch { 5 | 6 | static int binarySearch(int[] a, int x) { 7 | int left = 0, right = a.length - 1; 8 | while (left <= right) { 9 | int mid = left + (right - left) / 2; 10 | if (x == a[mid]) { 11 | return mid; 12 | } else if (x < a[mid]) { 13 | right = mid - 1; 14 | } else { 15 | left = mid + 1; 16 | } 17 | } 18 | return -1; 19 | } 20 | 21 | static int linearSearch(int[] a, int x) { 22 | for (int i = 0; i < a.length; i++) { 23 | if (a[i] == x) 24 | return i; 25 | } 26 | return -1; 27 | } 28 | 29 | public static void main(String[] args) { 30 | FastScanner scanner = new FastScanner(System.in); 31 | int n = scanner.nextInt(); 32 | int[] a = new int[n]; 33 | for (int i = 0; i < n; i++) { 34 | a[i] = scanner.nextInt(); 35 | } 36 | int m = scanner.nextInt(); 37 | int[] b = new int[m]; 38 | for (int i = 0; i < m; i++) { 39 | b[i] = scanner.nextInt(); 40 | } 41 | for (int i = 0; i < m; i++) { 42 | // replace with the call to binarySearch when implemented 43 | System.out.print(binarySearch(a, b[i]) + " "); 44 | } 45 | } 46 | 47 | static class FastScanner { 48 | BufferedReader br; 49 | StringTokenizer st; 50 | 51 | FastScanner(InputStream stream) { 52 | try { 53 | br = new BufferedReader(new InputStreamReader(stream)); 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | 59 | String next() { 60 | while (st == null || !st.hasMoreTokens()) { 61 | try { 62 | st = new StringTokenizer(br.readLine()); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | return st.nextToken(); 68 | } 69 | 70 | int nextInt() { 71 | return Integer.parseInt(next()); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/binary_search/binary_search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | 7 | int binary_search_iterative(const vector &a, int x) { 8 | int left = 0, right = (int) a.size(); 9 | while (left <= right) { 10 | int mid = left + (right - left) / 2; 11 | if (x == a[mid]) return mid; 12 | else if (x < a[mid]) right = mid - 1; 13 | else left = mid + 1; 14 | } 15 | return -1; 16 | } 17 | 18 | int linear_search(const vector &a, int x) { 19 | for (size_t i = 0; i < a.size(); ++i) { 20 | if (a[i] == x) return i; 21 | } 22 | return -1; 23 | } 24 | 25 | int main() { 26 | int n; 27 | std::cin >> n; 28 | vector a(n); 29 | for (size_t i = 0; i < a.size(); i++) { 30 | std::cin >> a[i]; 31 | } 32 | int m; 33 | std::cin >> m; 34 | vector b(m); 35 | for (int i = 0; i < m; ++i) { 36 | std::cin >> b[i]; 37 | } 38 | for (int i = 0; i < m; ++i) { 39 | //replace with the call to binary_search when implemented 40 | std::cout << binary_search_iterative(a, b[i]) << ' '; 41 | } 42 | } -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/binary_search/binary_search.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | 4 | 5 | def binary_search_iterative(a, x): 6 | left, right = 0, len(a) - 1 7 | 8 | while left <= right: 9 | mid = left + (right - left) // 2 10 | if a[mid] == x: 11 | return mid 12 | elif x < a[mid]: 13 | right = mid - 1 14 | else: 15 | left = mid + 1 16 | return -1 17 | 18 | 19 | def linear_search(a, x): 20 | for i in range(len(a)): 21 | if a[i] == x: 22 | return i 23 | return -1 24 | 25 | 26 | if __name__ == '__main__': 27 | input = sys.stdin.read() 28 | data = list(map(int, input.split())) 29 | n = data[0] 30 | m = data[n + 1] 31 | a = data[1: n + 1] 32 | for x in data[n + 2:]: 33 | # replace with the call to binary_search when implemented 34 | print(binary_search_iterative(a, x), end=' ') 35 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/closest/Closest.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | 4 | import static java.lang.Math.*; 5 | 6 | public class Closest { 7 | 8 | static class Point implements Comparable { 9 | long x, y; 10 | 11 | public Point(long x, long y) { 12 | this.x = x; 13 | this.y = y; 14 | } 15 | 16 | @Override 17 | public int compareTo(Point o) { 18 | return o.y == y ? Long.signum(x - o.x) : Long.signum(y - o.y); 19 | } 20 | } 21 | 22 | static double minimalDistance(int[] x, int y[]) { 23 | double ans = Double.POSITIVE_INFINITY; 24 | // write your code here 25 | return ans; 26 | } 27 | 28 | public static void main(String[] args) throws Exception { 29 | reader = new BufferedReader(new InputStreamReader(System.in)); 30 | writer = new PrintWriter(System.out); 31 | int n = nextInt(); 32 | int[] x = new int[n]; 33 | int[] y = new int[n]; 34 | for (int i = 0; i < n; i++) { 35 | x[i] = nextInt(); 36 | y[i] = nextInt(); 37 | } 38 | System.out.println(minimalDistance(x, y)); 39 | writer.close(); 40 | } 41 | 42 | static BufferedReader reader; 43 | static PrintWriter writer; 44 | static StringTokenizer tok = new StringTokenizer(""); 45 | 46 | static String next() { 47 | while (!tok.hasMoreTokens()) { 48 | String w = null; 49 | try { 50 | w = reader.readLine(); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } 54 | if (w == null) 55 | return null; 56 | tok = new StringTokenizer(w); 57 | } 58 | return tok.nextToken(); 59 | } 60 | 61 | static int nextInt() { 62 | return Integer.parseInt(next()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/closest/closest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::vector; 10 | using std::string; 11 | using std::pair; 12 | using std::min; 13 | 14 | 15 | double minimal_distance(vector x, vector y) { 16 | //write your code here 17 | return 0.; 18 | } 19 | 20 | int main() { 21 | size_t n; 22 | std::cin >> n; 23 | vector x(n); 24 | vector y(n); 25 | for (size_t i = 0; i < n; i++) { 26 | std::cin >> x[i] >> y[i]; 27 | } 28 | std::cout << std::fixed; 29 | std::cout << std::setprecision(9) << minimal_distance(x, y) << "\n"; 30 | } 31 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/closest/closest.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import math 4 | 5 | 6 | def minimum_distance(x, y): 7 | # write your code here 8 | return 10 ** 18 9 | 10 | 11 | if __name__ == '__main__': 12 | input = sys.stdin.read() 13 | data = list(map(int, input.split())) 14 | n = data[0] 15 | x = data[1::2] 16 | y = data[2::2] 17 | print("{0:.9f}".format(minimum_distance(x, y))) 18 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/inversions/Inversions.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Inversions { 4 | private static long merge(int[] a, int[] b, int left, int ave, int right) { 5 | int i = left, j = ave, k = left; 6 | long inv_count = 0; 7 | while (i <= ave - 1 && j <= right) { 8 | if (a[i] <= a[j]) { 9 | b[k] = a[i]; 10 | i++; 11 | } else { 12 | b[k] = a[j]; 13 | inv_count += ave - i; 14 | j++; 15 | } 16 | k++; 17 | } 18 | while (i <= ave - 1) { 19 | b[k] = a[i]; 20 | i++; 21 | k++; 22 | } 23 | while (j <= right) { 24 | b[k] = a[j]; 25 | j++; 26 | k++; 27 | } 28 | for (i = left; i <= right; i++) { 29 | a[i] = b[i]; 30 | } 31 | return inv_count; 32 | } 33 | 34 | private static long getNumberOfInversions(int[] a, int[] b, int left, int right) { 35 | long inv_count = 0; 36 | if (right <= left) { 37 | return inv_count; 38 | } 39 | int ave = left + (right - left) / 2; 40 | inv_count += getNumberOfInversions(a, b, left, ave); 41 | inv_count += getNumberOfInversions(a, b, ave + 1, right); 42 | inv_count += merge(a, b, left, ave + 1, right); 43 | return inv_count; 44 | } 45 | 46 | public static void main(String[] args) { 47 | Scanner scanner = new Scanner(System.in); 48 | int n = scanner.nextInt(); 49 | int[] a = new int[n]; 50 | for (int i = 0; i < n; i++) { 51 | a[i] = scanner.nextInt(); 52 | } 53 | int[] b = new int[n]; 54 | System.out.println(getNumberOfInversions(a, b, 0, a.length - 1)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/inversions/inversions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | long long get_inversions(vector &a, vector &b, size_t left, int ave, size_t right) { 7 | size_t i = left, j = ave, k = left; 8 | long long inv_count = 0; 9 | while (i <= ave - 1 && j <= right) { 10 | if (a[i] <= a[j]) { 11 | b[k] = a[i]; 12 | i++; 13 | } else { 14 | b[k] = a[j]; 15 | inv_count += ave - i; 16 | j++; 17 | } 18 | k++; 19 | } 20 | while (i <= ave - 1) { 21 | b[k] = a[i]; 22 | i++; 23 | k++; 24 | } 25 | while (j <= right) { 26 | b[k] = a[j]; 27 | j++; 28 | k++; 29 | } 30 | for (i = left; i <= right; i++) { 31 | a[i] = b[i]; 32 | } 33 | return inv_count; 34 | } 35 | 36 | long long merge_sort(vector &a, vector &b, size_t left, size_t right) { 37 | long long inv_count = 0; 38 | if (right <= left) return inv_count; 39 | size_t ave = left + (right - left) / 2; 40 | inv_count += merge_sort(a, b, left, ave); 41 | inv_count += merge_sort(a, b, ave + 1, right); 42 | inv_count += get_inversions(a, b, left, ave + 1, right); 43 | return inv_count; 44 | } 45 | 46 | int main() { 47 | int n; 48 | std::cin >> n; 49 | vector a(n); 50 | for (size_t i = 0; i < a.size(); i++) { 51 | std::cin >> a[i]; 52 | } 53 | vector b(a.size()); 54 | std::cout << merge_sort(a, b, 0, a.size() - 1) << '\n'; 55 | } 56 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/inversions/inversions.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | 4 | 5 | def merge(a, b, left, ave, right): 6 | inv_count = 0 7 | i, j, k = left, ave, left 8 | while i <= ave - 1 and j <= right: 9 | if a[i] <= a[j]: 10 | b[k] = a[i] 11 | i += 1 12 | else: 13 | b[k] = a[j] 14 | j += 1 15 | inv_count += ave - i 16 | k += 1 17 | while i <= ave - 1: 18 | b[k] = a[i] 19 | i += 1 20 | k += 1 21 | while j <= right: 22 | b[k] = a[j] 23 | j += 1 24 | k += 1 25 | for i in range(left, right + 1): 26 | a[i] = b[i] 27 | return inv_count 28 | 29 | 30 | def merge_sort(a, b, left, right): 31 | inv_count = 0 32 | if right > left: 33 | ave = (left + right) // 2 34 | inv_count += merge_sort(a, b, left, ave) 35 | inv_count += merge_sort(a, b, ave + 1, right) 36 | 37 | inv_count += merge(a, b, left, ave + 1, right) 38 | 39 | return inv_count 40 | 41 | 42 | if __name__ == '__main__': 43 | input = sys.stdin.read() 44 | n, *a = list(map(int, input.split())) 45 | b = n * [0] 46 | print(merge_sort(a, b, 0, len(a) - 1)) 47 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/majority_element/MajorityElement.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | 4 | public class MajorityElement { 5 | private static int getMajorityElement(int[] a, int left, int right) { 6 | if (left == right) { 7 | return -1; 8 | } 9 | if (left + 1 == right) { 10 | return a[left]; 11 | } 12 | int left_elem = getMajorityElement(a, left, (left + right - 1) / 2 + 1); 13 | int right_elem = getMajorityElement(a, (left + right - 1) / 2 + 1, right); 14 | 15 | int lcount = 0; 16 | for (int i = left; i < right; i++) { 17 | if (a[i] == left_elem) 18 | lcount += 1; 19 | } 20 | if (lcount > (right - left) / 2) 21 | return left_elem; 22 | 23 | int rcount = 0; 24 | for (int i = left; i < right; i++) { 25 | if (a[i] == right_elem) 26 | rcount += 1; 27 | } 28 | if (rcount > (right - left) / 2) 29 | return right_elem; 30 | return -1; 31 | } 32 | 33 | public static void main(String[] args) { 34 | FastScanner scanner = new FastScanner(System.in); 35 | int n = scanner.nextInt(); 36 | int[] a = new int[n]; 37 | for (int i = 0; i < n; i++) { 38 | a[i] = scanner.nextInt(); 39 | } 40 | if (getMajorityElement(a, 0, a.length) != -1) { 41 | System.out.println(1); 42 | } else { 43 | System.out.println(0); 44 | } 45 | } 46 | 47 | static class FastScanner { 48 | BufferedReader br; 49 | StringTokenizer st; 50 | 51 | FastScanner(InputStream stream) { 52 | try { 53 | br = new BufferedReader(new InputStreamReader(stream)); 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | 59 | String next() { 60 | while (st == null || !st.hasMoreTokens()) { 61 | try { 62 | st = new StringTokenizer(br.readLine()); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | return st.nextToken(); 68 | } 69 | 70 | int nextInt() { 71 | return Integer.parseInt(next()); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/majority_element/majority_element.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | 7 | int get_majority_element(vector &a, int left, int right) { 8 | if (left == right) return -1; 9 | if (left + 1 == right) return a[left]; 10 | 11 | int left_elem = get_majority_element(a, left, (left + right - 1) / 2 + 1); 12 | int right_elem = get_majority_element(a, (left + right - 1) / 2 + 1, right); 13 | 14 | int lcount = 0; 15 | for (int i = left; i < right; i++) { 16 | if (a[i] == left_elem) lcount += 1; 17 | } 18 | if (lcount > (right - left) / 2) return left_elem; 19 | 20 | int rcount = 0; 21 | for (int i = left; i < right; i++) { 22 | if (a[i] == right_elem) rcount += 1; 23 | } 24 | if (rcount > (right - left) / 2) return right_elem; 25 | 26 | return -1; 27 | } 28 | 29 | int main() { 30 | int n; 31 | std::cin >> n; 32 | vector a(n); 33 | for (size_t i = 0; i < a.size(); ++i) { 34 | std::cin >> a[i]; 35 | } 36 | std::cout << (get_majority_element(a, 0, a.size()) != -1) << '\n'; 37 | } 38 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/majority_element/majority_element.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | 4 | 5 | def get_majority_element(a, left, right): 6 | if left == right: 7 | return -1 8 | if left + 1 == right: 9 | return a[left] 10 | 11 | left_elem = get_majority_element(a, left, (left + right - 1) // 2 + 1) 12 | right_elem = get_majority_element(a, (left + right - 1) // 2 + 1, right) 13 | 14 | lcount = 0 15 | for i in range(left, right): 16 | if a[i] == left_elem: 17 | lcount += 1 18 | if lcount > (right - left) // 2: 19 | return left_elem 20 | 21 | rcount = 0 22 | for i in range(left, right): 23 | if a[i] == right_elem: 24 | rcount += 1 25 | if rcount > (right - left) // 2: 26 | return right_elem 27 | 28 | return -1 29 | 30 | 31 | if __name__ == '__main__': 32 | input = sys.stdin.read() 33 | n, *a = list(map(int, input.split())) 34 | if get_majority_element(a, 0, n) != -1: 35 | print(1) 36 | else: 37 | print(0) 38 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/points_and_segments/PointsAndSegments.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class PointsAndSegments { 4 | 5 | private static int[] fastCountSegments(int[] starts, int[] ends, int[] points) { 6 | int[] cnt = new int[points.length]; 7 | // write your code here 8 | return cnt; 9 | } 10 | 11 | private static int[] naiveCountSegments(int[] starts, int[] ends, int[] points) { 12 | int[] cnt = new int[points.length]; 13 | for (int i = 0; i < points.length; i++) { 14 | for (int j = 0; j < starts.length; j++) { 15 | if (starts[j] <= points[i] && points[i] <= ends[j]) { 16 | cnt[i]++; 17 | } 18 | } 19 | } 20 | return cnt; 21 | } 22 | 23 | public static void main(String[] args) { 24 | Scanner scanner = new Scanner(System.in); 25 | int n, m; 26 | n = scanner.nextInt(); 27 | m = scanner.nextInt(); 28 | int[] starts = new int[n]; 29 | int[] ends = new int[n]; 30 | int[] points = new int[m]; 31 | for (int i = 0; i < n; i++) { 32 | starts[i] = scanner.nextInt(); 33 | ends[i] = scanner.nextInt(); 34 | } 35 | for (int i = 0; i < m; i++) { 36 | points[i] = scanner.nextInt(); 37 | } 38 | // use fastCountSegments 39 | int[] cnt = naiveCountSegments(starts, ends, points); 40 | for (int x : cnt) { 41 | System.out.print(x + " "); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/points_and_segments/points_and_segments.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | vector fast_count_segments(vector starts, vector ends, vector points) { 7 | vector cnt(points.size()); 8 | //write your code here 9 | return cnt; 10 | } 11 | 12 | vector naive_count_segments(vector starts, vector ends, vector points) { 13 | vector cnt(points.size()); 14 | for (size_t i = 0; i < points.size(); i++) { 15 | for (size_t j = 0; j < starts.size(); j++) { 16 | cnt[i] += starts[j] <= points[i] && points[i] <= ends[j]; 17 | } 18 | } 19 | return cnt; 20 | } 21 | 22 | int main() { 23 | int n, m; 24 | std::cin >> n >> m; 25 | vector starts(n), ends(n); 26 | for (size_t i = 0; i < starts.size(); i++) { 27 | std::cin >> starts[i] >> ends[i]; 28 | } 29 | vector points(m); 30 | for (size_t i = 0; i < points.size(); i++) { 31 | std::cin >> points[i]; 32 | } 33 | //use fast_count_segments 34 | vector cnt = naive_count_segments(starts, ends, points); 35 | for (size_t i = 0; i < cnt.size(); i++) { 36 | std::cout << cnt[i] << ' '; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/points_and_segments/points_and_segments.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | from itertools import chain 4 | 5 | 6 | def fast_count_segments(starts, ends, points): 7 | cnt = [0] * len(points) 8 | start_points = zip(starts, ['l'] * len(starts), range(len(starts))) 9 | end_points = zip(ends, ['r'] * len(ends), range(len(ends))) 10 | point_points = zip(points, ['p'] * len(points), range(len(points))) 11 | 12 | sort_list = chain(start_points, end_points, point_points) 13 | sort_list = sorted(sort_list, key=lambda a: (a[0], a[1])) 14 | segment = 0 15 | i = 0 16 | for num, letter, index in sort_list: 17 | if letter == 'l': 18 | segment += 1 19 | elif letter == 'r': 20 | segment -= 1 21 | else: 22 | cnt[index] = segment 23 | i += 1 24 | return cnt 25 | 26 | 27 | def naive_count_segments(starts, ends, points): 28 | cnt = [0] * len(points) 29 | for i in range(len(points)): 30 | for j in range(len(starts)): 31 | if starts[j] <= points[i] <= ends[j]: 32 | cnt[i] += 1 33 | return cnt 34 | 35 | 36 | if __name__ == '__main__': 37 | input = sys.stdin.read() 38 | data = list(map(int, input.split())) 39 | n = data[0] 40 | m = data[1] 41 | starts = data[2:2 * n + 2:2] 42 | ends = data[3:2 * n + 2:2] 43 | points = data[2 * n + 2:] 44 | # use fast_count_segments 45 | cnt = fast_count_segments(starts, ends, points) 46 | for x in cnt: 47 | print(x, end=' ') 48 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/sorting/Sorting.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | 4 | public class Sorting { 5 | private static Random random = new Random(); 6 | 7 | private static int[] partition3(int[] a, int l, int r) { 8 | int m1 = l; 9 | int m2 = r; 10 | int i = l; 11 | int x = a[l]; 12 | int[] m = { m1, m2 }; 13 | 14 | while (i <= m2) { 15 | if (a[i] < x) { 16 | int temp = a[m1]; 17 | a[m1] = a[i]; 18 | a[i] = temp; 19 | m1++; 20 | i++; 21 | } else if (a[i] == x) { 22 | i++; 23 | } else { 24 | int temp = a[m2]; 25 | a[m2] = a[i]; 26 | a[i] = temp; 27 | m2--; 28 | } 29 | m[0] = m1; 30 | m[1] = m2; 31 | } 32 | 33 | return m; 34 | } 35 | 36 | private static int partition2(int[] a, int l, int r) { 37 | int x = a[l]; 38 | int j = l; 39 | for (int i = l + 1; i <= r; i++) { 40 | if (a[i] <= x) { 41 | j++; 42 | int t = a[i]; 43 | a[i] = a[j]; 44 | a[j] = t; 45 | } 46 | } 47 | int t = a[l]; 48 | a[l] = a[j]; 49 | a[j] = t; 50 | return j; 51 | } 52 | 53 | private static void randomizedQuickSort(int[] a, int l, int r) { 54 | if (l >= r) { 55 | return; 56 | } 57 | int k = random.nextInt(r - l + 1) + l; 58 | int t = a[l]; 59 | a[l] = a[k]; 60 | a[k] = t; 61 | int[] m = partition3(a, l, r); 62 | randomizedQuickSort(a, l, m[0] - 1); 63 | randomizedQuickSort(a, m[1] + 1, r); 64 | } 65 | 66 | public static void main(String[] args) { 67 | FastScanner scanner = new FastScanner(System.in); 68 | int n = scanner.nextInt(); 69 | int[] a = new int[n]; 70 | for (int i = 0; i < n; i++) { 71 | a[i] = scanner.nextInt(); 72 | } 73 | randomizedQuickSort(a, 0, n - 1); 74 | for (int i = 0; i < n; i++) { 75 | System.out.print(a[i] + " "); 76 | } 77 | } 78 | 79 | static class FastScanner { 80 | BufferedReader br; 81 | StringTokenizer st; 82 | 83 | FastScanner(InputStream stream) { 84 | try { 85 | br = new BufferedReader(new InputStreamReader(stream)); 86 | } catch (Exception e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | 91 | String next() { 92 | while (st == null || !st.hasMoreTokens()) { 93 | try { 94 | st = new StringTokenizer(br.readLine()); 95 | } catch (IOException e) { 96 | e.printStackTrace(); 97 | } 98 | } 99 | return st.nextToken(); 100 | } 101 | 102 | int nextInt() { 103 | return Integer.parseInt(next()); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/sorting/sorting.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::swap; 7 | 8 | vector quick_sort_partition3(vector &a, int l, int r) { 9 | int x = a[l]; 10 | int p_l = l; 11 | int i = l; 12 | int p_e = r; 13 | vector m(2); 14 | while (i <= p_e) { 15 | if (a[i] < x) { 16 | swap(a[p_l], a[i]); 17 | p_l++; 18 | i++; 19 | } else if (a[i] == x) { 20 | i++; 21 | } else { 22 | swap(a[i], a[p_e]); 23 | p_e -= 1; 24 | } 25 | m[0] = p_l; 26 | m[1] = p_e; 27 | } 28 | return m; 29 | } 30 | 31 | int partition2(vector &a, int l, int r) { 32 | int x = a[l]; 33 | int j = l; 34 | for (int i = l + 1; i <= r; i++) { 35 | if (a[i] <= x) { 36 | j++; 37 | swap(a[i], a[j]); 38 | } 39 | } 40 | swap(a[l], a[j]); 41 | return j; 42 | } 43 | 44 | void randomized_quick_sort(vector &a, int l, int r) { 45 | if (l >= r) { 46 | return; 47 | } 48 | 49 | int k = l + rand() % (r - l + 1); 50 | swap(a[l], a[k]); 51 | vector m = quick_sort_partition3(a, l, r); 52 | 53 | randomized_quick_sort(a, l, m[0] - 1); 54 | randomized_quick_sort(a, m[1] + 1, r); 55 | } 56 | 57 | int main() { 58 | int n; 59 | std::cin >> n; 60 | vector a(n); 61 | for (size_t i = 0; i < a.size(); ++i) { 62 | std::cin >> a[i]; 63 | } 64 | randomized_quick_sort(a, 0, a.size() - 1); 65 | for (size_t i = 0; i < a.size(); ++i) { 66 | std::cout << a[i] << ' '; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_4/03_divide_and_conquer_starter_files_20160804/sorting/sorting.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | import random 4 | 5 | 6 | def partition3(a, left, right): 7 | pivot_value = a[left] 8 | p_l = i = left 9 | p_e = right 10 | while i <= p_e: 11 | if a[i] < pivot_value: 12 | a[i], a[p_l] = a[p_l], a[i] 13 | p_l += 1 14 | i += 1 15 | elif a[i] == pivot_value: 16 | i += 1 17 | else: 18 | a[i], a[p_e] = a[p_e], a[i] 19 | p_e -= 1 20 | pIndexes = [p_l, p_e] 21 | return pIndexes 22 | 23 | 24 | def partition2(a, left, right): 25 | pivot = random.randint(left, right) 26 | a[right], a[pivot] = a[pivot], a[right] 27 | pivot_value = a[right] 28 | pIndex = left 29 | for i in range(left, right): 30 | if a[i] <= pivot_value: 31 | a[i], a[pIndex] = a[pIndex], a[i] 32 | pIndex += 1 33 | a[right], a[pIndex] = a[pIndex], a[right] 34 | return pIndex 35 | 36 | 37 | def randomized_quick_sort(a, left, right): 38 | if left >= right: 39 | return 40 | 41 | pivot = random.randint(left, right) 42 | a[left], a[pivot] = a[pivot], a[left] 43 | pIndex = partition3(a, left, right) 44 | randomized_quick_sort(a, left, pIndex[0] - 1) 45 | randomized_quick_sort(a, pIndex[1] + 1, right) 46 | 47 | 48 | if __name__ == '__main__': 49 | input = sys.stdin.read() 50 | n, *a = list(map(int, input.split())) 51 | randomized_quick_sort(a, 0, n - 1) 52 | for x in a: 53 | print(x, end=' ') 54 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_problems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mablatnik/Algorithmic-Toolbox/5d79938e2f2d97f2100f4555e2ac2f2b79f8f36f/algorithmic_toolbox/week_5/04_dynamic_programming_problems.pdf -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/edit_distance/EditDistance.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class EditDistance { 4 | public static int EditDistance(String s, String t) { 5 | //write your code here 6 | return 0; 7 | } 8 | public static void main(String args[]) { 9 | Scanner scan = new Scanner(System.in); 10 | 11 | String s = scan.next(); 12 | String t = scan.next(); 13 | 14 | System.out.println(EditDistance(s, t)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/edit_distance/edit_distance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::string; 5 | 6 | int edit_distance(const string &str1, const string &str2) { 7 | //write your code here 8 | return 0; 9 | } 10 | 11 | int main() { 12 | string str1; 13 | string str2; 14 | std::cin >> str1 >> str2; 15 | std::cout << edit_distance(str1, str2) << std::endl; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/edit_distance/edit_distance.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | def edit_distance(s, t): 3 | #write your code here 4 | return 0 5 | 6 | if __name__ == "__main__": 7 | print(edit_distance(input(), input())) 8 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/knapsack/Knapsack.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Knapsack { 4 | static int optimalWeight(int W, int[] w) { 5 | int num_items = 0; 6 | for (int item : w) { 7 | if (item <= W) 8 | num_items++; 9 | } 10 | int[] items = new int[num_items]; 11 | int index = 0; 12 | for (int i = 0; i < w.length - 1; i++) { 13 | if (w[i] <= W) { 14 | items[index] = w[i]; 15 | index++; 16 | } 17 | } 18 | 19 | int capacity = W + 1; 20 | 21 | int K[][] = new int[items.length + 1][capacity]; 22 | 23 | for (int col = 0; col <= W; col++) { 24 | K[0][col] = 0; 25 | } 26 | 27 | for (int row = 0; row <= items.length; row++) { 28 | K[row][0] = 0; 29 | } 30 | 31 | for (int item = 1; item <= items.length; item++) { 32 | for (int weight = 1; weight <= W; weight++) { 33 | if (items[item - 1] <= weight) { 34 | K[item][weight] = Math.max(items[item - 1] + K[item - 1][weight - items[item - 1]], 35 | K[item - 1][weight]); 36 | } else { 37 | K[item][weight] = K[item - 1][weight]; 38 | } 39 | } 40 | } 41 | return K[items.length + 1][capacity]; 42 | } 43 | 44 | public static void main(String[] args) { 45 | Scanner scanner = new Scanner(System.in); 46 | int W, n; 47 | W = scanner.nextInt(); 48 | n = scanner.nextInt(); 49 | int[] w = new int[n]; 50 | for (int i = 0; i < n; i++) { 51 | w[i] = scanner.nextInt(); 52 | } 53 | System.out.println(optimalWeight(W, w)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/knapsack/knapsack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | int optimal_weight(int W, const vector &w) { 7 | //write your code here 8 | int current_weight = 0; 9 | for (size_t i = 0; i < w.size(); ++i) { 10 | if (current_weight + w[i] <= W) { 11 | current_weight += w[i]; 12 | } 13 | } 14 | return current_weight; 15 | } 16 | 17 | int main() { 18 | int n, W; 19 | std::cin >> W >> n; 20 | vector w(n); 21 | for (int i = 0; i < n; i++) { 22 | std::cin >> w[i]; 23 | } 24 | std::cout << optimal_weight(W, w) << '\n'; 25 | } 26 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/knapsack/knapsack.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | 4 | 5 | def optimal_weight(W, w): 6 | items = [0] 7 | for item in w: 8 | if item <= W: 9 | items.append(item) 10 | 11 | item_length = len(items) 12 | capacity = W + 1 13 | 14 | weights = [[0 for _ in range(item_length)] for _ in range(capacity)] 15 | 16 | for j in range(1, item_length): 17 | for i in range(1, capacity): 18 | previous = weights[i][j - 1] 19 | current = items[j] + weights[i - items[j]][j - 1] 20 | if current > i: 21 | weights[i][j] = previous 22 | else: 23 | weights[i][j] = max(previous, current) 24 | 25 | return weights[-1][-1] 26 | 27 | 28 | if __name__ == '__main__': 29 | input = sys.stdin.read() 30 | W, n, *w = list(map(int, input.split())) 31 | print(optimal_weight(W, w)) 32 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/lcs3/LCS3.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class LCS3 { 4 | 5 | private static int lcs3(int[] a, int[] b, int[] c) { 6 | //Write your code here 7 | return Math.min(Math.min(a.length, b.length), c.length); 8 | } 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | int an = scanner.nextInt(); 13 | int[] a = new int[an]; 14 | for (int i = 0; i < an; i++) { 15 | a[i] = scanner.nextInt(); 16 | } 17 | int bn = scanner.nextInt(); 18 | int[] b = new int[bn]; 19 | for (int i = 0; i < bn; i++) { 20 | b[i] = scanner.nextInt(); 21 | } 22 | int cn = scanner.nextInt(); 23 | int[] c = new int[cn]; 24 | for (int i = 0; i < cn; i++) { 25 | c[i] = scanner.nextInt(); 26 | } 27 | System.out.println(lcs3(a, b, c)); 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/lcs3/lcs3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | int lcs3(vector &a, vector &b, vector &c) { 7 | //write your code here 8 | return std::min(std::min(a.size(), b.size()), c.size()); 9 | } 10 | 11 | int main() { 12 | size_t an; 13 | std::cin >> an; 14 | vector a(an); 15 | for (size_t i = 0; i < an; i++) { 16 | std::cin >> a[i]; 17 | } 18 | size_t bn; 19 | std::cin >> bn; 20 | vector b(bn); 21 | for (size_t i = 0; i < bn; i++) { 22 | std::cin >> b[i]; 23 | } 24 | size_t cn; 25 | std::cin >> cn; 26 | vector c(cn); 27 | for (size_t i = 0; i < cn; i++) { 28 | std::cin >> c[i]; 29 | } 30 | std::cout << lcs3(a, b, c) << std::endl; 31 | } 32 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/lcs3/lcs3.py: -------------------------------------------------------------------------------- 1 | #Uses python3 2 | 3 | import sys 4 | 5 | def lcs3(a, b, c): 6 | #write your code here 7 | return min(len(a), len(b), len(c)) 8 | 9 | if __name__ == '__main__': 10 | input = sys.stdin.read() 11 | data = list(map(int, input.split())) 12 | an = data[0] 13 | data = data[1:] 14 | a = data[:an] 15 | data = data[an:] 16 | bn = data[0] 17 | data = data[1:] 18 | b = data[:bn] 19 | data = data[bn:] 20 | cn = data[0] 21 | data = data[1:] 22 | c = data[:cn] 23 | print(lcs3(a, b, c)) 24 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/placing_parentheses/PlacingParentheses.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class PlacingParentheses { 4 | private static long getMaximValue(String exp) { 5 | //write your code here 6 | return 0; 7 | } 8 | 9 | private static long eval(long a, long b, char op) { 10 | if (op == '+') { 11 | return a + b; 12 | } else if (op == '-') { 13 | return a - b; 14 | } else if (op == '*') { 15 | return a * b; 16 | } else { 17 | assert false; 18 | return 0; 19 | } 20 | } 21 | 22 | public static void main(String[] args) { 23 | Scanner scanner = new Scanner(System.in); 24 | String exp = scanner.next(); 25 | System.out.println(getMaximValue(exp)); 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/placing_parentheses/placing_parentheses.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::vector; 7 | using std::string; 8 | using std::max; 9 | using std::min; 10 | 11 | long long eval(long long a, long long b, char op) { 12 | if (op == '*') { 13 | return a * b; 14 | } else if (op == '+') { 15 | return a + b; 16 | } else if (op == '-') { 17 | return a - b; 18 | } else { 19 | assert(0); 20 | } 21 | } 22 | 23 | long long get_maximum_value(const string &exp) { 24 | //write your code here 25 | return 0; 26 | } 27 | 28 | int main() { 29 | string s; 30 | std::cin >> s; 31 | std::cout << get_maximum_value(s) << '\n'; 32 | } 33 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/placing_parentheses/placing_parentheses.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | def evalt(a, b, op): 3 | if op == '+': 4 | return a + b 5 | elif op == '-': 6 | return a - b 7 | elif op == '*': 8 | return a * b 9 | else: 10 | assert False 11 | 12 | def get_maximum_value(dataset): 13 | #write your code here 14 | return 0 15 | 16 | 17 | if __name__ == "__main__": 18 | print(get_maximum_value(input())) 19 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/primitive_calculator/PrimitiveCalculator.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class PrimitiveCalculator { 4 | private static List optimal_sequence(int n) { 5 | List sequence = new ArrayList(); 6 | while (n >= 1) { 7 | sequence.add(n); 8 | if (n % 3 == 0) { 9 | n /= 3; 10 | } else if (n % 2 == 0) { 11 | n /= 2; 12 | } else { 13 | n -= 1; 14 | } 15 | } 16 | Collections.reverse(sequence); 17 | return sequence; 18 | } 19 | 20 | private static List dynamic_sequence(int n) { 21 | int[] a = new int[n + 1]; 22 | int[] predecessor = new int[n + 1]; 23 | 24 | for (int i = 2; i <= n; i++) { 25 | a[i] = a[i - 1] + 1; 26 | predecessor[i] = i - 1; 27 | if (i % 3 == 0) { 28 | if (a[i / 3] < a[i]) { 29 | a[i] = a[i / 3] + 1; 30 | predecessor[i] = i / 3; 31 | } 32 | } 33 | if (i % 2 == 0) { 34 | if (a[i / 2] < a[i]) { 35 | a[i] = a[i / 2] + 1; 36 | predecessor[i] = i / 2; 37 | } 38 | } 39 | } 40 | 41 | ArrayList sequence = new ArrayList(); 42 | 43 | for (int i = n; i != 0; i = predecessor[i]) { 44 | sequence.add(i); 45 | } 46 | 47 | Collections.reverse(sequence); 48 | return sequence; 49 | } 50 | 51 | public static void main(String[] args) { 52 | Scanner scanner = new Scanner(System.in); 53 | int n = scanner.nextInt(); 54 | List sequence = dynamic_sequence(n); 55 | System.out.println(sequence.size() - 1); 56 | for (Integer x : sequence) { 57 | System.out.print(x + " "); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/primitive_calculator/primitive_calculator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::vector; 7 | using std::min; 8 | 9 | vector optimal_sequence(int n) { 10 | std::vector sequence; 11 | while (n >= 1) { 12 | sequence.push_back(n); 13 | if (n % 3 == 0) { 14 | n /= 3; 15 | } else if (n % 2 == 0) { 16 | n /= 2; 17 | } else { 18 | n = n - 1; 19 | } 20 | } 21 | reverse(sequence.begin(), sequence.end()); 22 | return sequence; 23 | } 24 | 25 | vector dynamic_sequence(int n) { 26 | vector a(n+1); 27 | vector count_index; 28 | vector sequence; 29 | vector option_list; 30 | 31 | a[1] = 1; 32 | for(int i=2; i> n; 70 | vector sequence = dynamic_sequence(n); 71 | std::cout << sequence.size() - 1 << std::endl; 72 | for (size_t i = 0; i < sequence.size(); ++i) { 73 | std::cout << sequence[i] << " "; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/primitive_calculator/primitive_calculator.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | 4 | 5 | def optimal_sequence(n): 6 | sequence = [] 7 | while n >= 1: 8 | sequence.append(n) 9 | if n % 3 == 0: 10 | n //= 3 11 | elif n % 2 == 0: 12 | n //= 2 13 | else: 14 | n = n - 1 15 | return reversed(sequence) 16 | 17 | 18 | def dynamic_sequence(n): 19 | operations_count = [0] * (n + 1) 20 | 21 | operations_count[1] = 1 22 | for i in range(2, n + 1): 23 | count_index = [i - 1] 24 | if i % 2 == 0: 25 | count_index.append(i // 2) 26 | if i % 3 == 0: 27 | count_index.append(i // 3) 28 | 29 | min_count = min([operations_count[x] for x in count_index]) 30 | operations_count[i] = min_count + 1 31 | 32 | current_value = n 33 | value_trail = [current_value] 34 | while current_value != 1: 35 | option_list = [current_value - 1] 36 | if current_value % 2 == 0: 37 | option_list.append(current_value // 2) 38 | if current_value % 3 == 0: 39 | option_list.append(current_value // 3) 40 | 41 | current_value = min( 42 | [(c, operations_count[c]) for c in option_list], 43 | key=lambda x: x[1] 44 | )[0] 45 | value_trail.append(current_value) 46 | return reversed(value_trail) 47 | 48 | 49 | input = sys.stdin.read() 50 | n = int(input) 51 | sequence = list(dynamic_sequence(n)) 52 | print(len(sequence) - 1) 53 | for x in sequence: 54 | print(x, end=' ') 55 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/primitive_calculator/primitive_calculator2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::min; 7 | 8 | vector optimal_sequence(int n) { 9 | std::vector sequence; 10 | while (n >= 1) { 11 | sequence.push_back(n); 12 | if (n % 3 == 0) { 13 | n /= 3; 14 | } else if (n % 2 == 0) { 15 | n /= 2; 16 | } else { 17 | n = n - 1; 18 | } 19 | } 20 | reverse(sequence.begin(), sequence.end()); 21 | return sequence; 22 | } 23 | 24 | vector dynamic_sequence(int n) { 25 | vector sequence; 26 | vector a(n+1); 27 | 28 | a[0] = 0; 29 | for(int i=1; i 1) { 38 | sequence.push_back(i); 39 | if (a[i-1] == a[i] -1) 40 | i = i-1; 41 | else if (i%2 && (a[i/2] == a[i] -1)) 42 | i = i/2; 43 | else if (i%3 && (a[i/3] == a[i] -1)) 44 | i = i/3; 45 | } 46 | sequence.push_back(1); 47 | reverse(sequence.begin(), sequence.end()); 48 | return sequence; 49 | } 50 | 51 | int main() { 52 | int n; 53 | std::cin >> n; 54 | vector sequence = dynamic_sequence(n); 55 | std::cout << sequence.size() - 1 << std::endl; 56 | for (size_t i = 0; i < sequence.size(); ++i) { 57 | std::cout << sequence[i] << " "; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /algorithmic_toolbox/week_5/04_dynamic_programming_starter_files/primitive_calculator/primitive_calculator3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::min; 7 | 8 | vector optimal_sequence(int n) { 9 | std::vector sequence; 10 | while (n >= 1) { 11 | sequence.push_back(n); 12 | if (n % 3 == 0) { 13 | n /= 3; 14 | } else if (n % 2 == 0) { 15 | n /= 2; 16 | } else { 17 | n = n - 1; 18 | } 19 | } 20 | reverse(sequence.begin(), sequence.end()); 21 | return sequence; 22 | } 23 | 24 | vector dynamic_sequence(int n) { 25 | vector a(n+1); 26 | vector predecessor(n+1); 27 | 28 | for (int i = 2; i <= n; i++) { 29 | a[i] = a[i-1] + 1; 30 | predecessor[i] = i - 1; 31 | if (i % 3 == 0) { 32 | if (a[i/3] < a[i]) { 33 | a[i] = a[i/3] + 1; 34 | predecessor[i] = i/3; 35 | } 36 | } 37 | if (i % 2 == 0) { 38 | if (a[i/2] < a[i]) { 39 | a[i] = a[i/2] + 1; 40 | predecessor[i] = i/2; 41 | } 42 | } 43 | } 44 | 45 | vector sequence; 46 | 47 | for (int i = n; i !=0; i = predecessor[i]) { 48 | sequence.push_back(i); 49 | } 50 | reverse(sequence.begin(), sequence.end()); 51 | return sequence; 52 | } 53 | 54 | int main() { 55 | int n; 56 | std::cin >> n; 57 | vector sequence = dynamic_sequence(n); 58 | std::cout << sequence.size() - 1 << std::endl; 59 | for (size_t i = 0; i < sequence.size(); ++i) { 60 | std::cout << sequence[i] << " "; 61 | } 62 | } 63 | --------------------------------------------------------------------------------