├── .gitignore ├── Learning Algorithms Through Programming and Puzzle Solving.pdf ├── README.md ├── extra_slides_week5.pdf ├── toolbox_statements.pdf ├── week1_programming_challenges ├── .DS_Store ├── 1_sum_of_two_digits │ ├── APlusB.cpp │ ├── APlusB.cs │ ├── APlusB.hs │ ├── APlusB.java │ ├── APlusB.js │ ├── APlusB.kt │ ├── APlusB.py │ ├── APlusB.rb │ ├── APlusB.rs │ └── APlusB.scala └── 2_maximum_pairwise_product │ ├── MaxPairwiseProduct.java │ ├── MaxPairwiseProduct.kt │ ├── max_pairwise_product.cpp │ ├── max_pairwise_product.js │ ├── max_pairwise_product.py │ └── max_pairwise_product.rb ├── week2_algorithmic_warmup ├── .DS_Store ├── 1_fibonacci_number │ ├── Fibonacci.java │ ├── Fibonacci.kt │ ├── fibonacci.cpp │ ├── fibonacci.hs │ ├── fibonacci.js │ ├── fibonacci.py │ └── fibonacci.rb ├── 2_last_digit_of_fibonacci_number │ ├── FibonacciLastDigit.java │ ├── FibonacciLastDigit.kt │ ├── fibonacci_last_digit.cpp │ ├── fibonacci_last_digit.hs │ ├── fibonacci_last_digit.js │ ├── fibonacci_last_digit.py │ └── fibonacci_last_digit.rb ├── 3_greatest_common_divisor │ ├── GCD.java │ ├── GCD.kt │ ├── euclidean_algorithm_psedocode.png │ ├── gcd.cpp │ ├── gcd.hs │ ├── gcd.js │ ├── gcd.py │ └── gcd.rb ├── 4_least_common_multiple │ ├── LCM.java │ ├── LCM.kt │ ├── by_learners │ │ └── lcm.rb │ ├── lcm.cpp │ ├── lcm.hs │ └── lcm.py ├── 5_fibonacci_number_again │ ├── FibonacciHuge.java │ ├── FibonacciHuge.kt │ ├── fibonacci_huge.cpp │ ├── fibonacci_huge.hs │ ├── fibonacci_huge.js │ ├── fibonacci_huge.py │ └── fibonacci_huge.rb ├── 6_last_digit_of_the_sum_of_fibonacci_numbers │ ├── FibonacciSumLastDigit.java │ ├── FibonacciSumLastDigit.kt │ ├── by_learners │ │ └── fibonacci_sum_last_digit.rb │ ├── fibonacci_sum_last_digit.cpp │ ├── fibonacci_sum_last_digit.hs │ └── fibonacci_sum_last_digit.py ├── 7_last_digit_of_the_sum_of_fibonacci_numbers_again │ ├── FibonacciPartialSum.java │ ├── FibonacciPartialSum.kt │ ├── by_learners │ │ └── fib_partial_sum.rb │ ├── fibonacci_partial_sum.cpp │ ├── fibonacci_partial_sum.hs │ └── fibonacci_partial_sum.py └── 8_last_digit_of_the_sum_of_squares_of_fibonacci_numbers │ ├── FibonacciSumSquares.java │ ├── fibonacci_sum_squares.cpp │ └── fibonacci_sum_squares.py ├── week3_greedy_algorithms ├── 1_money_change │ ├── Change.java │ ├── Change.kt │ ├── by_learners │ │ └── change.rb │ ├── change.cpp │ ├── change.hs │ └── change.py ├── 2_maximum_value_of_the_loot │ ├── FractionalKnapsack.java │ ├── FractionalKnapsack.kt │ ├── fractional_knapsack.cpp │ ├── fractional_knapsack.hs │ ├── fractional_knapsack.js │ ├── fractional_knapsack.py │ ├── fractional_knapsack.rb │ └── pseudocode.png ├── 3_car_fueling │ ├── CarFueling.java │ ├── car_fueling.cpp │ ├── car_fueling.py │ └── pseudocode.png ├── 4_maximum_advertisement_revenue │ ├── DotProduct.java │ ├── DotProduct.kt │ ├── by_learners │ │ └── dot_rpoduct.rb │ ├── dot_product.cpp │ ├── dot_product.hs │ └── dot_product.py ├── 5_collecting_signatures │ ├── CoveringSegments.java │ ├── CoveringSegments.kt │ ├── by_learners │ │ └── covering_segments.rb │ ├── covering_segments.cpp │ ├── covering_segments.hs │ └── covering_segments.py ├── 6_maximum_number_of_prizes │ ├── DifferentSummands.java │ ├── DifferentSummands.kt │ ├── by_learners │ │ └── different_summands.rb │ ├── different_summands.cpp │ ├── different_summands.hs │ └── different_summands.py └── 7_maximum_salary │ ├── LargestNumber.java │ ├── LargestNumber.kt │ ├── by_learners │ └── largest_number.rb │ ├── largest_number.cpp │ ├── largest_number.hs │ └── largest_number.py ├── week4_divide_and_conquer ├── 1_binary_search │ ├── BinarySearch.java │ ├── BinarySearch.kt │ ├── binary_search.cpp │ ├── binary_search.js │ ├── binary_search.py │ ├── binary_search.rb │ └── pseudocode.png ├── 2_binary_search_duplicates │ ├── BinarySearch.java │ ├── BinarySearch.kt │ ├── binary_search.cpp │ ├── binary_search.js │ ├── binary_search.py │ └── binary_search.rb ├── 3_majority_element │ ├── MajorityElement.java │ ├── MajorityElement.kt │ ├── by_learners │ │ └── majority_element.rb │ ├── majority_element.cpp │ └── majority_element.py ├── 4_improving_quicksort │ ├── Sorting.java │ ├── Sorting.kt │ ├── by_learners │ │ └── sorting.rb │ ├── sorting.cpp │ └── sorting.py ├── 5_number_of_inversions │ ├── Inversions.java │ ├── Inversions.kt │ ├── by_learners │ │ └── inversions.rb │ ├── inversions.cpp │ └── inversions.py ├── 6_organizing_a_lottery │ ├── PointsAndSegments.java │ ├── PointsAndSegments.kt │ ├── by_learners │ │ └── points_and_segments.rb │ ├── points_and_segments.cpp │ └── points_and_segments.py └── 7_closest_points │ ├── Closest.java │ ├── Closest.kt │ ├── by_learners │ └── closest.rb │ ├── closest.cpp │ └── closest.py ├── week5_dynamic_programming1 ├── 1_money_change_again │ ├── ChangeDP.java │ ├── ChangeDP.kt │ ├── change_dp.cpp │ ├── change_dp.py │ └── pseudocode.png ├── 2_primitive_calculator │ ├── PrimitiveCalculator.java │ ├── PrimitiveCalculator.kt │ ├── by_learners │ │ └── primitive_calculator.rb │ ├── primitive_calculator.cpp │ └── primitive_calculator.py ├── 3_edit_distance │ ├── EditDistance.java │ ├── EditDistance.kt │ ├── by_learners │ │ └── edit_distance.rb │ ├── edit_distance.cpp │ ├── edit_distance.py │ ├── pseudocode.png │ └── test.ipynb ├── 4_longest_common_subsequence_of_two_sequences │ ├── LCS2.java │ ├── LCS2.kt │ ├── lcs2.cpp │ └── lcs2.py └── 5_longest_common_subsequence_of_three_sequences │ ├── LCS3.java │ ├── LCS3.kt │ ├── by_learners │ └── lcs3.rb │ ├── lcs3.cpp │ └── lcs3.py └── week6_dynamic_programming2 ├── 1_maximum_amount_of_gold ├── Knapsack.java ├── Knapsack.kt ├── by_learners │ └── knapsack.rb ├── knapsack.cpp ├── knapsack.py └── pseudocode.png ├── 2_partitioning_souvenirs ├── Partition3.java ├── Partition3.kt ├── partition3.cpp └── partition3.py └── 3_maximum_value_of_an_arithmetic_expression ├── PlacingParentheses.java ├── PlacingParentheses.kt ├── by_learners └── placing_parentheses.rb ├── placing_parentheses.cpp ├── placing_parentheses.py ├── pseudocode_minmax.png └── pseudocode_parentheses.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store 32 | .DS_Store? 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | ehthumbs.db 37 | Thumbs.db -------------------------------------------------------------------------------- /Learning Algorithms Through Programming and Puzzle Solving.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/Learning Algorithms Through Programming and Puzzle Solving.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # algorithmic-toolbox-solutions 2 | This repo includes all of the solutions to the Algorithmic Toolbox course from Coursera. All code has been written in Python3. 3 | -------------------------------------------------------------------------------- /extra_slides_week5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/extra_slides_week5.pdf -------------------------------------------------------------------------------- /toolbox_statements.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/toolbox_statements.pdf -------------------------------------------------------------------------------- /week1_programming_challenges/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week1_programming_challenges/.DS_Store -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int sum_of_two_digits(int first_digit, int second_digit) { 4 | return first_digit + second_digit; 5 | } 6 | 7 | int main() { 8 | int a = 0; 9 | int b = 0; 10 | std::cin >> a; 11 | std::cin >> b; 12 | std::cout << sum_of_two_digits(a, b); 13 | return 0; 14 | } -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace APlusB 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | var input = Console.ReadLine(); 10 | var tokens = input.Split(' '); 11 | var a = int.Parse(tokens[0]); 12 | var b = int.Parse(tokens[1]); 13 | Console.WriteLine(a + b); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.hs: -------------------------------------------------------------------------------- 1 | 2 | main = do 3 | s <- getLine 4 | let w = words s 5 | readInt :: String -> Int 6 | readInt = read 7 | x = map readInt w 8 | t = sum x 9 | putStrLn $ show t 10 | -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | class APlusB { 4 | static int sumOfTwoDigits(int first_digit, int second_digit) { 5 | return first_digit + second_digit; 6 | } 7 | 8 | public static void main(String[] args) { 9 | Scanner s = new Scanner(System.in); 10 | int a = s.nextInt(); 11 | int b = s.nextInt(); 12 | System.out.println(sumOfTwoDigits(a, b)); 13 | } 14 | } -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.js: -------------------------------------------------------------------------------- 1 | var readline = require('readline'); 2 | 3 | process.stdin.setEncoding('utf8'); 4 | var rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | rl.on('line', readLine); 10 | 11 | function readLine (line) { 12 | if (line !== "\n") { 13 | var a = parseInt(line.toString().split(' ')[0], 10); 14 | var b = parseInt(line.toString().split(' ')[1], 10); 15 | console.log(a + b); 16 | process.exit(); 17 | } 18 | } -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun main(args: Array) { 4 | val s = Scanner(System.`in`) 5 | val a = s.nextInt() 6 | val b = s.nextInt() 7 | println(a + b) 8 | } -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.py: -------------------------------------------------------------------------------- 1 | def sum_of_two_digits(first_digit, second_digit): 2 | """ 3 | Input: 2 integer numbers 4 | Output: sum of these 2 numbers 5 | """ 6 | return first_digit + second_digit 7 | 8 | 9 | if __name__ == '__main__': 10 | a, b = map(int, input().split()) 11 | print(sum_of_two_digits(a, b)) 12 | -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.rb: -------------------------------------------------------------------------------- 1 | a, b = gets.split(' ') 2 | puts a.to_i + b.to_i -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut buff = String::new(); 3 | ::std::io::stdin().read_line(&mut buff); 4 | let mut words = buff.split_whitespace(); 5 | 6 | let a: i64 = words.next().unwrap().parse().unwrap(); 7 | let b: i64 = words.next().unwrap().parse().unwrap(); 8 | 9 | println!("{}", a + b); 10 | } 11 | -------------------------------------------------------------------------------- /week1_programming_challenges/1_sum_of_two_digits/APlusB.scala: -------------------------------------------------------------------------------- 1 | // by Guillaume Guy 2 | 3 | object APlusB extends App { 4 | override def main(args: Array[String]): Unit = { 5 | val scanner = new java.util.Scanner(System.in) 6 | val line = scanner.nextLine() 7 | val result = (line.split(" ").map( x => BigInt(x)) take 2).sum 8 | System.out.print(result ) 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /week1_programming_challenges/2_maximum_pairwise_product/MaxPairwiseProduct.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | 4 | public class MaxPairwiseProduct { 5 | static int getMaxPairwiseProduct(int[] numbers) { 6 | int max_product = 0; 7 | int n = numbers.length; 8 | 9 | for (int first = 0; first < n; ++first) { 10 | for (int second = first + 1; second < n; ++second) { 11 | max_product = Math.max(max_product, 12 | numbers[first] * numbers[second]); 13 | } 14 | } 15 | 16 | return max_product; 17 | } 18 | 19 | public static void main(String[] args) { 20 | FastScanner scanner = new FastScanner(System.in); 21 | int n = scanner.nextInt(); 22 | int[] numbers = new int[n]; 23 | for (int i = 0; i < n; i++) { 24 | numbers[i] = scanner.nextInt(); 25 | } 26 | System.out.println(getMaxPairwiseProduct(numbers)); 27 | } 28 | 29 | static class FastScanner { 30 | BufferedReader br; 31 | StringTokenizer st; 32 | 33 | FastScanner(InputStream stream) { 34 | try { 35 | br = new BufferedReader(new 36 | InputStreamReader(stream)); 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | String next() { 43 | while (st == null || !st.hasMoreTokens()) { 44 | try { 45 | st = new StringTokenizer(br.readLine()); 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | return st.nextToken(); 51 | } 52 | 53 | int nextInt() { 54 | return Integer.parseInt(next()); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /week1_programming_challenges/2_maximum_pairwise_product/MaxPairwiseProduct.kt: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader 2 | import java.io.IOException 3 | import java.io.InputStream 4 | import java.io.InputStreamReader 5 | import java.util.* 6 | 7 | fun getMaxPairwiseProduct(numbers: IntArray): Int { 8 | var result = 0 9 | val n = numbers.size 10 | for (i in 0 until n) { 11 | for (j in i + 1 until n) { 12 | if (numbers[i] * numbers[j] > result) { 13 | result = numbers[i] * numbers[j] 14 | } 15 | } 16 | } 17 | return result 18 | } 19 | 20 | fun main(args: Array) { 21 | val scanner = FastScanner(System.`in`) 22 | val n = scanner.nextInt() 23 | val numbers = IntArray(n) 24 | for (i in 0 until n) { 25 | numbers[i] = scanner.nextInt() 26 | } 27 | println(getMaxPairwiseProduct(numbers)) 28 | } 29 | 30 | class FastScanner(stream: InputStream) { 31 | var br: BufferedReader = BufferedReader(InputStreamReader(stream)) 32 | var st: StringTokenizer? = null 33 | 34 | fun next(): String { 35 | while (st == null || !st!!.hasMoreTokens()) { 36 | try { 37 | st = StringTokenizer(br.readLine()) 38 | } catch (e: IOException) { 39 | e.printStackTrace() 40 | } 41 | } 42 | return st!!.nextToken() 43 | } 44 | 45 | fun nextInt() = next().toInt() 46 | } -------------------------------------------------------------------------------- /week1_programming_challenges/2_maximum_pairwise_product/max_pairwise_product.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int MaxPairwiseProduct(const std::vector& numbers) { 6 | int max_product = 0; 7 | int n = numbers.size(); 8 | 9 | for (int first = 0; first < n; ++first) { 10 | for (int second = first + 1; second < n; ++second) { 11 | max_product = std::max(max_product, 12 | numbers[first] * numbers[second]); 13 | } 14 | } 15 | 16 | return max_product; 17 | } 18 | 19 | int main() { 20 | int n; 21 | std::cin >> n; 22 | std::vector numbers(n); 23 | for (int i = 0; i < n; ++i) { 24 | std::cin >> numbers[i]; 25 | } 26 | 27 | std::cout << MaxPairwiseProduct(numbers) << "\n"; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /week1_programming_challenges/2_maximum_pairwise_product/max_pairwise_product.js: -------------------------------------------------------------------------------- 1 | // by Alexander Nikolskiy 2 | 3 | const readline = require('readline'); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | process.stdin.setEncoding('utf8'); 10 | rl.once('line', () => { 11 | rl.on('line', readLine); 12 | }); 13 | 14 | function readLine (line) { 15 | const arr = line.toString().split(' ').map(Number); 16 | 17 | console.log(max(arr)); 18 | process.exit(); 19 | } 20 | 21 | function max(arr) { 22 | // write your code here 23 | } 24 | 25 | module.exports = max; 26 | -------------------------------------------------------------------------------- /week1_programming_challenges/2_maximum_pairwise_product/max_pairwise_product.py: -------------------------------------------------------------------------------- 1 | def max_pairwise_product(numbers): 2 | """ 3 | Input: A list of non-negative integers 4 | Output: The product of two maximum values in the list (integer) 5 | # Naive method O(n^2) 6 | # for first in range(n): 7 | # for second in range(first + 1, n): 8 | # max_product = max(max_product, 9 | # numbers[first] * numbers[second]) 10 | """ 11 | # Time: O(n) 12 | n = len(numbers) 13 | # Find the first max 14 | first = -1 15 | for i in range(n): 16 | if first == -1 or numbers[i] >= numbers[first]: 17 | first = i 18 | 19 | # Find the second max, excluded the first max 20 | second = -1 21 | for j in range(n): 22 | if (j != first) and (second == -1 or numbers[j] >= numbers[second]): 23 | second = j 24 | 25 | max_product = numbers[first] * numbers[second] 26 | 27 | return max_product 28 | 29 | 30 | if __name__ == '__main__': 31 | _ = int(input()) 32 | input_numbers = list(map(int, input().split())) 33 | print(max_pairwise_product(input_numbers)) 34 | -------------------------------------------------------------------------------- /week1_programming_challenges/2_maximum_pairwise_product/max_pairwise_product.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def max_pairwise_product(a) 5 | # naive implementation 6 | # replace it 7 | result = 0 8 | n = a.size 9 | (0..n-1).each do |i| 10 | (i+1..n-1).each do |j| 11 | if a[i]*a[j] > result 12 | result = a[i]*a[j] 13 | end 14 | end 15 | end 16 | result 17 | end 18 | 19 | if __FILE__ == $0 20 | data = STDIN.read.split().map(&:to_i) 21 | n = data[0] 22 | a = data[1..n] 23 | puts "#{max_pairwise_product(a)}" 24 | end -------------------------------------------------------------------------------- /week2_algorithmic_warmup/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week2_algorithmic_warmup/.DS_Store -------------------------------------------------------------------------------- /week2_algorithmic_warmup/1_fibonacci_number/Fibonacci.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class Fibonacci { 4 | private static long calc_fib(int n) { 5 | if (n <= 1) 6 | return n; 7 | 8 | return calc_fib(n - 1) + calc_fib(n - 2); 9 | } 10 | 11 | public static void main(String args[]) { 12 | Scanner in = new Scanner(System.in); 13 | int n = in.nextInt(); 14 | 15 | System.out.println(calc_fib(n)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/1_fibonacci_number/Fibonacci.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun calcFib(n: Long): Long { 4 | return if (n <= 1) n else calcFib(n - 1) + calcFib(n - 2) 5 | } 6 | 7 | fun main(args: Array) { 8 | val scanner = Scanner(System.`in`) 9 | val n = scanner.nextLong() 10 | 11 | println(calcFib(n)) 12 | } -------------------------------------------------------------------------------- /week2_algorithmic_warmup/1_fibonacci_number/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 | // write your code here 26 | 27 | return 0; 28 | } 29 | 30 | void test_solution() { 31 | assert(fibonacci_fast(3) == 2); 32 | assert(fibonacci_fast(10) == 55); 33 | for (int n = 0; n < 20; ++n) 34 | assert(fibonacci_fast(n) == fibonacci_naive(n)); 35 | } 36 | 37 | int main() { 38 | int n = 0; 39 | std::cin >> n; 40 | 41 | std::cout << fibonacci_naive(n) << '\n'; 42 | //test_solution(); 43 | //std::cout << fibonacci_fast(n) << '\n'; 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/1_fibonacci_number/fibonacci.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | import Control.Exception (assert) 4 | 5 | -- The following code calls a naive algorithm for computing a Fibonacci number. 6 | -- 7 | -- What to do: 8 | -- 1. Compile the following code and run it on an input "40" to check that it is slow. 9 | -- You may also want to submit it to the grader to ensure that it gets the "time limit exceeded" message. 10 | -- 2. Implement the fibonacci_fast procedure. 11 | -- 3. Remove the line that prints the result of the naive algorithm, comment the lines reading the input, 12 | -- uncomment the line with a call to test_solution, compile the program, and run it. 13 | -- This will ensure that your efficient algorithm returns the same as the naive one for small values of n. 14 | -- 4. If test_solution reveals a bug in your implementation, debug it, fix it, and repeat step 3. 15 | -- 5. Remove the call to test_solution, uncomment the line with a call to fibonacci_fast (and the lines reading the input), 16 | -- and submit it to the grader. 17 | 18 | fibonacci_naive :: Int -> Int 19 | fibonacci_naive 0 = 0 20 | fibonacci_naive 1 = 1 21 | fibonacci_naive n = fibonacci_naive (n - 1) + fibonacci_naive (n - 2) 22 | 23 | fibonacci_fast :: Int -> Int 24 | fibonacci_fast n = 0 -- write your code here 25 | 26 | test_solution :: IO () 27 | test_solution = and tests `seq` return () 28 | where 29 | tests = 30 | [ assert (fibonacci_fast 3 == 2) True 31 | , assert (fibonacci_fast 10 == 55) True 32 | ] ++ map (\i -> assert (fibonacci_fast i == fibonacci_naive i) True) [0..20] 33 | 34 | main :: IO () 35 | main = do 36 | [w] <- fmap words getLine 37 | let n = read w 38 | 39 | print $ fibonacci_naive n 40 | --test_solution 41 | --print $ fibonacci_fast n 42 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/1_fibonacci_number/fibonacci.js: -------------------------------------------------------------------------------- 1 | // by Alexander Nikolskiy 2 | 3 | const readline = require('readline'); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | process.stdin.setEncoding('utf8'); 10 | rl.on('line', readLine); 11 | 12 | function readLine(line) { 13 | console.log(fib(parseInt(line, 10))); 14 | process.exit(); 15 | } 16 | 17 | function fib(n) { 18 | // write your code here 19 | } 20 | 21 | module.exports = fib; 22 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/1_fibonacci_number/fibonacci.py: -------------------------------------------------------------------------------- 1 | def fibonacci_number(n): 2 | """ 3 | This is the iterative solution to the problem, O(n) time 4 | Input: An integer n 5 | Output: The n-th Fibonacci number 6 | 7 | Visualization: https://www.cs.usfca.edu/~galles/visualization/DPFib.html 8 | Recursive solution: O(2^n) time 9 | """ 10 | if n == 0: 11 | return 0 12 | 13 | fib_numbers = [0] * (n+1) 14 | fib_numbers[0] = 0 15 | fib_numbers[1] = 1 16 | 17 | for i in range(2, len(fib_numbers)): # Loop run in O(n) times 18 | fib_numbers[i] = fib_numbers[i-1] + fib_numbers[i-2] # O(1) 19 | 20 | return fib_numbers[-1] 21 | 22 | 23 | 24 | if __name__ == '__main__': 25 | input_n = int(input()) 26 | print(fibonacci_number(input_n)) 27 | 28 | # Time complexity: O(n) -------------------------------------------------------------------------------- /week2_algorithmic_warmup/1_fibonacci_number/fibonacci.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def calc_fib(n) 5 | return n if n <= 1 6 | # slow 7 | # fix me 8 | calc_fib(n - 1) + calc_fib(n - 2) 9 | end 10 | 11 | if __FILE__ == $0 12 | n = gets.to_i 13 | puts "#{calc_fib(n)}" 14 | end 15 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/2_last_digit_of_fibonacci_number/FibonacciLastDigit.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 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 void main(String[] args) { 21 | Scanner scanner = new Scanner(System.in); 22 | int n = scanner.nextInt(); 23 | int c = getFibonacciLastDigitNaive(n); 24 | System.out.println(c); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/2_last_digit_of_fibonacci_number/FibonacciLastDigit.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getFibonacciLastDigitNaive(n: Int): Int { 4 | if (n <= 1) 5 | return n 6 | 7 | var previous = 0 8 | var current = 1 9 | 10 | for (i in 0 until n - 1) { 11 | val tmpPrevious = previous 12 | previous = current 13 | current += tmpPrevious 14 | } 15 | 16 | return current % 10 17 | } 18 | 19 | fun main(args: Array) { 20 | val scanner = Scanner(System.`in`) 21 | val n = scanner.nextInt() 22 | val c = getFibonacciLastDigitNaive(n) 23 | println(c) 24 | } -------------------------------------------------------------------------------- /week2_algorithmic_warmup/2_last_digit_of_fibonacci_number/fibonacci_last_digit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int get_fibonacci_last_digit_naive(int n) { 4 | if (n <= 1) 5 | return n; 6 | 7 | int previous = 0; 8 | int current = 1; 9 | 10 | for (int i = 0; i < n - 1; ++i) { 11 | int tmp_previous = previous; 12 | previous = current; 13 | current = tmp_previous + current; 14 | } 15 | 16 | return current % 10; 17 | } 18 | 19 | int main() { 20 | int n; 21 | std::cin >> n; 22 | int c = get_fibonacci_last_digit_naive(n); 23 | std::cout << c << '\n'; 24 | } 25 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/2_last_digit_of_fibonacci_number/fibonacci_last_digit.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | fibonacci_last_digit :: Int -> Int 4 | fibonacci_last_digit = helper (0, 1) 5 | where 6 | helper (a, _) 0 = a `mod` 10 7 | helper (a, b) n = helper (b, a + b) (n - 1) 8 | 9 | main :: IO () 10 | main = do 11 | [n] <- fmap words getLine 12 | print $ fibonacci_last_digit (read n) 13 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/2_last_digit_of_fibonacci_number/fibonacci_last_digit.js: -------------------------------------------------------------------------------- 1 | // by Alexander Nikolskiy 2 | 3 | const readline = require('readline'); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | process.stdin.setEncoding('utf8'); 10 | rl.on('line', readLine); 11 | 12 | function readLine(line) { 13 | console.log(fib(parseInt(line, 10))); 14 | process.exit(); 15 | } 16 | 17 | function fib(n) { 18 | // write your code here 19 | } 20 | 21 | module.exports = fib; 22 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/2_last_digit_of_fibonacci_number/fibonacci_last_digit.py: -------------------------------------------------------------------------------- 1 | def fibonacci_last_digit(n): 2 | """ 3 | Input: An integer number 4 | Output: The last digit of the n-th Fibonacci number 5 | 6 | Property: the sequence of final digits in Fibonacci numbers repeats in cycles of 60 7 | 8 | https://math.stackexchange.com/questions/113536/fibonaccis-final-digits-cycle-every-60-numbers#:~:text=References%3A,the%20last%20four%20in%20%2C%20etc. 9 | 10 | """ 11 | if n <= 1: 12 | return n 13 | last_digits = [0] * 60 14 | 15 | # Stage 1: Find the sequence of the last digits in the first 60 elements of the Fibonacci series 16 | last_digits[0] = 0 17 | last_digits[1] = 1 18 | for i in range(2, len(last_digits)): 19 | last_digits[i] = (last_digits[i-1] + last_digits[i-2]) % 10 # store the last digit 20 | 21 | # Stage 2: Return the last digit of n 22 | return last_digits[n % 60] 23 | 24 | # Time complexity: O(1) 25 | if __name__ == '__main__': 26 | n = int(input()) 27 | print(fibonacci_last_digit(n)) 28 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/2_last_digit_of_fibonacci_number/fibonacci_last_digit.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def fib_last_digit(n) 5 | # fix me 6 | 0 7 | end 8 | 9 | if __FILE__ == $0 10 | n = gets.to_i 11 | puts "#{fib_last_digit(n)}" 12 | end -------------------------------------------------------------------------------- /week2_algorithmic_warmup/3_greatest_common_divisor/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 | public static void main(String args[]) { 18 | Scanner scanner = new Scanner(System.in); 19 | int a = scanner.nextInt(); 20 | int b = scanner.nextInt(); 21 | 22 | System.out.println(gcd_naive(a, b)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/3_greatest_common_divisor/GCD.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun gcdNaive(a: Int, b: Int): Int { 4 | var currentGcd = 1 5 | var d = 2 6 | while (d <= a && d <= b) { 7 | if (a % d == 0 && b % d == 0) { 8 | if (d > currentGcd) { 9 | currentGcd = d 10 | } 11 | } 12 | ++d 13 | } 14 | 15 | return currentGcd 16 | } 17 | 18 | fun main(args: Array) { 19 | val scanner = Scanner(System.`in`) 20 | val a = scanner.nextInt() 21 | val b = scanner.nextInt() 22 | 23 | println(gcdNaive(a, b)) 24 | } -------------------------------------------------------------------------------- /week2_algorithmic_warmup/3_greatest_common_divisor/euclidean_algorithm_psedocode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week2_algorithmic_warmup/3_greatest_common_divisor/euclidean_algorithm_psedocode.png -------------------------------------------------------------------------------- /week2_algorithmic_warmup/3_greatest_common_divisor/gcd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int gcd_naive(int a, int b) { 4 | int current_gcd = 1; 5 | for (int d = 2; d <= a && d <= b; d++) { 6 | if (a % d == 0 && b % d == 0) { 7 | if (d > current_gcd) { 8 | current_gcd = d; 9 | } 10 | } 11 | } 12 | return current_gcd; 13 | } 14 | 15 | int main() { 16 | int a, b; 17 | std::cin >> a >> b; 18 | std::cout << gcd_naive(a, b) << std::endl; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/3_greatest_common_divisor/gcd.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | gcd_naive :: Int -> Int -> Int 4 | gcd_naive a b = maximum [ d | d <- [1 .. min a b], a `mod` d == 0 && b `mod` d == 0 ] 5 | 6 | main :: IO () 7 | main = do 8 | [a, b] <- fmap words getLine 9 | print $ gcd_naive (read a) (read b) 10 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/3_greatest_common_divisor/gcd.js: -------------------------------------------------------------------------------- 1 | // by Alexander Nikolskiy 2 | 3 | const readline = require('readline'); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | process.stdin.setEncoding('utf8'); 10 | rl.on('line', readLine); 11 | 12 | function readLine(line) { 13 | if (line !== "\n") { 14 | const a = parseInt(line.toString().split(' ')[0], 10); 15 | const b = parseInt(line.toString().split(' ')[1], 10); 16 | 17 | console.log(gcd(a, b)); 18 | process.exit(); 19 | } 20 | } 21 | 22 | function gcd(a, b) { 23 | // write your code here 24 | } 25 | 26 | module.exports = gcd; 27 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/3_greatest_common_divisor/gcd.py: -------------------------------------------------------------------------------- 1 | def gcd(a, b): 2 | """ 3 | Input: 2 integers a, b 4 | Output: the greatest common divisor between a and b 5 | 6 | # naive solution 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 | # return current_gcd 13 | 14 | """ 15 | 16 | if a == 0: 17 | return b 18 | elif b == 0: 19 | return a 20 | 21 | if a >= b: 22 | return gcd(a % b, b) 23 | else: 24 | return gcd(a, b % a) 25 | 26 | if __name__ == "__main__": 27 | a, b = map(int, input().split()) 28 | print(gcd(a, b)) 29 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/3_greatest_common_divisor/gcd.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def gcd(a, b) 5 | # fix me 6 | a * b 7 | end 8 | 9 | if __FILE__ == $0 10 | a, b = gets.split().map(&:to_i) 11 | puts "#{gcd(a, b)}" 12 | end -------------------------------------------------------------------------------- /week2_algorithmic_warmup/4_least_common_multiple/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 | public static void main(String args[]) { 13 | Scanner scanner = new Scanner(System.in); 14 | int a = scanner.nextInt(); 15 | int b = scanner.nextInt(); 16 | 17 | System.out.println(lcm_naive(a, b)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/4_least_common_multiple/LCM.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun lcmNaive(a: Int, b: Int): Long { 4 | for (l in 1..a.toLong() * b) 5 | if (l % a == 0L && l % b == 0L) 6 | return l 7 | 8 | return a.toLong() * b 9 | } 10 | 11 | fun main(args: Array) { 12 | val scanner = Scanner(System.`in`) 13 | val a = scanner.nextInt() 14 | val b = scanner.nextInt() 15 | 16 | println(lcmNaive(a, b)) 17 | } -------------------------------------------------------------------------------- /week2_algorithmic_warmup/4_least_common_multiple/by_learners/lcm.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def gcd(a, b) 5 | # fix me 6 | a * b 7 | end 8 | 9 | def lcm(a, b) 10 | # fix me 11 | a * b 12 | end 13 | 14 | if __FILE__ == $0 15 | a, b = gets.split().map(&:to_i) 16 | puts "#{lcm(a, b)}" 17 | end 18 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/4_least_common_multiple/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 main() { 12 | int a, b; 13 | std::cin >> a >> b; 14 | std::cout << lcm_naive(a, b) << std::endl; 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/4_least_common_multiple/lcm.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | lcm_naive :: Int -> Int -> Integer 4 | lcm_naive a b = minimum [ l | l <- [1 .. a' * b'], l `mod` a' == 0 && l `mod` b' == 0 ] 5 | where 6 | a' = fromIntegral a :: Integer 7 | b' = fromIntegral b :: Integer 8 | 9 | main :: IO () 10 | main = do 11 | [a, b] <- fmap words getLine 12 | print $ lcm_naive (read a) (read b) 13 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/4_least_common_multiple/lcm.py: -------------------------------------------------------------------------------- 1 | def lcm(a, b): 2 | """ 3 | Input: 2 integers a, b 4 | Output: the least common multiple of a and b 5 | 6 | Property: lcm(a, b) * gcd(a, b) = a * b 7 | 8 | # naive solution 9 | # for l in range(1, a * b + 1): 10 | # if l % a == 0 and l % b == 0: # (if l is divisible by a and l is divisible by b) 11 | # return l 12 | # assert False 13 | """ 14 | # Step 1: Compute gcd(a, b) 15 | def gcd(a, b): 16 | if a == 0: 17 | return b 18 | elif b == 0: 19 | return a 20 | 21 | if a >= b: 22 | return gcd(a % b, b) 23 | else: 24 | return gcd(a, b % a) 25 | 26 | # Step 2: Compute lcm(a, b) 27 | 28 | return int((a * b) / gcd(a, b)) 29 | 30 | if __name__ == '__main__': 31 | a, b = map(int, input().split()) 32 | print(lcm(a, b)) 33 | 34 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/5_fibonacci_number_again/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 | public static void main(String[] args) { 21 | Scanner scanner = new Scanner(System.in); 22 | long n = scanner.nextLong(); 23 | long m = scanner.nextLong(); 24 | System.out.println(getFibonacciHugeNaive(n, m)); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/5_fibonacci_number_again/FibonacciHuge.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getFibonacciHugeNaive(n: Long, m: Long): Long { 4 | if (n <= 1) return n 5 | 6 | var previous: Long = 0 7 | var current: Long = 1 8 | 9 | for (i in 0 until n - 1) { 10 | val tmpPrevious = previous 11 | previous = current 12 | current += tmpPrevious 13 | } 14 | 15 | return current % m 16 | } 17 | 18 | fun main(args: Array) { 19 | val scanner = Scanner(System.`in`) 20 | val n = scanner.nextLong() 21 | val m = scanner.nextLong() 22 | println(getFibonacciHugeNaive(n, m)) 23 | } -------------------------------------------------------------------------------- /week2_algorithmic_warmup/5_fibonacci_number_again/fibonacci_huge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | long long get_fibonacci_huge_naive(long long n, long long m) { 4 | if (n <= 1) 5 | return n; 6 | 7 | long long previous = 0; 8 | long long current = 1; 9 | 10 | for (long long i = 0; i < n - 1; ++i) { 11 | long long tmp_previous = previous; 12 | previous = current; 13 | current = tmp_previous + current; 14 | } 15 | 16 | return current % m; 17 | } 18 | 19 | int main() { 20 | long long n, m; 21 | std::cin >> n >> m; 22 | std::cout << get_fibonacci_huge_naive(n, m) << '\n'; 23 | } 24 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/5_fibonacci_number_again/fibonacci_huge.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | get_fibonacci_huge_naive :: Integer -> Int -> Int 4 | get_fibonacci_huge_naive n m = helper (0, 1) n 5 | where 6 | helper (a, _) 0 = a `mod` m 7 | helper (a, b) i = helper (b, a + b) (i - 1) 8 | 9 | main :: IO () 10 | main = do 11 | [n, m] <- fmap words getLine 12 | print $ get_fibonacci_huge_naive (read n) (read m) 13 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/5_fibonacci_number_again/fibonacci_huge.js: -------------------------------------------------------------------------------- 1 | // by Alexander Nikolskiy 2 | 3 | const readline = require('readline'); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | process.stdin.setEncoding('utf8'); 10 | rl.on('line', readLine); 11 | 12 | function readLine(line) { 13 | if (line !== "\n") { 14 | const n = parseInt(line.toString().split(' ')[0], 10); 15 | const m = parseInt(line.toString().split(' ')[1], 10); 16 | 17 | console.log(getFibMod(n, m)); 18 | process.exit(); 19 | } 20 | } 21 | 22 | 23 | function getFibMod(n, m) { 24 | // write your code here 25 | } 26 | 27 | module.exports = getFibMod; 28 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/5_fibonacci_number_again/fibonacci_huge.py: -------------------------------------------------------------------------------- 1 | def fibonacci_huge(n, m): 2 | """ 3 | Input: 2 integers n, m 4 | Output: The n-th Fibonacci number modulo m 5 | 6 | To compute, say, F2015 mod 3 we just need to find the remainder of 2015 7 | when divided by 8. Since 2015 = 251*8 + 7, we conclude that 8 | F2015 mod 3 = F7 mod 3 = 1 9 | 10 | Read Learning Algorithms Through Programming and Puzzle Solving slides 11 | Pisano period: https://www.geeksforgeeks.org/fibonacci-number-modulo-m-and-pisano-period/ 12 | 13 | # naive solution 14 | # if n <= 1: 15 | # return n 16 | 17 | # previous = 0 18 | # current = 1 19 | 20 | # for _ in range(n - 1): 21 | # previous, current = current, previous + current 22 | 23 | # return current % m 24 | """ 25 | # The period always starts with 01 26 | # Fi mod m is periodic for every m 27 | # the period of Fi mod m does not exceed m^2 28 | previous, current = 0, 1 29 | for i in range(m*m): 30 | previous, current = current, (previous + current) % m 31 | 32 | if previous == 0 and current == 1: 33 | pisano_period = i + 1 34 | break 35 | 36 | n = n % pisano_period 37 | if n == 0: 38 | return 0 39 | 40 | previous_mod, current_mod = 0, 1 41 | for _ in range(n - 1): 42 | previous_mod, current_mod = current_mod, (previous_mod + current_mod) % m 43 | 44 | return current_mod 45 | 46 | if __name__ == '__main__': 47 | n, m = map(int, input().split()) 48 | print(fibonacci_huge(n, m)) 49 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/5_fibonacci_number_again/fibonacci_huge.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def fib_huge(n, m) 5 | # fix me 6 | 0 7 | end 8 | 9 | if __FILE__ == $0 10 | a, b = gets.split().map(&:to_i) 11 | puts "#{fib_huge(a, b)}" 12 | end -------------------------------------------------------------------------------- /week2_algorithmic_warmup/6_last_digit_of_the_sum_of_fibonacci_numbers/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 void main(String[] args) { 23 | Scanner scanner = new Scanner(System.in); 24 | long n = scanner.nextLong(); 25 | long s = getFibonacciSumNaive(n); 26 | System.out.println(s); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/6_last_digit_of_the_sum_of_fibonacci_numbers/FibonacciSumLastDigit.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getFibonacciSumNaive(n: Long): Long { 4 | if (n <= 1) 5 | return n 6 | 7 | var previous: Long = 0 8 | var current: Long = 1 9 | var sum: Long = 1 10 | 11 | for (i in 0 until n - 1) { 12 | val tmpPrevious = previous 13 | previous = current 14 | current += tmpPrevious 15 | sum += current 16 | } 17 | 18 | return sum % 10 19 | } 20 | 21 | fun main(args: Array) { 22 | val scanner = Scanner(System.`in`) 23 | val n = scanner.nextLong() 24 | val s = getFibonacciSumNaive(n) 25 | println(s) 26 | } -------------------------------------------------------------------------------- /week2_algorithmic_warmup/6_last_digit_of_the_sum_of_fibonacci_numbers/by_learners/fibonacci_sum_last_digit.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def fib_sum_last_digit(n) 5 | # write your code here 6 | 0 7 | end 8 | 9 | if __FILE__ == $0 10 | n = gets.to_i 11 | puts "#{fib_sum_last_digit(n)}" 12 | end 13 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/6_last_digit_of_the_sum_of_fibonacci_numbers/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 main() { 22 | long long n = 0; 23 | std::cin >> n; 24 | std::cout << fibonacci_sum_naive(n); 25 | } 26 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/6_last_digit_of_the_sum_of_fibonacci_numbers/fibonacci_sum_last_digit.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | fibonacci_sum_naive :: Integer -> Int 4 | fibonacci_sum_naive = helper (0, 1, 0) 5 | where 6 | helper (_, _, s) 0 = s `mod` 10 7 | helper (a, b, s) i = helper (b, a + b, s + b) (i - 1) 8 | 9 | main :: IO () 10 | main = do 11 | [n] <- fmap words getLine 12 | print $ fibonacci_sum_naive (read n) 13 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/6_last_digit_of_the_sum_of_fibonacci_numbers/fibonacci_sum_last_digit.py: -------------------------------------------------------------------------------- 1 | def fibonacci_sum(n): 2 | """ 3 | Input: An integer n 4 | Output: The last digit of S_n = F0 + F1 + ... + Fn 5 | 6 | Property 1: S_n = F_(n+2) - 1 7 | Property 2: The last digits of the Fibonacci sequence repeat in a cycle of 60 8 | 9 | Formula S_n: https://www.youtube.com/watch?v=VKc7qUdurMk&ab_channel=DrPeyam 10 | 11 | # naive solution 12 | # if n <= 1: 13 | # return n 14 | 15 | # previous, current, _sum = 0, 1, 1 16 | 17 | # for _ in range(n - 1): 18 | # previous, current = current, previous + current 19 | # _sum += current 20 | 21 | # return _sum % 10 22 | """ 23 | 24 | last_digits = [0] * 60 25 | last_digits[0] = 0 26 | last_digits[1] = 1 27 | for i in range(2, len(last_digits)): 28 | last_digits[i] = (last_digits[i - 1] + last_digits[i - 2]) % 10 29 | 30 | if last_digits[(n + 2) % 60] == 0: 31 | return 9 # because of S_n = F_(n+2) - 1 32 | else: 33 | return last_digits[(n + 2) % 60] - 1 34 | 35 | 36 | if __name__ == '__main__': 37 | n = int(input()) 38 | print(fibonacci_sum(n)) 39 | 40 | # Time complexity: O(1) -------------------------------------------------------------------------------- /week2_algorithmic_warmup/7_last_digit_of_the_sum_of_fibonacci_numbers_again/FibonacciPartialSum.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class FibonacciPartialSum { 4 | private static long getFibonacciPartialSumNaive(long from, long to) { 5 | long sum = 0; 6 | 7 | long current = 0; 8 | long next = 1; 9 | 10 | for (long i = 0; i <= to; ++i) { 11 | if (i >= from) { 12 | sum += current; 13 | } 14 | 15 | long new_current = next; 16 | next = next + current; 17 | current = new_current; 18 | } 19 | 20 | return sum % 10; 21 | } 22 | 23 | public static void main(String[] args) { 24 | Scanner scanner = new Scanner(System.in); 25 | long from = scanner.nextLong(); 26 | long to = scanner.nextLong(); 27 | System.out.println(getFibonacciPartialSumNaive(from, to)); 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/7_last_digit_of_the_sum_of_fibonacci_numbers_again/FibonacciPartialSum.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getFibonacciPartialSumNaive(from: Long, to: Long): Long { 4 | var sum: Long = 0 5 | 6 | var current: Long = 0 7 | var next: Long = 1 8 | 9 | for (i in 0..to) { 10 | if (i >= from) { 11 | sum += current 12 | } 13 | 14 | val newCurrent = next 15 | next += current 16 | current = newCurrent 17 | } 18 | 19 | return sum % 10 20 | } 21 | 22 | fun main(args: Array) { 23 | val scanner = Scanner(System.`in`) 24 | val from = scanner.nextLong() 25 | val to = scanner.nextLong() 26 | println(getFibonacciPartialSumNaive(from, to)) 27 | } -------------------------------------------------------------------------------- /week2_algorithmic_warmup/7_last_digit_of_the_sum_of_fibonacci_numbers_again/by_learners/fib_partial_sum.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def fib_partial_sum(m, n) 5 | # write your code here 6 | 0 7 | end 8 | 9 | if __FILE__ == $0 10 | m, n = gets.split().map(&:to_i) 11 | puts "#{fib_partial_sum(m, n)}" 12 | end 13 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/7_last_digit_of_the_sum_of_fibonacci_numbers_again/fibonacci_partial_sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using std::vector; 4 | 5 | long long get_fibonacci_partial_sum_naive(long long from, long long to) { 6 | long long sum = 0; 7 | 8 | long long current = 0; 9 | long long next = 1; 10 | 11 | for (long long i = 0; i <= to; ++i) { 12 | if (i >= from) { 13 | sum += current; 14 | } 15 | 16 | long long new_current = next; 17 | next = next + current; 18 | current = new_current; 19 | } 20 | 21 | return sum % 10; 22 | } 23 | 24 | int main() { 25 | long long from, to; 26 | std::cin >> from >> to; 27 | std::cout << get_fibonacci_partial_sum_naive(from, to) << '\n'; 28 | } 29 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/7_last_digit_of_the_sum_of_fibonacci_numbers_again/fibonacci_partial_sum.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | fibonacci_partial_sum_naive :: Integer -> Integer -> Int 4 | fibonacci_partial_sum_naive from to = let (a', b', _) = helper (0, 1, 0) from 5 | (_, _, s) = helper (a', b', a') (to - from) 6 | in s 7 | where 8 | helper (a, b, s) 0 = (a, b, s `mod` 10) 9 | helper (a, b, s) i = helper (b, a + b, s + b) (i - 1) 10 | 11 | main :: IO () 12 | main = do 13 | [from, to] <- fmap words getLine 14 | print $ fibonacci_partial_sum_naive (read from) (read to) 15 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/7_last_digit_of_the_sum_of_fibonacci_numbers_again/fibonacci_partial_sum.py: -------------------------------------------------------------------------------- 1 | # Uses python3 2 | import sys 3 | 4 | def fibonacci_partial_sum_naive(from_, to): 5 | """ 6 | Input: 2 integers m, n (m = from_, n = to) 7 | Output: The last digit of F_m + F_(m + 1) + ... + F_n 8 | 9 | Property: S_(m -> n) = S_n - S_(m - 1) = F_(n+2) - F_(m+1) 10 | 11 | # naive solution 12 | # _sum = 0 13 | 14 | # current = 0 15 | # _next = 1 16 | 17 | # for i in range(to + 1): 18 | # if i >= from_: 19 | # _sum += current 20 | 21 | # current, _next = _next, current + _next 22 | # return _sum % 10 23 | """ 24 | 25 | 26 | last_digits = [0] * 60 27 | last_digits[0] = 0 28 | last_digits[1] = 1 29 | for i in range(2, len(last_digits)): 30 | last_digits[i] = (last_digits[i - 1] + last_digits[i - 2]) % 10 31 | 32 | return (last_digits[(to + 2) % 60] - last_digits[(from_ + 1) % 60]) % 10 33 | 34 | 35 | 36 | if __name__ == '__main__': 37 | input = sys.stdin.read() 38 | from_, to = map(int, input.split()) 39 | print(fibonacci_partial_sum_naive(from_, to)) 40 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/8_last_digit_of_the_sum_of_squares_of_fibonacci_numbers/FibonacciSumSquares.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class FibonacciSumSquares { 4 | private static long getFibonacciSumSquaresNaive(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 * current; 17 | } 18 | 19 | return sum % 10; 20 | } 21 | 22 | public static void main(String[] args) { 23 | Scanner scanner = new Scanner(System.in); 24 | long n = scanner.nextLong(); 25 | long s = getFibonacciSumSquaresNaive(n); 26 | System.out.println(s); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/8_last_digit_of_the_sum_of_squares_of_fibonacci_numbers/fibonacci_sum_squares.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fibonacci_sum_squares_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 * current; 16 | } 17 | 18 | return sum % 10; 19 | } 20 | 21 | int main() { 22 | long long n = 0; 23 | std::cin >> n; 24 | std::cout << fibonacci_sum_squares_naive(n); 25 | } 26 | -------------------------------------------------------------------------------- /week2_algorithmic_warmup/8_last_digit_of_the_sum_of_squares_of_fibonacci_numbers/fibonacci_sum_squares.py: -------------------------------------------------------------------------------- 1 | def fibonacci_sum_squares(n): 2 | """ 3 | Input: An integer n 4 | Output: (F0^2 + F1^2 + ... +Fn^2) mod 10 5 | 6 | Property: F0^2 + F1^2 + ... +Fn^2 = F_n * F_(n+1) 7 | 8 | Proof: https://math.stackexchange.com/questions/2613609/summation-of-squares-of-fibonacci-numbers 9 | 10 | # naive solution 11 | # if n <= 1: 12 | # return n 13 | 14 | # previous, current, sum = 0, 1, 1 15 | 16 | # for _ in range(n - 1): 17 | # previous, current = current, previous + current 18 | # sum += current * current 19 | 20 | # return sum % 10 21 | """ 22 | last_digits = [0] * 60 23 | last_digits[0] = 0 24 | last_digits[1] = 1 25 | for i in range(2, len(last_digits)): 26 | last_digits[i] = (last_digits[i - 1] + last_digits[i - 2]) % 10 27 | 28 | return (last_digits[n % 60] * last_digits[(n+1) % 60]) % 10 29 | 30 | 31 | if __name__ == '__main__': 32 | n = int(input()) 33 | print(fibonacci_sum_squares(n)) 34 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/1_money_change/Change.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class Change { 4 | private static int getChange(int m) { 5 | //write your code here 6 | return m; 7 | } 8 | 9 | public static void main(String[] args) { 10 | Scanner scanner = new Scanner(System.in); 11 | int m = scanner.nextInt(); 12 | System.out.println(getChange(m)); 13 | 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/1_money_change/Change.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getChange(m: Int): Int { 4 | //write your code here 5 | return m 6 | } 7 | 8 | fun main(args: Array) { 9 | val scanner = Scanner(System.`in`) 10 | val m = scanner.nextInt() 11 | println(getChange(m)) 12 | } -------------------------------------------------------------------------------- /week3_greedy_algorithms/1_money_change/by_learners/change.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def get_change(n) 5 | count = 0 6 | coins = [1, 5, 10] 7 | # write your code here 8 | count 9 | end 10 | 11 | if __FILE__ == $0 12 | n = gets.to_i 13 | puts "#{get_change(n)}" 14 | end 15 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/1_money_change/change.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int get_change(int m) { 4 | //write your code here 5 | return n; 6 | } 7 | 8 | int main() { 9 | int m; 10 | std::cin >> m; 11 | std::cout << get_change(m) << '\n'; 12 | } 13 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/1_money_change/change.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | get_change :: Int -> Int 4 | get_change m = n -- write your code here 5 | 6 | main :: IO () 7 | main = do 8 | [m] <- fmap words getLine 9 | print $ get_change (read m) 10 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/1_money_change/change.py: -------------------------------------------------------------------------------- 1 | def change(money): 2 | """ 3 | Input: An integer money 4 | Output: The minimum number of coins with denominations 1, 5, and 10 that changes money. 5 | 6 | We try to change as many largest coins with maximal denomination (10) as possible 7 | and apply the same procedure to 5 and 1 8 | 9 | """ 10 | count = 0 11 | while money > 0: 12 | if money >= 10: 13 | money -= 10 14 | elif money < 10 and money >= 5: 15 | money -= 5 16 | elif money < 5: 17 | money -= 1 18 | 19 | count += 1 20 | 21 | return count 22 | 23 | 24 | if __name__ == '__main__': 25 | m = int(input()) 26 | print(change(m)) 27 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/2_maximum_value_of_the_loot/FractionalKnapsack.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class FractionalKnapsack { 4 | private static double getOptimalValue(int capacity, int[] values, int[] weights) { 5 | double value = 0; 6 | //write your code here 7 | 8 | return value; 9 | } 10 | 11 | public static void main(String args[]) { 12 | Scanner scanner = new Scanner(System.in); 13 | int n = scanner.nextInt(); 14 | int capacity = scanner.nextInt(); 15 | int[] values = new int[n]; 16 | int[] weights = new int[n]; 17 | for (int i = 0; i < n; i++) { 18 | values[i] = scanner.nextInt(); 19 | weights[i] = scanner.nextInt(); 20 | } 21 | System.out.println(getOptimalValue(capacity, values, weights)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/2_maximum_value_of_the_loot/FractionalKnapsack.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getOptimalValue(capacity: Int, values: IntArray, weights: IntArray): Double { 4 | //write your code here 5 | return 0.0 6 | } 7 | 8 | fun main(args: Array) { 9 | val scanner = Scanner(System.`in`) 10 | val n = scanner.nextInt() 11 | val capacity = scanner.nextInt() 12 | val values = IntArray(n) 13 | val weights = IntArray(n) 14 | for (i in 0 until n) { 15 | values[i] = scanner.nextInt() 16 | weights[i] = scanner.nextInt() 17 | } 18 | println(getOptimalValue(capacity, values, weights)) 19 | } -------------------------------------------------------------------------------- /week3_greedy_algorithms/2_maximum_value_of_the_loot/fractional_knapsack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | double get_optimal_value(int capacity, vector weights, vector values) { 7 | double value = 0.0; 8 | 9 | // write your code here 10 | 11 | return value; 12 | } 13 | 14 | int main() { 15 | int n; 16 | int capacity; 17 | std::cin >> n >> capacity; 18 | vector values(n); 19 | vector weights(n); 20 | for (int i = 0; i < n; i++) { 21 | std::cin >> values[i] >> weights[i]; 22 | } 23 | 24 | double optimal_value = get_optimal_value(capacity, weights, values); 25 | 26 | std::cout.precision(10); 27 | std::cout << optimal_value << std::endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/2_maximum_value_of_the_loot/fractional_knapsack.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | import Control.Monad (replicateM) 4 | import Numeric (showFFloat) 5 | 6 | 7 | type Item = (Int, Int) 8 | 9 | get_optimal_value :: Int -> [Item] -> Double 10 | get_optimal_value capacity items = value -- write your code here 11 | 12 | main :: IO () 13 | main = do 14 | [n', capacity'] <- fmap words getLine 15 | let (n, capacity) = (read n', read capacity') 16 | items <- replicateM n $ fmap ((\[v, w] -> (read v, read w)) . words) getLine 17 | printFloat $ get_optimal_value capacity items 18 | where 19 | printFloat x = putStrLn $ showFFloat (Just 4) x "" 20 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/2_maximum_value_of_the_loot/fractional_knapsack.js: -------------------------------------------------------------------------------- 1 | // by Alexander Nikolskiy 2 | 3 | const readline = require('readline'); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | process.stdin.setEncoding('utf8'); 10 | 11 | rl.once('line', line => { 12 | const [itemsCount, knapsackCapacity] = line.toString().split(' ').map(Number); 13 | const values = []; 14 | const weights = []; 15 | let count = 0; 16 | 17 | rl.on('line', line => { 18 | const [v, w] = readLine(line); 19 | values.push(v); 20 | weights.push(w); 21 | 22 | if (++count >= itemsCount) { 23 | console.log(max(itemsCount, knapsackCapacity, values, weights)); 24 | process.exit(); 25 | } 26 | }); 27 | }); 28 | 29 | function readLine(line) { 30 | const v = parseInt(line.toString().split(' ')[0], 10); 31 | const w = parseInt(line.toString().split(' ')[1], 10); 32 | 33 | return [v, w]; 34 | } 35 | 36 | function max(count, capacity, values, weights) { 37 | // write your code here 38 | } 39 | 40 | module.exports = max; 41 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/2_maximum_value_of_the_loot/fractional_knapsack.py: -------------------------------------------------------------------------------- 1 | from sys import stdin 2 | 3 | 4 | def optimal_value(capacity, weights, values): 5 | """ 6 | Take as Much of the Most Expensive Compound as You Can 7 | 8 | Time: O(n^2) 9 | 10 | """ 11 | if capacity == 0 or not weights: 12 | return 0. 13 | 14 | prices = [] 15 | for v, w in zip(values, weights): 16 | prices.append(v / w) # calculate value / weight = item value / 1 weight 17 | 18 | m = 0 # the index of the most expensive item 19 | for i in range(len(prices)): 20 | if prices[i] > prices[m]: 21 | m = i 22 | 23 | amount = min(weights[m], capacity) 24 | value = prices[m] * amount 25 | 26 | capacity -= amount 27 | del weights[m] 28 | del values[m] 29 | 30 | return value + optimal_value(capacity, weights, values) 31 | 32 | 33 | if __name__ == "__main__": 34 | data = list(map(int, stdin.read().split())) 35 | n, capacity = data[0:2] 36 | values = data[2:(2 * n + 2):2] 37 | weights = data[3:(2 * n + 2):2] 38 | opt_value = optimal_value(capacity, weights, values) 39 | print("{:.10f}".format(opt_value)) 40 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/2_maximum_value_of_the_loot/fractional_knapsack.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def get_optimal_value(capacity, weights, values) 5 | value = 0.0 6 | # write your code here 7 | value 8 | end 9 | 10 | if __FILE__ == $0 11 | data = STDIN.read.split().map(&:to_i) 12 | n, capacity = data[0,2] 13 | values = data.values_at(*(2..2*n).step(2)) 14 | weights = data.values_at(*(3..2*n+1).step(2)) 15 | 16 | answer = get_optimal_value(capacity, weights, values) 17 | puts "#{'%.4f' % answer}" 18 | end -------------------------------------------------------------------------------- /week3_greedy_algorithms/2_maximum_value_of_the_loot/pseudocode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week3_greedy_algorithms/2_maximum_value_of_the_loot/pseudocode.png -------------------------------------------------------------------------------- /week3_greedy_algorithms/3_car_fueling/CarFueling.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | 4 | public class CarFueling { 5 | static int computeMinRefills(int dist, int tank, int[] stops) { 6 | return -1; 7 | } 8 | 9 | public static void main(String[] args) { 10 | Scanner scanner = new Scanner(System.in); 11 | int dist = scanner.nextInt(); 12 | int tank = scanner.nextInt(); 13 | int n = scanner.nextInt(); 14 | int stops[] = new int[n]; 15 | for (int i = 0; i < n; i++) { 16 | stops[i] = scanner.nextInt(); 17 | } 18 | 19 | System.out.println(computeMinRefills(dist, tank, stops)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/3_car_fueling/car_fueling.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cin; 5 | using std::cout; 6 | using std::vector; 7 | using std::max; 8 | 9 | int compute_min_refills(int dist, int tank, vector & stops) { 10 | // write your code here 11 | return -1; 12 | } 13 | 14 | 15 | int main() { 16 | int d = 0; 17 | cin >> d; 18 | int m = 0; 19 | cin >> m; 20 | int n = 0; 21 | cin >> n; 22 | 23 | vector stops(n); 24 | for (size_t i = 0; i < n; ++i) 25 | cin >> stops.at(i); 26 | 27 | cout << compute_min_refills(d, m, stops) << "\n"; 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/3_car_fueling/car_fueling.py: -------------------------------------------------------------------------------- 1 | from sys import stdin 2 | 3 | 4 | def min_refills(distance, tank, stops): 5 | # distance:d, tank: m 6 | location = 0 7 | if location + tank >= distance: 8 | return 0 9 | if (not stops) or (stops[0] - location > tank): 10 | return -1 11 | 12 | last_stop = location 13 | while stops and stops[0] - location <= tank: 14 | last_stop = stops[0] 15 | del stops[0] # warning 16 | # stops.pop(0) # warning 17 | # stops = stops[1:] # time limit exceeded 18 | 19 | 20 | for i in range(len(stops)): 21 | stops[i] -= last_stop 22 | 23 | eval = min_refills(distance - last_stop, tank, stops) # There must be this line because every time we call min_fills(), stops is globally changed. We need the function is called once 24 | if eval == -1: 25 | return -1 26 | else: 27 | return 1 + eval 28 | 29 | 30 | 31 | if __name__ == '__main__': 32 | d, m, _, *stops = map(int, stdin.read().split()) 33 | print(min_refills(d, m, stops)) 34 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/3_car_fueling/pseudocode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week3_greedy_algorithms/3_car_fueling/pseudocode.png -------------------------------------------------------------------------------- /week3_greedy_algorithms/4_maximum_advertisement_revenue/DotProduct.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class DotProduct { 4 | private static long maxDotProduct(int[] a, int[] b) { 5 | //write your code here 6 | long result = 0; 7 | for (int i = 0; i < a.length; i++) { 8 | result += (long)a[i] * (long)b[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 | int[] a = new int[n]; 17 | for (int i = 0; i < n; i++) { 18 | a[i] = scanner.nextInt(); 19 | } 20 | int[] b = new int[n]; 21 | for (int i = 0; i < n; i++) { 22 | b[i] = scanner.nextInt(); 23 | } 24 | System.out.println(maxDotProduct(a, b)); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/4_maximum_advertisement_revenue/DotProduct.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun maxDotProduct(a: IntArray, b: IntArray): Long { 4 | //write your code here 5 | var result: Long = 0 6 | for (i in a.indices) { 7 | result += (a[i] * b[i]).toLong() 8 | } 9 | return result 10 | } 11 | 12 | fun main(args: Array) { 13 | val scanner = Scanner(System.`in`) 14 | val n = scanner.nextInt() 15 | val a = IntArray(n) 16 | for (i in 0 until n) { 17 | a[i] = scanner.nextInt() 18 | } 19 | val b = IntArray(n) 20 | for (i in 0 until n) { 21 | b[i] = scanner.nextInt() 22 | } 23 | println(maxDotProduct(a, b)) 24 | } -------------------------------------------------------------------------------- /week3_greedy_algorithms/4_maximum_advertisement_revenue/by_learners/dot_rpoduct.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def max_dot_product(a, b) 5 | #write your code here 6 | end 7 | 8 | if __FILE__ == $0 9 | data = STDIN.read.split().map(&:to_i) 10 | n = data[0] 11 | a, b = data[1..n], data[n+1..2*n] 12 | puts "#{min_dot_product(a, b)}" 13 | end -------------------------------------------------------------------------------- /week3_greedy_algorithms/4_maximum_advertisement_revenue/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 | // write your code here 9 | long long result = 0; 10 | for (size_t i = 0; i < a.size(); i++) { 11 | result += ((long long) a[i]) * b[i]; 12 | } 13 | return result; 14 | } 15 | 16 | int main() { 17 | size_t n; 18 | std::cin >> n; 19 | vector a(n), b(n); 20 | for (size_t i = 0; i < n; i++) { 21 | std::cin >> a[i]; 22 | } 23 | for (size_t i = 0; i < n; i++) { 24 | std::cin >> b[i]; 25 | } 26 | std::cout << max_dot_product(a, b) << std::endl; 27 | } 28 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/4_maximum_advertisement_revenue/dot_product.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | max_dot_product :: [Int] -> [Int] -> Integer 4 | max_dot_product as bs = result -- write your code here 5 | 6 | main :: IO () 7 | main = do 8 | _ <- getLine 9 | as <- fmap (map read . words) getLine 10 | bs <- fmap (map read . words) getLine 11 | print $ max_dot_product as bs 12 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/4_maximum_advertisement_revenue/dot_product.py: -------------------------------------------------------------------------------- 1 | from itertools import permutations 2 | 3 | 4 | def max_dot_product(first_sequence, second_sequence): 5 | """ 6 | Input: 2 sequences of integers 7 | Output: Maximum dot product of 2 sequences 8 | 9 | Find maximum of first_sequence, maximum of second_sequence 10 | Take away 2 values and then continue until one of the sequence is empty 11 | 12 | # naive solution 13 | # max_product = 0 14 | # for permutation in permutations(second_sequence): 15 | # dot_product = sum(first_sequence[i] * permutation[i] for i in range(len(first_sequence))) 16 | # max_product = max(max_product, dot_product) 17 | 18 | # return max_product 19 | """ 20 | 21 | # second_sequence: clicks, first_sequence: prices 22 | max_product = 0 23 | clicks = second_sequence 24 | prices = first_sequence 25 | 26 | while clicks and prices: 27 | c, p = 0, 0 28 | for i in range(len(clicks)): 29 | if clicks[i] > clicks[c]: 30 | c = i 31 | 32 | for i in range(len(prices)): 33 | if prices[i] > prices[p]: 34 | p = i 35 | max_product += clicks[c] * prices[p] 36 | 37 | clicks.pop(c) 38 | prices.pop(p) 39 | 40 | return max_product 41 | 42 | 43 | if __name__ == '__main__': 44 | n = int(input()) 45 | prices = list(map(int, input().split())) 46 | clicks = list(map(int, input().split())) 47 | assert len(prices) == len(clicks) == n 48 | print(max_dot_product(prices, clicks)) 49 | 50 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/5_collecting_signatures/CoveringSegments.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class CoveringSegments { 4 | 5 | private static int[] optimalPoints(Segment[] segments) { 6 | //write your code here 7 | int[] points = new int[2 * segments.length]; 8 | for (int i = 0; i < segments.length; i++) { 9 | points[2 * i] = segments[i].start; 10 | points[2 * i + 1] = segments[i].end; 11 | } 12 | return points; 13 | } 14 | 15 | private static class Segment { 16 | int start, end; 17 | 18 | Segment(int start, int end) { 19 | this.start = start; 20 | this.end = end; 21 | } 22 | } 23 | public static void main(String[] args) { 24 | Scanner scanner = new Scanner(System.in); 25 | int n = scanner.nextInt(); 26 | Segment[] segments = new Segment[n]; 27 | for (int i = 0; i < n; i++) { 28 | int start, end; 29 | start = scanner.nextInt(); 30 | end = scanner.nextInt(); 31 | segments[i] = new Segment(start, end); 32 | } 33 | int[] points = optimalPoints(segments); 34 | System.out.println(points.length); 35 | for (int point : points) { 36 | System.out.print(point + " "); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/5_collecting_signatures/CoveringSegments.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun optimalPoints(segments: MutableList): IntArray { 4 | //write your code here 5 | val points = IntArray(2 * segments.size) 6 | for (i in segments.indices) { 7 | points[2 * i] = segments[i].start 8 | points[2 * i + 1] = segments[i].end 9 | } 10 | return points 11 | } 12 | 13 | class Segment(var start: Int, var end: Int) 14 | 15 | fun main(args: Array) { 16 | val scanner = Scanner(System.`in`) 17 | val n = scanner.nextInt() 18 | val segments = ArrayList(n) 19 | repeat (n) { 20 | val start: Int = scanner.nextInt() 21 | val end: Int = scanner.nextInt() 22 | segments += Segment(start, end) 23 | } 24 | val points = optimalPoints(segments) 25 | println(points.size) 26 | for (point in points) { 27 | print(point.toString() + " ") 28 | } 29 | } -------------------------------------------------------------------------------- /week3_greedy_algorithms/5_collecting_signatures/by_learners/covering_segments.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | Segment = Struct.new("Segment", :start, :end) 5 | 6 | def optimal_points(segments) 7 | points = [] 8 | return points if segments.empty? 9 | #write your code here 10 | points 11 | end 12 | 13 | if __FILE__ == $0 14 | data = STDIN.read.split().map(&:to_i) 15 | n = data[0] 16 | segments = data[1..2*n].each_slice(2).to_a.map { |e| Segment.new(e[0], e[1]) } 17 | points = optimal_points(segments) 18 | puts "#{points.size}" 19 | puts "#{points.join(' ')}" 20 | end -------------------------------------------------------------------------------- /week3_greedy_algorithms/5_collecting_signatures/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 | vector optimal_points(vector &segments) { 13 | vector points; 14 | //write your code here 15 | for (size_t i = 0; i < segments.size(); ++i) { 16 | points.push_back(segments[i].start); 17 | points.push_back(segments[i].end); 18 | } 19 | return points; 20 | } 21 | 22 | int main() { 23 | int n; 24 | std::cin >> n; 25 | vector segments(n); 26 | for (size_t i = 0; i < segments.size(); ++i) { 27 | std::cin >> segments[i].start >> segments[i].end; 28 | } 29 | vector points = optimal_points(segments); 30 | std::cout << points.size() << "\n"; 31 | for (size_t i = 0; i < points.size(); ++i) { 32 | std::cout << points[i] << " "; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/5_collecting_signatures/covering_segments.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | import Control.Monad (replicateM) 4 | 5 | 6 | optimal_points :: [(Int, Int)] -> [Int] 7 | optimal_points segments = map fst segments -- write your code here 8 | 9 | main :: IO () 10 | main = do 11 | n' <- getLine 12 | let n = read n' 13 | segments <- replicateM n $ fmap ((\[s, e] -> (read s, read e)) . words) getLine 14 | let points = optimal_points segments 15 | print $ length points 16 | putStrLn $ unwords (map show points) 17 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/5_collecting_signatures/covering_segments.py: -------------------------------------------------------------------------------- 1 | from sys import stdin 2 | from collections import namedtuple 3 | 4 | Segment = namedtuple('Segment', 'start end') 5 | 6 | def optimal_points(segments): 7 | """ 8 | https://stackoverflow.com/questions/37936571/covering-segments-by-points 9 | 10 | """ 11 | points = [] 12 | # for s in segments: 13 | # points.append(s.start) 14 | # points.append(s.end) 15 | # points = [3, 6] 16 | while segments: 17 | m = 0 18 | for i in range(len(segments)): 19 | if segments[i].end < segments[m].end: 20 | m = i 21 | points.append(segments[m].end) 22 | 23 | drops = [] 24 | for i in range(len(segments)): 25 | if (points[-1] >= segments[i].start) and (points[-1] <= segments[i].end): 26 | drops.append(i) 27 | segments = [segments[i] for i in range(len(segments)) if i not in drops] 28 | 29 | return points 30 | 31 | 32 | if __name__ == '__main__': 33 | input = stdin.read() 34 | n, *data = map(int, input.split()) 35 | segments = list(map(lambda x: Segment(x[0], x[1]), zip(data[::2], data[1::2]))) 36 | points = optimal_points(segments) 37 | print(len(points)) 38 | print(*points) 39 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/6_maximum_number_of_prizes/DifferentSummands.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class DifferentSummands { 4 | private static List optimalSummands(int n) { 5 | List summands = new ArrayList(); 6 | //write your code here 7 | return summands; 8 | } 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | int n = scanner.nextInt(); 13 | List summands = optimalSummands(n); 14 | System.out.println(summands.size()); 15 | for (Integer summand : summands) { 16 | System.out.print(summand + " "); 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/6_maximum_number_of_prizes/DifferentSummands.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun optimalSummands(n: Int): List { 4 | //write your code here 5 | return ArrayList() 6 | } 7 | 8 | fun main(args: Array) { 9 | val scanner = Scanner(System.`in`) 10 | val n = scanner.nextInt() 11 | val summands = optimalSummands(n) 12 | println(summands.size) 13 | for (summand in summands) { 14 | print(summand.toString() + " ") 15 | } 16 | } -------------------------------------------------------------------------------- /week3_greedy_algorithms/6_maximum_number_of_prizes/by_learners/different_summands.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def optimal_summands(n) 5 | summands = [] 6 | #write your code here 7 | summands 8 | end 9 | 10 | if __FILE__ == $0 11 | n = gets.to_i 12 | summands = optimal_summands(n) 13 | puts "#{summands.size}" 14 | puts "#{summands.join(' ')}" 15 | end -------------------------------------------------------------------------------- /week3_greedy_algorithms/6_maximum_number_of_prizes/different_summands.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | vector optimal_summands(int n) { 7 | vector summands; 8 | //write your code here 9 | return summands; 10 | } 11 | 12 | int main() { 13 | int n; 14 | std::cin >> n; 15 | vector summands = optimal_summands(n); 16 | std::cout << summands.size() << '\n'; 17 | for (size_t i = 0; i < summands.size(); ++i) { 18 | std::cout << summands[i] << ' '; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/6_maximum_number_of_prizes/different_summands.hs: -------------------------------------------------------------------------------- 1 | -- by Kirill Elagin 2 | 3 | optimal_summands :: Int -> [Int] 4 | optimal_summands n = [n] -- write your code here 5 | 6 | main :: IO () 7 | main = do 8 | n <- getLine 9 | let summands = optimal_summands (read n) 10 | print $ length summands 11 | putStrLn $ unwords (map show summands) 12 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/6_maximum_number_of_prizes/different_summands.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def optimal_summands(n): 4 | summands = [] 5 | # n = 8 => summands = [1, 2, 5] 6 | # n = 6 => summands = [1, 2, 3] 7 | # Explaination: The smallest number that can be made with k different summands 8 | # is just the sum of all numbers from 1 to k. Any number smaller than that will have fewer summands... at most k-1 9 | # To maximize k, we need to find k such that 1+2+...+k = k(k+1) / 2 <= n 10 | # After k is found, to make the sum of k different summands equal to n, 11 | # we calculate 1+2+...+(k-1) = k(k-1) / 2 and then the k-th summand as n - k(k-1) / 2 12 | 13 | k = math.floor((-1 + math.sqrt(1+8*n)) / 2) 14 | for i in range(1, k): 15 | summands.append(i) 16 | summands.append(int(n - k*(k-1) / 2)) 17 | return summands 18 | 19 | 20 | if __name__ == '__main__': 21 | n = int(input()) 22 | summands = optimal_summands(n) 23 | print(len(summands)) 24 | print(*summands) 25 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/7_maximum_salary/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 | 24 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/7_maximum_salary/LargestNumber.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun largestNumber(a: MutableList): String { 4 | //write your code here 5 | return a.joinToString("") 6 | } 7 | 8 | fun main(args: Array) { 9 | val scanner = Scanner(System.`in`) 10 | val n = scanner.nextInt() 11 | val a = ArrayList(n) 12 | repeat(n) { 13 | a += scanner.next() 14 | } 15 | println(largestNumber(a)) 16 | } -------------------------------------------------------------------------------- /week3_greedy_algorithms/7_maximum_salary/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 -------------------------------------------------------------------------------- /week3_greedy_algorithms/7_maximum_salary/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 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/7_maximum_salary/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 | -------------------------------------------------------------------------------- /week3_greedy_algorithms/7_maximum_salary/largest_number.py: -------------------------------------------------------------------------------- 1 | from itertools import permutations 2 | 3 | def is_better(number, max_number): 4 | number1 = int(str(number) + str(max_number)) 5 | number2 = int(str(max_number) + str(number)) 6 | if number1 >= number2: 7 | return True 8 | else: 9 | return False 10 | 11 | def largest_number(numbers): 12 | """ 13 | See the pseudocode in toolbox_statements.pdf 14 | """ 15 | # numbers = list(map(str, numbers)) 16 | 17 | # largest = 0 18 | 19 | # for permutation in permutations(numbers): 20 | # largest = max(largest, int("".join(permutation))) 21 | 22 | # return largest 23 | 24 | numbers = list(map(int, numbers)) 25 | largest = '' 26 | while numbers: 27 | max_number_idx = 0 28 | max_number = 0 29 | for idx, number in enumerate(numbers): 30 | if is_better(number, max_number): 31 | max_number = number 32 | max_number_idx = idx 33 | 34 | largest += str(max_number) 35 | 36 | numbers.pop(max_number_idx) 37 | 38 | return int(largest) 39 | 40 | 41 | 42 | if __name__ == '__main__': 43 | _ = int(input()) 44 | input_numbers = input().split() 45 | print(largest_number(input_numbers)) 46 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/1_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; 8 | //write your code here 9 | 10 | return -1; 11 | } 12 | 13 | static int linearSearch(int[] a, int x) { 14 | for (int i = 0; i < a.length; i++) { 15 | if (a[i] == x) return i; 16 | } 17 | return -1; 18 | } 19 | 20 | public static void main(String[] args) { 21 | FastScanner scanner = new FastScanner(System.in); 22 | int n = scanner.nextInt(); 23 | int[] a = new int[n]; 24 | for (int i = 0; i < n; i++) { 25 | a[i] = scanner.nextInt(); 26 | } 27 | int m = scanner.nextInt(); 28 | int[] b = new int[m]; 29 | for (int i = 0; i < m; i++) { 30 | b[i] = scanner.nextInt(); 31 | } 32 | for (int i = 0; i < m; i++) { 33 | //replace with the call to binarySearch when implemented 34 | System.out.print(linearSearch(a, b[i]) + " "); 35 | } 36 | } 37 | static class FastScanner { 38 | BufferedReader br; 39 | StringTokenizer st; 40 | 41 | FastScanner(InputStream stream) { 42 | try { 43 | br = new BufferedReader(new InputStreamReader(stream)); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | 49 | String next() { 50 | while (st == null || !st.hasMoreTokens()) { 51 | try { 52 | st = new StringTokenizer(br.readLine()); 53 | } catch (IOException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | return st.nextToken(); 58 | } 59 | 60 | int nextInt() { 61 | return Integer.parseInt(next()); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/1_binary_search/BinarySearch.kt: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader 2 | import java.io.IOException 3 | import java.io.InputStream 4 | import java.io.InputStreamReader 5 | import java.util.* 6 | 7 | fun binarySearch(a: IntArray, x: Int): Int { 8 | val left = 0 9 | val right = a.size 10 | //write your code here 11 | 12 | return -1 13 | } 14 | 15 | fun linearSearch(a: IntArray, x: Int): Int { 16 | for (i in a.indices) { 17 | if (a[i] == x) return i 18 | } 19 | return -1 20 | } 21 | 22 | fun main(args: Array) { 23 | val scanner = FastScanner(System.`in`) 24 | val n = scanner.nextInt() 25 | val a = IntArray(n) 26 | for (i in 0 until n) { 27 | a[i] = scanner.nextInt() 28 | } 29 | val m = scanner.nextInt() 30 | val b = IntArray(m) 31 | for (i in 0 until m) { 32 | b[i] = scanner.nextInt() 33 | } 34 | for (i in 0 until m) { 35 | //replace with the call to binarySearch when implemented 36 | print(linearSearch(a, b[i]).toString() + " ") 37 | } 38 | } 39 | 40 | class FastScanner(stream: InputStream) { 41 | var br: BufferedReader = BufferedReader(InputStreamReader(stream)) 42 | var st: StringTokenizer? = null 43 | 44 | fun next(): String { 45 | while (st == null || !st!!.hasMoreTokens()) { 46 | try { 47 | st = StringTokenizer(br.readLine()) 48 | } catch (e: IOException) { 49 | e.printStackTrace() 50 | } 51 | } 52 | return st!!.nextToken() 53 | } 54 | 55 | fun nextInt() = next().toInt() 56 | } -------------------------------------------------------------------------------- /week4_divide_and_conquer/1_binary_search/binary_search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | 7 | int binary_search(const vector &a, int x) { 8 | int left = 0, right = (int)a.size(); 9 | //write your code here 10 | } 11 | 12 | int linear_search(const vector &a, int x) { 13 | for (size_t i = 0; i < a.size(); ++i) { 14 | if (a[i] == x) return i; 15 | } 16 | return -1; 17 | } 18 | 19 | int main() { 20 | int n; 21 | std::cin >> n; 22 | vector a(n); 23 | for (size_t i = 0; i < a.size(); i++) { 24 | std::cin >> a[i]; 25 | } 26 | int m; 27 | std::cin >> m; 28 | vector b(m); 29 | for (int i = 0; i < m; ++i) { 30 | std::cin >> b[i]; 31 | } 32 | for (int i = 0; i < m; ++i) { 33 | //replace with the call to binary_search when implemented 34 | std::cout << linear_search(a, b[i]) << ' '; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/1_binary_search/binary_search.js: -------------------------------------------------------------------------------- 1 | // by Alexander Nikolskiy 2 | 3 | const readline = require('readline'); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | process.stdin.setEncoding('utf8'); 10 | rl.once('line', line => { 11 | const arr = line.toString().split(' ').slice(1).map(Number); 12 | 13 | rl.once('line', line => { 14 | const keys = line.toString().split(' ').slice(1).map(Number); 15 | const result = []; 16 | 17 | for (let key of keys) { 18 | result.push(binarySearch(arr, key)); 19 | } 20 | 21 | const res = result.join(' '); 22 | const maxLength = 50000; 23 | 24 | for (let i = 0; i < res.length; i += maxLength) { 25 | process.stdout.write(res.slice(i, i + maxLength)); 26 | } 27 | 28 | process.stdout.write('\n'); 29 | process.exit(); 30 | }) 31 | }); 32 | 33 | function binarySearch(arr = [], key) { 34 | // write your code here 35 | } 36 | 37 | module.exports = binarySearch; 38 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/1_binary_search/binary_search.py: -------------------------------------------------------------------------------- 1 | def binary_search(keys, query): 2 | # write your code here 3 | min_idx = 0 4 | max_idx = len(keys) - 1 5 | while min_idx <= max_idx: 6 | mid_idx = (min_idx + max_idx) // 2 7 | if keys[mid_idx] == query: 8 | return mid_idx 9 | elif keys[mid_idx] > query: 10 | max_idx = mid_idx - 1 11 | else: 12 | min_idx = mid_idx + 1 13 | 14 | return -1 15 | 16 | 17 | if __name__ == '__main__': 18 | num_keys = int(input()) 19 | input_keys = list(map(int, input().split())) 20 | assert len(input_keys) == num_keys 21 | 22 | num_queries = int(input()) 23 | input_queries = list(map(int, input().split())) 24 | assert len(input_queries) == num_queries 25 | 26 | for q in input_queries: 27 | print(binary_search(input_keys, q), end=' ') 28 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/1_binary_search/binary_search.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def binary_search(x, a) 5 | #write your code here 6 | -1 7 | end 8 | 9 | if __FILE__ == $0 10 | data = STDIN.read.split().map(&:to_i) 11 | n = data[0] 12 | a = data[1..n] 13 | m = data[n+1] 14 | data[n+2, m].each { |b| print("#{binary_search(b, a)} ") } 15 | puts "" 16 | end 17 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/1_binary_search/pseudocode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week4_divide_and_conquer/1_binary_search/pseudocode.png -------------------------------------------------------------------------------- /week4_divide_and_conquer/2_binary_search_duplicates/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; 8 | //write your code here 9 | 10 | return -1; 11 | } 12 | 13 | static int linearSearch(int[] a, int x) { 14 | for (int i = 0; i < a.length; i++) { 15 | if (a[i] == x) return i; 16 | } 17 | return -1; 18 | } 19 | 20 | public static void main(String[] args) { 21 | FastScanner scanner = new FastScanner(System.in); 22 | int n = scanner.nextInt(); 23 | int[] a = new int[n]; 24 | for (int i = 0; i < n; i++) { 25 | a[i] = scanner.nextInt(); 26 | } 27 | int m = scanner.nextInt(); 28 | int[] b = new int[m]; 29 | for (int i = 0; i < m; i++) { 30 | b[i] = scanner.nextInt(); 31 | } 32 | for (int i = 0; i < m; i++) { 33 | //replace with the call to binarySearch when implemented 34 | System.out.print(linearSearch(a, b[i]) + " "); 35 | } 36 | } 37 | static class FastScanner { 38 | BufferedReader br; 39 | StringTokenizer st; 40 | 41 | FastScanner(InputStream stream) { 42 | try { 43 | br = new BufferedReader(new InputStreamReader(stream)); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | 49 | String next() { 50 | while (st == null || !st.hasMoreTokens()) { 51 | try { 52 | st = new StringTokenizer(br.readLine()); 53 | } catch (IOException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | return st.nextToken(); 58 | } 59 | 60 | int nextInt() { 61 | return Integer.parseInt(next()); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/2_binary_search_duplicates/BinarySearch.kt: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader 2 | import java.io.IOException 3 | import java.io.InputStream 4 | import java.io.InputStreamReader 5 | import java.util.* 6 | 7 | fun binarySearch(a: IntArray, x: Int): Int { 8 | val left = 0 9 | val right = a.size 10 | //write your code here 11 | 12 | return -1 13 | } 14 | 15 | fun linearSearch(a: IntArray, x: Int): Int { 16 | for (i in a.indices) { 17 | if (a[i] == x) return i 18 | } 19 | return -1 20 | } 21 | 22 | fun main(args: Array) { 23 | val scanner = FastScanner(System.`in`) 24 | val n = scanner.nextInt() 25 | val a = IntArray(n) 26 | for (i in 0 until n) { 27 | a[i] = scanner.nextInt() 28 | } 29 | val m = scanner.nextInt() 30 | val b = IntArray(m) 31 | for (i in 0 until m) { 32 | b[i] = scanner.nextInt() 33 | } 34 | for (i in 0 until m) { 35 | //replace with the call to binarySearch when implemented 36 | print(linearSearch(a, b[i]).toString() + " ") 37 | } 38 | } 39 | 40 | class FastScanner(stream: InputStream) { 41 | var br: BufferedReader = BufferedReader(InputStreamReader(stream)) 42 | var st: StringTokenizer? = null 43 | 44 | fun next(): String { 45 | while (st == null || !st!!.hasMoreTokens()) { 46 | try { 47 | st = StringTokenizer(br.readLine()) 48 | } catch (e: IOException) { 49 | e.printStackTrace() 50 | } 51 | } 52 | return st!!.nextToken() 53 | } 54 | 55 | fun nextInt() = next().toInt() 56 | } -------------------------------------------------------------------------------- /week4_divide_and_conquer/2_binary_search_duplicates/binary_search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | 7 | int binary_search(const vector &a, int x) { 8 | int left = 0, right = (int)a.size(); 9 | //write your code here 10 | } 11 | 12 | int linear_search(const vector &a, int x) { 13 | for (size_t i = 0; i < a.size(); ++i) { 14 | if (a[i] == x) return i; 15 | } 16 | return -1; 17 | } 18 | 19 | int main() { 20 | int n; 21 | std::cin >> n; 22 | vector a(n); 23 | for (size_t i = 0; i < a.size(); i++) { 24 | std::cin >> a[i]; 25 | } 26 | int m; 27 | std::cin >> m; 28 | vector b(m); 29 | for (int i = 0; i < m; ++i) { 30 | std::cin >> b[i]; 31 | } 32 | for (int i = 0; i < m; ++i) { 33 | //replace with the call to binary_search when implemented 34 | std::cout << linear_search(a, b[i]) << ' '; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/2_binary_search_duplicates/binary_search.js: -------------------------------------------------------------------------------- 1 | // by Alexander Nikolskiy 2 | 3 | const readline = require('readline'); 4 | const rl = readline.createInterface({ 5 | input: process.stdin, 6 | terminal: false 7 | }); 8 | 9 | process.stdin.setEncoding('utf8'); 10 | rl.once('line', line => { 11 | const arr = line.toString().split(' ').slice(1).map(Number); 12 | 13 | rl.once('line', line => { 14 | const keys = line.toString().split(' ').slice(1).map(Number); 15 | const result = []; 16 | 17 | for (let key of keys) { 18 | result.push(binarySearch(arr, key)); 19 | } 20 | 21 | const res = result.join(' '); 22 | const maxLength = 50000; 23 | 24 | for (let i = 0; i < res.length; i += maxLength) { 25 | process.stdout.write(res.slice(i, i + maxLength)); 26 | } 27 | 28 | process.stdout.write('\n'); 29 | process.exit(); 30 | }) 31 | }); 32 | 33 | function binarySearch(arr = [], key) { 34 | // write your code here 35 | } 36 | 37 | module.exports = binarySearch; 38 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/2_binary_search_duplicates/binary_search.py: -------------------------------------------------------------------------------- 1 | def binary_search(keys, query): 2 | # write your code here 3 | min_idx = 0 4 | max_idx = len(keys) - 1 5 | while min_idx <= max_idx: 6 | mid_idx = (min_idx + max_idx) // 2 7 | if keys[mid_idx] == query: 8 | if mid_idx - 1 < 0: 9 | return mid_idx 10 | if keys[mid_idx - 1] != query: 11 | return mid_idx 12 | max_idx = mid_idx - 1 13 | elif keys[mid_idx] > query: 14 | max_idx = mid_idx - 1 15 | else: 16 | min_idx = mid_idx + 1 17 | 18 | return -1 19 | 20 | 21 | 22 | if __name__ == '__main__': 23 | num_keys = int(input()) 24 | input_keys = list(map(int, input().split())) 25 | assert len(input_keys) == num_keys 26 | 27 | num_queries = int(input()) 28 | input_queries = list(map(int, input().split())) 29 | assert len(input_queries) == num_queries 30 | 31 | for q in input_queries: 32 | print(binary_search(input_keys, q), end=' ') 33 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/2_binary_search_duplicates/binary_search.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def binary_search(x, a) 5 | #write your code here 6 | -1 7 | end 8 | 9 | if __FILE__ == $0 10 | data = STDIN.read.split().map(&:to_i) 11 | n = data[0] 12 | a = data[1..n] 13 | m = data[n+1] 14 | data[n+2, m].each { |b| print("#{binary_search(b, a)} ") } 15 | puts "" 16 | end 17 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/3_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 | //write your code here 13 | return -1; 14 | } 15 | 16 | public static void main(String[] args) { 17 | FastScanner scanner = new FastScanner(System.in); 18 | int n = scanner.nextInt(); 19 | int[] a = new int[n]; 20 | for (int i = 0; i < n; i++) { 21 | a[i] = scanner.nextInt(); 22 | } 23 | if (getMajorityElement(a, 0, a.length) != -1) { 24 | System.out.println(1); 25 | } else { 26 | System.out.println(0); 27 | } 28 | } 29 | static class FastScanner { 30 | BufferedReader br; 31 | StringTokenizer st; 32 | 33 | FastScanner(InputStream stream) { 34 | try { 35 | br = new BufferedReader(new InputStreamReader(stream)); 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | String next() { 42 | while (st == null || !st.hasMoreTokens()) { 43 | try { 44 | st = new StringTokenizer(br.readLine()); 45 | } catch (IOException e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | return st.nextToken(); 50 | } 51 | 52 | int nextInt() { 53 | return Integer.parseInt(next()); 54 | } 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/3_majority_element/MajorityElement.kt: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader 2 | import java.io.IOException 3 | import java.io.InputStream 4 | import java.io.InputStreamReader 5 | import java.util.* 6 | 7 | fun getMajorityElement(a: IntArray, left: Int, right: Int): Int { 8 | if (left == right) return -1 9 | if (left + 1 == right) return a[left] 10 | //write your code here 11 | return -1 12 | } 13 | 14 | fun main(args: Array) { 15 | val scanner = FastScanner(System.`in`) 16 | val n = scanner.nextInt() 17 | val a = IntArray(n) 18 | for (i in 0 until n) { 19 | a[i] = scanner.nextInt() 20 | } 21 | if (getMajorityElement(a, 0, a.size) != -1) { 22 | println(1) 23 | } else { 24 | println(0) 25 | } 26 | } 27 | 28 | class FastScanner(stream: InputStream) { 29 | var br: BufferedReader = BufferedReader(InputStreamReader(stream)) 30 | var st: StringTokenizer? = null 31 | 32 | fun next(): String { 33 | while (st == null || !st!!.hasMoreTokens()) { 34 | try { 35 | st = StringTokenizer(br.readLine()) 36 | } catch (e: IOException) { 37 | e.printStackTrace() 38 | } 39 | } 40 | return st!!.nextToken() 41 | } 42 | 43 | fun nextInt() = next().toInt() 44 | } -------------------------------------------------------------------------------- /week4_divide_and_conquer/3_majority_element/by_learners/majority_element.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def get_majority_element(a, left, right) 5 | return -1 if left >= right 6 | return a[left] if right - left == 1 7 | 8 | # write your code here 9 | -1 10 | end 11 | 12 | if __FILE__ == $0 13 | n, *a = STDIN.read.split().map(&:to_i) 14 | answer = get_majority_element(a, 0, n) != -1 15 | puts "#{answer ? 1 : 0}" 16 | end 17 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/3_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 | //write your code here 11 | return -1; 12 | } 13 | 14 | int main() { 15 | int n; 16 | std::cin >> n; 17 | vector a(n); 18 | for (size_t i = 0; i < a.size(); ++i) { 19 | std::cin >> a[i]; 20 | } 21 | std::cout << (get_majority_element(a, 0, a.size()) != -1) << '\n'; 22 | } 23 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/3_majority_element/majority_element.py: -------------------------------------------------------------------------------- 1 | # def majority_element_naive(elements): 2 | # for e in elements: 3 | # if elements.count(e) > len(elements) / 2: 4 | # return 1 5 | 6 | # return 0 7 | 8 | 9 | def count_frequency(elements, left, right, key): 10 | count = 0 11 | for i in range(left, right+1): 12 | if elements[i] == key: 13 | count += 1 14 | return count 15 | 16 | def majority(elements, left, right): 17 | if left == right: 18 | return elements[left] 19 | 20 | mid = (left + right) // 2 21 | left_majority_element = majority(elements, left, mid) 22 | right_majority_element = majority(elements, mid+1, right) 23 | 24 | if left_majority_element == right_majority_element: 25 | return right_majority_element 26 | 27 | count_left = count_frequency(elements, left, right, left_majority_element) 28 | count_right = count_frequency(elements, left, right, right_majority_element) 29 | # print('count left', count_left) 30 | # print('count right', count_right) 31 | if count_left < count_right: 32 | return right_majority_element 33 | else: 34 | return left_majority_element 35 | 36 | 37 | def majority_element(elements): 38 | # O(nlogn) time 39 | # Property: the majority element of the initial array is also the majority element 40 | # of one of the two halves 41 | # break the initial array into halves and solve each half 42 | 43 | result = majority(elements, 0, len(elements) - 1) 44 | count = 0 45 | for e in elements: 46 | if e == result: 47 | count += 1 48 | if count > len(elements) // 2: 49 | return 1 50 | else: 51 | return 0 52 | 53 | 54 | if __name__ == '__main__': 55 | input_n = int(input()) 56 | input_elements = list(map(int, input().split())) 57 | assert len(input_elements) == input_n 58 | print(majority_element(input_elements)) 59 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/4_improving_quicksort/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 | //write your code here 9 | 10 | 11 | int m1 = l; 12 | int m2 = r; 13 | int[] m = {m1, m2}; 14 | return m; 15 | } 16 | 17 | private static int partition2(int[] a, int l, int r) { 18 | int x = a[l]; 19 | int j = l; 20 | for (int i = l + 1; i <= r; i++) { 21 | if (a[i] <= x) { 22 | j++; 23 | int t = a[i]; 24 | a[i] = a[j]; 25 | a[j] = t; 26 | } 27 | } 28 | int t = a[l]; 29 | a[l] = a[j]; 30 | a[j] = t; 31 | return j; 32 | } 33 | 34 | private static void randomizedQuickSort(int[] a, int l, int r) { 35 | if (l >= r) { 36 | return; 37 | } 38 | int k = random.nextInt(r - l + 1) + l; 39 | int t = a[l]; 40 | a[l] = a[k]; 41 | a[k] = t; 42 | //use partition3 43 | int m = partition2(a, l, r); 44 | randomizedQuickSort(a, l, m - 1); 45 | randomizedQuickSort(a, m + 1, r); 46 | } 47 | 48 | public static void main(String[] args) { 49 | FastScanner scanner = new FastScanner(System.in); 50 | int n = scanner.nextInt(); 51 | int[] a = new int[n]; 52 | for (int i = 0; i < n; i++) { 53 | a[i] = scanner.nextInt(); 54 | } 55 | randomizedQuickSort(a, 0, n - 1); 56 | for (int i = 0; i < n; i++) { 57 | System.out.print(a[i] + " "); 58 | } 59 | } 60 | 61 | static class FastScanner { 62 | BufferedReader br; 63 | StringTokenizer st; 64 | 65 | FastScanner(InputStream stream) { 66 | try { 67 | br = new BufferedReader(new InputStreamReader(stream)); 68 | } catch (Exception e) { 69 | e.printStackTrace(); 70 | } 71 | } 72 | 73 | String next() { 74 | while (st == null || !st.hasMoreTokens()) { 75 | try { 76 | st = new StringTokenizer(br.readLine()); 77 | } catch (IOException e) { 78 | e.printStackTrace(); 79 | } 80 | } 81 | return st.nextToken(); 82 | } 83 | 84 | int nextInt() { 85 | return Integer.parseInt(next()); 86 | } 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/4_improving_quicksort/Sorting.kt: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader 2 | import java.io.IOException 3 | import java.io.InputStream 4 | import java.io.InputStreamReader 5 | import java.util.* 6 | 7 | private val random = Random() 8 | 9 | fun partition3(a: IntArray, l: Int, r: Int): IntArray { 10 | //write your code here 11 | return intArrayOf(l, r) 12 | } 13 | 14 | fun partition2(a: IntArray, l: Int, r: Int): Int { 15 | val x = a[l] 16 | var j = l 17 | for (i in l + 1..r) { 18 | if (a[i] <= x) { 19 | j++ 20 | val t = a[i] 21 | a[i] = a[j] 22 | a[j] = t 23 | } 24 | } 25 | val t = a[l] 26 | a[l] = a[j] 27 | a[j] = t 28 | return j 29 | } 30 | 31 | fun randomizedQuickSort(a: IntArray, l: Int, r: Int) { 32 | if (l >= r) { 33 | return 34 | } 35 | val k = random.nextInt(r - l + 1) + l 36 | val t = a[l] 37 | a[l] = a[k] 38 | a[k] = t 39 | //use partition3 40 | val m = partition2(a, l, r) 41 | randomizedQuickSort(a, l, m - 1) 42 | randomizedQuickSort(a, m + 1, r) 43 | } 44 | 45 | fun main(args: Array) { 46 | val scanner = FastScanner(System.`in`) 47 | val n = scanner.nextInt() 48 | val a = IntArray(n) 49 | for (i in 0 until n) { 50 | a[i] = scanner.nextInt() 51 | } 52 | randomizedQuickSort(a, 0, n - 1) 53 | for (i in 0 until n) { 54 | print(a[i].toString() + " ") 55 | } 56 | } 57 | 58 | class FastScanner(stream: InputStream) { 59 | var br: BufferedReader = BufferedReader(InputStreamReader(stream)) 60 | var st: StringTokenizer? = null 61 | 62 | fun next(): String { 63 | while (st == null || !st!!.hasMoreTokens()) { 64 | try { 65 | st = StringTokenizer(br.readLine()) 66 | } catch (e: IOException) { 67 | e.printStackTrace() 68 | } 69 | } 70 | return st!!.nextToken() 71 | } 72 | 73 | fun nextInt() = next().toInt() 74 | } -------------------------------------------------------------------------------- /week4_divide_and_conquer/4_improving_quicksort/by_learners/sorting.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def partition3(a, l, r) 5 | #write your code here 6 | 7 | end 8 | 9 | def partition2(a, l, r) 10 | x = a[l] 11 | j = l 12 | (l + 1..r).each do |i| 13 | if a[i] <= x 14 | j += 1 15 | a[i], a[j] = a[j], a[i] 16 | end 17 | end 18 | a[l], a[j] = a[j], a[l] 19 | j 20 | end 21 | 22 | def randomized_quick_sort(a, l, r) 23 | return nil if l >= r 24 | 25 | k = rand(l..r) 26 | a[l], a[k] = a[k], a[l] 27 | # use partition3 28 | m = partition2(a, l, r) 29 | randomized_quick_sort(a, l, m - 1); 30 | randomized_quick_sort(a, m + 1, r); 31 | end 32 | 33 | if __FILE__ == $0 34 | n, *a = STDIN.read.split().map(&:to_i) 35 | randomized_quick_sort(a, 0, n - 1) 36 | puts "#{a.join(' ')}" 37 | end 38 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/4_improving_quicksort/sorting.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::swap; 7 | 8 | int partition2(vector &a, int l, int r) { 9 | int x = a[l]; 10 | int j = l; 11 | for (int i = l + 1; i <= r; i++) { 12 | if (a[i] <= x) { 13 | j++; 14 | swap(a[i], a[j]); 15 | } 16 | } 17 | swap(a[l], a[j]); 18 | return j; 19 | } 20 | 21 | void randomized_quick_sort(vector &a, int l, int r) { 22 | if (l >= r) { 23 | return; 24 | } 25 | 26 | int k = l + rand() % (r - l + 1); 27 | swap(a[l], a[k]); 28 | int m = partition2(a, l, r); 29 | 30 | randomized_quick_sort(a, l, m - 1); 31 | randomized_quick_sort(a, m + 1, r); 32 | } 33 | 34 | int main() { 35 | int n; 36 | std::cin >> n; 37 | vector a(n); 38 | for (size_t i = 0; i < a.size(); ++i) { 39 | std::cin >> a[i]; 40 | } 41 | randomized_quick_sort(a, 0, a.size() - 1); 42 | for (size_t i = 0; i < a.size(); ++i) { 43 | std::cout << a[i] << ' '; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/4_improving_quicksort/sorting.py: -------------------------------------------------------------------------------- 1 | from random import randint 2 | 3 | # O(nlogn) time 4 | def partition3(array, left, right): 5 | # write your code here 6 | pivot = array[left] 7 | 8 | low = left + 1 9 | high = right 10 | mid = left + 1 11 | while mid <= high: 12 | if array[mid] < pivot: 13 | array[mid], array[low] = array[low], array[mid] 14 | mid += 1 15 | low += 1 16 | elif array[mid] == pivot: 17 | mid += 1 18 | else: 19 | array[mid], array[high] = array[high], array[mid] 20 | high -= 1 21 | array[left], array[low-1] = array[low - 1], array[left] 22 | 23 | return low-1, high 24 | 25 | 26 | 27 | 28 | def randomized_quick_sort(array, left, right): 29 | if left >= right: 30 | return 31 | k = randint(left, right) 32 | array[left], array[k] = array[k], array[left] 33 | m1, m2 = partition3(array, left, right) 34 | randomized_quick_sort(array, left, m1 - 1) 35 | randomized_quick_sort(array, m2 + 1, right) 36 | 37 | 38 | if __name__ == '__main__': 39 | input_n = int(input()) 40 | elements = list(map(int, input().split())) 41 | assert len(elements) == input_n 42 | randomized_quick_sort(elements, 0, len(elements) - 1) 43 | print(*elements) 44 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/5_number_of_inversions/Inversions.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Inversions { 4 | 5 | private static long getNumberOfInversions(int[] a, int[] b, int left, int right) { 6 | long numberOfInversions = 0; 7 | if (right <= left + 1) { 8 | return numberOfInversions; 9 | } 10 | int ave = (left + right) / 2; 11 | numberOfInversions += getNumberOfInversions(a, b, left, ave); 12 | numberOfInversions += getNumberOfInversions(a, b, ave, right); 13 | //write your code here 14 | return numberOfInversions; 15 | } 16 | 17 | public static void main(String[] args) { 18 | Scanner scanner = new Scanner(System.in); 19 | int n = scanner.nextInt(); 20 | int[] a = new int[n]; 21 | for (int i = 0; i < n; i++) { 22 | a[i] = scanner.nextInt(); 23 | } 24 | int[] b = new int[n]; 25 | System.out.println(getNumberOfInversions(a, b, 0, a.length)); 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/5_number_of_inversions/Inversions.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getNumberOfInversions(a: IntArray, b: IntArray, left: Int, right: Int): Long { 4 | var numberOfInversions: Long = 0 5 | if (right <= left + 1) { 6 | return numberOfInversions 7 | } 8 | val ave = (left + right) / 2 9 | numberOfInversions += getNumberOfInversions(a, b, left, ave) 10 | numberOfInversions += getNumberOfInversions(a, b, ave, right) 11 | //write your code here 12 | return numberOfInversions 13 | } 14 | 15 | fun main(args: Array) { 16 | val scanner = Scanner(System.`in`) 17 | val n = scanner.nextInt() 18 | val a = IntArray(n) 19 | for (i in 0 until n) { 20 | a[i] = scanner.nextInt() 21 | } 22 | val b = IntArray(n) 23 | println(getNumberOfInversions(a, b, 0, a.size)) 24 | } -------------------------------------------------------------------------------- /week4_divide_and_conquer/5_number_of_inversions/by_learners/inversions.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | # helper function for faster copy 5 | # b[l..r - 1] = a[l..r] 6 | def copy(a, b, l, r) 7 | while l < r 8 | b[l] = a[l] 9 | l += 1 10 | end 11 | end 12 | 13 | def get_number_of_inversions(a, b, left, right) 14 | number_of_inversions = 0 15 | return 0 if right - left <= 1 16 | 17 | mid = left + (right - left) / 2 18 | number_of_inversions += get_number_of_inversions(a, b, left, mid) 19 | number_of_inversions += get_number_of_inversions(a, b, mid, right) 20 | #write your code here 21 | 22 | return number_of_inversions 23 | end 24 | 25 | if __FILE__ == $0 26 | n, *a = STDIN.read.split().map(&:to_i) 27 | b = Array.new(n, 0) 28 | puts get_number_of_inversions(a, b, 0, n) 29 | end 30 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/5_number_of_inversions/inversions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | long long get_number_of_inversions(vector &a, vector &b, size_t left, size_t right) { 7 | long long number_of_inversions = 0; 8 | if (right <= left + 1) return number_of_inversions; 9 | size_t ave = left + (right - left) / 2; 10 | number_of_inversions += get_number_of_inversions(a, b, left, ave); 11 | number_of_inversions += get_number_of_inversions(a, b, ave, right); 12 | //write your code here 13 | return number_of_inversions; 14 | } 15 | 16 | int main() { 17 | int n; 18 | std::cin >> n; 19 | vector a(n); 20 | for (size_t i = 0; i < a.size(); i++) { 21 | std::cin >> a[i]; 22 | } 23 | vector b(a.size()); 24 | std::cout << get_number_of_inversions(a, b, 0, a.size()) << '\n'; 25 | } 26 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/5_number_of_inversions/inversions.py: -------------------------------------------------------------------------------- 1 | from itertools import combinations 2 | 3 | 4 | 5 | # def inversions_naive(a): 6 | # number_of_inversions = 0 7 | # for i, j in combinations(range(len(a)), 2): 8 | # if a[i] > a[j]: 9 | # number_of_inversions += 1 10 | # return number_of_inversions 11 | count = 0 12 | 13 | def merge(left_half, right_half): 14 | """ 15 | See the illustration of merge sort method here 16 | https://www.geeksforgeeks.org/counting-inversions/ 17 | """ 18 | global count 19 | sorted_list = [] 20 | # count = 0 21 | # print('left_half', left_half) 22 | # print('right_half', right_half) 23 | while left_half and right_half: 24 | if left_half[0] <= right_half[0]: 25 | sorted_list.append(left_half[0]) 26 | left_half.pop(0) 27 | else: 28 | sorted_list.append(right_half[0]) 29 | count += len(left_half) 30 | right_half.pop(0) 31 | if left_half: 32 | sorted_list.extend(left_half) 33 | if right_half: 34 | sorted_list.extend(right_half) 35 | # print('count', count) 36 | return sorted_list 37 | 38 | def merge_sort(a, left, right): 39 | if left == right: 40 | return [a[left]] 41 | mid = (left + right) // 2 42 | left_half = merge_sort(a, left, mid) 43 | right_half = merge_sort(a, mid + 1, right) 44 | sorted_list = merge(left_half, right_half) 45 | return sorted_list 46 | 47 | 48 | 49 | def inversions(a): 50 | sorted_list = merge_sort(a, 0, len(a)-1) 51 | return count 52 | 53 | if __name__ == '__main__': 54 | input_n = int(input()) 55 | elements = list(map(int, input().split())) 56 | assert len(elements) == input_n 57 | print(inversions(elements)) 58 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/6_organizing_a_lottery/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 | 46 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/6_organizing_a_lottery/PointsAndSegments.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun fastCountSegments(starts: IntArray, ends: IntArray, points: IntArray): IntArray { 4 | //write your code here 5 | return IntArray(points.size) 6 | } 7 | 8 | fun naiveCountSegments(starts: IntArray, ends: IntArray, points: IntArray): IntArray { 9 | val cnt = IntArray(points.size) 10 | for (i in points.indices) { 11 | for (j in starts.indices) { 12 | if (starts[j] <= points[i] && points[i] <= ends[j]) { 13 | cnt[i]++ 14 | } 15 | } 16 | } 17 | return cnt 18 | } 19 | 20 | fun main(args: Array) { 21 | val scanner = Scanner(System.`in`) 22 | val n: Int 23 | val m: Int 24 | n = scanner.nextInt() 25 | m = scanner.nextInt() 26 | val starts = IntArray(n) 27 | val ends = IntArray(n) 28 | val points = IntArray(m) 29 | for (i in 0 until n) { 30 | starts[i] = scanner.nextInt() 31 | ends[i] = scanner.nextInt() 32 | } 33 | for (i in 0 until m) { 34 | points[i] = scanner.nextInt() 35 | } 36 | //use fastCountSegments 37 | val cnt = naiveCountSegments(starts, ends, points) 38 | for (x in cnt) { 39 | print(x.toString() + " ") 40 | } 41 | } -------------------------------------------------------------------------------- /week4_divide_and_conquer/6_organizing_a_lottery/by_learners/points_and_segments.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | Segment = Struct.new("Segment", :a, :b) do 5 | def contains?(point) 6 | a <= point and point <= b 7 | end 8 | end 9 | 10 | def fast_count_segments(segments, points) 11 | count = Array.new(points.size, 0) 12 | # write your code here 13 | count 14 | end 15 | 16 | def naive_count_segments(segments, points) 17 | points.map { |point| segments.count { |s| s.contains?(point) } } 18 | end 19 | 20 | if __FILE__ == $0 21 | data = STDIN.read.split().map(&:to_i) 22 | s, p = data[0], data[1] 23 | segments = data[2..2*s+1].each_slice(2).to_a.map { |e| Segment.new(e[0], e[1]) } 24 | points = data[2*s+2..-1] 25 | # replace naive with fast 26 | puts naive_count_segments(segments, points).join(' ') 27 | end 28 | 29 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/6_organizing_a_lottery/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 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/6_organizing_a_lottery/points_and_segments.py: -------------------------------------------------------------------------------- 1 | from sys import stdin 2 | from random import randint 3 | 4 | def is_less(a, b): 5 | if a[0] < b[0]: 6 | return True 7 | elif a[0] > b[0]: 8 | return False 9 | else: 10 | if a[1] < b[1]: 11 | return True 12 | else: 13 | return False 14 | 15 | def is_equal(a, b): 16 | if a[0] == b[0] and a[1] == b[1]: 17 | return True 18 | return False 19 | 20 | 21 | def partition3(array, left, right): 22 | # write your code here 23 | pivot = array[left] 24 | 25 | low = left + 1 26 | high = right 27 | mid = left + 1 28 | while mid <= high: 29 | # if array[mid] < pivot: 30 | if is_less(array[mid], pivot): 31 | array[mid], array[low] = array[low], array[mid] 32 | mid += 1 33 | low += 1 34 | # elif array[mid] == pivot: 35 | elif is_equal(array[mid], pivot): 36 | mid += 1 37 | elif not is_less(array[mid], pivot) and not is_equal(array[mid], pivot): 38 | array[mid], array[high] = array[high], array[mid] 39 | high -= 1 40 | array[left], array[low-1] = array[low - 1], array[left] 41 | 42 | return low-1, high 43 | 44 | def randomized_quick_sort(array, left, right): 45 | if left >= right: 46 | return 47 | k = randint(left, right) # choose the pivot index 48 | array[left], array[k] = array[k], array[left] # swap the pivot to left element, which is the pivot position 49 | m1, m2 = partition3(array, left, right) 50 | randomized_quick_sort(array, left, m1 - 1) 51 | randomized_quick_sort(array, m2 + 1, right) 52 | 53 | # def points_cover_naive(starts, ends, points): 54 | # assert len(starts) == len(ends) 55 | # count = [0] * len(points) 56 | 57 | # for index, point in enumerate(points): 58 | # for start, end in zip(starts, ends): 59 | # if start <= point <= end: 60 | # count[index] += 1 61 | 62 | # return count 63 | 64 | def points_cover(starts, ends, points): 65 | """ 66 | Explaination: https://towardsdatascience.com/course-1-algorithmic-toolbox-part-3-divide-and-conquer-dd9022bfa2c0 67 | Reference: https://gist.github.com/jseow5177/9360ba17eb59551e32985cbf66ef94b3 68 | """ 69 | 70 | LEFT, POINT, RIGHT = 1, 2, 3 71 | new_list = [] 72 | for start in starts: 73 | new_list.append((start, LEFT)) 74 | for end in ends: 75 | new_list.append((end, RIGHT)) 76 | for point in points: 77 | new_list.append((point, POINT)) 78 | 79 | randomized_quick_sort(new_list, 0, len(new_list) - 1) 80 | # new_list now is sorted 81 | points_count = [0] * len(points) 82 | 83 | # a dictionary to keep the indices of points 84 | points_index = {} 85 | for i, p in enumerate(points): 86 | if p not in points_index: 87 | points_index[p] = [i] 88 | else: 89 | points_index[p].append(i) 90 | 91 | count = 0 92 | for element in new_list: 93 | value, label = element[0], element[1] 94 | if label == LEFT: 95 | count += 1 96 | elif label == POINT: 97 | for i in points_index[value]: 98 | points_count[i] = count 99 | elif label == RIGHT: 100 | count -= 1 101 | 102 | return points_count 103 | 104 | 105 | 106 | if __name__ == '__main__': 107 | data = list(map(int, stdin.read().split())) 108 | n, m = data[0], data[1] 109 | input_starts, input_ends = data[2:2 * n + 2:2], data[3:2 * n + 2:2] 110 | input_points = data[2 * n + 2:] 111 | 112 | output_count = points_cover(input_starts, input_ends, input_points) 113 | print(*output_count) 114 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/7_closest_points/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 | 47 | static String next() { 48 | while (!tok.hasMoreTokens()) { 49 | String w = null; 50 | try { 51 | w = reader.readLine(); 52 | } catch (Exception e) { 53 | e.printStackTrace(); 54 | } 55 | if (w == null) 56 | return null; 57 | tok = new StringTokenizer(w); 58 | } 59 | return tok.nextToken(); 60 | } 61 | 62 | static int nextInt() { 63 | return Integer.parseInt(next()); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/7_closest_points/Closest.kt: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader 2 | import java.io.InputStreamReader 3 | import java.io.PrintWriter 4 | import java.util.* 5 | 6 | var tok = StringTokenizer("") 7 | 8 | class Point(var x: Long, var y: Long) : Comparable { 9 | override fun compareTo(other: Point): Int { 10 | return if (other.y == y) java.lang.Long.signum(x - other.x) 11 | else java.lang.Long.signum(y - other.y) 12 | } 13 | } 14 | 15 | fun minimalDistance(x: IntArray, y: IntArray): Double { 16 | //write your code here 17 | return java.lang.Double.POSITIVE_INFINITY 18 | } 19 | 20 | fun main(args: Array) { 21 | val writer = PrintWriter(System.out) 22 | val reader = BufferedReader(InputStreamReader(System.`in`)) 23 | val n = nextInt(reader) 24 | val x = IntArray(n) 25 | val y = IntArray(n) 26 | for (i in 0 until n) { 27 | x[i] = nextInt(reader) 28 | y[i] = nextInt(reader) 29 | } 30 | println(minimalDistance(x, y)) 31 | writer.close() 32 | } 33 | 34 | 35 | fun next(reader: BufferedReader): String? { 36 | while (!tok.hasMoreTokens()) { 37 | var w: String? = null 38 | try { 39 | w = reader.readLine() 40 | } catch (e: Exception) { 41 | e.printStackTrace() 42 | } 43 | 44 | if (w == null) 45 | return null 46 | tok = StringTokenizer(w) 47 | } 48 | return tok.nextToken() 49 | } 50 | 51 | fun nextInt(reader: BufferedReader): Int { 52 | return next(reader)!!.toInt() 53 | } -------------------------------------------------------------------------------- /week4_divide_and_conquer/7_closest_points/by_learners/closest.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def min(a, b) 5 | a < b ? a : b 6 | end 7 | 8 | def minimum_distance(x, y) 9 | # write your code here 10 | Math.sqrt(10 ** 36) 11 | end 12 | 13 | if __FILE__ == $0 14 | data = STDIN.read.split().map(&:to_i) 15 | n = data.size - 1 16 | x = (1..n).step(2).map { |i| data[i] } 17 | y = (2..n).step(2).map { |i| data[i] } 18 | puts "#{'%.4f' % minimum_distance(x, y)}" 19 | end -------------------------------------------------------------------------------- /week4_divide_and_conquer/7_closest_points/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 | -------------------------------------------------------------------------------- /week4_divide_and_conquer/7_closest_points/closest.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | from itertools import combinations 3 | from math import sqrt 4 | # import sys 5 | 6 | 7 | Point = namedtuple('Point', 'x y') 8 | 9 | 10 | def distance_squared(first_point, second_point): 11 | return (first_point.x - second_point.x) ** 2 + (first_point.y - second_point.y) ** 2 12 | 13 | 14 | # def minimum_distance_squared_naive(points): 15 | # min_distance_squared = float("inf") 16 | 17 | # for p, q in combinations(points, 2): 18 | # min_distance_squared = min(min_distance_squared, 19 | # distance_squared(p, q)) 20 | 21 | # return min_distance_squared 22 | 23 | def closest_pair(X, Y): # X, Y are already sorted 24 | # X is sorted points based on x coordinates 25 | # Y is sorted points based on y coordinates 26 | # base cases 27 | # print() 28 | # print('X', X) 29 | # print('Y', Y) 30 | if len(X) == 2: 31 | return distance_squared(X[0], X[1]) 32 | if len(X) == 3: 33 | return min(distance_squared(X[0], X[1]), distance_squared(X[0], X[2]), distance_squared(X[1], X[2])) 34 | 35 | 36 | mid = len(X) // 2 if len(X) % 2 == 0 else (len(X) // 2) + 1 37 | # print('X[mid]', X[mid]) 38 | d1 = closest_pair(X[:mid], Y[:mid]) 39 | # print('d1', d1) 40 | d2 = closest_pair(X[mid:], Y[mid:]) 41 | # print('d2', d2) 42 | d = min(d1, d2) 43 | # print('d', d) 44 | # print('X[mid].x - d', X[mid].x - d) 45 | # print('X[mid].x + d', X[mid].x + d) 46 | S = [point for point in Y if ((point.x <= X[mid].x + d) and (point.x >= X[mid].x - d))] 47 | # print('S', S) 48 | for i in range(len(S)): 49 | for j in range(1, 8): 50 | if i + j < len(S): 51 | d = min(d, distance_squared(S[i], S[i+j])) 52 | 53 | return d 54 | 55 | def minimum_distance_squared(points): 56 | """ 57 | References: 58 | https://www.youtube.com/watch?v=6u_hWxbOc7E&ab_channel=LingQi 59 | https://towardsdatascience.com/course-1-algorithmic-toolbox-part-3-divide-and-conquer-dd9022bfa2c0 60 | [CLRS] textbook, [section 33.4] about this problem 61 | [CLRS] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein. Introduction to Algorithms (3rd Edition). MIT Press and McGraw-Hill. 2009. 62 | 63 | """ 64 | X = sorted(points, key=lambda point: point.x) 65 | Y = sorted(points, key=lambda point: point.y) 66 | return closest_pair(X, Y) 67 | 68 | 69 | 70 | 71 | 72 | if __name__ == '__main__': 73 | input_n = int(input()) 74 | input_points = [] 75 | for _ in range(input_n): 76 | x, y = map(int, input().split()) 77 | input_point = Point(x, y) 78 | input_points.append(input_point) 79 | 80 | print("{0:.9f}".format(sqrt(minimum_distance_squared(input_points)))) 81 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/1_money_change_again/ChangeDP.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class ChangeDP { 4 | private static int getChange(int m) { 5 | //write your code here 6 | return m / 4; 7 | } 8 | 9 | public static void main(String[] args) { 10 | Scanner scanner = new Scanner(System.in); 11 | int m = scanner.nextInt(); 12 | System.out.println(getChange(m)); 13 | 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/1_money_change_again/ChangeDP.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getChange(m: Int): Int { 4 | //write your code here 5 | return m / 4 6 | } 7 | 8 | fun main(args: Array) { 9 | val scanner = Scanner(System.`in`) 10 | val m = scanner.nextInt() 11 | println(getChange(m)) 12 | } -------------------------------------------------------------------------------- /week5_dynamic_programming1/1_money_change_again/change_dp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int get_change(int m) { 4 | //write your code here 5 | return m / 4; 6 | } 7 | 8 | int main() { 9 | int m; 10 | std::cin >> m; 11 | std::cout << get_change(m) << '\n'; 12 | } 13 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/1_money_change_again/change_dp.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def change(money): 5 | # write your code here 6 | # denominations: 1, 3, 4 7 | # print('money', money) 8 | min_coins = [0] * (money+1) 9 | for m in range(1, money+1): 10 | min_coins[m] = sys.maxsize 11 | for coin in [1, 3, 4]: 12 | # print('m', m) 13 | # print('coin', coin) 14 | if m >= coin: 15 | # print('a') 16 | # print('money - coin', money-coin) # wrong, money -> m 17 | num_coins = min_coins[m - coin] + 1 18 | if num_coins < min_coins[m]: 19 | min_coins[m] = num_coins 20 | # print(min_coins) 21 | return min_coins[-1] 22 | 23 | 24 | if __name__ == '__main__': 25 | m = int(input()) 26 | print(change(m)) 27 | 28 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/1_money_change_again/pseudocode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week5_dynamic_programming1/1_money_change_again/pseudocode.png -------------------------------------------------------------------------------- /week5_dynamic_programming1/2_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 | public static void main(String[] args) { 21 | Scanner scanner = new Scanner(System.in); 22 | int n = scanner.nextInt(); 23 | List sequence = optimal_sequence(n); 24 | System.out.println(sequence.size() - 1); 25 | for (Integer x : sequence) { 26 | System.out.print(x + " "); 27 | } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/2_primitive_calculator/PrimitiveCalculator.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun optimalSequence(n: Int): List { 4 | var m = n 5 | val sequence = ArrayList() 6 | while (m >= 1) { 7 | sequence.add(m) 8 | when { 9 | m % 3 == 0 -> m /= 3 10 | m % 2 == 0 -> m /= 2 11 | else -> m -= 1 12 | } 13 | } 14 | return sequence.reversed() 15 | } 16 | 17 | fun main(args: Array) { 18 | val scanner = Scanner(System.`in`) 19 | val n = scanner.nextInt() 20 | val sequence = optimalSequence(n) 21 | println(sequence.size - 1) 22 | for (x in sequence) { 23 | print(x.toString() + " ") 24 | } 25 | } -------------------------------------------------------------------------------- /week5_dynamic_programming1/2_primitive_calculator/by_learners/primitive_calculator.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def minimum_operations(n) 5 | # change this code 6 | sequence = [] 7 | while n >= 1 8 | sequence.push(n) 9 | case 10 | when n % 3 == 0 11 | n /= 3 12 | when n % 2 == 0 13 | n /= 2 14 | else 15 | n -= 1 16 | end 17 | end 18 | sequence.reverse 19 | 20 | end 21 | 22 | if __FILE__ == $0 23 | n = gets.to_i 24 | answer = minimum_operations(n) 25 | puts answer.length - 1 26 | puts answer.join(' ') 27 | end -------------------------------------------------------------------------------- /week5_dynamic_programming1/2_primitive_calculator/primitive_calculator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | 7 | vector optimal_sequence(int n) { 8 | std::vector sequence; 9 | while (n >= 1) { 10 | sequence.push_back(n); 11 | if (n % 3 == 0) { 12 | n /= 3; 13 | } else if (n % 2 == 0) { 14 | n /= 2; 15 | } else { 16 | n = n - 1; 17 | } 18 | } 19 | reverse(sequence.begin(), sequence.end()); 20 | return sequence; 21 | } 22 | 23 | int main() { 24 | int n; 25 | std::cin >> n; 26 | vector sequence = optimal_sequence(n); 27 | std::cout << sequence.size() - 1 << std::endl; 28 | for (size_t i = 0; i < sequence.size(); ++i) { 29 | std::cout << sequence[i] << " "; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/2_primitive_calculator/primitive_calculator.py: -------------------------------------------------------------------------------- 1 | 2 | def compute_operations(n): 3 | if n == 1: 4 | return [1] 5 | cache = [1, 0, 1, 1] + [0]*(n-3) # initialized #operations of each i value 6 | for i in range(4, len(cache)): 7 | if i % 2 == 0 and i % 3 != 0: 8 | cache[i] = min(cache[i // 2] + 1, cache[i-1] + 1) 9 | 10 | if i % 2 != 0 and i % 3 == 0: 11 | cache[i] = min(cache[i // 3] + 1, cache[i-1] + 1) 12 | 13 | if i % 2 == 0 and i % 3 == 0: 14 | cache[i] = min(cache[i//2] + 1, cache[i // 3] + 1, cache[i-1] + 1) 15 | 16 | if i % 2 != 0 and i % 3 != 0: 17 | cache[i] = cache[i-1] + 1 18 | # cache[-1] is #operations needed for value n 19 | # backtrack the cache in the following 20 | result = [1] * (cache[-1] + 1) 21 | for i in range(cache[-1]): 22 | result[-i-1] = n 23 | if n % 2 == 0 and n % 3 != 0: 24 | if cache[n] == cache[n//2] + 1: 25 | n = n // 2 26 | else: 27 | n = n - 1 28 | continue 29 | 30 | if n % 3 == 0 and n % 2 != 0: 31 | if cache[n] == cache[n//3] + 1: 32 | n = n // 3 33 | else: 34 | n = n - 1 35 | continue 36 | 37 | if n % 2 != 0 and n % 3 != 0: 38 | n = n - 1 39 | continue 40 | 41 | if n % 2 == 0 and n % 3 == 0: 42 | if cache[n] == cache[n//2] + 1: 43 | n = n // 2 44 | elif cache[n] == cache[n//3] + 1: 45 | n = n // 3 46 | elif cache[n] == cache[n-1] + 1: 47 | n = n - 1 48 | continue 49 | 50 | return result 51 | 52 | 53 | 54 | 55 | 56 | if __name__ == '__main__': 57 | input_n = int(input()) 58 | output_sequence = compute_operations(input_n) 59 | # print(output_sequence) 60 | print(len(output_sequence) - 1) 61 | print(*output_sequence) 62 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/3_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 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/3_edit_distance/EditDistance.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getEditDistance(s: String, t: String): Int { 4 | //write your code here 5 | return 0 6 | } 7 | 8 | fun main(args: Array) { 9 | val scan = Scanner(System.`in`) 10 | 11 | val s = scan.next() 12 | val t = scan.next() 13 | 14 | println(getEditDistance(s, t)) 15 | } -------------------------------------------------------------------------------- /week5_dynamic_programming1/3_edit_distance/by_learners/edit_distance.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def edit_distance(a, b) 5 | # write your code here 6 | 0 7 | end 8 | 9 | if __FILE__ == $0 10 | a, b = gets, gets 11 | puts edit_distance(a, b) 12 | end 13 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/3_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 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/3_edit_distance/edit_distance.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def edit_distance(first_string, second_string): 4 | A = list(first_string) 5 | B = list(second_string) 6 | 7 | # D = [[0] * (len(B) + 1)] * (len(A) + 1) # It's gonna generate the wrong answer!!! 8 | D = [[0]*(len(B) + 1) for _ in range(len(A) + 1)] 9 | D[0] = [i for i in range(len(D[0]))] 10 | for i in range(len(D)): 11 | D[i][0] = i 12 | # print(D) 13 | for j in range(len(B)): # column-wise traversal 14 | for i in range(len(A)): 15 | # print('i + 1', i+1) 16 | # print('j', j) 17 | insertion = D[i + 1][j] + 1 18 | deletion = D[i][j + 1] + 1 19 | match = D[i][j] 20 | mismatch = D[i][j] + 1 21 | 22 | if A[i] == B[j]: 23 | D[i+1][j+1] = min(insertion, deletion, match) 24 | 25 | else: 26 | D[i+1][j+1] = min(insertion, deletion, mismatch) 27 | return D[-1][-1] 28 | 29 | 30 | if __name__ == "__main__": 31 | print(edit_distance(input(), input())) 32 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/3_edit_distance/pseudocode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week5_dynamic_programming1/3_edit_distance/pseudocode.png -------------------------------------------------------------------------------- /week5_dynamic_programming1/3_edit_distance/test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 3, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "['s', 'h', 'o', 'r', 't']\n", 13 | "['p', 'o', 'r', 't', 's']\n" 14 | ] 15 | } 16 | ], 17 | "source": [ 18 | "A = list('short')\n", 19 | "B = list('ports')\n", 20 | "print(A)\n", 21 | "print(B)" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 24, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "data": { 31 | "text/plain": [ 32 | "[[0, 0, 0, 0, 0, 0],\n", 33 | " [0, 0, 0, 0, 0, 0],\n", 34 | " [0, 0, 0, 0, 0, 0],\n", 35 | " [0, 0, 0, 0, 0, 0],\n", 36 | " [0, 0, 0, 0, 0, 0],\n", 37 | " [0, 0, 0, 0, 0, 0]]" 38 | ] 39 | }, 40 | "execution_count": 24, 41 | "metadata": {}, 42 | "output_type": "execute_result" 43 | } 44 | ], 45 | "source": [ 46 | "D = [[0] * 6] * 6\n", 47 | "D" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 25, 53 | "metadata": {}, 54 | "outputs": [ 55 | { 56 | "data": { 57 | "text/plain": [ 58 | "[[1, 0, 0, 0, 0, 0],\n", 59 | " [1, 0, 0, 0, 0, 0],\n", 60 | " [1, 0, 0, 0, 0, 0],\n", 61 | " [1, 0, 0, 0, 0, 0],\n", 62 | " [1, 0, 0, 0, 0, 0],\n", 63 | " [1, 0, 0, 0, 0, 0]]" 64 | ] 65 | }, 66 | "execution_count": 25, 67 | "metadata": {}, 68 | "output_type": "execute_result" 69 | } 70 | ], 71 | "source": [ 72 | "D[0][0] = 1\n", 73 | "D" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [] 82 | } 83 | ], 84 | "metadata": { 85 | "kernelspec": { 86 | "display_name": "Python 3.9.12 ('son')", 87 | "language": "python", 88 | "name": "python3" 89 | }, 90 | "language_info": { 91 | "codemirror_mode": { 92 | "name": "ipython", 93 | "version": 3 94 | }, 95 | "file_extension": ".py", 96 | "mimetype": "text/x-python", 97 | "name": "python", 98 | "nbconvert_exporter": "python", 99 | "pygments_lexer": "ipython3", 100 | "version": "3.9.12" 101 | }, 102 | "orig_nbformat": 4, 103 | "vscode": { 104 | "interpreter": { 105 | "hash": "a721664eb6b905a2e6c3ffc0132565e26c8b8df5580e05ce3e4cfb80dac08bae" 106 | } 107 | } 108 | }, 109 | "nbformat": 4, 110 | "nbformat_minor": 2 111 | } 112 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/4_longest_common_subsequence_of_two_sequences/LCS2.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class LCS2 { 4 | 5 | private static int lcs2(int[] a, int[] b) { 6 | //Write your code here 7 | return Math.min(a.length, b.length); 8 | } 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | int n = scanner.nextInt(); 13 | int[] a = new int[n]; 14 | for (int i = 0; i < n; i++) { 15 | a[i] = scanner.nextInt(); 16 | } 17 | 18 | int m = scanner.nextInt(); 19 | int[] b = new int[m]; 20 | for (int i = 0; i < m; i++) { 21 | b[i] = scanner.nextInt(); 22 | } 23 | 24 | System.out.println(lcs2(a, b)); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/4_longest_common_subsequence_of_two_sequences/LCS2.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | import kotlin.math.min 3 | 4 | fun lcs2(a: IntArray, b: IntArray): Int { 5 | //Write your code here 6 | return min(a.size, b.size) 7 | } 8 | 9 | fun main(args: Array) { 10 | val scanner = Scanner(System.`in`) 11 | val n = scanner.nextInt() 12 | val a = IntArray(n) 13 | for (i in 0 until n) { 14 | a[i] = scanner.nextInt() 15 | } 16 | 17 | val m = scanner.nextInt() 18 | val b = IntArray(m) 19 | for (i in 0 until m) { 20 | b[i] = scanner.nextInt() 21 | } 22 | 23 | println(lcs2(a, b)) 24 | } -------------------------------------------------------------------------------- /week5_dynamic_programming1/4_longest_common_subsequence_of_two_sequences/lcs2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | int lcs2(vector &a, vector &b) { 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 n; 13 | std::cin >> n; 14 | vector a(n); 15 | for (size_t i = 0; i < n; i++) { 16 | std::cin >> a[i]; 17 | } 18 | 19 | size_t m; 20 | std::cin >> m; 21 | vector b(m); 22 | for (size_t i = 0; i < m; i++) { 23 | std::cin >> b[i]; 24 | } 25 | 26 | std::cout << lcs2(a, b) << std::endl; 27 | } 28 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/4_longest_common_subsequence_of_two_sequences/lcs2.py: -------------------------------------------------------------------------------- 1 | def lcs2(first_sequence, second_sequence): 2 | # Goal: Maximizing the alignment score (muy = 0, sigma = 0) = Finding the maximum matches 3 | A = list(first_sequence) 4 | B = list(second_sequence) 5 | 6 | D = [[0]*(len(B)+1) for _ in range(len(A) + 1)] 7 | 8 | for i in range(len(A)): # row-wise traversal 9 | for j in range(len(B)): 10 | insertion = D[i+1][j] 11 | deletion = D[i][j+1] 12 | mismatch = D[i][j] 13 | match = D[i][j] + 1 14 | 15 | if A[i] == B[j]: 16 | D[i+1][j+1] = max(insertion, deletion, match) 17 | else: 18 | D[i+1][j+1] = max(insertion, deletion, mismatch) 19 | 20 | return D[-1][-1] 21 | 22 | 23 | if __name__ == '__main__': 24 | n = int(input()) 25 | a = list(map(int, input().split())) 26 | assert len(a) == n 27 | 28 | m = int(input()) 29 | b = list(map(int, input().split())) 30 | assert len(b) == m 31 | 32 | print(lcs2(a, b)) 33 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/5_longest_common_subsequence_of_three_sequences/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 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/5_longest_common_subsequence_of_three_sequences/LCS3.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | import kotlin.math.min 3 | 4 | fun lcs3(a: IntArray, b: IntArray, c: IntArray): Int { 5 | //Write your code here 6 | return min(min(a.size, b.size), c.size) 7 | } 8 | 9 | fun main(args: Array) { 10 | val scanner = Scanner(System.`in`) 11 | val an = scanner.nextInt() 12 | val a = IntArray(an) 13 | for (i in 0 until an) { 14 | a[i] = scanner.nextInt() 15 | } 16 | val bn = scanner.nextInt() 17 | val b = IntArray(bn) 18 | for (i in 0 until bn) { 19 | b[i] = scanner.nextInt() 20 | } 21 | val cn = scanner.nextInt() 22 | val c = IntArray(cn) 23 | for (i in 0 until cn) { 24 | c[i] = scanner.nextInt() 25 | } 26 | println(lcs3(a, b, c)) 27 | } -------------------------------------------------------------------------------- /week5_dynamic_programming1/5_longest_common_subsequence_of_three_sequences/by_learners/lcs3.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def lcs3(a, b, c) 5 | # write your code here 6 | [a.size, b.size, c.size].min 7 | end 8 | 9 | if __FILE__ == $0 10 | data = STDIN.read.split().map(&:to_i) 11 | n = data[0] 12 | a = data[1..n] 13 | m = data[n+1] 14 | b = data[n+2..n+1+m] 15 | c = data[n+3+m..-1] 16 | puts lcs3(a, b, c) 17 | end 18 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/5_longest_common_subsequence_of_three_sequences/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 | -------------------------------------------------------------------------------- /week5_dynamic_programming1/5_longest_common_subsequence_of_three_sequences/lcs3.py: -------------------------------------------------------------------------------- 1 | # import numpy as np 2 | 3 | def lcs3(first_sequence, second_sequence, third_sequence): 4 | # Goal: Maximizing the alignment score (muy = 0, sigma = 0) = Finding the maximum matches 5 | A = list(first_sequence) 6 | B = list(second_sequence) 7 | C = list(third_sequence) 8 | 9 | D = [[[0]*(len(C)+1) for _ in range(len(B)+1)] for _ in range(len(A) + 1)] 10 | # print(np.array(D).shape) 11 | for i in range(len(A)): # row-wise traversal 12 | for j in range(len(B)): 13 | for k in range(len(C)): 14 | indel1 = D[i+1][j][k] 15 | indel2 = D[i][j+1][k] 16 | indel3 = D[i][j][k+1] 17 | 18 | indel4 = D[i+1][j+1][k] 19 | indel5 = D[i][j+1][k+1] 20 | indel6 = D[i+1][j][k+1] 21 | 22 | mismatch = D[i][j][k] 23 | match = D[i][j][k] + 1 24 | 25 | if A[i] == B[j] and A[i] == C[k]: 26 | D[i+1][j+1][k+1] = max(indel1, indel2, indel3, indel4, indel5, indel6, match) 27 | else: 28 | D[i+1][j+1][k+1] = max(indel1, indel2, indel3, indel4, indel5, indel6, mismatch) 29 | 30 | return D[-1][-1][-1] 31 | 32 | if __name__ == '__main__': 33 | n = int(input()) 34 | a = list(map(int, input().split())) 35 | assert len(a) == n 36 | 37 | m = int(input()) 38 | b = list(map(int, input().split())) 39 | assert len(b) == m 40 | 41 | q = int(input()) 42 | c = list(map(int, input().split())) 43 | assert len(c) == q 44 | 45 | print(lcs3(a, b, c)) 46 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/1_maximum_amount_of_gold/Knapsack.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Knapsack { 4 | static int optimalWeight(int W, int[] w) { 5 | //write you code here 6 | int result = 0; 7 | for (int i = 0; i < w.length; i++) { 8 | if (result + w[i] <= W) { 9 | result += w[i]; 10 | } 11 | } 12 | return result; 13 | } 14 | 15 | public static void main(String[] args) { 16 | Scanner scanner = new Scanner(System.in); 17 | int W, n; 18 | W = scanner.nextInt(); 19 | n = scanner.nextInt(); 20 | int[] w = new int[n]; 21 | for (int i = 0; i < n; i++) { 22 | w[i] = scanner.nextInt(); 23 | } 24 | System.out.println(optimalWeight(W, w)); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/1_maximum_amount_of_gold/Knapsack.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun optimalWeight(w: Int, array: IntArray): Int { 4 | //write you code here 5 | var result = 0 6 | for (i in array.indices) { 7 | if (result + array[i] <= w) { 8 | result += array[i] 9 | } 10 | } 11 | return result 12 | } 13 | 14 | fun main(args: Array) { 15 | val scanner = Scanner(System.`in`) 16 | val w: Int 17 | val n: Int 18 | w = scanner.nextInt() 19 | n = scanner.nextInt() 20 | val array = IntArray(n) 21 | for (i in 0 until n) { 22 | array[i] = scanner.nextInt() 23 | } 24 | println(optimalWeight(w, array)) 25 | } -------------------------------------------------------------------------------- /week6_dynamic_programming2/1_maximum_amount_of_gold/by_learners/knapsack.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | def optimal_weight(w, weights) 5 | # write your code here 6 | result = 0 7 | weights.each { |weight| result += weight if result + weight <= w } 8 | result 9 | end 10 | 11 | if __FILE__ == $0 12 | w, _, *weights = STDIN.read.split().map(&:to_i) 13 | puts optimal_weight(w, weights) 14 | end 15 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/1_maximum_amount_of_gold/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 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/1_maximum_amount_of_gold/knapsack.py: -------------------------------------------------------------------------------- 1 | from sys import stdin 2 | 3 | 4 | def maximum_gold(capacity, weights): 5 | # capacity represented W 6 | # weights represented values 7 | # initilizaing values such that all value(0, j) = 0 (no weights) and value(w, 0) = 0 (no items) 8 | value = [[0]*(len(weights) + 1) for _ in range(capacity + 1)] 9 | for i in range(len(weights)): # for any item i 10 | for w in range(capacity): # for any capacity w 11 | value[w+1][i+1] = value[w+1][i] 12 | if weights[i] <= w+1: 13 | val = value[(w+1) - weights[i]][i] + weights[i] 14 | if val > value[w+1][i+1]: 15 | value[w+1][i+1] = val 16 | return value[-1][-1] 17 | 18 | 19 | 20 | 21 | if __name__ == '__main__': 22 | input_capacity, n, *input_weights = list(map(int, stdin.read().split())) 23 | assert len(input_weights) == n 24 | 25 | print(maximum_gold(input_capacity, input_weights)) 26 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/1_maximum_amount_of_gold/pseudocode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week6_dynamic_programming2/1_maximum_amount_of_gold/pseudocode.png -------------------------------------------------------------------------------- /week6_dynamic_programming2/2_partitioning_souvenirs/Partition3.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | 4 | public class Partition3 { 5 | private static int partition3(int[] A) { 6 | //write your code here 7 | return 0; 8 | } 9 | 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | int n = scanner.nextInt(); 13 | int[] A = new int[n]; 14 | for (int i = 0; i < n; i++) { 15 | A[i] = scanner.nextInt(); 16 | } 17 | System.out.println(partition3(A)); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/2_partitioning_souvenirs/Partition3.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun partition3(array: IntArray): Int { 4 | //write your code here 5 | return 0 6 | } 7 | 8 | fun main(args: Array) { 9 | val scanner = Scanner(System.`in`) 10 | val n = scanner.nextInt() 11 | val array = IntArray(n) 12 | for (i in 0 until n) { 13 | array[i] = scanner.nextInt() 14 | } 15 | println(partition3(array)) 16 | } -------------------------------------------------------------------------------- /week6_dynamic_programming2/2_partitioning_souvenirs/partition3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | 6 | int partition3(vector &A) { 7 | //write your code here 8 | return 0; 9 | } 10 | 11 | int main() { 12 | int n; 13 | std::cin >> n; 14 | vector A(n); 15 | for (size_t i = 0; i < A.size(); ++i) { 16 | std::cin >> A[i]; 17 | } 18 | std::cout << partition3(A) << '\n'; 19 | } 20 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/2_partitioning_souvenirs/partition3.py: -------------------------------------------------------------------------------- 1 | from sys import stdin 2 | 3 | def subset_sums(S, n, sum_S1, sum_S2, sum_S3): 4 | """ 5 | 3-partition problem 6 | https://www.techiedelight.com/3-partition-problem/ 7 | """ 8 | if sum_S1 == 0 and sum_S2 == 0 and sum_S3 == 0: 9 | return 1 10 | 11 | if n < 0: 12 | return 0 13 | 14 | A = 0 15 | if sum_S1 >= S[n]: 16 | A = subset_sums(S, n-1, sum_S1 - S[n], sum_S2, sum_S3) 17 | 18 | B = 0 19 | if A != 1 and sum_S2 >= S[n]: 20 | B = subset_sums(S, n-1, sum_S1, sum_S2 - S[n], sum_S3) 21 | 22 | C = 0 23 | if A != 1 and B != 1 and sum_S3 >= S[n]: 24 | C = subset_sums(S, n-1, sum_S1, sum_S2, sum_S3 - S[n]) 25 | 26 | return A or B or C 27 | 28 | 29 | def partition3(values): 30 | if len(values) < 3: 31 | return 0 32 | 33 | total = sum(values) 34 | if total % 3 != 0: 35 | return 0 36 | 37 | return subset_sums(values, len(values) - 1, total // 3, total // 3, total // 3) 38 | 39 | 40 | if __name__ == '__main__': 41 | input_n, *input_values = list(map(int, stdin.read().split())) 42 | assert input_n == len(input_values) 43 | print(partition3(input_values)) 44 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/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 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/PlacingParentheses.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun getMaximValue(exp: String): Long { 4 | //write your code here 5 | return 0 6 | } 7 | 8 | fun eval(a: Long, b: Long, op: Char): Long = when (op) { 9 | '+' -> a + b 10 | '-' -> a - b 11 | '*' -> a * b 12 | else -> { 13 | assert(false) 14 | 0 15 | } 16 | } 17 | 18 | fun main(args: Array) { 19 | val scanner = Scanner(System.`in`) 20 | val exp = scanner.next() 21 | println(getMaximValue(exp)) 22 | } -------------------------------------------------------------------------------- /week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/by_learners/placing_parentheses.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # by Andronik Ordian 3 | 4 | NUM_MAX = (2**(0.size * 8 - 2) - 1) 5 | NUM_MIN = -(2**(0.size * 8 - 2)) 6 | 7 | def evaluate(a, op, b) 8 | ops = { 9 | '+' => ->(x, y) { x + y }, 10 | '-' => ->(x, y) { x - y }, 11 | '*' => ->(x, y) { x * y } 12 | } 13 | ops[op].call(a, b) 14 | end 15 | 16 | 17 | def get_maximum_value(numbers, operations) 18 | # write your code here 19 | evaluate(2, '*', 2) 20 | end 21 | 22 | if __FILE__ == $0 23 | s = gets.chomp.bytes.to_a 24 | numbers = s.each_slice(2).map { |slice| slice.first - "0".bytes.first } 25 | operations = s.drop(1).each_slice(2).map(&:first).map(&:chr) 26 | puts get_maximum_value(numbers, operations) 27 | end 28 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/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 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/placing_parentheses.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def evaluate(a, b, op): 5 | if op == '+': 6 | return a + b 7 | elif op == '-': 8 | return a - b 9 | elif op == '*': 10 | return a * b 11 | else: 12 | assert False 13 | 14 | def min_max(i, j, m, M, ops): 15 | minimum = sys.maxsize # infinity 16 | maximum = -sys.maxsize # -infinity 17 | 18 | for k in range(i, j): 19 | # print('i=', i) 20 | # print('k=', k) 21 | # print('j+1=', j+1) 22 | a = evaluate(M[i][k], M[k+1][j], ops[k]) 23 | b = evaluate(M[i][k], m[k+1][j], ops[k]) 24 | c = evaluate(m[i][k], M[k+1][j], ops[k]) 25 | d = evaluate(m[i][k], m[k+1][j], ops[k]) 26 | 27 | minimum = min(minimum, a, b, c, d) 28 | maximum = max(maximum, a, b, c, d) 29 | 30 | return minimum, maximum 31 | 32 | 33 | 34 | def maximum_value(dataset): 35 | """ 36 | Reference: https://towardsdatascience.com/course-1-algorithmic-toolbox-part-4-dynamic-programming-223ffc01984a 37 | """ 38 | ops = [dataset[i] for i in range(len(dataset)) if i % 2 != 0] 39 | nums = [int(dataset[i]) for i in range(len(dataset)) if i % 2 == 0] 40 | # print(ops) 41 | # print(nums) 42 | m = [[0]*len(nums) for _ in range(len(nums))] 43 | M = [[0]*len(nums) for _ in range(len(nums))] 44 | for i in range(len(nums)): 45 | m[i][i] = nums[i] 46 | M[i][i] = nums[i] 47 | # print('m', m) 48 | # print('M', M) 49 | for s in range(1, len(nums)): 50 | for i in range(0, len(nums) - s): 51 | j = i + s 52 | m[i][j], M[i][j] = min_max(i, j, m, M, ops) 53 | # print('m', m) 54 | # print('M', M) 55 | return M[0][-1] 56 | 57 | 58 | 59 | 60 | if __name__ == "__main__": 61 | print(maximum_value(input())) 62 | -------------------------------------------------------------------------------- /week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/pseudocode_minmax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/pseudocode_minmax.png -------------------------------------------------------------------------------- /week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/pseudocode_parentheses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenhongson1902/algorithmic-toolbox-solutions/0479304d568150ed245bd7ae7e6a21e635281e75/week6_dynamic_programming2/3_maximum_value_of_an_arithmetic_expression/pseudocode_parentheses.png --------------------------------------------------------------------------------