From 2d8171b2b334f9712d3de162269607ce784d419d Mon Sep 17 00:00:00 2001 From: Nimrod Rak Date: Tue, 12 Oct 2021 10:18:41 +0300 Subject: [PATCH 01/94] added disjoint sets data structure --- .../disjoint_sets/disjoint_sets.rb | 37 +++++++++++++++++++ data_structures/disjoint_sets/node.rb | 20 ++++++++++ 2 files changed, 57 insertions(+) create mode 100644 data_structures/disjoint_sets/disjoint_sets.rb create mode 100644 data_structures/disjoint_sets/node.rb diff --git a/data_structures/disjoint_sets/disjoint_sets.rb b/data_structures/disjoint_sets/disjoint_sets.rb new file mode 100644 index 00000000..2d711850 --- /dev/null +++ b/data_structures/disjoint_sets/disjoint_sets.rb @@ -0,0 +1,37 @@ +require "./data_structures/disjoint_sets/node.rb" + +class DisjointSets + def make_set(d) + Node.new(d) + end + + def find_set(x) + raise ArgumentError unless x.class <= Node + x.parent=(find_set(x.parent)) unless x.parent == x + x.parent + end + + def union_set(x, y) + px = find_set(x) + py = find_set(y) + return if px == py + if px.rank > py.rank + py.parent = px + elsif py.rank > px.rank + px.parent = py + else + px.parent = py + py.rank += 1 + end + end +end + +ds = DisjointSets.new +one = ds.make_set(1) +two = ds.make_set(2) +three = ds.make_set(3) +ds.union_set(one, two) +puts ds.find_set(one) == ds.find_set(two) # should be true +ds.union_set(one, three) +puts ds.find_set(two) == ds.find_set(three) # should be true +puts one.rank + two.rank + three.rank == 1 # should be true \ No newline at end of file diff --git a/data_structures/disjoint_sets/node.rb b/data_structures/disjoint_sets/node.rb new file mode 100644 index 00000000..d1cdca5a --- /dev/null +++ b/data_structures/disjoint_sets/node.rb @@ -0,0 +1,20 @@ +class Node + attr_accessor :data, :parent, :rank + def initialize(data) + @data = data + @parent = self + @rank = 0 + end + def parent + @parent + end + def parent=(parent) + @parent = parent; + end + def rank + @rank + end + def rank=(rank) + @rank = rank + end +end \ No newline at end of file From 87db7cf633bd3d155370d5731db452e9fbaf53c1 Mon Sep 17 00:00:00 2001 From: Nimrod Rak Date: Tue, 12 Oct 2021 10:21:38 +0300 Subject: [PATCH 02/94] fixed importing issue --- .../disjoint_sets/disjoint_sets.rb | 21 ++++++++++++++++++- data_structures/disjoint_sets/node.rb | 20 ------------------ 2 files changed, 20 insertions(+), 21 deletions(-) delete mode 100644 data_structures/disjoint_sets/node.rb diff --git a/data_structures/disjoint_sets/disjoint_sets.rb b/data_structures/disjoint_sets/disjoint_sets.rb index 2d711850..d9624fe2 100644 --- a/data_structures/disjoint_sets/disjoint_sets.rb +++ b/data_structures/disjoint_sets/disjoint_sets.rb @@ -1,4 +1,23 @@ -require "./data_structures/disjoint_sets/node.rb" +class Node + attr_accessor :data, :parent, :rank + def initialize(data) + @data = data + @parent = self + @rank = 0 + end + def parent + @parent + end + def parent=(parent) + @parent = parent; + end + def rank + @rank + end + def rank=(rank) + @rank = rank + end +end class DisjointSets def make_set(d) diff --git a/data_structures/disjoint_sets/node.rb b/data_structures/disjoint_sets/node.rb deleted file mode 100644 index d1cdca5a..00000000 --- a/data_structures/disjoint_sets/node.rb +++ /dev/null @@ -1,20 +0,0 @@ -class Node - attr_accessor :data, :parent, :rank - def initialize(data) - @data = data - @parent = self - @rank = 0 - end - def parent - @parent - end - def parent=(parent) - @parent = parent; - end - def rank - @rank - end - def rank=(rank) - @rank = rank - end -end \ No newline at end of file From a9f13f40dc77a9e29d16e93e7cf092460cc2cd03 Mon Sep 17 00:00:00 2001 From: ApsaraGuhan <77098039+ApsaraGuhan@users.noreply.github.com> Date: Thu, 21 Oct 2021 11:15:42 +0530 Subject: [PATCH 03/94] Adding implementation of editdistance --- dynamic_programming/editdistance.rb | 74 +++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 dynamic_programming/editdistance.rb diff --git a/dynamic_programming/editdistance.rb b/dynamic_programming/editdistance.rb new file mode 100644 index 00000000..c4744cd5 --- /dev/null +++ b/dynamic_programming/editdistance.rb @@ -0,0 +1,74 @@ +require "test/unit" + +def editDistDP(str1, str2, m, n) + rows, cols = m+1,n+1 + + # Create a 2D array to store results of subproblems + dp = Array.new(rows) { Array.new(cols) } + + #using bottom up approach + for i in (0..m + 1-1) do + for j in (0..n + 1-1) do + + #If the first string is empty, insert all the characters of the second string + if i == 0 + dp[i][j] = j + + #If the second string is empty, insert all the characters of the first string + elsif j == 0 + dp[i][j] = i + + #If the last character in both the strings are same, we can ignore the character and move to the next character in both the strings + elsif str1[i-1] == str2[j-1] + dp[i][j] = dp[i-1][j-1] + + #If the last character of both the strings are different, find out the minimum value of the three operations(insert, delete, replace) + else + dp[i][j] = 1 +[dp[i][j-1],dp[i-1][j],dp[i-1][j-1]].min() + + end + + end + + end + + return dp[m][n] +end + + + + +class Editdistancetest < Test::Unit::TestCase + + #Test1 + #Replace 'n' with 'r' + #insert 'a' + #insert 't' + #No of total operations : 3 + def test_distance1 + assert_equal 3, editDistDP( "sunday","saturday",6,8), "Should return 3" + end + + #Test2 + #Replace 'a' with 'u' + #No of total operations : 1 + def test_distance2 + assert_equal 1, editDistDP("cat","cut",3,3), "editDistDpShould return 1" + end + + #Test3 + #Insert 'a','p', 'p','l','e','p','i','e' into string 1 + #No of total operations : 8 + def test_distance3 + assert_equal 8, editDistDP("","applepie",0,8), "editDistDpShould return 1" + end + + #Test4 + #Both the strings are equal, thus no operation needed + #No of total operations : 0 + def test_distance4 + assert_equal 0, editDistDP("Hello","Hello",5,5), "editDistDpShould return 1" + end + + end + From bf7d9dfe83947b47ae980181a407b14f7a97bb94 Mon Sep 17 00:00:00 2001 From: ApsaraGuhan <77098039+ApsaraGuhan@users.noreply.github.com> Date: Thu, 21 Oct 2021 11:23:22 +0530 Subject: [PATCH 04/94] Adding implementation of knapsack --- dynamic_programming/knapsack.rb | 64 +++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 dynamic_programming/knapsack.rb diff --git a/dynamic_programming/knapsack.rb b/dynamic_programming/knapsack.rb new file mode 100644 index 00000000..bcac5494 --- /dev/null +++ b/dynamic_programming/knapsack.rb @@ -0,0 +1,64 @@ +require "test/unit" + +# 0-1 Knapsack problem +# The function returns the maximum value that can be put in a knapsack of a given capacity + +def knapSack(weight, wt, val, n) + + rows, cols = n+1,weight+1 + # Create a 2D array to store results of subproblems + dp = Array.new(rows) { Array.new(cols) } + + for i in (0..n + 1-1) + for w in (0..weight + 1-1) + # if the weight is 0 or value is zero, the corresponding cell in the 2D array is set to 0 + if i == 0 || w == 0 + dp[i][w] = 0 + + #If the weight of an element is less than the capacity of the bag, the maximum value of the two cases is taken(Either the element is taken into consideration + #or is ignored) + elsif wt[i-1] <= w + dp[i][w] = [ val[i-1] + dp[i-1][w-wt[i-1]],dp[i-1][w]].max() + + #If the weight of the element is greater than the capacity of the bag, the cell is set to the value of the previous cell + else + dp[i][w] = dp[i-1][w] + end + end + end + + return dp[n][weight] +end + + + + + +class Knapsacktest < Test::Unit::TestCase + + #Test1 + def test_knapsack1 + assert_equal 220, knapSack(50,[10,20,30],[60,100,120],3), "Should return 220" + end + + + #Test2 + def test_knapsack2 + assert_equal 500, knapSack(50,[50, 20, 30],[100, 200, 300],3), "Should return 500" + end + + #Test3 + def test_knapsack3 + assert_equal 17, knapSack(10,[3,4,5, 2, 1],[10,2,3,4,0],5), "Should return 17" + end + + #Test4 + def test_knapsack4 + assert_equal 0, knapSack(0,[23, 17, 12, 8, 20],[199,200,30,41,10],5), "Should return 0" + end + + +end + + + \ No newline at end of file From 7fbd71df1f1ca8f798c58996cdfb313ef4d8d005 Mon Sep 17 00:00:00 2001 From: Administrator Date: Fri, 22 Oct 2021 13:02:39 +0200 Subject: [PATCH 05/94] add fibonacci search --- searches/fibonacci_search.rb | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 searches/fibonacci_search.rb diff --git a/searches/fibonacci_search.rb b/searches/fibonacci_search.rb new file mode 100644 index 00000000..0a845bd4 --- /dev/null +++ b/searches/fibonacci_search.rb @@ -0,0 +1,34 @@ +def fibonacci_search int arr, int element + n = n.size + f2 = 0 + f1 = 1 + f = f2 + f1 + offset = -1 + + while f < n do + f2 = f1; + f1 = f; + f = f2 + f1; + end + + while f > 1 do + i = [offset+f2, n-1].min + + if arr[i] < element + f = f1 + f1 = f2 + f2 = f - f1 + offset = i + elsif arr[i] > element + f = f2 + f1 = f1 - f2 + f2 = f - f1 + else + return i + end + end + + return offset + 1 if f1 && arr[offset + 1] == element + + -1 +end From d2445070fb0d75fdff914e3f0d21c31ef5c81b28 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Tue, 2 Nov 2021 06:26:31 +0000 Subject: [PATCH 06/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index f2a6c7a3..1c431437 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -56,6 +56,8 @@ * [Invert](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/invert.rb) * [Postorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/postorder_traversal.rb) * [Preorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/preorder_traversal.rb) + * Disjoint Sets + * [Disjoint Sets](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/disjoint_sets/disjoint_sets.rb) * Hash Table * [Anagram Checker](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/anagram_checker.rb) * [Arrays Intersection](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/arrays_intersection.rb) From 4fc9eba58a069d4808a7b798f4e44260046b35dc Mon Sep 17 00:00:00 2001 From: Vitor Oliveira Date: Mon, 1 Nov 2021 23:45:20 -0700 Subject: [PATCH 07/94] Fix lint --- ciphers/caesar.rb | 1 - ciphers/caesar_test.rb | 1 - ciphers/rsa.rb | 52 +++++++------- .../disjoint_sets/disjoint_sets.rb | 71 ++++++++----------- electronics/ohms_law.rb | 10 +-- 5 files changed, 64 insertions(+), 71 deletions(-) diff --git a/ciphers/caesar.rb b/ciphers/caesar.rb index c76ea743..8a15d9f0 100644 --- a/ciphers/caesar.rb +++ b/ciphers/caesar.rb @@ -30,4 +30,3 @@ def self.decrypt(ciphertext, shift) end.join end end - diff --git a/ciphers/caesar_test.rb b/ciphers/caesar_test.rb index 090945d8..be5a23e8 100644 --- a/ciphers/caesar_test.rb +++ b/ciphers/caesar_test.rb @@ -19,4 +19,3 @@ def run_tests(plaintext, expected_cipher, shift) assert_equal decrypted, plaintext end end - diff --git a/ciphers/rsa.rb b/ciphers/rsa.rb index 0b9520e5..c4aa097a 100644 --- a/ciphers/rsa.rb +++ b/ciphers/rsa.rb @@ -1,4 +1,4 @@ -require "prime" +require 'prime' def initialize(keys = {}) @e ||= keys[:e] @@ -7,16 +7,16 @@ def initialize(keys = {}) def cipher(message) message.bytes.map do |byte| - cbyte = ((byte.to_i ** e) % n).to_s + cbyte = ((byte.to_i**e) % n).to_s missing_chars = n.to_s.size - cbyte.size - "0" * missing_chars + cbyte + '0' * missing_chars + cbyte end.join end def decipher(ciphed_message) ciphed_message.chars.each_slice(n.to_s.size).map do |arr| - (arr.join.to_i ** d) % n - end.pack("c*") + (arr.join.to_i**d) % n + end.pack('c*') end def public_keys @@ -52,43 +52,47 @@ def d end def extended_gcd(a, b) - last_remainder, remainder = a.abs, b.abs - x, last_x, y, last_y = 0, 1, 1, 0 + last_remainder = a.abs + remainder = b.abs + x = 0 + last_x = 1 + y = 1 + last_y = 0 while remainder != 0 - last_remainder, (quotient, remainder) = remainder, last_remainder.divmod(remainder) + (quotient, remainder) = last_remainder.divmod(remainder) + last_remainder = remainder x, last_x = last_x - quotient * x, x y, last_y = last_y - quotient * y, y end - return last_remainder, last_x * (a < 0 ? -1 : 1) + [last_remainder, last_x * (a < 0 ? -1 : 1)] end def invmod(e, et) g, x = extended_gcd(e, et) - raise "The maths are broken!" if g != 1 + raise 'The maths are broken!' if g != 1 + x % et end def random_prime_number number = Random.rand(1..1000) - until Prime.prime?(number) || number == p || number == q - number = Random.rand(1..1000) - end + number = Random.rand(1..1000) until Prime.prime?(number) || number == p || number == q number end -def main() - puts "Enter the message you want to encrypt and decrypt with RSA algorithm: " - message = gets.chomp().to_s - puts "Encoded Text:" +def main + puts 'Enter the message you want to encrypt and decrypt with RSA algorithm: ' + message = gets.chomp.to_s + puts 'Encoded Text:' puts cipher(message) - puts "Decoded Text:" + puts 'Decoded Text:' puts decipher(cipher(message)) - puts "p: #{p()}" - puts "q: #{q()}" - puts "e: #{e()}" - puts "d: #{d()}" - puts "totient: #{totient()}" + puts "p: #{p}" + puts "q: #{q}" + puts "e: #{e}" + puts "d: #{d}" + puts "totient: #{totient}" end -main() +main diff --git a/data_structures/disjoint_sets/disjoint_sets.rb b/data_structures/disjoint_sets/disjoint_sets.rb index d9624fe2..f89dc63b 100644 --- a/data_structures/disjoint_sets/disjoint_sets.rb +++ b/data_structures/disjoint_sets/disjoint_sets.rb @@ -1,48 +1,39 @@ class Node - attr_accessor :data, :parent, :rank - def initialize(data) - @data = data - @parent = self - @rank = 0 - end - def parent - @parent - end - def parent=(parent) - @parent = parent; - end - def rank - @rank - end - def rank=(rank) - @rank = rank - end + attr_accessor :data, :parent, :rank, :parent, :rank + + def initialize(data) + @data = data + @parent = self + @rank = 0 + end end class DisjointSets - def make_set(d) - Node.new(d) - end + def make_set(d) + Node.new(d) + end - def find_set(x) - raise ArgumentError unless x.class <= Node - x.parent=(find_set(x.parent)) unless x.parent == x - x.parent - end + def find_set(x) + raise ArgumentError unless x.class <= Node - def union_set(x, y) - px = find_set(x) - py = find_set(y) - return if px == py - if px.rank > py.rank - py.parent = px - elsif py.rank > px.rank - px.parent = py - else - px.parent = py - py.rank += 1 - end - end + x.parent = (find_set(x.parent)) unless x.parent == x + x.parent + end + + def union_set(x, y) + px = find_set(x) + py = find_set(y) + return if px == py + + if px.rank > py.rank + py.parent = px + elsif py.rank > px.rank + px.parent = py + else + px.parent = py + py.rank += 1 + end + end end ds = DisjointSets.new @@ -53,4 +44,4 @@ def union_set(x, y) puts ds.find_set(one) == ds.find_set(two) # should be true ds.union_set(one, three) puts ds.find_set(two) == ds.find_set(three) # should be true -puts one.rank + two.rank + three.rank == 1 # should be true \ No newline at end of file +puts one.rank + two.rank + three.rank == 1 # should be true diff --git a/electronics/ohms_law.rb b/electronics/ohms_law.rb index bececb9e..4f7a4195 100644 --- a/electronics/ohms_law.rb +++ b/electronics/ohms_law.rb @@ -3,13 +3,13 @@ # Reference: https://en.wikipedia.org/wiki/Ohm's_law def ohms_law(i, r) - if(i > 0 && r > 0) + if i > 0 && r > 0 "The voltage for given #{i} ampheres current and #{r} ohms resistance is #{r * i} volts." else raise end - rescue - "Error: Please provide valid inputs only!" +rescue StandardError + 'Error: Please provide valid inputs only!' end # Valid inputs @@ -25,7 +25,7 @@ def ohms_law(i, r) # Error: Please provide valid inputs only! puts(ohms_law(-5, -10)) # Error: Please provide valid inputs only! -puts(ohms_law(5, "10")) +puts(ohms_law(5, '10')) # Error: Please provide valid inputs only! -puts(ohms_law("a", 10)) +puts(ohms_law('a', 10)) # Error: Please provide valid inputs only! From 4b34faccca554869ba31cb374a002c2dc74f693e Mon Sep 17 00:00:00 2001 From: Philip Schikora Date: Tue, 2 Nov 2021 12:41:47 +0100 Subject: [PATCH 08/94] Update fibonacci_search.rb --- searches/fibonacci_search.rb | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/searches/fibonacci_search.rb b/searches/fibonacci_search.rb index 0a845bd4..439ac41a 100644 --- a/searches/fibonacci_search.rb +++ b/searches/fibonacci_search.rb @@ -1,34 +1,34 @@ def fibonacci_search int arr, int element - n = n.size + n = n.size f2 = 0 f1 = 1 - f = f2 + f1 + f = f2 + f1 offset = -1 - while f < n do - f2 = f1; - f1 = f; - f = f2 + f1; + while f < n do + f2 = f1; + f1 = f; + f = f2 + f1; end - while f > 1 do - i = [offset+f2, n-1].min + while f > 1 do + i = [offset+f2, n-1].min - if arr[i] < element - f = f1 - f1 = f2 - f2 = f - f1 - offset = i - elsif arr[i] > element - f = f2 - f1 = f1 - f2 - f2 = f - f1 - else - return i + if arr[i] < element + f = f1 + f1 = f2 + f2 = f - f1 + offset = i + elsif arr[i] > element + f = f2 + f1 = f1 - f2 + f2 = f - f1 + else + return i end - end - - return offset + 1 if f1 && arr[offset + 1] == element + end + + return offset + 1 if f1 && arr[offset + 1] == element -1 end From 7cdef852491b620b327490a02de42fa4eb4c034c Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 14 Nov 2021 22:36:53 +0000 Subject: [PATCH 09/94] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 1c431437..1cfc847e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -92,6 +92,7 @@ * [Count Sorted Vowel Strings](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/count_sorted_vowel_strings.rb) * [Fibonacci](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/fibonacci.rb) * [House Robber](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/house_robber.rb) + * [Knapsack](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/knapsack.rb) * [Ones And Zeros](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/ones_and_zeros.rb) * [Pascal Triangle Ii](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/pascal_triangle_ii.rb) From 4b87fc569a016e0ca61dd0db0a21ce79292bdcc8 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 14 Nov 2021 22:37:09 +0000 Subject: [PATCH 10/94] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 1cfc847e..c0338ff0 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -90,6 +90,7 @@ * [Climbing Stairs](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/climbing_stairs.rb) * [Coin Change](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/coin_change.rb) * [Count Sorted Vowel Strings](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/count_sorted_vowel_strings.rb) + * [Editdistance](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/editdistance.rb) * [Fibonacci](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/fibonacci.rb) * [House Robber](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/house_robber.rb) * [Knapsack](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/knapsack.rb) From b4122a0fa70d16388feb4655df21da503d127d81 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 14 Nov 2021 22:37:37 +0000 Subject: [PATCH 11/94] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index c0338ff0..e990225e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -161,6 +161,7 @@ * [Binary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/binary_search.rb) * [Depth First Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/depth_first_search.rb) * [Double Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/double_linear_search.rb) + * [Fibonacci Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/fibonacci_search.rb) * [Jump Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/jump_search.rb) * [Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/linear_search.rb) * [Number Of Islands](https://github.com/TheAlgorithms/Ruby/blob/master/searches/number_of_islands.rb) From 41cf83403bfaea67870ee2ed792c41fbc95308fd Mon Sep 17 00:00:00 2001 From: shan Date: Mon, 20 Dec 2021 15:56:36 -0500 Subject: [PATCH 12/94] New improved implementation of bubble sort --- .idea/misc.xml | 4 + .idea/vcs.xml | 6 ++ .idea/workspace.xml | 162 +++++++++++++++++++++++++++++++++++++++++ sorting/bubble_sort.rb | 26 ++++--- 4 files changed, 186 insertions(+), 12 deletions(-) create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..39160804 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 00000000..81935e2e --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1640032781494 + + + + + + + + + + + + + \ No newline at end of file diff --git a/sorting/bubble_sort.rb b/sorting/bubble_sort.rb index 9bef7f12..13b01d12 100644 --- a/sorting/bubble_sort.rb +++ b/sorting/bubble_sort.rb @@ -1,19 +1,21 @@ def bubble_sort(array) - n = array.length - loop do - swapped = false - - (n - 1).times do |i| - if array[i] > array[i + 1] - array[i], array[i + 1] = array[i + 1], array[i] - swapped = true + array_length = array.length + return array if array_length <= 1 + unsorted_until_index = array_length - 1 + sorted = false + until sorted + sorted = true + for i in (0..unsorted_until_index) + if array[i+1] + if array[i] > array[i+1] + array[i], array[i+1] = array[i+1], array[i] + sorted = false + end end end - - break unless swapped + unsorted_until_index -= 1 end - - array + return array end if $0 == __FILE__ From 7b98525265301cbe23a1c62a448aa2fe07b1b6e4 Mon Sep 17 00:00:00 2001 From: shan Date: Tue, 21 Dec 2021 15:53:24 -0500 Subject: [PATCH 13/94] removed ide files --- .idea/misc.xml | 4 -- .idea/vcs.xml | 6 -- .idea/workspace.xml | 162 -------------------------------------------- 3 files changed, 172 deletions(-) delete mode 100644 .idea/misc.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 39160804..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 81935e2e..00000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1640032781494 - - - - - - - - - - - - - \ No newline at end of file From 4d89a333a8fa96bd7d9177c7a3d869acedb2b8b5 Mon Sep 17 00:00:00 2001 From: shan Date: Tue, 21 Dec 2021 15:57:15 -0500 Subject: [PATCH 14/94] Removed unwanted index check --- sorting/bubble_sort.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sorting/bubble_sort.rb b/sorting/bubble_sort.rb index 13b01d12..0c97c813 100644 --- a/sorting/bubble_sort.rb +++ b/sorting/bubble_sort.rb @@ -5,12 +5,10 @@ def bubble_sort(array) sorted = false until sorted sorted = true - for i in (0..unsorted_until_index) - if array[i+1] - if array[i] > array[i+1] - array[i], array[i+1] = array[i+1], array[i] - sorted = false - end + 0.upto(unsorted_until_index - 1) do |i| + if array[i] > array[i+1] + array[i], array[i+1] = array[i+1], array[i] + sorted = false end end unsorted_until_index -= 1 From 8d64f47ed0c4b3735c9338d68f745906df151e01 Mon Sep 17 00:00:00 2001 From: vzvu3k6k Date: Mon, 27 Dec 2021 18:11:25 +0900 Subject: [PATCH 15/94] Use Ruby 3.1 in testing --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 241b25ed..89798d40 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,6 @@ jobs: - uses: actions/checkout@master - uses: ruby/setup-ruby@master with: - ruby-version: '3.0' + ruby-version: '3.1' - name: Run tests run: rake test From 2f3aebfadaa2d26db43324c708ab1e547e8b6c5c Mon Sep 17 00:00:00 2001 From: Narbe Voskanian Date: Fri, 23 Sep 2022 15:08:43 -0700 Subject: [PATCH 16/94] rename project_euler problem directory names to match the README --- project_euler/{problem_1 => problem_001}/sol1.rb | 0 project_euler/{problem_2 => problem_002}/sol1.rb | 0 project_euler/{problem_3 => problem_003}/sol1.rb | 0 project_euler/{problem_3 => problem_003}/sol2.rb | 0 project_euler/{problem_4 => problem_004}/sol1.rb | 0 project_euler/{problem_4 => problem_004}/sol2.rb | 0 project_euler/{problem_5 => problem_005}/sol1.rb | 0 project_euler/{problem_20 => problem_020}/sol1.rb | 0 project_euler/{problem_21 => problem_021}/sol1.rb | 0 project_euler/{problem_22 => problem_022}/p022_names.txt | 0 project_euler/{problem_22 => problem_022}/sol1.rb | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename project_euler/{problem_1 => problem_001}/sol1.rb (100%) rename project_euler/{problem_2 => problem_002}/sol1.rb (100%) rename project_euler/{problem_3 => problem_003}/sol1.rb (100%) rename project_euler/{problem_3 => problem_003}/sol2.rb (100%) rename project_euler/{problem_4 => problem_004}/sol1.rb (100%) rename project_euler/{problem_4 => problem_004}/sol2.rb (100%) rename project_euler/{problem_5 => problem_005}/sol1.rb (100%) rename project_euler/{problem_20 => problem_020}/sol1.rb (100%) rename project_euler/{problem_21 => problem_021}/sol1.rb (100%) rename project_euler/{problem_22 => problem_022}/p022_names.txt (100%) rename project_euler/{problem_22 => problem_022}/sol1.rb (100%) diff --git a/project_euler/problem_1/sol1.rb b/project_euler/problem_001/sol1.rb similarity index 100% rename from project_euler/problem_1/sol1.rb rename to project_euler/problem_001/sol1.rb diff --git a/project_euler/problem_2/sol1.rb b/project_euler/problem_002/sol1.rb similarity index 100% rename from project_euler/problem_2/sol1.rb rename to project_euler/problem_002/sol1.rb diff --git a/project_euler/problem_3/sol1.rb b/project_euler/problem_003/sol1.rb similarity index 100% rename from project_euler/problem_3/sol1.rb rename to project_euler/problem_003/sol1.rb diff --git a/project_euler/problem_3/sol2.rb b/project_euler/problem_003/sol2.rb similarity index 100% rename from project_euler/problem_3/sol2.rb rename to project_euler/problem_003/sol2.rb diff --git a/project_euler/problem_4/sol1.rb b/project_euler/problem_004/sol1.rb similarity index 100% rename from project_euler/problem_4/sol1.rb rename to project_euler/problem_004/sol1.rb diff --git a/project_euler/problem_4/sol2.rb b/project_euler/problem_004/sol2.rb similarity index 100% rename from project_euler/problem_4/sol2.rb rename to project_euler/problem_004/sol2.rb diff --git a/project_euler/problem_5/sol1.rb b/project_euler/problem_005/sol1.rb similarity index 100% rename from project_euler/problem_5/sol1.rb rename to project_euler/problem_005/sol1.rb diff --git a/project_euler/problem_20/sol1.rb b/project_euler/problem_020/sol1.rb similarity index 100% rename from project_euler/problem_20/sol1.rb rename to project_euler/problem_020/sol1.rb diff --git a/project_euler/problem_21/sol1.rb b/project_euler/problem_021/sol1.rb similarity index 100% rename from project_euler/problem_21/sol1.rb rename to project_euler/problem_021/sol1.rb diff --git a/project_euler/problem_22/p022_names.txt b/project_euler/problem_022/p022_names.txt similarity index 100% rename from project_euler/problem_22/p022_names.txt rename to project_euler/problem_022/p022_names.txt diff --git a/project_euler/problem_22/sol1.rb b/project_euler/problem_022/sol1.rb similarity index 100% rename from project_euler/problem_22/sol1.rb rename to project_euler/problem_022/sol1.rb From 6007e52b99e9940901fb47553a8a18bbde07b22f Mon Sep 17 00:00:00 2001 From: ryanneilparker Date: Thu, 6 Oct 2022 10:19:01 +0000 Subject: [PATCH 17/94] Add binary insertion sort --- sorting/binary_insertion_sort.rb | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 sorting/binary_insertion_sort.rb diff --git a/sorting/binary_insertion_sort.rb b/sorting/binary_insertion_sort.rb new file mode 100644 index 00000000..68e403c5 --- /dev/null +++ b/sorting/binary_insertion_sort.rb @@ -0,0 +1,51 @@ +# Ruby implementation +# of binary insertion sort algorithm + + + +require 'pry' + +def binary_search(arr, val, start, stop) + while start <= stop + + mid = (start + stop) / 2 + + if val == arr[mid] # val is in the middle + return mid + elsif val > arr[mid] # val is on the right side + start = mid + 1 + else + stop = mid - 1 # val is on the left side + end + end + + start +end + +def binary_insertion_sort(arr) + n = arr.size + + (0...n).each do |index| + j = index - 1 + selected = arr[index] + + # find location where selected value should be inserted + location = binary_search(arr, selected, 0, j) + + # move all elements after location to make space + while j >= location + arr[j + 1] = arr[j] + j -= 1 + arr[j + 1] = selected + end + end + + arr +end + +if $0 == __FILE__ + puts 'Enter a list of numbers separated by space' + + list = gets.split.map(&:to_i) + p binary_insertion_sort(list) +end \ No newline at end of file From c32ffeccb06acd667891d98b2d9ba7c7c29a67d9 Mon Sep 17 00:00:00 2001 From: ryanneilparker Date: Thu, 6 Oct 2022 10:22:24 +0000 Subject: [PATCH 18/94] Add binary_insertion_sort.rb --- sorting/binary_insertion_sort.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sorting/binary_insertion_sort.rb b/sorting/binary_insertion_sort.rb index 68e403c5..c487464b 100644 --- a/sorting/binary_insertion_sort.rb +++ b/sorting/binary_insertion_sort.rb @@ -1,9 +1,4 @@ -# Ruby implementation -# of binary insertion sort algorithm - - - -require 'pry' +# Ruby implementation of binary insertion sort algorithm def binary_search(arr, val, start, stop) while start <= stop From e927c673fa82a30a9a526987b7b59cd7a5a5e814 Mon Sep 17 00:00:00 2001 From: ryanneilparker Date: Thu, 6 Oct 2022 10:26:34 +0000 Subject: [PATCH 19/94] Add binary_insertion_sort_test.rb --- sorting/binary_insertion_sort_test.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 sorting/binary_insertion_sort_test.rb diff --git a/sorting/binary_insertion_sort_test.rb b/sorting/binary_insertion_sort_test.rb new file mode 100644 index 00000000..68594e1d --- /dev/null +++ b/sorting/binary_insertion_sort_test.rb @@ -0,0 +1,11 @@ +require 'minitest/autorun' +require_relative './sort_tests' +require_relative './binary_insertion_sort' + +class TestBubbleSort < Minitest::Test + include SortTests + + def sort(input) + binary_insertion_sort(input) + end +end \ No newline at end of file From f2fdc233bfc1b36b376bb6ce990b2f4c1ffaefac Mon Sep 17 00:00:00 2001 From: ryanneilparker Date: Thu, 6 Oct 2022 10:29:43 +0000 Subject: [PATCH 20/94] Correct test class --- sorting/binary_insertion_sort_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorting/binary_insertion_sort_test.rb b/sorting/binary_insertion_sort_test.rb index 68594e1d..7b83d4be 100644 --- a/sorting/binary_insertion_sort_test.rb +++ b/sorting/binary_insertion_sort_test.rb @@ -2,7 +2,7 @@ require_relative './sort_tests' require_relative './binary_insertion_sort' -class TestBubbleSort < Minitest::Test +class TestBinaryInsertionSort < Minitest::Test include SortTests def sort(input) From f5392bd696bbc6ba827cdbbb96a16873edab5e93 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Wed, 2 Nov 2022 04:54:32 +0000 Subject: [PATCH 21/94] updating DIRECTORY.md --- DIRECTORY.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index e990225e..67bef39f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -138,24 +138,24 @@ * [Number Of Days](https://github.com/TheAlgorithms/Ruby/blob/master/other/number_of_days.rb) ## Project Euler - * Problem 1 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_1/sol1.rb) - * Problem 2 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_2/sol1.rb) - * Problem 20 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_20/sol1.rb) - * Problem 21 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_21/sol1.rb) - * Problem 22 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_22/sol1.rb) - * Problem 3 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_3/sol1.rb) - * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_3/sol2.rb) - * Problem 4 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_4/sol1.rb) - * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_4/sol2.rb) - * Problem 5 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_5/sol1.rb) + * Problem 001 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_001/sol1.rb) + * Problem 002 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_002/sol1.rb) + * Problem 003 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_003/sol1.rb) + * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_003/sol2.rb) + * Problem 004 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol1.rb) + * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) + * Problem 005 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) + * Problem 020 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) + * Problem 021 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_021/sol1.rb) + * Problem 022 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_022/sol1.rb) ## Searches * [Binary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/binary_search.rb) From 7f09955d63ed04f719a7091367b09f0c8a9acc8a Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 8 Dec 2022 15:44:02 +0000 Subject: [PATCH 22/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 67bef39f..e3b37c5b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -172,6 +172,8 @@ ## Sorting * [Bead Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bead_sort.rb) * [Bead Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bead_sort_test.rb) + * [Binary Insertion Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/binary_insertion_sort.rb) + * [Binary Insertion Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/binary_insertion_sort_test.rb) * [Bogo Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bogo_sort.rb) * [Bogo Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bogo_sort_test.rb) * [Bubble Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bubble_sort.rb) From d731f18ab0f6a0e3bb9c93a86e7ac0604ee64356 Mon Sep 17 00:00:00 2001 From: vzvu3k6k Date: Thu, 29 Dec 2022 00:40:33 +0900 Subject: [PATCH 23/94] Use Ruby 3.2 in testing --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 89798d40..62cd4b3e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,6 @@ jobs: - uses: actions/checkout@master - uses: ruby/setup-ruby@master with: - ruby-version: '3.1' + ruby-version: '3.2' - name: Run tests run: rake test From 3966a347809ab68f1a939d565162e0a73407b340 Mon Sep 17 00:00:00 2001 From: Stepfen Shawn Date: Thu, 2 Feb 2023 11:46:33 +0800 Subject: [PATCH 24/94] Update LICENSE.md Update copyright year: 2021 -> 2023 --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index f6bcf04e..6d7f310d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 The Algorithms +Copyright (c) 2023 The Algorithms Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 7fa7c5bae06440a8544afceb5e2ee8b363906f3d Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Mon, 6 Feb 2023 18:45:44 +0100 Subject: [PATCH 25/94] Adding max-heap implementation --- data_structures/heaps/max_heap.rb | 87 ++++++++++++++++++++++++++ data_structures/heaps/max_heap_test.rb | 36 +++++++++++ 2 files changed, 123 insertions(+) create mode 100644 data_structures/heaps/max_heap.rb create mode 100644 data_structures/heaps/max_heap_test.rb diff --git a/data_structures/heaps/max_heap.rb b/data_structures/heaps/max_heap.rb new file mode 100644 index 00000000..7996f7c4 --- /dev/null +++ b/data_structures/heaps/max_heap.rb @@ -0,0 +1,87 @@ +## +# This class represents an array-backed max-heap. + +class MaxHeap + + attr_reader :arr + attr_accessor :heap_size + + ## + # Creates a new max-heap using the provided collection of initial values, if provided (empty by default). + # Note: a clone of the input collection is created to avoid alterations to the input. + + def initialize(elements = []) + @arr = [0] + elements.map(&:clone) + @heap_size = arr.size - 1 + for i in ((arr.size / 2).floor).downto 1 + max_heapify(i) + end + end + + def to_array + return arr[1..heap_size].map(&:clone) + end + + def empty? + return heap_size == 0 + end + + def max + return nil if empty? + return @arr[1] + end + + def extract_max + return nil if empty? + m = max + @arr[1] = @arr[heap_size] + @heap_size -= 1 + max_heapify(1) + return m + end + + def insert(k) + @heap_size += 1 + @arr[heap_size] = -Float::INFINITY + increase_to(heap_size, k) + end + + private + def max_heapify(i) + l = left(i) + r = right(i) + m = i + if l <= heap_size && arr[l] > arr[i] + m = l + end + if r <= heap_size && arr[r] > arr[m] + m = r + end + if m != i + arr[i], arr[m] = arr[m], arr[i] + max_heapify(m) + end + end + + def increase_to(i, k) + raise ArgumentError.new('MaxHeap#increase_to does not support lower values for the key') if arr[i] > k + @arr[i] = k + j = i + while parent(j) > 0 && arr[parent(j)] < arr[j] + arr[j], arr[parent(j)] = arr[parent(j)], arr[j] + j = parent(j) + end + end + + def parent(i) + return (i / 2).floor + end + + def left(i) + return 2*i + end + + def right(i) + return 2*i + 1 + end +end \ No newline at end of file diff --git a/data_structures/heaps/max_heap_test.rb b/data_structures/heaps/max_heap_test.rb new file mode 100644 index 00000000..502fe6f3 --- /dev/null +++ b/data_structures/heaps/max_heap_test.rb @@ -0,0 +1,36 @@ +require 'minitest/autorun' +require_relative 'max_heap' + +class TestMaxHeap < Minitest::Test + def test_to_array_returns_array_representation + heap = MaxHeap.new([4, 1, 3, 3, 16, 9, 10, 14, 8, 7]) + assert heap.to_array == [16, 14, 10, 8, 7, 9, 3, 3, 4, 1] + end + + def test_empty_returns_true_for_empty_heap + heap = MaxHeap.new + assert heap.empty? + end + + def test_empty_returns_false_for_non_empty_heap + heap = MaxHeap.new([1]) + assert !heap.empty? + end + + def test_max_returns_maximum_heap_element + heap = MaxHeap.new([4, 1, 3]) + assert heap.max == 4 + end + + def test_extract_max_returns_and_removes_maximum_heap_element + heap = MaxHeap.new([4, 1, 3]) + assert heap.extract_max == 4 + assert heap.to_array == [3, 1] + end + + def test_insert_adds_element_to_appropriate_position + heap = MaxHeap.new([4, 1, 3]) + heap.insert(2) + assert heap.to_array == [4, 2, 3, 1] + end +end From fb1f5dd67936be0919f25578b27fc8b246585f68 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Mon, 6 Feb 2023 18:52:42 +0100 Subject: [PATCH 26/94] Adding unit tests for element not found in max-heap --- data_structures/heaps/max_heap_test.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data_structures/heaps/max_heap_test.rb b/data_structures/heaps/max_heap_test.rb index 502fe6f3..ef0bbf76 100644 --- a/data_structures/heaps/max_heap_test.rb +++ b/data_structures/heaps/max_heap_test.rb @@ -22,12 +22,22 @@ def test_max_returns_maximum_heap_element assert heap.max == 4 end + def test_max_returns_nil_if_empty_heap + heap = MaxHeap.new + assert heap.max.nil? + end + def test_extract_max_returns_and_removes_maximum_heap_element heap = MaxHeap.new([4, 1, 3]) assert heap.extract_max == 4 assert heap.to_array == [3, 1] end + def test_extract_max_returns_nil_if_empty_heap + heap = MaxHeap.new + assert heap.extract_max.nil? + end + def test_insert_adds_element_to_appropriate_position heap = MaxHeap.new([4, 1, 3]) heap.insert(2) From cb556451d2ebfd16a2203072315063cca9117a30 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Wed, 8 Feb 2023 01:06:02 +0000 Subject: [PATCH 27/94] updating DIRECTORY.md --- DIRECTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index e3b37c5b..b2ce68eb 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -69,6 +69,9 @@ * [Richest Customer Wealth](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/richest_customer_wealth.rb) * [Two Sum](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/two_sum.rb) * [Uncommon Words](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/uncommon_words.rb) + * Heaps + * [Max Heap](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/heaps/max_heap.rb) + * [Max Heap Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/heaps/max_heap_test.rb) * Linked Lists * [Circular Linked List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/circular_linked_list.rb) * [Doubly Linked List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/doubly_linked_list.rb) From 1846c762ed0a08b0f218c919552a9c4e932b6ff3 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Thu, 9 Feb 2023 12:30:16 +0100 Subject: [PATCH 28/94] Solving the `Top k most frequent words` problem using a max-heap --- strings/max_k_most_frequent_words.rb | 36 +++++++++++++++++++++++ strings/max_k_most_frequent_words_test.rb | 28 ++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 strings/max_k_most_frequent_words.rb create mode 100644 strings/max_k_most_frequent_words_test.rb diff --git a/strings/max_k_most_frequent_words.rb b/strings/max_k_most_frequent_words.rb new file mode 100644 index 00000000..210fb46f --- /dev/null +++ b/strings/max_k_most_frequent_words.rb @@ -0,0 +1,36 @@ +require_relative '../data_structures/heaps/max_heap' + +## +# This class represents a word count information +# (i.e. how many occurrences for a word). + +class WordCount + include Comparable + + attr_reader :word + attr_reader :occurrences + + def <=>(other) + occurrences <=> other.occurrences + end + + def initialize(word, occurrences) + @word = word + @occurrences = occurrences + end +end + +## +# Returns the `k` most frequently occurring words, in non-increasing order of occurrence. +# In this context, a word is defined as an element in the provided list. +# +# In case `k` is greater than the number of distinct words, a value of `k` equal +# to the number of distinct words will be considered, instead. + +def max_k_most_frequent_words(words, k) + count_by_word = words.tally + heap = MaxHeap.new(count_by_word.map { |w, c| WordCount.new(w, c) }) + most_frequent_words = [] + [k, count_by_word.size].min.times { most_frequent_words.append(heap.extract_max.word) } + most_frequent_words +end \ No newline at end of file diff --git a/strings/max_k_most_frequent_words_test.rb b/strings/max_k_most_frequent_words_test.rb new file mode 100644 index 00000000..a6397fc3 --- /dev/null +++ b/strings/max_k_most_frequent_words_test.rb @@ -0,0 +1,28 @@ +require 'minitest/autorun' +require_relative 'max_k_most_frequent_words' + +class TestMaxKMostFrequentWords < Minitest::Test + def test_top_3_frequent_words + assert max_k_most_frequent_words(['a', 'b', 'c', 'a', 'c', 'c'], 3) == ['c', 'a', 'b'] + end + + def test_top_2_frequent_words + assert max_k_most_frequent_words(['a', 'b', 'c', 'a', 'c', 'c'], 2) == ['c', 'a'] + end + + def test_top_frequent_word + assert max_k_most_frequent_words(['a', 'b', 'c', 'a', 'c', 'c'], 1) == ['c'] + end + + def test_no_frequent_word_given_zero_k + assert max_k_most_frequent_words(['a', 'b', 'c', 'a', 'c', 'c'], 0) == [] + end + + def test_no_frequent_word_given_empty_word_list + assert max_k_most_frequent_words([], 1) == [] + end + + def test_all_frequent_words_given_k_too_large + assert max_k_most_frequent_words(['a', 'a'], 2) == ['a'] + end +end From e2f6bd95940aeef38f6a55964acd0b28919952ad Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Fri, 10 Feb 2023 03:55:53 +0000 Subject: [PATCH 29/94] updating DIRECTORY.md --- DIRECTORY.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index b2ce68eb..51a0e9e7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -205,3 +205,7 @@ * [Shell Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/shell_sort_test.rb) * [Sort Color](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/sort_color.rb) * [Sort Tests](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/sort_tests.rb) + +## Strings + * [Max K Most Frequent Words](https://github.com/TheAlgorithms/Ruby/blob/master/strings/max_k_most_frequent_words.rb) + * [Max K Most Frequent Words Test](https://github.com/TheAlgorithms/Ruby/blob/master/strings/max_k_most_frequent_words_test.rb) From 7ca6ac71142f22fb63024167adafd778e8c63110 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Sun, 12 Feb 2023 11:13:24 +0100 Subject: [PATCH 30/94] Adding `counting sort` implementation --- sorting/counting_sort.rb | 26 ++++++++++++++++++++++ sorting/counting_sort_test.rb | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 sorting/counting_sort.rb create mode 100644 sorting/counting_sort_test.rb diff --git a/sorting/counting_sort.rb b/sorting/counting_sort.rb new file mode 100644 index 00000000..a50f6365 --- /dev/null +++ b/sorting/counting_sort.rb @@ -0,0 +1,26 @@ +## +# Given a non-negative integer value_upper_bound and an array of integers arr with values between 0 and value_upper_bound, +# returns a sorted copy of the input array. +# When value_upper_bound = O(arr.length), sorting runs in O(arr.length). + +def counting_sort(arr, value_upper_bound) + if !value_upper_bound.integer? || value_upper_bound < 0 + raise ArgumentError.new("counting_sort must be invoked with integer value_upper_bound >= 0") + end + if !arr.all? { |elem| elem.integer? && elem.between?(0, value_upper_bound) } + raise ArgumentError.new("counting_sort must be invoked with integer array elements in (0..value_upper_bound)") + end + sorted_arr = Array.new(arr.length) { 0 } + tmp_arr = Array.new(value_upper_bound+1) { 0 } + for elem in arr + tmp_arr[elem] += 1 + end + for i in 1..value_upper_bound + tmp_arr[i] += tmp_arr[i-1] + end + arr.reverse_each do |elem| + sorted_arr[tmp_arr[elem]-1] = elem + tmp_arr[elem] -= 1 + end + sorted_arr +end diff --git a/sorting/counting_sort_test.rb b/sorting/counting_sort_test.rb new file mode 100644 index 00000000..8cabfba4 --- /dev/null +++ b/sorting/counting_sort_test.rb @@ -0,0 +1,42 @@ +require 'minitest/autorun' +require_relative 'counting_sort' + +class TestCountingSort < Minitest::Test + def test_empty_array_given_empty_array + assert counting_sort([], 1).empty? + end + + def test_array_sorted_correctly + assert counting_sort([1, 5, 3, 0, 4, 2, 4], 5) == [0, 1, 2, 3, 4, 4, 5] + end + + def test_exception_given_non_integer_upper_bound + assert_raises ArgumentError do + counting_sort([1, 3, 2], 5.5) + end + end + + def test_exception_given_negative_upper_bound + assert_raises ArgumentError do + counting_sort([1, 3, 2], -1) + end + end + + def test_exception_given_non_integer_elements + assert_raises ArgumentError do + counting_sort([1, 3, 2.5], 5) + end + end + + def test_exception_given_negative_elements + assert_raises ArgumentError do + counting_sort([1, 3, -2], 5) + end + end + + def test_exception_given_elements_above_upper_bound + assert_raises ArgumentError do + counting_sort([1, 3, 6], 5) + end + end +end From 74f8c496c1bd148301f023334454e5a159ee5c98 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Thu, 16 Feb 2023 23:17:53 +0100 Subject: [PATCH 31/94] Adding BinarySearchTree implementation --- data_structures/binary_trees/bst.rb | 176 +++++++++++++++++++++++ data_structures/binary_trees/bst_test.rb | 112 +++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 data_structures/binary_trees/bst.rb create mode 100644 data_structures/binary_trees/bst_test.rb diff --git a/data_structures/binary_trees/bst.rb b/data_structures/binary_trees/bst.rb new file mode 100644 index 00000000..3ec5aab0 --- /dev/null +++ b/data_structures/binary_trees/bst.rb @@ -0,0 +1,176 @@ +class BinarySearchTreeNode + + attr_reader :key + attr_accessor :left + attr_accessor :right + + def initialize(key) + @key = key + end +end + +## +# This class represents a binary search tree (not implementing self-balancing) with distinct node keys. +# Starting from the root, every node has up to two children (one left and one right child node). +# +# For the BST property: +# - the keys of nodes in the left subtree of a node are strictly less than the key of the node; +# - the keys of nodes in the right subtree of a node are strictly greater than the key of the node. +# +# The main operations of this data structure (insertion, deletion, membership) run - in worst case - in O(n), +# where n is the number of nodes in the tree. +# The average case for those operations is O(log(n)) due to the structure of the tree. + +class BinarySearchTree + + attr_reader :size + attr_accessor :root + + def initialize(keys=[]) + @size = 0 + keys.each {|key| insert_key(key) } + end + + def empty? + size == 0 + end + + def insert_key(key) + @size += 1 + if root.nil? + @root = BinarySearchTreeNode.new(key) + return + end + parent = root + while (key < parent.key && !parent.left.nil? && parent.left.key != key) || + (key > parent.key && !parent.right.nil? && parent.right.key != key) + parent = key < parent.key ? parent.left : parent.right + end + if key < parent.key + raise ArgumentError.new("Key #{key} is already present in the BinarySearchTree") unless parent.left.nil? + parent.left = BinarySearchTreeNode.new(key) + else + raise ArgumentError.new("Key #{key} is already present in the BinarySearchTree") unless parent.right.nil? + parent.right = BinarySearchTreeNode.new(key) + end + end + + def min_key(node=root) + return nil if node.nil? + min_key_node(node).key + end + + def max_key(node=root) + return nil if node.nil? + max_key_node(node).key + end + + def contains_key?(key) + !find_node_with_key(key).nil? + end + + def delete_key(key) + parent = find_parent_of_node_with_key(key) + if parent.nil? + return if root.nil? || root.key != key + @size -= 1 + @root = adjusted_subtree_after_deletion(root.left, root.right) + return + end + if key < parent.key + node = parent.left + parent.left = adjusted_subtree_after_deletion(node.left, node.right) + else + node = parent.right + parent.right = adjusted_subtree_after_deletion(node.left, node.right) + end + @size -= 1 + end + + def traverse_preorder(key_consumer, node=root) + return if node.nil? + key_consumer.call(node.key) + traverse_preorder(key_consumer, node.left) unless node.left.nil? + traverse_preorder(key_consumer, node.right) unless node.right.nil? + end + + def traverse_inorder(key_consumer, node=root) + return if node.nil? + traverse_inorder(key_consumer, node.left) unless node.left.nil? + key_consumer.call(node.key) + traverse_inorder(key_consumer, node.right) unless node.right.nil? + end + + def traverse_postorder(key_consumer, node=root) + return if node.nil? + traverse_postorder(key_consumer, node.left) unless node.left.nil? + traverse_postorder(key_consumer, node.right) unless node.right.nil? + key_consumer.call(node.key) + end + + def to_array(visit_traversal=:traverse_preorder) + visited = [] + method(visit_traversal).call(->(key) { visited.append(key) }) + visited + end + + private + def min_key_node(node=root) + return nil if node.nil? + until node.left.nil? + node = node.left + end + node + end + + def max_key_node(node=root) + return nil if node.nil? + until node.right.nil? + node = node.right + end + node + end + + def find_node_with_key(key) + node = root + until node.nil? || node.key == key + node = key < node.key ? node.left : node.right + end + node + end + + def find_parent_of_node_with_key(key) + return nil if root.nil? || root.key == key + parent = root + until parent.nil? + if key < parent.key + return nil if parent.left.nil? + return parent if parent.left.key == key + parent = parent.left + else + return nil if parent.right.nil? + return parent if parent.right.key == key + parent = parent.right + end + end + nil + end + + def adjusted_subtree_after_deletion(left, right) + return right if left.nil? + return left if right.nil? + if right.left.nil? + right.left = left + return right + end + successor_parent = right + until successor_parent.left.left.nil? + successor_parent = successor_parent.left + end + successor = successor_parent.left + successor_parent.left = successor.right + successor.right = right + successor.left = left + successor + end +end diff --git a/data_structures/binary_trees/bst_test.rb b/data_structures/binary_trees/bst_test.rb new file mode 100644 index 00000000..5a761dde --- /dev/null +++ b/data_structures/binary_trees/bst_test.rb @@ -0,0 +1,112 @@ +require 'minitest/autorun' +require_relative 'bst' + +class TestBinarySearchTree < Minitest::Test + def test_default_constructor_creates_empty_tree + bst = BinarySearchTree.new + assert bst.to_array.empty? + end + + def test_default_constructor_creates_tree_with_given_keys + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + assert bst.to_array == [4, 2, 1, 3, 6] + end + + def test_exception_when_inserting_key_already_present + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + assert_raises ArgumentError do + bst.insert_key(6) + end + end + + def test_size_returns_zero_given_empty_tree + bst = BinarySearchTree.new + assert bst.size == 0 + end + + def test_empty_returns_number_of_nodes_in_tree + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + assert bst.size == 5 + end + + def test_empty_returns_true_given_empty_tree + bst = BinarySearchTree.new + assert bst.empty? + end + + def test_empty_returns_false_given_non_empty_tree + bst = BinarySearchTree.new([1]) + assert !bst.empty? + end + + def test_min_key_returns_minimum_key + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + assert bst.min_key == 1 + end + + def test_max_key_returns_maximum_key + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + assert bst.max_key == 6 + end + + def test_contains_key_returns_true_if_key_in_tree + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + assert bst.contains_key?(3) + end + + def test_contains_key_returns_false_if_key_not_in_tree + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + assert !bst.contains_key?(7) + end + + def test_delete_key_does_nothing_if_key_not_in_tree + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + bst.delete_key(7) + assert bst.to_array == [4, 2, 1, 3, 6] + end + + def test_delete_key_keeps_bst_property_if_leaf_node + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + bst.delete_key(1) + assert bst.to_array == [4, 2, 3, 6] + end + + def test_delete_key_keeps_bst_property_if_node_with_left_child + bst = BinarySearchTree.new([4, 2, 3, 1]) + bst.delete_key(4) + assert bst.to_array == [2, 1, 3] + end + + def test_delete_key_keeps_bst_property_if_node_with_right_child + bst = BinarySearchTree.new([4, 2, 6, 3]) + bst.delete_key(2) + assert bst.to_array == [4, 3, 6] + end + + def test_delete_key_keeps_bst_property_if_node_with_both_children + bst = BinarySearchTree.new([4, 2, 7, 3, 1, 5, 10, 6]) + bst.delete_key(4) + assert bst.to_array == [5, 2, 1, 3, 7, 6, 10] + end + + def test_preorder_traversal_uses_expected_order + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + visited = [] + bst.traverse_preorder(->(key) { visited.append(key) }) + assert visited == [4, 2, 1, 3, 6] + end + + def test_inorder_traversal_uses_expected_order + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + visited = [] + bst.traverse_inorder(->(key) { visited.append(key) }) + assert visited == [1, 2, 3, 4, 6] + end + + def test_postorder_traversal_uses_expected_order + bst = BinarySearchTree.new([4, 2, 6, 3, 1]) + visited = [] + bst.traverse_postorder(->(key) { visited.append(key) }) + assert visited == [1, 3, 2, 6, 4] + end +end From 286c0e4dde6b931bd5ab6cec791a7a9e03b543ba Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Fri, 17 Feb 2023 23:07:55 +0100 Subject: [PATCH 32/94] Adding AVL Tree implementation --- data_structures/binary_trees/avl_tree.rb | 281 ++++++++++++++++++ data_structures/binary_trees/avl_tree_test.rb | 132 ++++++++ 2 files changed, 413 insertions(+) create mode 100644 data_structures/binary_trees/avl_tree.rb create mode 100644 data_structures/binary_trees/avl_tree_test.rb diff --git a/data_structures/binary_trees/avl_tree.rb b/data_structures/binary_trees/avl_tree.rb new file mode 100644 index 00000000..2774e811 --- /dev/null +++ b/data_structures/binary_trees/avl_tree.rb @@ -0,0 +1,281 @@ +class AvlTreeNode + + attr_reader :key + attr_accessor :parent + attr_accessor :left + attr_accessor :right + attr_accessor :height + + def initialize(key, parent=nil) + @key = key + @parent = parent + @height = 1 + end +end + +## +# This class represents an AVL tree (a self-balancing binary search tree) with distinct node keys. +# Starting from the root, every node has up to two children (one left and one right child node). +# +# For the BST property: +# - the keys of nodes in the left subtree of a node are strictly less than the key of the node; +# - the keys of nodes in the right subtree of a node are strictly greater than the key of the node. +# +# Due to self-balancing upon key insertion and deletion, the main operations of this data structure +# (insertion, deletion, membership) run - in worst case - in O(log(n)), where n is the number of nodes in the tree. + +class AvlTree + + attr_reader :size + attr_accessor :root + + def initialize(keys=[]) + @size = 0 + keys.each {|key| insert_key(key) } + end + + def empty? + size == 0 + end + + def insert_key(key) + @size += 1 + if root.nil? + @root = AvlTreeNode.new(key) + return + end + parent = root + while (key < parent.key && !parent.left.nil? && parent.left.key != key) || + (key > parent.key && !parent.right.nil? && parent.right.key != key) + parent = key < parent.key ? parent.left : parent.right + end + if key < parent.key + raise ArgumentError.new("Key #{key} is already present in the AvlTree") unless parent.left.nil? + parent.left = AvlTreeNode.new(key, parent) + else + raise ArgumentError.new("Key #{key} is already present in the AvlTree") unless parent.right.nil? + parent.right = AvlTreeNode.new(key, parent) + end + balance(parent) + end + + def min_key(node=root) + return nil if node.nil? + min_key_node(node).key + end + + def max_key(node=root) + return nil if node.nil? + max_key_node(node).key + end + + def contains_key?(key) + !find_node_with_key(key).nil? + end + + def delete_key(key) + parent = find_parent_of_node_with_key(key) + if parent.nil? + return if root.nil? || root.key != key + @size -= 1 + @root = adjusted_subtree_after_deletion(root.left, root.right) + root.parent = nil + balance(root.right.nil? ? root : root.right) + return + end + if key < parent.key + node = parent.left + parent.left = adjusted_subtree_after_deletion(node.left, node.right) + unless parent.left.nil? + parent.left.parent = parent + balance(parent.left.right.nil? ? parent.left : parent.left.right) + end + else + node = parent.right + parent.right = adjusted_subtree_after_deletion(node.left, node.right) + unless parent.right.nil? + parent.right.parent = parent + balance(parent.right.right.nil? ? parent.right : parent.right.right) + end + end + @size -= 1 + end + + def traverse_preorder(key_consumer, node=root) + return if node.nil? + key_consumer.call(node.key) + traverse_preorder(key_consumer, node.left) unless node.left.nil? + traverse_preorder(key_consumer, node.right) unless node.right.nil? + end + + def traverse_inorder(key_consumer, node=root) + return if node.nil? + traverse_inorder(key_consumer, node.left) unless node.left.nil? + key_consumer.call(node.key) + traverse_inorder(key_consumer, node.right) unless node.right.nil? + end + + def traverse_postorder(key_consumer, node=root) + return if node.nil? + traverse_postorder(key_consumer, node.left) unless node.left.nil? + traverse_postorder(key_consumer, node.right) unless node.right.nil? + key_consumer.call(node.key) + end + + def to_array(visit_traversal=:traverse_preorder) + visited = [] + method(visit_traversal).call(->(key) { visited.append(key) }) + visited + end + + private + def min_key_node(node=root) + return nil if node.nil? + until node.left.nil? + node = node.left + end + node + end + + def max_key_node(node=root) + return nil if node.nil? + until node.right.nil? + node = node.right + end + node + end + + def find_node_with_key(key) + node = root + until node.nil? || node.key == key + node = key < node.key ? node.left : node.right + end + node + end + + def find_parent_of_node_with_key(key) + return nil if root.nil? || root.key == key + parent = root + until parent.nil? + if key < parent.key + return nil if parent.left.nil? + return parent if parent.left.key == key + parent = parent.left + else + return nil if parent.right.nil? + return parent if parent.right.key == key + parent = parent.right + end + end + nil + end + + def adjusted_subtree_after_deletion(left, right) + return right if left.nil? + return left if right.nil? + if right.left.nil? + right.left = left + left.parent = right + return right + end + successor_parent = right + until successor_parent.left.left.nil? + successor_parent = successor_parent.left + end + successor = successor_parent.left + successor_parent.left = successor.right + successor.right.parent = successor_parent unless successor.right.nil? + successor.right = right + right.parent = successor + successor.left = left + left.parent = successor + successor + end + + def balance(node) + return if node.nil? + left_height = node.left&.height || 0 + right_height = node.right&.height || 0 + # Assumption: the subtrees rooted at `node.left` and `node.right` are balanced + adjust_height(node) + if right_height - left_height > 1 + # `node` is right-heavy + if !node.right.left.nil? && (node.right.left.height || 0) > (node.right.right&.height || 0) + rotate_right_left(node) + else + rotate_left(node) + end + elsif left_height - right_height > 1 + # `node` is left-heavy + if !node.left.right.nil? && (node.left.right.height || 0) > (node.left.left&.height || 0) + rotate_left_right(node) + else + rotate_right(node) + end + end + + balance(node.parent) + end + + def rotate_left(node) + new_root = node.right + if node == root + @root = new_root + elsif node.parent.left == node + node.parent.left = new_root + else + node.parent.right = new_root + end + new_root.parent = node.parent + if new_root.left.nil? + node.right = nil + new_root.left = node + node.parent = new_root + else + node.right = new_root.left + new_root.left.parent = node + new_root.left = node + node.parent = new_root + end + adjust_height(node) + adjust_height(new_root) + end + + def rotate_right(node) + new_root = node.left + if node == root + @root = new_root + elsif node.parent.left == node + node.parent.left = new_root + else + node.parent.right = new_root + end + new_root.parent = node.parent + if new_root.right.nil? + node.left = nil + new_root.right = node + node.parent = new_root + else + node.left = new_root.right + new_root.right.parent = node + new_root.right = node + node.parent = new_root + end + adjust_height(node) + adjust_height(new_root) + end + + def rotate_right_left(node) + rotate_right(node.right) + rotate_left(node) + end + + def rotate_left_right(node) + rotate_left(node.left) + rotate_right(node) + end + + def adjust_height(node) + node.height = 1 + [node.left&.height || 0, node.right&.height || 0].max + end +end diff --git a/data_structures/binary_trees/avl_tree_test.rb b/data_structures/binary_trees/avl_tree_test.rb new file mode 100644 index 00000000..df577f3b --- /dev/null +++ b/data_structures/binary_trees/avl_tree_test.rb @@ -0,0 +1,132 @@ +require 'minitest/autorun' +require_relative 'avl_tree' + +class TestAvlTree < Minitest::Test + def test_default_constructor_creates_empty_tree + tree = AvlTree.new + assert tree.to_array.empty? + end + + def test_default_constructor_creates_tree_with_given_keys + tree = AvlTree.new([1, 2, 3, 4, 5, 6, 7]) + assert tree.to_array == [4, 2, 1, 3, 6, 5, 7] + end + + def test_exception_when_inserting_key_already_present + tree = AvlTree.new([4, 2, 6, 3, 1]) + assert_raises ArgumentError do + tree.insert_key(6) + end + end + + def test_size_returns_zero_given_empty_tree + tree = AvlTree.new + assert tree.size == 0 + end + + def test_empty_returns_number_of_nodes_in_tree + tree = AvlTree.new([4, 2, 6, 3, 1]) + assert tree.size == 5 + end + + def test_empty_returns_true_given_empty_tree + tree = AvlTree.new + assert tree.empty? + end + + def test_empty_returns_false_given_non_empty_tree + tree = AvlTree.new([1]) + assert !tree.empty? + end + + def test_min_key_returns_minimum_key + tree = AvlTree.new([4, 2, 6, 3, 1]) + assert tree.min_key == 1 + end + + def test_max_key_returns_maximum_key + tree = AvlTree.new([4, 2, 6, 3, 1]) + assert tree.max_key == 6 + end + + def test_contains_key_returns_true_if_key_in_tree + tree = AvlTree.new([4, 2, 6, 3, 1]) + assert tree.contains_key?(3) + end + + def test_contains_key_returns_false_if_key_not_in_tree + tree = AvlTree.new([4, 2, 6, 3, 1]) + assert !tree.contains_key?(7) + end + + def test_delete_key_does_nothing_if_key_not_in_tree + tree = AvlTree.new([4, 2, 6, 3, 1]) + tree.delete_key(7) + assert tree.to_array == [4, 2, 1, 3, 6] + end + + def test_delete_key_keeps_avl_property_if_leaf_node + tree = AvlTree.new([1, 2, 3, 4, 5, 6, 7]) + tree.delete_key(3) + assert tree.to_array == [4, 2, 1, 6, 5, 7] + end + + def test_delete_key_keeps_avl_property_if_node_with_left_child + tree = AvlTree.new([4, 2, 5, 1]) + tree.delete_key(2) + assert tree.to_array == [4, 1, 5] + end + + def test_delete_key_keeps_avl_property_if_node_with_right_child + tree = AvlTree.new([4, 2, 5, 6]) + tree.delete_key(5) + assert tree.to_array == [4, 2, 6] + end + + def test_delete_key_keeps_avl_property_if_node_with_both_children + tree = AvlTree.new([1, 2, 3, 4, 5, 6, 7, 8, 9]) + tree.delete_key(4) + assert tree.to_array == [5, 2, 1, 3, 8, 6, 7, 9] + end + + def test_preorder_traversal_uses_expected_order + tree = AvlTree.new([1, 2, 3, 4, 5, 6, 7]) + visited = [] + tree.traverse_preorder(->(key) { visited.append(key) }) + assert visited == [4, 2, 1, 3, 6, 5, 7] + end + + def test_inorder_traversal_uses_expected_order + tree = AvlTree.new([1, 2, 3, 4, 5, 6, 7]) + visited = [] + tree.traverse_inorder(->(key) { visited.append(key) }) + assert visited == [1, 2, 3, 4, 5, 6, 7] + end + + def test_postorder_traversal_uses_expected_order + tree = AvlTree.new([1, 2, 3, 4, 5, 6, 7]) + visited = [] + tree.traverse_postorder(->(key) { visited.append(key) }) + assert visited == [1, 3, 2, 5, 7, 6, 4] + end + + def test_left_rotation + tree = AvlTree.new([1, 2, 3]) + assert tree.to_array == [2, 1, 3] + end + + def test_right_rotation + tree = AvlTree.new([3, 2, 1]) + assert tree.to_array == [2, 1, 3] + end + + def test_right_left_rotation + tree = AvlTree.new([1, 3, 2]) + assert tree.to_array == [2, 1, 3] + end + + def test_left_right_rotation + tree = AvlTree.new([3, 1, 2]) + assert tree.to_array == [2, 1, 3] + end +end From 612f4bfa3226bd91c60b58deb07e1e06562157de Mon Sep 17 00:00:00 2001 From: domix80 Date: Sun, 19 Feb 2023 10:41:20 +0100 Subject: [PATCH 33/94] Feat: Project Euler Problem 6 --- DIRECTORY.md | 2 ++ project_euler/problem_006/sol1.rb | 35 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 project_euler/problem_006/sol1.rb diff --git a/DIRECTORY.md b/DIRECTORY.md index 51a0e9e7..59f47c06 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,6 +153,8 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) + * Problem 006 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_006/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 diff --git a/project_euler/problem_006/sol1.rb b/project_euler/problem_006/sol1.rb new file mode 100644 index 00000000..28de45ce --- /dev/null +++ b/project_euler/problem_006/sol1.rb @@ -0,0 +1,35 @@ +#Project Euler Problem 6: #https://projecteuler.net/problem=6 + +#Sum square difference + +#The sum of the squares of the first ten natural numbers #is, +# 1^2 + 2^2 + ... + 10^2 = 385 +#The square of the sum of the first ten natural numbers #is, +# (1 + 2 + ... + 10)^2 = 55^2 = 3025 +#Hence the difference between the sum of the squares of #the first ten +#natural numbers and the square of the sum is 3025 - 385 = 2640. +#Find the difference between the sum of the squares of the first one +#hundred natural numbers and the square of the sum. + +def solution?(num) + x = 1 + y = 1 + result = 1 + gap = 3 + while y < num + x += gap + gap += 2 + y += 1 + result += x + end + r_n_pow2_plus_n_pow2 = result + r_sum_n_pow2 = (((num / 2) + 0.5) * num) ** 2 + + r_sum_n_pow2 - r_n_pow2_plus_n_pow2 +end + +answer = 0 +answer = solution?(10) + + +p answer From bc455a62c56d58eeab636dba6ee77234acfa9661 Mon Sep 17 00:00:00 2001 From: domix80 Date: Sun, 19 Feb 2023 11:30:30 +0100 Subject: [PATCH 34/94] Feat: Project Euler Problem 7 --- DIRECTORY.md | 2 ++ project_euler/problem_007/sol1.rb | 40 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 project_euler/problem_007/sol1.rb diff --git a/DIRECTORY.md b/DIRECTORY.md index 51a0e9e7..2fb4b772 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,6 +153,8 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) + * Problem 007 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_007/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 diff --git a/project_euler/problem_007/sol1.rb b/project_euler/problem_007/sol1.rb new file mode 100644 index 00000000..a249557c --- /dev/null +++ b/project_euler/problem_007/sol1.rb @@ -0,0 +1,40 @@ +#Project Euler Problem 7: #https://projecteuler.net/problem=7 +#10001st prime +#By listing the first six prime numbers: 2, 3, 5, 7, 11, #and 13, we +#can see that the 6th prime is 13. +#What is the 10001st prime number? +#References: https://en.wikipedia.org/wiki/Prime_number + +def is_prime?(number) + value = true + if number > 1 and number < 4 + # 2 and 3 are primes + value = true + elsif number < 2 or number % 2 == 0 or number % 3 == 0 + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + value = false + end + end_range = (Math.sqrt(number) + 1).to_i + # All primes number are in format of 6k +/- 1 + for i in (5..end_range).step(6) + if number % i == 0 or number % (i + 2) == 0 + value = false + end + end + result = value +end + +def solution?(nth) + primes = Array.new() + num = 2 + while primes.length < nth + if is_prime?(num) + primes.append(num) + end + num += 1 + end + primes[primes.length - 1] +end + +answer = solution?(1001) +p answer \ No newline at end of file From 5ee0eef4ffff80773c59dc680af9a91ec15b50b8 Mon Sep 17 00:00:00 2001 From: domix80 Date: Sun, 19 Feb 2023 11:35:53 +0100 Subject: [PATCH 35/94] Change the testing number --- project_euler/problem_007/sol1.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project_euler/problem_007/sol1.rb b/project_euler/problem_007/sol1.rb index a249557c..aba7f60d 100644 --- a/project_euler/problem_007/sol1.rb +++ b/project_euler/problem_007/sol1.rb @@ -36,5 +36,5 @@ def solution?(nth) primes[primes.length - 1] end -answer = solution?(1001) +answer = solution?(10001) p answer \ No newline at end of file From c672adfe082f6ab4f93fe8cacb31de3bab58a293 Mon Sep 17 00:00:00 2001 From: domix80 Date: Sun, 19 Feb 2023 11:47:44 +0100 Subject: [PATCH 36/94] Feat: Project Euler Problem 10 --- DIRECTORY.md | 2 ++ project_euler/problem_010/sol1.rb | 42 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 project_euler/problem_010/sol1.rb diff --git a/DIRECTORY.md b/DIRECTORY.md index 51a0e9e7..f523f179 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,6 +153,8 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) + * Problem 010 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_010/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 diff --git a/project_euler/problem_010/sol1.rb b/project_euler/problem_010/sol1.rb new file mode 100644 index 00000000..a173ac60 --- /dev/null +++ b/project_euler/problem_010/sol1.rb @@ -0,0 +1,42 @@ +#Project Euler Problem 10: #https://projecteuler.net/problem=10 +#Summation of primes +#The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. +#Find the sum of all the primes below two million. +#References: - https://en.wikipedia.org/wiki/Prime_number +def is_prime?(number) + value = true + if number > 1 and number < 4 + # 2 and 3 are primes + value = true + elsif number < 2 or number % 2 == 0 or number % 3 == 0 + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + value = false + end + end_range = (Math.sqrt(number) + 1).to_i + # All primes number are in format of 6k +/- 1 + for i in (5..end_range).step(6) + if number % i == 0 or number % (i + 2) == 0 + value = false + end + end + result = value +end + +def solution?(max_total) + sum = 1 + num = 2 + value = 1 + while num < max_total and value < max_total + if is_prime?(num) + value += num + if value < max_total + sum = value + end + end + num += 1 + end + result = sum +end + +answer = solution?(2000000) +p answer \ No newline at end of file From e8105e4e5f09cafece05839a658b75d8b06b406f Mon Sep 17 00:00:00 2001 From: domix80 Date: Sun, 19 Feb 2023 13:05:45 +0100 Subject: [PATCH 37/94] Feat: Project Euler Problem 25 --- DIRECTORY.md | 2 ++ project_euler/problem_025/sol1.rb | 45 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 project_euler/problem_025/sol1.rb diff --git a/DIRECTORY.md b/DIRECTORY.md index 51a0e9e7..1c733fe0 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -159,6 +159,8 @@ * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_021/sol1.rb) * Problem 022 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_022/sol1.rb) + * Problem 025 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_025/sol1.rb) ## Searches * [Binary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/binary_search.rb) diff --git a/project_euler/problem_025/sol1.rb b/project_euler/problem_025/sol1.rb new file mode 100644 index 00000000..e13e53bd --- /dev/null +++ b/project_euler/problem_025/sol1.rb @@ -0,0 +1,45 @@ +#The Fibonacci sequence is defined by the recurrence relation: +# Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1. +#Hence the first 12 terms will be: +# +# F1 = 1 +# F2 = 1 +# F3 = 2 +# F4 = 3 +# F5 = 5 +# F7 = 13 +# F8 = 21 +# F6 = 8 +# F9 = 34 +# F10 = 55 +# F11 = 89 +# F12 = 144 +# +#The 12th term, F12, is the first term to contain three digits. +#What is the index of the first term in the Fibonacci sequence to contain 1000 digits? + +def solution?() + #Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1. + resultn1 = 1 + resultn2 = 1 + result = 2 + index = 3 + num_digits = 1000 + value = true + while value + resultn2 = resultn1 + resultn1 = result + if (resultn1 + resultn2).abs.digits.length < num_digits + value = true + else + value = false + end + result = resultn1 + resultn2 + index += 1 + end + res = index +end + +answer = solution?() +p answer + \ No newline at end of file From 14f538a8cfd76180863b498cb82bdd2452126233 Mon Sep 17 00:00:00 2001 From: domix80 Date: Sun, 19 Feb 2023 14:05:13 +0100 Subject: [PATCH 38/94] Feat: Project Euler Problem 14 --- DIRECTORY.md | 2 ++ project_euler/problem_014/sol1.rb | 42 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 project_euler/problem_014/sol1.rb diff --git a/DIRECTORY.md b/DIRECTORY.md index 51a0e9e7..b5f5cb20 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,6 +153,8 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) + * Problem 014 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_014/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 diff --git a/project_euler/problem_014/sol1.rb b/project_euler/problem_014/sol1.rb new file mode 100644 index 00000000..44ae22f6 --- /dev/null +++ b/project_euler/problem_014/sol1.rb @@ -0,0 +1,42 @@ +#Problem 14: https://projecteuler.net/problem=14 + +#Problem Statement: +#The following iterative sequence is defined for the set of positive integers: +# +# n → n/2 (n is even) +# n → 3n + 1 (n is odd) +# +#Using the rule above and starting with 13, we generate the following sequence: +# +# 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1 +# +#It can be seen that this sequence (starting at 13 and finishing at 1) contains +#10 terms. Although it has not been proved yet (Collatz Problem), it is thought +#that all starting numbers finish at 1. + +#Which starting number, under one million, produces the longest chain? + +def solution?() + index_best_result = 0 + for num in 2..1000000 + index_candidate = 0 + n = num + while n > 1 + if n%2 == 0 + n = n / 2 + else + n = (3*n) + 1 + end + index_candidate +=1 + end + if index_best_result < index_candidate + index_best_result = index_candidate + value = num + end + end + result = value +end + +answer = solution?() +p answer + \ No newline at end of file From de8a63dbc92578a6a7b9b8a42d30afc75307f497 Mon Sep 17 00:00:00 2001 From: domix80 Date: Mon, 20 Feb 2023 21:14:50 +0100 Subject: [PATCH 39/94] Update DIRECTORY.md --- DIRECTORY.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 2fb4b772..51a0e9e7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,8 +153,6 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) - * Problem 007 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_007/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From 7804fad30f3d899fdce4db2626cd48b2bd4915e2 Mon Sep 17 00:00:00 2001 From: domix80 Date: Mon, 20 Feb 2023 21:16:11 +0100 Subject: [PATCH 40/94] Update DIRECTORY.md --- DIRECTORY.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index f523f179..51a0e9e7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,8 +153,6 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) - * Problem 010 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_010/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From 3168a992396c23a5b8cbcbba71fdd49f598686a4 Mon Sep 17 00:00:00 2001 From: domix80 Date: Mon, 20 Feb 2023 21:16:48 +0100 Subject: [PATCH 41/94] Update DIRECTORY.md --- DIRECTORY.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index b5f5cb20..db241904 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -152,9 +152,7 @@ * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol1.rb) * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) - * Problem 014 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_014/sol1.rb) + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From 740ed1795a23c99a6aa8ac5cb608db17812daebe Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 16:24:55 +0100 Subject: [PATCH 42/94] Update DIRECTORY.md Co-authored-by: Amos Paribocci --- DIRECTORY.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 59f47c06..51a0e9e7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,8 +153,6 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) - * Problem 006 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_006/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From 95930cc22925d40a7d9e004ec2838916676af0d3 Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:12:39 +0100 Subject: [PATCH 43/94] Update solution file and remove link from directory --- DIRECTORY.md | 2 -- project_euler/problem_006/sol1.rb | 8 +++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 59f47c06..51a0e9e7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,8 +153,6 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) - * Problem 006 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_006/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 diff --git a/project_euler/problem_006/sol1.rb b/project_euler/problem_006/sol1.rb index 28de45ce..a243852e 100644 --- a/project_euler/problem_006/sol1.rb +++ b/project_euler/problem_006/sol1.rb @@ -11,7 +11,8 @@ #Find the difference between the sum of the squares of the first one #hundred natural numbers and the square of the sum. -def solution?(num) +def solution?() + num = 10 x = 1 y = 1 result = 1 @@ -28,8 +29,5 @@ def solution?(num) r_sum_n_pow2 - r_n_pow2_plus_n_pow2 end -answer = 0 -answer = solution?(10) - - +answer = solution?() p answer From b6b58732478c83f0d49e62f87362205f98272127 Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:17:13 +0100 Subject: [PATCH 44/94] Update sol1.rb Follow the guidelines --- project_euler/problem_007/sol1.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/project_euler/problem_007/sol1.rb b/project_euler/problem_007/sol1.rb index aba7f60d..20f14c6f 100644 --- a/project_euler/problem_007/sol1.rb +++ b/project_euler/problem_007/sol1.rb @@ -24,7 +24,8 @@ def is_prime?(number) result = value end -def solution?(nth) +def solution?() + nth = 10001 primes = Array.new() num = 2 while primes.length < nth @@ -36,5 +37,5 @@ def solution?(nth) primes[primes.length - 1] end -answer = solution?(10001) +answer = solution?() p answer \ No newline at end of file From fa6ebf5f78abccd858f8f82a2931bd6c1e15b358 Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:18:37 +0100 Subject: [PATCH 45/94] Update sol1.rb follow the guideline --- project_euler/problem_010/sol1.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/project_euler/problem_010/sol1.rb b/project_euler/problem_010/sol1.rb index a173ac60..7a0a68e4 100644 --- a/project_euler/problem_010/sol1.rb +++ b/project_euler/problem_010/sol1.rb @@ -22,7 +22,8 @@ def is_prime?(number) result = value end -def solution?(max_total) +def solution?() + max_total = 2000000 sum = 1 num = 2 value = 1 @@ -38,5 +39,5 @@ def solution?(max_total) result = sum end -answer = solution?(2000000) +answer = solution?() p answer \ No newline at end of file From 1b45e7bc0b80f8345ca2e5cb5d8a1018b802a75f Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:19:48 +0100 Subject: [PATCH 46/94] Update DIRECTORY.md Remove the link from Directory.md --- DIRECTORY.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 1c733fe0..d7028960 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -158,9 +158,7 @@ * Problem 021 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_021/sol1.rb) * Problem 022 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_022/sol1.rb) - * Problem 025 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_025/sol1.rb) + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_022/sol1.rb) ## Searches * [Binary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/binary_search.rb) From bb5df875377e3c9d4dfb918e8b554cde9b6b3a19 Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:36:46 +0100 Subject: [PATCH 47/94] Update project_euler/problem_006/sol1.rb Co-authored-by: Amos Paribocci --- project_euler/problem_006/sol1.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/project_euler/problem_006/sol1.rb b/project_euler/problem_006/sol1.rb index a243852e..b00c9e78 100644 --- a/project_euler/problem_006/sol1.rb +++ b/project_euler/problem_006/sol1.rb @@ -11,8 +11,7 @@ #Find the difference between the sum of the squares of the first one #hundred natural numbers and the square of the sum. -def solution?() - num = 10 +def solution(num=10) x = 1 y = 1 result = 1 @@ -29,5 +28,5 @@ def solution?() r_sum_n_pow2 - r_n_pow2_plus_n_pow2 end -answer = solution?() +answer = solution() p answer From 0db648a4d6a61c918044ffd71cd416c636544c1d Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:39:37 +0100 Subject: [PATCH 48/94] Update sol1.rb --- project_euler/problem_007/sol1.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/project_euler/problem_007/sol1.rb b/project_euler/problem_007/sol1.rb index 20f14c6f..44bacca8 100644 --- a/project_euler/problem_007/sol1.rb +++ b/project_euler/problem_007/sol1.rb @@ -24,8 +24,7 @@ def is_prime?(number) result = value end -def solution?() - nth = 10001 +def solution(nth = 10001) primes = Array.new() num = 2 while primes.length < nth @@ -37,5 +36,5 @@ def solution?() primes[primes.length - 1] end -answer = solution?() +answer = solution() p answer \ No newline at end of file From 90101189b119b99c92bd8e371d54b7c1159ad9a9 Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:40:19 +0100 Subject: [PATCH 49/94] Update sol1.rb --- project_euler/problem_010/sol1.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/project_euler/problem_010/sol1.rb b/project_euler/problem_010/sol1.rb index 7a0a68e4..1d7b37db 100644 --- a/project_euler/problem_010/sol1.rb +++ b/project_euler/problem_010/sol1.rb @@ -22,8 +22,7 @@ def is_prime?(number) result = value end -def solution?() - max_total = 2000000 +def solution(max_total = 2000000) sum = 1 num = 2 value = 1 @@ -39,5 +38,5 @@ def solution?() result = sum end -answer = solution?() +answer = solution() p answer \ No newline at end of file From 61abd3629d5636ed55fdff6c8ca4460f6db98b93 Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:41:48 +0100 Subject: [PATCH 50/94] Update sol1.rb --- project_euler/problem_014/sol1.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project_euler/problem_014/sol1.rb b/project_euler/problem_014/sol1.rb index 44ae22f6..5a50f0eb 100644 --- a/project_euler/problem_014/sol1.rb +++ b/project_euler/problem_014/sol1.rb @@ -16,7 +16,7 @@ #Which starting number, under one million, produces the longest chain? -def solution?() +def solution() index_best_result = 0 for num in 2..1000000 index_candidate = 0 @@ -37,6 +37,6 @@ def solution?() result = value end -answer = solution?() +answer = solution() p answer \ No newline at end of file From 076f202136bbf33a9d2cf0ca452d54be675f6b73 Mon Sep 17 00:00:00 2001 From: domix80 Date: Tue, 21 Feb 2023 18:42:34 +0100 Subject: [PATCH 51/94] Update sol1.rb --- project_euler/problem_025/sol1.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/project_euler/problem_025/sol1.rb b/project_euler/problem_025/sol1.rb index e13e53bd..7a9c7c6a 100644 --- a/project_euler/problem_025/sol1.rb +++ b/project_euler/problem_025/sol1.rb @@ -18,13 +18,12 @@ #The 12th term, F12, is the first term to contain three digits. #What is the index of the first term in the Fibonacci sequence to contain 1000 digits? -def solution?() +def solution(num_digits = 1000) #Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1. resultn1 = 1 resultn2 = 1 result = 2 index = 3 - num_digits = 1000 value = true while value resultn2 = resultn1 @@ -40,6 +39,6 @@ def solution?() res = index end -answer = solution?() +answer = solution() p answer \ No newline at end of file From b5b127173f3c42bf4f13c72a8fcf22c29b73d058 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Wed, 22 Feb 2023 23:40:36 +0000 Subject: [PATCH 52/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 51a0e9e7..dc4ec9ee 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,6 +153,8 @@ * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) + * Problem 006 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_006/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From bb177176165d1b2b3686619681bbabca28c70329 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 23 Feb 2023 05:11:35 +0000 Subject: [PATCH 53/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index dc4ec9ee..87817acc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -52,6 +52,8 @@ * [Two Sum](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/two_sum.rb) * [Two Sum Ii](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/two_sum_ii.rb) * Binary Trees + * [Bst](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/bst.rb) + * [Bst Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/bst_test.rb) * [Inorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/inorder_traversal.rb) * [Invert](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/invert.rb) * [Postorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/postorder_traversal.rb) From c57fe1d3467aa2db2000fb472dbbff5c8a408474 Mon Sep 17 00:00:00 2001 From: domix80 Date: Thu, 23 Feb 2023 16:01:09 +0100 Subject: [PATCH 54/94] Update project_euler/problem_014/sol1.rb Co-authored-by: Stepfen Shawn --- project_euler/problem_014/sol1.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/project_euler/problem_014/sol1.rb b/project_euler/problem_014/sol1.rb index 5a50f0eb..6a671dc8 100644 --- a/project_euler/problem_014/sol1.rb +++ b/project_euler/problem_014/sol1.rb @@ -38,5 +38,4 @@ def solution() end answer = solution() -p answer - \ No newline at end of file +p answer \ No newline at end of file From 4501f7fd99662708bcd688c3a86ac5ac6be9785b Mon Sep 17 00:00:00 2001 From: domix80 Date: Thu, 23 Feb 2023 16:01:35 +0100 Subject: [PATCH 55/94] Update project_euler/problem_010/sol1.rb Co-authored-by: Stepfen Shawn --- project_euler/problem_010/sol1.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project_euler/problem_010/sol1.rb b/project_euler/problem_010/sol1.rb index 1d7b37db..01a98a69 100644 --- a/project_euler/problem_010/sol1.rb +++ b/project_euler/problem_010/sol1.rb @@ -2,7 +2,7 @@ #Summation of primes #The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. #Find the sum of all the primes below two million. -#References: - https://en.wikipedia.org/wiki/Prime_number +#References: https://en.wikipedia.org/wiki/Prime_number def is_prime?(number) value = true if number > 1 and number < 4 From d422a0b8aa71da5364080eb139ecf934addfd268 Mon Sep 17 00:00:00 2001 From: domix80 Date: Thu, 23 Feb 2023 16:01:44 +0100 Subject: [PATCH 56/94] Update project_euler/problem_010/sol1.rb Co-authored-by: Stepfen Shawn --- project_euler/problem_010/sol1.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project_euler/problem_010/sol1.rb b/project_euler/problem_010/sol1.rb index 01a98a69..053fb624 100644 --- a/project_euler/problem_010/sol1.rb +++ b/project_euler/problem_010/sol1.rb @@ -1,4 +1,4 @@ -#Project Euler Problem 10: #https://projecteuler.net/problem=10 +#Project Euler Problem 10: https://projecteuler.net/problem=10 #Summation of primes #The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. #Find the sum of all the primes below two million. From 4420ff4172a87348054b5bbd462a2d3f6c2616f7 Mon Sep 17 00:00:00 2001 From: domix80 Date: Thu, 23 Feb 2023 16:02:35 +0100 Subject: [PATCH 57/94] Update project_euler/problem_007/sol1.rb Co-authored-by: Stepfen Shawn --- project_euler/problem_007/sol1.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project_euler/problem_007/sol1.rb b/project_euler/problem_007/sol1.rb index 44bacca8..b17f1ad7 100644 --- a/project_euler/problem_007/sol1.rb +++ b/project_euler/problem_007/sol1.rb @@ -1,4 +1,4 @@ -#Project Euler Problem 7: #https://projecteuler.net/problem=7 +#Project Euler Problem 7: https://projecteuler.net/problem=7 #10001st prime #By listing the first six prime numbers: 2, 3, 5, 7, 11, #and 13, we #can see that the 6th prime is 13. From 9c3eb0577e0a55fa69046ae699a932267d1674da Mon Sep 17 00:00:00 2001 From: domix80 Date: Thu, 23 Feb 2023 16:02:42 +0100 Subject: [PATCH 58/94] Update project_euler/problem_007/sol1.rb Co-authored-by: Stepfen Shawn --- project_euler/problem_007/sol1.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project_euler/problem_007/sol1.rb b/project_euler/problem_007/sol1.rb index b17f1ad7..1f79cfbc 100644 --- a/project_euler/problem_007/sol1.rb +++ b/project_euler/problem_007/sol1.rb @@ -1,6 +1,6 @@ #Project Euler Problem 7: https://projecteuler.net/problem=7 #10001st prime -#By listing the first six prime numbers: 2, 3, 5, 7, 11, #and 13, we +#By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we #can see that the 6th prime is 13. #What is the 10001st prime number? #References: https://en.wikipedia.org/wiki/Prime_number From 07870b08d61fc2f9f11e8614c1beeaf60ad3367b Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 23 Feb 2023 15:08:18 +0000 Subject: [PATCH 59/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 87817acc..ce186cd9 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -157,6 +157,8 @@ * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) * Problem 006 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_006/sol1.rb) + * Problem 007 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_007/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From 0139f78699f9b9db00ce01466d05e1013a922a96 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 23 Feb 2023 15:09:51 +0000 Subject: [PATCH 60/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index ce186cd9..24e3f1af 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -159,6 +159,8 @@ * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_006/sol1.rb) * Problem 007 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_007/sol1.rb) + * Problem 010 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_010/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From 203fbb7e6b8140dbcc289df29fc50951b9723e31 Mon Sep 17 00:00:00 2001 From: domix80 Date: Thu, 23 Feb 2023 17:10:48 +0100 Subject: [PATCH 61/94] Update DIRECTORY.md Restore original values --- DIRECTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index db241904..51a0e9e7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -152,7 +152,7 @@ * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol1.rb) * [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_004/sol2.rb) * Problem 005 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_005/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From 1dbf6795c31103c2ae59cc205b99e8573980f53b Mon Sep 17 00:00:00 2001 From: domix80 Date: Thu, 23 Feb 2023 20:39:16 +0100 Subject: [PATCH 62/94] Update DIRECTORY.md --- DIRECTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index d7028960..51a0e9e7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -158,7 +158,7 @@ * Problem 021 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_021/sol1.rb) * Problem 022 - * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_022/sol1.rb) + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_022/sol1.rb) ## Searches * [Binary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/binary_search.rb) From 9346d99eeabecfc209ffe1b6e00870248fc46512 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 23 Feb 2023 23:09:21 +0000 Subject: [PATCH 63/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 24e3f1af..796edb31 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -161,6 +161,8 @@ * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_007/sol1.rb) * Problem 010 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_010/sol1.rb) + * Problem 014 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_014/sol1.rb) * Problem 020 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_020/sol1.rb) * Problem 021 From fc19420049a2447f5bc1b06d9cf6b7ccc71956a2 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 23 Feb 2023 23:37:18 +0000 Subject: [PATCH 64/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 796edb31..7f20a0e7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -169,6 +169,8 @@ * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_021/sol1.rb) * Problem 022 * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_022/sol1.rb) + * Problem 025 + * [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_025/sol1.rb) ## Searches * [Binary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/binary_search.rb) From d0c14110de5803cb96c64376e631b9ba6efedd19 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 27 Feb 2023 13:20:36 +0000 Subject: [PATCH 65/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 7f20a0e7..ebe2285a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -199,6 +199,8 @@ * [Cocktail Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/cocktail_sort_test.rb) * [Comb Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/comb_sort.rb) * [Comb Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/comb_sort_test.rb) + * [Counting Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/counting_sort.rb) + * [Counting Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/counting_sort_test.rb) * [Heap Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/heap_sort.rb) * [Heap Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/heap_sort_test.rb) * [Insertion Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/insertion_sort.rb) From bea6a1fc25495c8c4e2d43bfa48d30defdad8b5d Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Thu, 16 Feb 2023 21:54:37 +0100 Subject: [PATCH 66/94] Implementing Boyer-Moore-Horspool substring search algorithm --- strings/boyer_moore_horspool_search.rb | 60 +++++++++++++++++++++ strings/boyer_moore_horspool_search_test.rb | 20 +++++++ 2 files changed, 80 insertions(+) create mode 100644 strings/boyer_moore_horspool_search.rb create mode 100644 strings/boyer_moore_horspool_search_test.rb diff --git a/strings/boyer_moore_horspool_search.rb b/strings/boyer_moore_horspool_search.rb new file mode 100644 index 00000000..78eb7afd --- /dev/null +++ b/strings/boyer_moore_horspool_search.rb @@ -0,0 +1,60 @@ +## +# This class represents a table of {bad_match_character => slide_offset} +# to be used in Boyer-Moore-Horspool substring finding algorithm. + +class BadMatchTable + + attr_reader :pattern + attr_reader :table + + def initialize(pattern) + @pattern = pattern + @table = {} + for i in 0...pattern.size + @table[pattern[i]] = pattern.size - 1 - i + end + end + + ## + # Given a mismatch character belonging to the search string, returns + # the offset to be used when sliding the pattern towards the right. + + def slide_offset(mismatch_char) + table.fetch(mismatch_char, pattern.size) + end +end + +## +# Returns the first starting index of the given pattern's occurrence (as a substring) +# in the provided search string if a match is found, -1 otherwise. + +def first_match_index(search_string, pattern) + matches = matches_indices(search_string, pattern, true) + matches.empty? ? -1 : matches[0] +end + +## +# Returns the list of starting indices of the given pattern's occurrences (as a substring) +# in the provided search string. +# If no match is found, an empty list is returned. +# If `stop_at_first_match` is provided as `true`, the returned list will contain at most one element, +# being the leftmost encountered match in the search string. + +def matches_indices(search_string, pattern, stop_at_first_match=false) + table = BadMatchTable.new(pattern) + i = pattern.size - 1 + indices = [] + while i < search_string.size + for j in 0...pattern.size + if search_string[i-j] != pattern[pattern.size-1-j] + i += table.slide_offset(search_string[i-j]) + break + elsif j == pattern.size-1 + indices.append(i-j) + return indices if stop_at_first_match + i += 1 + end + end + end + indices +end diff --git a/strings/boyer_moore_horspool_search_test.rb b/strings/boyer_moore_horspool_search_test.rb new file mode 100644 index 00000000..990e4f57 --- /dev/null +++ b/strings/boyer_moore_horspool_search_test.rb @@ -0,0 +1,20 @@ +require 'minitest/autorun' +require_relative 'boyer_moore_horspool_search' + +class TestBoyerMooreHorspoolSearch < Minitest::Test + def test_first_match_returns_negative_index_if_no_match + assert first_match_index('abcdefghijk', 'defz') < 0 + end + + def test_first_match_returns_first_match_index + assert first_match_index('abcdefghijkghilmno', 'ghi') == 6 + end + + def test_match_indices_returns_empty_list_if_no_match + assert matches_indices('abcdefghijk', 'defz').empty? + end + + def test_match_indices_returns_list_of_match_indices + assert matches_indices('abcdefghijkghilmno', 'ghi') == [6, 11] + end +end From cae9ac5fd66a3377140c3a2452b380537558a768 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Tue, 11 Apr 2023 06:51:01 +0000 Subject: [PATCH 67/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index ebe2285a..28b97ffa 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -52,6 +52,8 @@ * [Two Sum](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/two_sum.rb) * [Two Sum Ii](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/two_sum_ii.rb) * Binary Trees + * [Avl Tree](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/avl_tree.rb) + * [Avl Tree Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/avl_tree_test.rb) * [Bst](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/bst.rb) * [Bst Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/bst_test.rb) * [Inorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/inorder_traversal.rb) From 28f15835ad64eb438ba31ea9f1663dc7b616cfd2 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Tue, 11 Apr 2023 07:07:46 +0000 Subject: [PATCH 68/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 28b97ffa..3941010a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -223,5 +223,7 @@ * [Sort Tests](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/sort_tests.rb) ## Strings + * [Boyer Moore Horspool Search](https://github.com/TheAlgorithms/Ruby/blob/master/strings/boyer_moore_horspool_search.rb) + * [Boyer Moore Horspool Search Test](https://github.com/TheAlgorithms/Ruby/blob/master/strings/boyer_moore_horspool_search_test.rb) * [Max K Most Frequent Words](https://github.com/TheAlgorithms/Ruby/blob/master/strings/max_k_most_frequent_words.rb) * [Max K Most Frequent Words Test](https://github.com/TheAlgorithms/Ruby/blob/master/strings/max_k_most_frequent_words_test.rb) From 3902bef7a6baf67eb144e8edc281d5e18227a2c6 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Mon, 22 May 2023 08:13:05 +0200 Subject: [PATCH 69/94] Adding unweighted graph data structure --- data_structures/graphs/unweighted_graph.rb | 62 ++++++++++++++ .../graphs/unweighted_graph_test.rb | 82 +++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 data_structures/graphs/unweighted_graph.rb create mode 100644 data_structures/graphs/unweighted_graph_test.rb diff --git a/data_structures/graphs/unweighted_graph.rb b/data_structures/graphs/unweighted_graph.rb new file mode 100644 index 00000000..8da857ac --- /dev/null +++ b/data_structures/graphs/unweighted_graph.rb @@ -0,0 +1,62 @@ +require 'set' + +## +# This class aims to represent unweighted graphs +# (i.e. graphs for which edges between nodes have no specific weight associated to them). +# +# Both directed (i.e. an edge between node U and node V does not imply an edge in the opposite direction) +# and undirected graphs are supported, depending on the constructor invocation. + +class UnweightedGraph + attr_reader :nodes + attr_reader :directed + + def initialize(nodes: [], neighbors: {}, directed: true) + @nodes = Set[] + @neighbors = {} + @directed = directed + for node in nodes + add_node(node) + end + neighbors.each do |node, neighbors| + for neighbor in neighbors + add_edge(node, neighbor) + end + end + end + + def add_node(node) + if include?(node) + raise ArgumentError, "node #{node} already exists in this graph!" + end + @nodes.add(node) + @neighbors[node] = Set[] + end + + def add_edge(start_node, end_node) + if has_neighbor?(start_node, end_node) + raise ArgumentError, "node #{start_node} already has an edge to #{end_node} in this graph!" + end + @neighbors[start_node].add(end_node) + @neighbors[end_node].add(start_node) unless directed + end + + def neighbors(node) + unless include?(node) + raise ArgumentError, "node #{node} does not exist in this graph!" + end + @neighbors[node] + end + + def empty? + nodes.empty? + end + + def include?(node) + nodes.include?(node) + end + + def has_neighbor?(start_node, end_node) + neighbors(start_node).include?(end_node) + end +end diff --git a/data_structures/graphs/unweighted_graph_test.rb b/data_structures/graphs/unweighted_graph_test.rb new file mode 100644 index 00000000..b4f74439 --- /dev/null +++ b/data_structures/graphs/unweighted_graph_test.rb @@ -0,0 +1,82 @@ +require 'minitest/autorun' +require 'set' +require_relative 'unweighted_graph' + +class TestUnweightedGraph < Minitest::Test + def test_directed_unweighted_graph_creation + graph = UnweightedGraph.new(nodes: [:u, :v, :w], neighbors: {:u => [:v]}, directed: true) + + assert graph.nodes.to_set == Set[:u, :v, :w] + assert graph.neighbors(:u).to_set == Set[:v] + assert graph.neighbors(:v).empty? + assert graph.neighbors(:w).empty? + end + + def test_undirected_unweighted_graph_creation + graph = UnweightedGraph.new(nodes: [:u, :v, :w], neighbors: {:u => [:v]}, directed: false) + + assert graph.nodes.to_set == Set[:u, :v, :w] + assert graph.neighbors(:u).to_set == Set[:v] + assert graph.neighbors(:v).to_set == Set[:u] + assert graph.neighbors(:w).empty? + end + + def test_empty_returns_true_for_empty_graph + graph = UnweightedGraph.new + + assert graph.empty? + end + + def test_empty_returns_false_for_non_empty_graph + graph = UnweightedGraph.new(nodes: [:u]) + + assert !graph.empty? + end + + def test_include_returns_true_for_graph_nodes + graph = UnweightedGraph.new(nodes: [:u]) + + assert graph.include?(:u) + end + + def test_include_returns_false_for_non_graph_nodes + graph = UnweightedGraph.new + + assert !graph.include?(:u) + end + + def test_has_neighbor_returns_true_for_graph_node_neighbors + graph = UnweightedGraph.new(nodes: [:u, :v], neighbors: {:u => [:v]}) + + assert graph.has_neighbor?(:u, :v) + end + + def test_has_neighbor_returns_false_for_non_graph_node_neighbors + graph = UnweightedGraph.new(nodes: [:u, :v]) + + assert !graph.has_neighbor?(:u, :v) + end + + def test_add_node_adds_node_to_graph + graph = UnweightedGraph.new + graph.add_node(:u) + + assert graph.nodes.to_set == Set[:u] + end + + def test_add_edge_adds_edge_to_directed_unweighted_graph + graph = UnweightedGraph.new(nodes: [:u, :v], directed: true) + graph.add_edge(:u, :v) + + assert graph.neighbors(:u).to_set == Set[:v] + assert graph.neighbors(:v).empty? + end + + def test_add_edge_adds_edge_to_directed_unweighted_graph + graph = UnweightedGraph.new(nodes: [:u, :v], directed: false) + graph.add_edge(:u, :v) + + assert graph.neighbors(:u).to_set == Set[:v] + assert graph.neighbors(:v).to_set == Set[:u] + end +end From b7d60d275914ce5fbf9ea523c8e1b8c9fca89c13 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Mon, 22 May 2023 08:13:16 +0200 Subject: [PATCH 70/94] Adding weighted graph data structure --- data_structures/graphs/weighted_graph.rb | 66 ++++++++++++++ data_structures/graphs/weighted_graph_test.rb | 88 +++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 data_structures/graphs/weighted_graph.rb create mode 100644 data_structures/graphs/weighted_graph_test.rb diff --git a/data_structures/graphs/weighted_graph.rb b/data_structures/graphs/weighted_graph.rb new file mode 100644 index 00000000..86e6a175 --- /dev/null +++ b/data_structures/graphs/weighted_graph.rb @@ -0,0 +1,66 @@ +require 'set' + +## +# This class aims to represent weighted graphs +# (i.e. graphs for which edges between nodes have specific weights associated to them). +# +# Both directed (i.e. an edge between node U and node V does not imply an edge in the opposite direction) +# and undirected graphs are supported, depending on the constructor invocation. + +class WeightedGraph + attr_reader :nodes + attr_reader :directed + + def initialize(nodes: [], edges: {}, directed: true) + @nodes = Set[] + @edges = {} + @directed = directed + for node in nodes + add_node(node) + end + edges.each do |node, edges| + for neighbor, weight in edges + add_edge(node, neighbor, weight) + end + end + end + + def add_node(node) + if include?(node) + raise ArgumentError, "node #{node} already exists in this graph!" + end + @nodes.add(node) + @edges[node] = {} + end + + def add_edge(start_node, end_node, weight) + if has_neighbor?(start_node, end_node) + raise ArgumentError, "node #{start_node} already has an edge to #{end_node} in this graph!" + end + @edges[start_node][end_node] = weight + @edges[end_node][start_node] = weight unless directed + end + + def edges(node) + unless include?(node) + raise ArgumentError, "node #{node} does not exist in this graph!" + end + @edges[node] + end + + def empty? + nodes.empty? + end + + def include?(node) + nodes.include?(node) + end + + def has_neighbor?(start_node, end_node) + edges(start_node).key?(end_node) + end + + def edge_weight(start_node, end_node) + edges(start_node)[end_node] + end +end diff --git a/data_structures/graphs/weighted_graph_test.rb b/data_structures/graphs/weighted_graph_test.rb new file mode 100644 index 00000000..229d457f --- /dev/null +++ b/data_structures/graphs/weighted_graph_test.rb @@ -0,0 +1,88 @@ +require 'minitest/autorun' +require 'set' +require_relative 'weighted_graph' + +class TestWeightedGraph < Minitest::Test + def test_directed_weighted_graph_creation + graph = WeightedGraph.new(nodes: [:u, :v, :w], edges: {:u => [[:v, 1]]}, directed: true) + + assert graph.nodes.to_set == Set[:u, :v, :w] + assert graph.edges(:u) == {:v => 1} + assert graph.edges(:v).empty? + assert graph.edges(:w).empty? + end + + def test_undirected_weighted_graph_creation + graph = WeightedGraph.new(nodes: [:u, :v, :w], edges: {:u => [[:v, 1]]}, directed: false) + + assert graph.nodes.to_set == Set[:u, :v, :w] + assert graph.edges(:u) == {:v => 1} + assert graph.edges(:v) == {:u => 1} + assert graph.edges(:w).empty? + end + + def test_empty_returns_true_for_empty_graph + graph = WeightedGraph.new + + assert graph.empty? + end + + def test_empty_returns_false_for_non_empty_graph + graph = WeightedGraph.new(nodes: [:u]) + + assert !graph.empty? + end + + def test_include_returns_true_for_graph_nodes + graph = WeightedGraph.new(nodes: [:u]) + + assert graph.include?(:u) + end + + def test_include_returns_false_for_non_graph_nodes + graph = WeightedGraph.new + + assert !graph.include?(:u) + end + + def test_has_neighbor_returns_true_for_graph_node_neighbors + graph = WeightedGraph.new(nodes: [:u, :v], edges: {:u => [[:v, 1]]}) + + assert graph.has_neighbor?(:u, :v) + end + + def test_has_neighbor_returns_false_for_non_graph_node_neighbors + graph = WeightedGraph.new(nodes: [:u, :v]) + + assert !graph.has_neighbor?(:u, :v) + end + + def test_edge_weight_returns_neighbor_edge_weight + graph = WeightedGraph.new(nodes: [:u, :v], edges: {:u => [[:v, 4]]}) + + assert graph.edge_weight(:u, :v) == 4 + end + + def test_add_node_adds_node_to_graph + graph = WeightedGraph.new + graph.add_node(:u) + + assert graph.nodes.to_set == Set[:u] + end + + def test_add_edge_adds_edge_to_directed_weighted_graph + graph = WeightedGraph.new(nodes: [:u, :v], directed: true) + graph.add_edge(:u, :v, 2) + + assert graph.edges(:u) == {:v => 2} + assert graph.edges(:v).empty? + end + + def test_add_edge_adds_edge_to_directed_weighted_graph + graph = WeightedGraph.new(nodes: [:u, :v], directed: false) + graph.add_edge(:u, :v, 2) + + assert graph.edges(:u) == {:v => 2} + assert graph.edges(:v) == {:u => 2} + end +end From af56ad064f984b052159b82f95ba76aafe2a8657 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Tue, 23 May 2023 03:47:36 +0000 Subject: [PATCH 71/94] updating DIRECTORY.md --- DIRECTORY.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 3941010a..732c1e8f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -62,6 +62,11 @@ * [Preorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/preorder_traversal.rb) * Disjoint Sets * [Disjoint Sets](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/disjoint_sets/disjoint_sets.rb) + * Graphs + * [Unweighted Graph](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/unweighted_graph.rb) + * [Unweighted Graph Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/unweighted_graph_test.rb) + * [Weighted Graph](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/weighted_graph.rb) + * [Weighted Graph Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/weighted_graph_test.rb) * Hash Table * [Anagram Checker](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/anagram_checker.rb) * [Arrays Intersection](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/arrays_intersection.rb) From 360cba9a6114c6082ecf23d188759a8c8b6c946d Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Tue, 23 May 2023 08:37:39 +0200 Subject: [PATCH 72/94] Implementing unweighted graph BFS --- data_structures/graphs/bfs.rb | 56 +++++++++++++++++++++++++ data_structures/graphs/bfs_test.rb | 67 ++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 data_structures/graphs/bfs.rb create mode 100644 data_structures/graphs/bfs_test.rb diff --git a/data_structures/graphs/bfs.rb b/data_structures/graphs/bfs.rb new file mode 100644 index 00000000..fcb1b335 --- /dev/null +++ b/data_structures/graphs/bfs.rb @@ -0,0 +1,56 @@ +require 'set' + +## +# This class represents the result of a breadth-first search performed on an unweighted graph. +# +# It exposes: +# - the set of visited nodes +# - a hash of distances by node from the search root node +# (only for visited nodes, 0 for the search root node); +# - a hash of parent nodes by node +# (only for visited nodes, nil for the search root node). + +class GraphBfsResult + attr_reader :visited + attr_reader :parents + attr_reader :distances + + def initialize(visited, parents, distances) + @visited = visited + @parents = parents + @distances = distances + end +end + +## +# Performs a breadth-first search for the provided graph, starting at the given node. +# Returns the search result (see GraphBfsResult). +# +# The algorithm has a time complexity of O(|V| + |E|), where: +# - |V| is the number of nodes in the graph; +# - |E| is the number of edges in the graph. + +def bfs(graph, start_node) + seen = Set[] + visited = Set[] + parents = { start_node => nil } + distances = { start_node => 0 } + + seen.add(start_node) + q = Queue.new + q.push(start_node) + until q.empty? + node = q.pop + for neighbor in graph.neighbors(node) + unless seen.include?(neighbor) + seen.add(neighbor) + distances[neighbor] = distances[node] + 1 + parents[neighbor] = node + q.push(neighbor) + end + end + visited.add(node) + end + + GraphBfsResult.new(visited, parents, distances) +end diff --git a/data_structures/graphs/bfs_test.rb b/data_structures/graphs/bfs_test.rb new file mode 100644 index 00000000..933adab3 --- /dev/null +++ b/data_structures/graphs/bfs_test.rb @@ -0,0 +1,67 @@ +require 'minitest/autorun' +require_relative 'bfs' +require_relative 'unweighted_graph' + +class TestBfs < Minitest::Test + def test_bfs_visits_single_graph_node + graph = UnweightedGraph.new(nodes: [:u, :v, :w], directed: false) + graph.add_edge(:u, :v) + + bfs_result = bfs(graph, :w) + + assert bfs_result.visited.to_set == [:w].to_set + assert bfs_result.parents == { + :w => nil + } + assert bfs_result.distances == { + :w => 0 + } + end + + def test_bfs_visits_undirected_graph_fully + graph = UnweightedGraph.new(nodes: [:u, :v, :w, :x], directed: false) + graph.add_edge(:u, :v) + graph.add_edge(:u, :w) + graph.add_edge(:w, :x) + + bfs_result = bfs(graph, :u) + + assert bfs_result.visited.to_set == [:u, :v, :w, :x].to_set + assert bfs_result.parents == { + :u => nil, + :v => :u, + :w => :u, + :x => :w + } + assert bfs_result.distances == { + :u => 0, + :v => 1, + :w => 1, + :x => 2 + } + end + + def test_bfs_visits_undirected_graph_partially + graph = UnweightedGraph.new(nodes: [:u, :v, :w, :x, :y, :z], directed: false) + graph.add_edge(:u, :v) + graph.add_edge(:w, :x) + graph.add_edge(:x, :y) + graph.add_edge(:y, :z) + + bfs_result = bfs(graph, :x) + + assert bfs_result.visited.to_set == [:w, :x, :y, :z].to_set + assert bfs_result.parents == { + :w => :x, + :x => nil, + :y => :x, + :z => :y + } + assert bfs_result.distances == { + :w => 1, + :x => 0, + :y => 1, + :z => 2 + } + end +end From 0b42d46b83729bca5ee8ffe2b5c8d4562245fab9 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Tue, 23 May 2023 08:38:06 +0200 Subject: [PATCH 73/94] Correcting test method names --- data_structures/graphs/unweighted_graph_test.rb | 2 +- data_structures/graphs/weighted_graph_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/graphs/unweighted_graph_test.rb b/data_structures/graphs/unweighted_graph_test.rb index b4f74439..734cc748 100644 --- a/data_structures/graphs/unweighted_graph_test.rb +++ b/data_structures/graphs/unweighted_graph_test.rb @@ -72,7 +72,7 @@ def test_add_edge_adds_edge_to_directed_unweighted_graph assert graph.neighbors(:v).empty? end - def test_add_edge_adds_edge_to_directed_unweighted_graph + def test_add_edge_adds_edge_to_undirected_unweighted_graph graph = UnweightedGraph.new(nodes: [:u, :v], directed: false) graph.add_edge(:u, :v) diff --git a/data_structures/graphs/weighted_graph_test.rb b/data_structures/graphs/weighted_graph_test.rb index 229d457f..d30023a1 100644 --- a/data_structures/graphs/weighted_graph_test.rb +++ b/data_structures/graphs/weighted_graph_test.rb @@ -78,7 +78,7 @@ def test_add_edge_adds_edge_to_directed_weighted_graph assert graph.edges(:v).empty? end - def test_add_edge_adds_edge_to_directed_weighted_graph + def test_add_edge_adds_edge_to_undirected_weighted_graph graph = WeightedGraph.new(nodes: [:u, :v], directed: false) graph.add_edge(:u, :v, 2) From b561094aa5fa189a3b730077c5cc989e156a7570 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Tue, 23 May 2023 09:19:54 +0200 Subject: [PATCH 74/94] Adding node consumer support on graph BFS --- data_structures/graphs/bfs.rb | 8 +++++++- data_structures/graphs/bfs_test.rb | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/data_structures/graphs/bfs.rb b/data_structures/graphs/bfs.rb index fcb1b335..313f164b 100644 --- a/data_structures/graphs/bfs.rb +++ b/data_structures/graphs/bfs.rb @@ -25,12 +25,13 @@ def initialize(visited, parents, distances) ## # Performs a breadth-first search for the provided graph, starting at the given node. # Returns the search result (see GraphBfsResult). +# Nodes are consumed upon discovery using the provided node consumer (nothing, by default). # # The algorithm has a time complexity of O(|V| + |E|), where: # - |V| is the number of nodes in the graph; # - |E| is the number of edges in the graph. -def bfs(graph, start_node) +def bfs(graph, start_node, node_consumer=method(:do_nothing_on_node)) seen = Set[] visited = Set[] parents = { start_node => nil } @@ -41,6 +42,7 @@ def bfs(graph, start_node) q.push(start_node) until q.empty? node = q.pop + node_consumer.call(node) for neighbor in graph.neighbors(node) unless seen.include?(neighbor) seen.add(neighbor) @@ -54,3 +56,7 @@ def bfs(graph, start_node) GraphBfsResult.new(visited, parents, distances) end + +private +def do_nothing_on_node(node) +end diff --git a/data_structures/graphs/bfs_test.rb b/data_structures/graphs/bfs_test.rb index 933adab3..5e2d0eb0 100644 --- a/data_structures/graphs/bfs_test.rb +++ b/data_structures/graphs/bfs_test.rb @@ -18,7 +18,7 @@ def test_bfs_visits_single_graph_node } end - def test_bfs_visits_undirected_graph_fully + def test_bfs_visits_graph_fully graph = UnweightedGraph.new(nodes: [:u, :v, :w, :x], directed: false) graph.add_edge(:u, :v) graph.add_edge(:u, :w) @@ -41,7 +41,7 @@ def test_bfs_visits_undirected_graph_fully } end - def test_bfs_visits_undirected_graph_partially + def test_bfs_visits_graph_partially graph = UnweightedGraph.new(nodes: [:u, :v, :w, :x, :y, :z], directed: false) graph.add_edge(:u, :v) graph.add_edge(:w, :x) @@ -64,4 +64,15 @@ def test_bfs_visits_undirected_graph_partially :z => 2 } end + + def test_bfs_visits_with_node_consumer + graph = UnweightedGraph.new(nodes: [:u, :v, :w], directed: false) + graph.add_edge(:u, :v) + graph.add_edge(:u, :w) + + visit_order = [] + bfs(graph, :w, ->(node) { visit_order.append(node) }) + + assert visit_order == [:w, :u, :v] + end end From 85a1175c76f75f222fbbf0da03ca719b10264e32 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Tue, 23 May 2023 10:14:23 +0200 Subject: [PATCH 75/94] Splitting consumers for seen and visited nodes in graph BFS --- data_structures/graphs/bfs.rb | 9 ++++++--- data_structures/graphs/bfs_test.rb | 19 +++++++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/data_structures/graphs/bfs.rb b/data_structures/graphs/bfs.rb index 313f164b..9d9facfa 100644 --- a/data_structures/graphs/bfs.rb +++ b/data_structures/graphs/bfs.rb @@ -25,33 +25,36 @@ def initialize(visited, parents, distances) ## # Performs a breadth-first search for the provided graph, starting at the given node. # Returns the search result (see GraphBfsResult). -# Nodes are consumed upon discovery using the provided node consumer (nothing, by default). +# Nodes are consumed using the provided consumers upon being first seen, or being completely visited +# (nothing, by default). # # The algorithm has a time complexity of O(|V| + |E|), where: # - |V| is the number of nodes in the graph; # - |E| is the number of edges in the graph. -def bfs(graph, start_node, node_consumer=method(:do_nothing_on_node)) +def bfs(graph, start_node, seen_node_consumer: method(:do_nothing_on_node), visited_node_consumer: method(:do_nothing_on_node)) seen = Set[] visited = Set[] parents = { start_node => nil } distances = { start_node => 0 } seen.add(start_node) + seen_node_consumer.call(start_node) q = Queue.new q.push(start_node) until q.empty? node = q.pop - node_consumer.call(node) for neighbor in graph.neighbors(node) unless seen.include?(neighbor) seen.add(neighbor) distances[neighbor] = distances[node] + 1 parents[neighbor] = node + seen_node_consumer.call(neighbor) q.push(neighbor) end end visited.add(node) + visited_node_consumer.call(node) end GraphBfsResult.new(visited, parents, distances) diff --git a/data_structures/graphs/bfs_test.rb b/data_structures/graphs/bfs_test.rb index 5e2d0eb0..ab3f9d14 100644 --- a/data_structures/graphs/bfs_test.rb +++ b/data_structures/graphs/bfs_test.rb @@ -65,14 +65,25 @@ def test_bfs_visits_graph_partially } end - def test_bfs_visits_with_node_consumer + def test_bfs_visits_with_seen_node_consumer graph = UnweightedGraph.new(nodes: [:u, :v, :w], directed: false) graph.add_edge(:u, :v) graph.add_edge(:u, :w) - visit_order = [] - bfs(graph, :w, ->(node) { visit_order.append(node) }) + seen_order = [] + bfs(graph, :w, seen_node_consumer: ->(node) { seen_order.append(node) }) - assert visit_order == [:w, :u, :v] + assert seen_order == [:w, :u, :v] + end + + def test_bfs_visits_with_visited_node_consumer + graph = UnweightedGraph.new(nodes: [:u, :v, :w], directed: false) + graph.add_edge(:u, :v) + graph.add_edge(:u, :w) + + visited_order = [] + bfs(graph, :w, visited_node_consumer: ->(node) { visited_order.append(node) }) + + assert visited_order == [:w, :u, :v] end end From 5f0a19ce82a4c5aec77b972424f981148c9cff43 Mon Sep 17 00:00:00 2001 From: Amos Paribocci Date: Tue, 23 May 2023 13:49:52 +0200 Subject: [PATCH 76/94] Implementing topological sorting for DAGs --- data_structures/graphs/topological_sort.rb | 37 +++++++++++++ .../graphs/topological_sort_test.rb | 52 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 data_structures/graphs/topological_sort.rb create mode 100644 data_structures/graphs/topological_sort_test.rb diff --git a/data_structures/graphs/topological_sort.rb b/data_structures/graphs/topological_sort.rb new file mode 100644 index 00000000..88955e48 --- /dev/null +++ b/data_structures/graphs/topological_sort.rb @@ -0,0 +1,37 @@ +require 'set' + +## +# This class aims to provide topological sorting capabilities for directed acyclic graphs. +# +# Topological sorting runs in O(|V|), where |V| is the number of graph nodes. + +class TopologicalSorter + attr_reader :graph + + def initialize(graph) + raise ArgumentError, "Topological sort is only applicable to directed graphs!" unless graph.directed + @graph = graph + end + + def topological_sort + @sorted_nodes = [] + @seen = Set[] + @visited = Set[] + for node in graph.nodes + dfs_visit(node) + end + @sorted_nodes + end + + private + def dfs_visit(node) + return if @visited.include?(node) + raise ArgumentError, "Cycle in graph detected on node #{node}!" if @seen.include?(node) + @seen.add(node) + for neighbor in graph.neighbors(node) + dfs_visit(neighbor) + end + @visited.add(node) + @sorted_nodes.unshift(node) + end +end diff --git a/data_structures/graphs/topological_sort_test.rb b/data_structures/graphs/topological_sort_test.rb new file mode 100644 index 00000000..01472dad --- /dev/null +++ b/data_structures/graphs/topological_sort_test.rb @@ -0,0 +1,52 @@ +require 'minitest/autorun' +require_relative 'topological_sort' +require_relative 'unweighted_graph' + +class TestTopologicalSort < Minitest::Test + def test_topological_sort_returns_valid_order_for_acyclic_graph + wardrobe_items = [:underwear, :trousers, :belt, :shirt, :tie, :jacket, :socks, :shoes, :watch] + wardrobe_graph = UnweightedGraph.new(nodes: wardrobe_items, directed: true) + wardrobe_graph.add_edge(:underwear, :trousers) + wardrobe_graph.add_edge(:underwear, :shoes) + wardrobe_graph.add_edge(:socks, :shoes) + wardrobe_graph.add_edge(:trousers, :shoes) + wardrobe_graph.add_edge(:trousers, :belt) + wardrobe_graph.add_edge(:shirt, :belt) + wardrobe_graph.add_edge(:belt, :jacket) + wardrobe_graph.add_edge(:shirt, :tie) + wardrobe_graph.add_edge(:tie, :jacket) + + sorted_items = TopologicalSorter.new(wardrobe_graph).topological_sort + + assert sorted_items.index(:underwear) < sorted_items.index(:trousers) + assert sorted_items.index(:underwear) < sorted_items.index(:shoes) + assert sorted_items.index(:socks) < sorted_items.index(:shoes) + assert sorted_items.index(:trousers) < sorted_items.index(:shoes) + assert sorted_items.index(:trousers) < sorted_items.index(:belt) + assert sorted_items.index(:shirt) < sorted_items.index(:belt) + assert sorted_items.index(:belt) < sorted_items.index(:jacket) + assert sorted_items.index(:shirt) < sorted_items.index(:tie) + assert sorted_items.index(:tie) < sorted_items.index(:jacket) + end + + def test_topological_sort_raises_exception_for_undirected_graph + nodes = [:u, :v] + graph = UnweightedGraph.new(nodes: nodes, directed: false) + graph.add_edge(:u, :v) + + assert_raises ArgumentError do + TopologicalSorter.new(graph).topological_sort + end + end + + def test_topological_sort_raises_exception_for_cyclic_graph + nodes = [:u, :v] + graph = UnweightedGraph.new(nodes: nodes, directed: true) + graph.add_edge(:u, :v) + graph.add_edge(:v, :u) + + assert_raises ArgumentError do + TopologicalSorter.new(graph).topological_sort + end + end +end From 450ba13fb9f5a0188012723824b01723fc996885 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sat, 27 May 2023 11:10:42 +0000 Subject: [PATCH 77/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 732c1e8f..47ad6313 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -63,6 +63,8 @@ * Disjoint Sets * [Disjoint Sets](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/disjoint_sets/disjoint_sets.rb) * Graphs + * [Topological Sort](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/topological_sort.rb) + * [Topological Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/topological_sort_test.rb) * [Unweighted Graph](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/unweighted_graph.rb) * [Unweighted Graph Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/unweighted_graph_test.rb) * [Weighted Graph](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/weighted_graph.rb) From 14149d1eaf65fde9311a1d7e87fefa4e33fcb09e Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sat, 27 May 2023 11:18:41 +0000 Subject: [PATCH 78/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 47ad6313..b962c281 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -63,6 +63,8 @@ * Disjoint Sets * [Disjoint Sets](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/disjoint_sets/disjoint_sets.rb) * Graphs + * [Bfs](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/bfs.rb) + * [Bfs Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/bfs_test.rb) * [Topological Sort](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/topological_sort.rb) * [Topological Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/topological_sort_test.rb) * [Unweighted Graph](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/graphs/unweighted_graph.rb) From 31c930eb504442b042ea79804c267e2150c86b14 Mon Sep 17 00:00:00 2001 From: David Leal Date: Fri, 16 Jun 2023 18:51:25 +0000 Subject: [PATCH 79/94] chore: use workflow from the `scripts` repository --- .github/workflows/test.yml | 6 +- .github/workflows/update_directory_md.yml | 83 ++++++++--------------- 360 | 0 3 files changed, 30 insertions(+), 59 deletions(-) delete mode 100644 360 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 62cd4b3e..650e892e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,11 +1,11 @@ -name: test +name: Build/test code on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - uses: ruby/setup-ruby@master + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 with: ruby-version: '3.2' - name: Run tests diff --git a/.github/workflows/update_directory_md.yml b/.github/workflows/update_directory_md.yml index e0b19811..7bb2a0b8 100644 --- a/.github/workflows/update_directory_md.yml +++ b/.github/workflows/update_directory_md.yml @@ -1,59 +1,30 @@ -name: update_directory_md -on: [push] +name: Directory writer +on: + push: + branches: + - main + schedule: + # ┌───────────── minute (0 - 59) + # │ ┌───────────── hour (0 - 23) + # │ │ ┌───────────── day of the month (1 - 31) + # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) + # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) + # │ │ │ │ │ + # │ │ │ │ │ + # │ │ │ │ │ + # * * * * * + - cron: '0 0 * * 1' jobs: - update_directory_md: + build: + if: github.repository == 'TheAlgorithms/Ruby' # We only need this to run in our repository. runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - uses: actions/setup-python@master - - name: update_directory_md - shell: python - run: | - import os - from typing import Iterator - URL_BASE = "https://github.com/TheAlgorithms/Ruby/blob/master" - g_output = [] - - def good_filepaths(top_dir: str = ".") -> Iterator[str]: - for dirpath, dirnames, filenames in os.walk(top_dir): - dirnames[:] = [d for d in dirnames if d[0] not in "._"] - for filename in filenames: - if os.path.splitext(filename)[1].lower() == ".rb": - yield os.path.join(dirpath, filename).lstrip("./") - - def md_prefix(i): - return f"{i * ' '}*" if i else "\n##" - - def print_path(old_path: str, new_path: str) -> str: - global g_output - old_parts = old_path.split(os.sep) - for i, new_part in enumerate(new_path.split(os.sep)): - if i + 1 > len(old_parts) or old_parts[i] != new_part: - if new_part: - g_output.append(f"{md_prefix(i)} {new_part.replace('_', ' ').title()}") - return new_path - - def build_directory_md(top_dir: str = ".") -> str: - global g_output - old_path = "" - for filepath in sorted(good_filepaths(), key=str.lower): - filepath, filename = os.path.split(filepath) - if filepath != old_path: - old_path = print_path(old_path, filepath) - indent = (filepath.count(os.sep) + 1) if filepath else 0 - url = "/".join((URL_BASE, filepath, filename)).replace(" ", "%20") - filename = os.path.splitext(filename.replace("_", " ").title())[0] - g_output.append(f"{md_prefix(indent)} [{filename}]({url})") - return "\n".join(g_output) - with open("DIRECTORY.md", "w") as out_file: - out_file.write(build_directory_md(".") + "\n") - - - name: Update DIRECTORY.md - run: | - cat DIRECTORY.md - git config --global user.name github-actions - git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com' - git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY - git add DIRECTORY.md - git commit -am "updating DIRECTORY.md" || true - git push --force origin HEAD:$GITHUB_REF || true + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Build directory + uses: TheAlgorithms/scripts/directory_md@main + with: + language: Ruby + working-directory: . + filetypes: .rb diff --git a/360 b/360 deleted file mode 100644 index e69de29b..00000000 From e254026ec6af659dfcc74c214ed8f68d97ec1345 Mon Sep 17 00:00:00 2001 From: David Leal Date: Tue, 20 Jun 2023 14:48:24 -0600 Subject: [PATCH 80/94] chore: apply suggestions from code review Co-authored-by: vzvu3k6k --- .github/workflows/update_directory_md.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update_directory_md.yml b/.github/workflows/update_directory_md.yml index 7bb2a0b8..62dc4b03 100644 --- a/.github/workflows/update_directory_md.yml +++ b/.github/workflows/update_directory_md.yml @@ -2,7 +2,7 @@ name: Directory writer on: push: branches: - - main + - master schedule: # ┌───────────── minute (0 - 59) # │ ┌───────────── hour (0 - 23) From 4dab82985e862624cf6e02b04a5ac37a3c7f7889 Mon Sep 17 00:00:00 2001 From: AMQOR Merouane Date: Wed, 21 Jun 2023 17:03:58 +0100 Subject: [PATCH 81/94] Add gnome sort --- sorting/gnome_sort.rb | 12 ++++++++++++ sorting/gnome_sort_test.rb | 11 +++++++++++ 2 files changed, 23 insertions(+) create mode 100644 sorting/gnome_sort.rb create mode 100644 sorting/gnome_sort_test.rb diff --git a/sorting/gnome_sort.rb b/sorting/gnome_sort.rb new file mode 100644 index 00000000..0e6768eb --- /dev/null +++ b/sorting/gnome_sort.rb @@ -0,0 +1,12 @@ +def gnome_sort(arr) + i = 0 + while i < arr.length + if i == 0 || arr[i] >= arr[i - 1] + i += 1 + else + arr[i], arr[i - 1] = arr[i - 1], arr[i] + i -= 1 + end + end + arr +end diff --git a/sorting/gnome_sort_test.rb b/sorting/gnome_sort_test.rb new file mode 100644 index 00000000..992ee2ad --- /dev/null +++ b/sorting/gnome_sort_test.rb @@ -0,0 +1,11 @@ +require 'minitest/autorun' +require_relative './sort_tests' +require_relative './gnome_sort' + +class TestGnomeSort < Minitest::Test + include SortTests + + def sort(input) + gnome_sort(input) + end +end From 16b1f5a09eaff32bba7427fa2632aa7172050a82 Mon Sep 17 00:00:00 2001 From: vzvu3k6k Date: Thu, 22 Jun 2023 03:12:42 +0900 Subject: [PATCH 82/94] Temporarily revert "Merge pull request #209 from Panquesito7/scripts_workflow" This reverts commit 275bed9a78a9a7a5951d2c84d7f75acc71e6edd4, reversing changes made to 14149d1eaf65fde9311a1d7e87fefa4e33fcb09e. This action failed for some reason. https://github.com/TheAlgorithms/Ruby/actions/runs/5337370931/jobs/9673337632 I'll revert this merge commit temporarily until it is fixed. --- .github/workflows/test.yml | 6 +- .github/workflows/update_directory_md.yml | 83 +++++++++++++++-------- 360 | 0 3 files changed, 59 insertions(+), 30 deletions(-) create mode 100644 360 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 650e892e..62cd4b3e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,11 +1,11 @@ -name: Build/test code +name: test on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: ruby/setup-ruby@v1 + - uses: actions/checkout@master + - uses: ruby/setup-ruby@master with: ruby-version: '3.2' - name: Run tests diff --git a/.github/workflows/update_directory_md.yml b/.github/workflows/update_directory_md.yml index 62dc4b03..e0b19811 100644 --- a/.github/workflows/update_directory_md.yml +++ b/.github/workflows/update_directory_md.yml @@ -1,30 +1,59 @@ -name: Directory writer -on: - push: - branches: - - master - schedule: - # ┌───────────── minute (0 - 59) - # │ ┌───────────── hour (0 - 23) - # │ │ ┌───────────── day of the month (1 - 31) - # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) - # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) - # │ │ │ │ │ - # │ │ │ │ │ - # │ │ │ │ │ - # * * * * * - - cron: '0 0 * * 1' +name: update_directory_md +on: [push] jobs: - build: - if: github.repository == 'TheAlgorithms/Ruby' # We only need this to run in our repository. + update_directory_md: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Build directory - uses: TheAlgorithms/scripts/directory_md@main - with: - language: Ruby - working-directory: . - filetypes: .rb + - uses: actions/checkout@master + - uses: actions/setup-python@master + - name: update_directory_md + shell: python + run: | + import os + from typing import Iterator + URL_BASE = "https://github.com/TheAlgorithms/Ruby/blob/master" + g_output = [] + + def good_filepaths(top_dir: str = ".") -> Iterator[str]: + for dirpath, dirnames, filenames in os.walk(top_dir): + dirnames[:] = [d for d in dirnames if d[0] not in "._"] + for filename in filenames: + if os.path.splitext(filename)[1].lower() == ".rb": + yield os.path.join(dirpath, filename).lstrip("./") + + def md_prefix(i): + return f"{i * ' '}*" if i else "\n##" + + def print_path(old_path: str, new_path: str) -> str: + global g_output + old_parts = old_path.split(os.sep) + for i, new_part in enumerate(new_path.split(os.sep)): + if i + 1 > len(old_parts) or old_parts[i] != new_part: + if new_part: + g_output.append(f"{md_prefix(i)} {new_part.replace('_', ' ').title()}") + return new_path + + def build_directory_md(top_dir: str = ".") -> str: + global g_output + old_path = "" + for filepath in sorted(good_filepaths(), key=str.lower): + filepath, filename = os.path.split(filepath) + if filepath != old_path: + old_path = print_path(old_path, filepath) + indent = (filepath.count(os.sep) + 1) if filepath else 0 + url = "/".join((URL_BASE, filepath, filename)).replace(" ", "%20") + filename = os.path.splitext(filename.replace("_", " ").title())[0] + g_output.append(f"{md_prefix(indent)} [{filename}]({url})") + return "\n".join(g_output) + with open("DIRECTORY.md", "w") as out_file: + out_file.write(build_directory_md(".") + "\n") + + - name: Update DIRECTORY.md + run: | + cat DIRECTORY.md + git config --global user.name github-actions + git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com' + git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY + git add DIRECTORY.md + git commit -am "updating DIRECTORY.md" || true + git push --force origin HEAD:$GITHUB_REF || true diff --git a/360 b/360 new file mode 100644 index 00000000..e69de29b From a3fc6eb9176bae908688d0b4fc4b52c8fb5e3ede Mon Sep 17 00:00:00 2001 From: vzvu3k6k Date: Thu, 22 Jun 2023 03:36:15 +0900 Subject: [PATCH 83/94] chore: remove needless file Co-authored-by: David Leal --- 360 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 360 diff --git a/360 b/360 deleted file mode 100644 index e69de29b..00000000 From b6677b2cddf64db9930aac6e121d6c6521198162 Mon Sep 17 00:00:00 2001 From: vzvu3k6k Date: Thu, 22 Jun 2023 03:38:34 +0900 Subject: [PATCH 84/94] chore: specify GitHub action versions Co-authored-by: David Leal --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 62cd4b3e..650e892e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,11 +1,11 @@ -name: test +name: Build/test code on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - uses: ruby/setup-ruby@master + - uses: actions/checkout@v3 + - uses: ruby/setup-ruby@v1 with: ruby-version: '3.2' - name: Run tests From 58b362dd9fa49fddb08f430166b8fa47acc03439 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Wed, 21 Jun 2023 19:12:33 +0000 Subject: [PATCH 85/94] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index b962c281..9e71daa0 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -212,6 +212,8 @@ * [Comb Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/comb_sort_test.rb) * [Counting Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/counting_sort.rb) * [Counting Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/counting_sort_test.rb) + * [Gnome Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/gnome_sort.rb) + * [Gnome Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/gnome_sort_test.rb) * [Heap Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/heap_sort.rb) * [Heap Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/heap_sort_test.rb) * [Insertion Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/insertion_sort.rb) From 2f6c267980626fc5dc6ccccfd369a1d9751a9b9b Mon Sep 17 00:00:00 2001 From: Stepfen Shawn Date: Tue, 4 Jul 2023 22:39:12 +0800 Subject: [PATCH 86/94] Update the link of gitter chat --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a66a07ac..a8b8cde4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # The Algorithms - Ruby -[![Gitter chat](https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square)](https://gitter.im/TheAlgorithms)  +[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/#TheAlgorithms_community:gitter.im)  [![contributions welcome](https://img.shields.io/static/v1.svg?label=Contributions&message=Welcome&color=0059b3&style=flat-square)](https://github.com/TheAlgorithms/Ruby/blob/master/CONTRIBUTING.md)  ![](https://img.shields.io/github/repo-size/TheAlgorithms/Ruby.svg?label=Repo%20size&style=flat-square)  [![Discord chat](https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=7289DA&style=flat-square)](https://discord.gg/c7MnfGFGa6)  From fcca542509a5a315b6ae1d5e9a2cdb9055998c64 Mon Sep 17 00:00:00 2001 From: Ircadius Date: Sun, 1 Oct 2023 08:12:55 +0700 Subject: [PATCH 87/94] Add hamming_distance algorithm --- strings/hamming_distance.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 strings/hamming_distance.rb diff --git a/strings/hamming_distance.rb b/strings/hamming_distance.rb new file mode 100644 index 00000000..faa738e7 --- /dev/null +++ b/strings/hamming_distance.rb @@ -0,0 +1,23 @@ +# https://en.wikipedia.org/wiki/Hamming_distance + +def hamming_distance(str1, str2) + abort 'Strings must be of the same length' unless str1.length == str2.length + + str1.chars.zip(str2.chars).sum { |chr1, chr2| chr1 == chr2 ? 0 : 1 } +end + +if $0 == __FILE__ + # Valid inputs + puts hamming_distance 'ruby', 'rust' + # => 2 + puts hamming_distance 'karolin', 'kathrin' + # => 3 + puts hamming_distance 'kathrin', 'kerstin' + # => 4 + puts hamming_distance '0000', '1111' + # => 4 + + # Invalid inputs + puts hamming_distance 'ruby', 'foobar' + # => Strings must be of the same length +end From a26e5a43938dca3237ce651122744778f11f102b Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:25:13 +0000 Subject: [PATCH 88/94] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 9e71daa0..020f9507 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -236,5 +236,6 @@ ## Strings * [Boyer Moore Horspool Search](https://github.com/TheAlgorithms/Ruby/blob/master/strings/boyer_moore_horspool_search.rb) * [Boyer Moore Horspool Search Test](https://github.com/TheAlgorithms/Ruby/blob/master/strings/boyer_moore_horspool_search_test.rb) + * [Hamming Distance](https://github.com/TheAlgorithms/Ruby/blob/master/strings/hamming_distance.rb) * [Max K Most Frequent Words](https://github.com/TheAlgorithms/Ruby/blob/master/strings/max_k_most_frequent_words.rb) * [Max K Most Frequent Words Test](https://github.com/TheAlgorithms/Ruby/blob/master/strings/max_k_most_frequent_words_test.rb) From e4a887c6c40b245383bb071a692608deecfc6cbc Mon Sep 17 00:00:00 2001 From: vil02 Date: Mon, 15 Jan 2024 17:10:40 +0100 Subject: [PATCH 89/94] fix: use `GITHUB_ACTOR` in `git config` --- .github/workflows/update_directory_md.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update_directory_md.yml b/.github/workflows/update_directory_md.yml index e0b19811..5eca9aa9 100644 --- a/.github/workflows/update_directory_md.yml +++ b/.github/workflows/update_directory_md.yml @@ -51,8 +51,8 @@ jobs: - name: Update DIRECTORY.md run: | cat DIRECTORY.md - git config --global user.name github-actions - git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com' + git config --global user.name "$GITHUB_ACTOR" + git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com" git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY git add DIRECTORY.md git commit -am "updating DIRECTORY.md" || true From 0a5774076235d33e67ec6365ab4ae79e71ebbb63 Mon Sep 17 00:00:00 2001 From: vil02 Date: Wed, 17 Jan 2024 15:18:44 +0100 Subject: [PATCH 90/94] chore: update `actions/checkout` to `v4` --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 650e892e..e295b1ce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: '3.2' From 64777732f822618a86a1412db489f5be6afd7470 Mon Sep 17 00:00:00 2001 From: vil02 Date: Wed, 17 Jan 2024 15:24:51 +0100 Subject: [PATCH 91/94] style: remove trailing spaces from `update_directory_md.yml` --- .github/workflows/update_directory_md.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/update_directory_md.yml b/.github/workflows/update_directory_md.yml index 5eca9aa9..83732bd9 100644 --- a/.github/workflows/update_directory_md.yml +++ b/.github/workflows/update_directory_md.yml @@ -13,17 +13,17 @@ jobs: from typing import Iterator URL_BASE = "https://github.com/TheAlgorithms/Ruby/blob/master" g_output = [] - + def good_filepaths(top_dir: str = ".") -> Iterator[str]: for dirpath, dirnames, filenames in os.walk(top_dir): dirnames[:] = [d for d in dirnames if d[0] not in "._"] for filename in filenames: if os.path.splitext(filename)[1].lower() == ".rb": yield os.path.join(dirpath, filename).lstrip("./") - + def md_prefix(i): return f"{i * ' '}*" if i else "\n##" - + def print_path(old_path: str, new_path: str) -> str: global g_output old_parts = old_path.split(os.sep) @@ -32,7 +32,7 @@ jobs: if new_part: g_output.append(f"{md_prefix(i)} {new_part.replace('_', ' ').title()}") return new_path - + def build_directory_md(top_dir: str = ".") -> str: global g_output old_path = "" @@ -47,7 +47,7 @@ jobs: return "\n".join(g_output) with open("DIRECTORY.md", "w") as out_file: out_file.write(build_directory_md(".") + "\n") - + - name: Update DIRECTORY.md run: | cat DIRECTORY.md From 5363715e7b8825644865f20a75cbc76c18a0400e Mon Sep 17 00:00:00 2001 From: vzvu3k6k Date: Tue, 30 Jan 2024 01:14:54 +0900 Subject: [PATCH 92/94] Use Ruby 3.3 in testing --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e295b1ce..c26963b5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,6 @@ jobs: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: - ruby-version: '3.2' + ruby-version: '3.3' - name: Run tests run: rake test From 697e3f2b5bb02521665033f370dd78a086bebabf Mon Sep 17 00:00:00 2001 From: Stepfen Shawn Date: Thu, 29 Feb 2024 22:31:03 +0800 Subject: [PATCH 93/94] Update copyright year --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index 6d7f310d..eb813ea4 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 The Algorithms +Copyright (c) 2024 The Algorithms Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 1225a9fb9cf48aa54dd4b89aedb366e0d19f9e8f Mon Sep 17 00:00:00 2001 From: vzvu3k6k Date: Fri, 10 Jan 2025 20:09:47 +0900 Subject: [PATCH 94/94] Use Ruby 3.4 in testing --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c26963b5..61670702 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,6 @@ jobs: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: - ruby-version: '3.3' + ruby-version: '3.4' - name: Run tests run: rake test