Merge branch 'master' into jk-common-characters

This commit is contained in:
Vitor Oliveira 2021-06-04 01:20:13 -07:00 committed by GitHub
commit bf6d576453
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 2598 additions and 13 deletions

View file

@ -1,12 +1,22 @@
## Backtracking
* [Generate Paranthesis](https://github.com/TheAlgorithms/Ruby/blob/master/backtracking/generate_paranthesis.rb)
## Bit Manipulation
* [Binary And Operator](https://github.com/TheAlgorithms/Ruby/blob/master/bit_manipulation/binary_and_operator.rb)
* [Binary Count Setbits](https://github.com/TheAlgorithms/Ruby/blob/master/bit_manipulation/binary_count_setbits.rb)
* [Binary Count Trailing Zeroes](https://github.com/TheAlgorithms/Ruby/blob/master/bit_manipulation/binary_count_trailing_zeroes.rb)
* [Binary Or Operator](https://github.com/TheAlgorithms/Ruby/blob/master/bit_manipulation/binary_or_operator.rb)
* [Binary Xor Operator](https://github.com/TheAlgorithms/Ruby/blob/master/bit_manipulation/binary_xor_operator.rb)
* [Power Of Two](https://github.com/TheAlgorithms/Ruby/blob/master/bit_manipulation/power_of_two.rb)
* [Single Bit Binary Operations](https://github.com/TheAlgorithms/Ruby/blob/master/bit_manipulation/single_bit_binary_operations.rb)
## Ciphers
* [Merkle Hellman Cryptosystem](https://github.com/TheAlgorithms/Ruby/blob/master/ciphers/merkle_hellman_cryptosystem.rb)
## Conversions
* [Temperature Conversions](https://github.com/TheAlgorithms/Ruby/blob/master/conversions/temperature_conversions.rb)
* [Weight Conversions](https://github.com/TheAlgorithms/Ruby/blob/master/conversions/weight_conversions.rb)
## Data Structures
* Arrays
@ -15,15 +25,22 @@
* [Find The Highest Altitude](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/find_the_highest_altitude.rb)
* [Fizz Buzz](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/fizz_buzz.rb)
* [Get Products Of All Other Elements](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/get_products_of_all_other_elements.rb)
* [Good Pairs](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/good_pairs.rb)
* [Intersection](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/intersection.rb)
* [Next Greater Element](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/next_greater_element.rb)
* [Remove Elements](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/remove_elements.rb)
* [Richest Customer Wealth](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/richest_customer_wealth.rb)
* [Shortest Word Distance](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/shortest_word_distance.rb)
* [Shuffle Array](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/shuffle_array.rb)
* [Single Number](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/single_number.rb)
* [Sort Squares Of An Array](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/sort_squares_of_an_array.rb)
* [Sorted Arrays Intersection](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/sorted_arrays_intersection.rb)
* Strings
* [Anagram Checker](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/anagram_checker.rb)
* [Jewels And Stones](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/jewels_and_stones.rb)
* [Palindrome](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/palindrome.rb)
* [Remove Vowels](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/remove_vowels.rb)
* [Sudoku](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/sudoku.rb)
* [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
@ -32,15 +49,20 @@
* [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)
* 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)
* [Common Characters](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/common_characters.rb)
* [Find All Duplicates In An Array](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/find_all_duplicates_in_an_array.rb)
* [Good Pairs](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/good_pairs.rb)
* [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)
* 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)
* [Singly Linked List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/singly_linked_list.rb)
* Queues
* [Circular Queue](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/queues/circular_queue.rb)
* [Queue](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/queues/queue.rb)
* Stacks
* [Stack](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/stacks/stack.rb)
@ -54,22 +76,36 @@
## Dynamic Programming
* [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)
* [Fibonacci](https://github.com/TheAlgorithms/Ruby/blob/master/dynamic_programming/fibonacci.rb)
## Maths
* [Abs](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs.rb)
* [Abs Max](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs_max.rb)
* [Abs Min](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs_min.rb)
* [Abs Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs_test.rb)
* [Add](https://github.com/TheAlgorithms/Ruby/blob/master/maths/add.rb)
* [Add Digits](https://github.com/TheAlgorithms/Ruby/blob/master/maths/add_digits.rb)
* [Aliquot Sum](https://github.com/TheAlgorithms/Ruby/blob/master/maths/aliquot_sum.rb)
* [Aliquot Sum Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/aliquot_sum_test.rb)
* [Armstrong Number](https://github.com/TheAlgorithms/Ruby/blob/master/maths/armstrong_number.rb)
* [Average Mean](https://github.com/TheAlgorithms/Ruby/blob/master/maths/average_mean.rb)
* [Average Median](https://github.com/TheAlgorithms/Ruby/blob/master/maths/average_median.rb)
* [Binary To Decimal](https://github.com/TheAlgorithms/Ruby/blob/master/maths/binary_to_decimal.rb)
* [Ceil](https://github.com/TheAlgorithms/Ruby/blob/master/maths/ceil.rb)
* [Ceil Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/ceil_test.rb)
* [Count Sorted Vowel Strings](https://github.com/TheAlgorithms/Ruby/blob/master/maths/count_sorted_vowel_strings.rb)
* [Decimal To Binary](https://github.com/TheAlgorithms/Ruby/blob/master/maths/decimal_to_binary.rb)
* [Factorial](https://github.com/TheAlgorithms/Ruby/blob/master/maths/factorial.rb)
* [Factorial Non Recursive Non Iterative](https://github.com/TheAlgorithms/Ruby/blob/master/maths/factorial_non_recursive_non_iterative.rb)
* [Fibonacci](https://github.com/TheAlgorithms/Ruby/blob/master/maths/fibonacci.rb)
* [Find Max](https://github.com/TheAlgorithms/Ruby/blob/master/maths/find_max.rb)
* [Find Min](https://github.com/TheAlgorithms/Ruby/blob/master/maths/find_min.rb)
* [Lucas Series](https://github.com/TheAlgorithms/Ruby/blob/master/maths/lucas_series.rb)
* [Number Of Digits](https://github.com/TheAlgorithms/Ruby/blob/master/maths/number_of_digits.rb)
* [Power Of Two](https://github.com/TheAlgorithms/Ruby/blob/master/maths/power_of_two.rb)
* [Prime Number](https://github.com/TheAlgorithms/Ruby/blob/master/maths/prime_number.rb)
* [Roman To Integer](https://github.com/TheAlgorithms/Ruby/blob/master/maths/roman_to_integer.rb)
* [Square Root](https://github.com/TheAlgorithms/Ruby/blob/master/maths/square_root.rb)
* [Square Root Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/square_root_test.rb)
* [Sum Of Digits](https://github.com/TheAlgorithms/Ruby/blob/master/maths/sum_of_digits.rb)
@ -98,28 +134,36 @@
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_5/sol1.rb)
## Searches
* [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)
* [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)
* [Recursive Double Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/recursive_double_linear_search.rb)
* [Recursive Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/recursive_linear_search.rb)
* [Ternary Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/ternary_search.rb)
* [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)
* [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)
* [Recursive Double Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/recursive_double_linear_search.rb)
* [Recursive Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/recursive_linear_search.rb)
* [Ternary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/ternary_search.rb)
## 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)
* [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)
* [Bubble Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bubble_sort_test.rb)
* [Bucket Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bucket_sort.rb)
* [Bucket Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bucket_sort_test.rb)
* [Cocktail Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/cocktail_sort.rb)
* [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)
* [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)
* [Insertion Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/insertion_sort_test.rb)
* [Merge Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/merge_sort.rb)
* [Merge Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/merge_sort_test.rb)
* [Pancake Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/pancake_sort.rb)
* [Pancake Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/pancake_sort_test.rb)
* [Quicksort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/quicksort.rb)
* [Quicksort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/quicksort_test.rb)
* [Radix Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/radix_sort.rb)
@ -128,4 +172,5 @@
* [Selection Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/selection_sort_test.rb)
* [Shell Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/shell_sort.rb)
* [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)

View file

@ -0,0 +1,106 @@
# Given n pairs of parentheses, write a function to generate all combinations
# of well-formed parentheses.
#
# Example 1:
#
# Input: n = 3
# Output: ["((()))","(()())","(())()","()(())","()()()"]
# Example 2:
#
# Input: n = 1
# Output: ["()"]
#
#
# Constraints:
#
# 1 <= n <= 8
# Approach:
#
# Let's only add '(' or ')' when we know it will remain a valid sequence.
# We can do this by keeping track of the number of opening and closing brackets
# we have placed so far.
#
# We can start an opening bracket if we still have one (of n) left to place.
# And we could start a closing bracket if it'd not exceed the number of opening
# brackets.
# Complexity Analysis
#
# Time Complexity: O(4^n/sqrt(n)). Each valid sequence has at most n steps during the backtracking procedure.
# Space Complexity: O(4^n/sqrt(n)), as described above, and using O(n) space to store the sequence.
# Refer to the attached diagram for recursion,
# The numbers next to each node are the counts of left and right parantheses
# @param {Integer} n
# @return {String[]}
def generate_parenthesis(n)
parenthesis = []
backtrack(parenthesis, "", 0, 0, n)
parenthesis
end
def backtrack(parenthesis, curr, open, close, max)
if curr.length == max * 2
parenthesis.push(curr)
return
end
if open < max
backtrack(parenthesis, curr + "(", open + 1, close, max)
end
if close < open
backtrack(parenthesis, curr + ")", open, close + 1, max)
end
end
n = 3
print(generate_parenthesis(n))
# Output: ["((()))","(()())","(())()","()(())","()()()"]
# *** Example: n = 3 *** Space after each DFS instance
# backtrack called with 0 0 []
# backtrack called with ( 1 0 []
# backtrack called with (( 2 0 []
# backtrack called with ((( 3 0 []
# backtrack called with ((() 3 1 []
# backtrack called with ((()) 3 2 []
# backtrack called with ((())) 3 3 []
# backtrack return with ((()) 3 2 ["((()))"]
# backtrack return with ((() 3 1 ["((()))"]
# backtrack return with ((( 3 0 ["((()))"]
# backtrack called with (() 2 1 ["((()))"]
# backtrack called with (()( 3 1 ["((()))"]
# backtrack called with (()() 3 2 ["((()))"]
# backtrack called with (()()) 3 3 ["((()))"]
# backtrack return with (()() 3 2 ["((()))", "(()())"]
# backtrack return with (()( 3 1 ["((()))", "(()())"]
# backtrack called with (()) 2 2 ["((()))", "(()())"]
# backtrack called with (())( 3 2 ["((()))", "(()())"]
# backtrack called with (())() 3 3 ["((()))", "(()())"]
# backtrack return with (())( 3 2 ["((()))", "(()())", "(())()"]
# backtrack return with (()) 2 2 ["((()))", "(()())", "(())()"]
# backtrack return with (() 2 1 ["((()))", "(()())", "(())()"]
# backtrack return with (( 2 0 ["((()))", "(()())", "(())()"]
# backtrack called with () 1 1 ["((()))", "(()())", "(())()"]
# backtrack called with ()( 2 1 ["((()))", "(()())", "(())()"]
# backtrack called with ()(( 3 1 ["((()))", "(()())", "(())()"]
# backtrack called with ()(() 3 2 ["((()))", "(()())", "(())()"]
# backtrack called with ()(()) 3 3 ["((()))", "(()())", "(())()"]
# backtrack return with ()(() 3 2 ["((()))", "(()())", "(())()", "()(())"]
# backtrack return with ()(( 3 1 ["((()))", "(()())", "(())()", "()(())"]
# backtrack called with ()() 2 2 ["((()))", "(()())", "(())()", "()(())"]
# backtrack called with ()()( 3 2 ["((()))", "(()())", "(())()", "()(())"]
# backtrack called with ()()() 3 3 ["((()))", "(()())", "(())()", "()(())"]
# backtrack return with ()()( 3 2 ["((()))", "(()())", "(())()", "()(())", "()()()"]
# backtrack return with ()() 2 2 ["((()))", "(()())", "(())()", "()(())", "()()()"]
# backtrack return with ()( 2 1 ["((()))", "(()())", "(())()", "()(())", "()()()"]
# backtrack return with () 1 1 ["((()))", "(()())", "(())()", "()(())", "()()()"]
# backtrack return with ( 1 0 ["((()))", "(()())", "(())()", "()(())", "()()()"]
# backtrack return with 0 0 ["((()))", "(()())", "(())()", "()(())", "()()()"]
n = 1
print(generate_parenthesis(n))
# Output: ["()"]

View file

@ -0,0 +1,23 @@
def binary_and(x, y)
raise 'Input must only contain positive integers' if x < 0 or y < 0
"0b" + (x & y).to_s(2)
end
begin
binary_and(-1, 0)
rescue => e
puts e.message
end
# Input must only contain positive integers
puts binary_and(1, 1)
# 0b1
puts binary_and(0, 1)
# 0b0
puts binary_and(1024, 1024)
# 0b10000000000
puts binary_and(0, 1023)
# 0b0000000000
puts binary_and(16, 58)
# 0b010000

View file

@ -0,0 +1,26 @@
def binary_count_setbits(x)
raise 'Input must be a positive integer' if x < 0
binary = x.to_s(2)
binary.chars.map { |c| c.to_i }.reduce(:+)
end
begin
binary_count_setbits(-1)
rescue => e
puts e.message
end
# Input must be a positive integer
puts binary_count_setbits(0)
# 0
puts binary_count_setbits(1)
# 1
puts binary_count_setbits(1024)
# 1
puts binary_count_setbits(1023)
# 10

View file

@ -0,0 +1,36 @@
def binary_count_trailing_zeroes(x)
raise 'Input must be a positive integer' if x < 0
binary = x.to_s(2)
count = 0
binary.chars.reverse_each do |char|
break if char == "1"
count += 1
end
count
end
begin
binary_count_trailing_zeroes(-1)
rescue => e
puts e.message
end
# Input must be a positive integer
puts binary_count_trailing_zeroes(0)
# 1
puts binary_count_trailing_zeroes(1023)
# 0
puts binary_count_trailing_zeroes(1024)
# 10
puts binary_count_trailing_zeroes(54)
# 1
puts binary_count_trailing_zeroes(121024)
# 6

View file

@ -0,0 +1,24 @@
def binary_or(x, y)
raise 'Input must only contain positive integers' if x < 0 or y < 0
"0b" + (x | y).to_s(2)
end
begin
binary_or(-1, 0)
rescue => e
puts e.message
end
# Input must only contain positive integers
puts binary_or(1, 1)
# 0b1
puts binary_or(0, 1)
# 0b1
puts binary_or(1024, 1024)
# 0b10000000000
puts binary_or(0, 1023)
# 0b1111111111
puts binary_or(16, 58)
# 0b110010

View file

@ -0,0 +1,44 @@
def binary_xor(x, y)
raise 'Input must only contain positive integers' if x < 0 or y < 0
binary_x = x.to_s(2)
binary_y = y.to_s(2)
if binary_x.length > binary_y.length
prefix = "0" * (binary_x.length - binary_y.length)
binary_y = prefix + binary_y
elsif binary_y.length > binary_x.length
prefix = "0" * (binary_y.length - binary_x.length)
binary_x = prefix + binary_x
end
result = "0b"
binary_x.each_char.with_index do |x_char, i|
y_char = binary_y[i]
if (x_char == "1" && y_char != "1") || (x_char != "1" && y_char == "1")
result += "1"
else
result += "0"
end
end
result
end
begin
binary_xor(-1, 0)
rescue => e
puts e.message
end
# Input must only contain positive integers
puts binary_xor(1, 1)
# 0b0
puts binary_xor(0, 1)
# 0b1
puts binary_xor(1024, 1024)
# 0b00000000000
puts binary_xor(0, 1023)
# 0b1111111111
puts binary_xor(16, 58)
# 0b101010

View file

@ -0,0 +1,100 @@
def set_bit(x, position)
raise "position must be >= 0" if position < 0
x | (1 << position)
end
puts set_bit(0, 0)
# 1
puts set_bit(0, 4)
# 16
puts set_bit(8, 3)
# 8
puts set_bit(8, 4)
# 24
begin
puts set_bit(8, -4)
rescue => e
puts e.message
end
# position must be >= 0
def clear_bit(x, position)
raise "position must be > 0" if position < 0
x & ~(1 << position)
end
puts clear_bit(0, 0)
# 0
puts clear_bit(0, 4)
# 0
puts clear_bit(8, 3)
# 0
puts clear_bit(24, 4)
# 8
begin
puts clear_bit(0, -4)
rescue => e
puts e.message
end
# position must be > 0
def flip_bit(x, position)
raise "position must be > 0" if position < 0
x ^ (1 << position)
end
puts flip_bit(0, 0)
# 1
puts flip_bit(0, 4)
# 16
puts flip_bit(8, 3)
# 0
puts flip_bit(24, 4)
# 8
begin
puts flip_bit(0, -4)
rescue => e
puts e.message
end
# position must be > 0
def is_bit_set(x, position)
raise "position must be > 0" if position < 0
((x >> position) & 1) == 1
end
puts is_bit_set(0, 0)
# false
puts is_bit_set(1, 0)
# true
puts is_bit_set(8, 3)
# true
puts is_bit_set(24, 4)
# true
begin
puts is_bit_set(0, -4)
rescue => e
puts e.message
end
# position must be > 0

View file

@ -0,0 +1,106 @@
# A ruby program for weight conversions
module WeightConversion
# Kilogram -> Gram = (kilogram_value * 1000) grams
def self.kilogram_to_gram(kilogram_input)
raise StandardError unless Integer === kilogram_input
gram = kilogram_input * 1000
"#{kilogram_input} kg = #{gram} g"
end
# Gram -> Kilogram = (gram_value / 1000) kilograms
def self.gram_to_kilogram(gram_input)
kilogram = gram_input / 1000
"#{gram_input} g = #{kilogram} kg"
end
# Pound -> Ounce = (pound_value * 16) oz
def self.pound_to_ounce(pound_input)
ounce = pound_input * 16
"#{pound_input} lb = #{ounce} oz"
end
# Ounce -> Pound = (ounce_value / 16) lb
def self.ounce_to_pound(ounce_input)
pound = ounce_input / 16
"#{ounce_input} oz = #{pound} lb"
end
# Kilogram -> Pound = (kilogram_input * 2.205) lb
def self.kilogram_to_pound(kilogram_input)
pound = (kilogram_input * 2.205).round(2)
"#{kilogram_input} kg = #{pound} lb"
end
# Pound -> Kilogram = (pound_input / 2.205) kg
def self.pound_to_kilogram(pound_input)
raise StandardError unless Integer === pound_input
kilogram = (pound_input / 2.205).round(2)
"#{pound_input} lb = #{kilogram} kg"
end
end
#
# Valid inputs
#
puts WeightConversion.kilogram_to_gram(2)
# 2 kg = 2000 g
puts WeightConversion.gram_to_kilogram(3000)
# 3000 g = 3 kg
puts WeightConversion.pound_to_ounce(16)
# 16 lb = 256 oz
puts WeightConversion.ounce_to_pound(16)
# 16 oz = 1 lb
puts WeightConversion.kilogram_to_pound(1)
# 1 kg = 2.21 lb
puts WeightConversion.pound_to_kilogram(100)
# 100 lb = 45.35 kg
#
# Invalid inputs
#
begin
puts WeightConversion.kilogram_to_gram("a")
rescue StandardError
puts "Error: Please provide number only!"
end
begin
puts WeightConversion.kilogram_to_gram("3000")
rescue StandardError
puts "Error: Please provide number only!"
end
begin
puts WeightConversion.kilogram_to_gram("16")
rescue StandardError
puts "Error: Please provide number only!"
end
begin
puts WeightConversion.kilogram_to_gram("x ")
rescue StandardError
puts "Error: Please provide number only!"
end
begin
puts WeightConversion.kilogram_to_gram("weight")
rescue StandardError
puts "Error: Please provide number only!"
end
begin
puts WeightConversion.kilogram_to_gram("100")
rescue StandardError
puts "Error: Please provide number only!"
end

View file

@ -0,0 +1,42 @@
# Challenge name: Number of good pairs
#
# Given an array of integers nums.
# A pair (i,j) is called good if nums[i] == nums[j] and i < j.
# Return the number of good pairs.
#
# @param {Integer[]} nums
# @return {Integer}
#
#
# Approach 1: Brute Force
#
# Time Complexity: O(n^2)
#
def num_identical_pairs(nums)
count = 0
nums.each_with_index do |num, i|
target = num
nums.each_with_index do |num, j|
next if i >= j
if num == target
count += 1
end
end
end
count
end
nums = [1, 2, 3, 1, 1, 3]
puts(num_identical_pairs(nums))
# Output: 4
# Explanation: There are 4 good pairs (0,3), (0,4), (3,4), (2,5) 0-indexed.
nums = [1, 1, 1, 1]
puts(num_identical_pairs(nums))
# Output: 6
# Explanation: Each pair in the array are good.
nums = [1, 2, 3]
puts(num_identical_pairs(nums))
# Output: 0

View file

@ -0,0 +1,125 @@
# Challenge name: Intersection of two arrays ii
#
# Given two arrays, write a function to compute their intersection.
#
# @param {Integer[]} nums1
# @param {Integer[]} nums2
# @return {Integer[]}
#
# Approach 1: Brute Force
#
# Time Complexity: O(n^2)
#
def intersect(arr1, arr2)
result = []
if arr1.length < arr2.length
shorter = arr1
longer = arr2
else
shorter = arr2
longer = arr1
end
shorter.each do |matcher|
longer.each do |number|
next if number != matcher
result.push(number)
break
end
end
result
end
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
puts intersect(nums1, nums2)
# => [2,2]
nums1 = [4, 9, 5]
nums2 = [9, 4, 9, 8, 4]
puts intersect(nums1, nums2)
# => [4,9]
#
# Approach 2: Hash
#
# Complexity Analysis
#
# Time Complexity: O(n+m), where n and m are the lengths of the arrays.
# We iterate through the first, and then through the second array; insert
# and lookup operations in the hash map take a constant time.
#
# Space Complexity: O(min(n,m)). We use hash map to store numbers (and their
# counts) from the smaller array.
#
def intersect(arr1, arr2)
result = []
hash = Hash.new(0)
arr2.each {|num| hash[num] += 1 }
arr1.each do |num|
if hash.has_key?(num)
result << num if hash[num] >= 1
hash[num] -= 1
end
end
result
end
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
puts intersect(nums1, nums2)
# => [2,2]
nums1 = [4, 9, 5]
nums2 = [9, 4, 9, 8, 4]
puts intersect(nums1, nums2)
# => [4,9]
#
# Approach 3: Two Pointers
#
# Complexity analysis:
# Time Complexity: O(nlogn + mlogm), where n and m are the lengths of the arrays. We sort two arrays independently and then do a linear scan.
# Space Complexity: from O(logn+logm) to O(n+m), depending on the implementation of the sorting algorithm.
#
def intersect(nums1, nums2)
result = []
p1 = 0
p2 = 0
nums1 = nums1.sort
nums2 = nums2.sort
while p1 < nums1.length && p2 < nums2.length
if nums1[p1] < nums2[p2]
p1 += 1
elsif nums1[p1] > nums2[p2]
p2 += 1
elsif nums1[p1] == nums2[p2]
result << nums1[p1]
p1 += 1
p2 += 1
end
end
result
end
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
intersect(nums1, nums2)
nums1 = [1, 2, 2, 1]
nums2 = [2, 2]
puts intersect(nums1, nums2)
# => [2,2]
nums1 = [4, 9, 5]
nums2 = [9, 4, 9, 8, 4]
puts intersect(nums1, nums2)
# => [4,9]

View file

@ -0,0 +1,64 @@
# You are given two integer arrays nums1 and nums2 both of unique elements, where nums1 is a subset of nums2.
#
# Find all the next greater numbers for nums1's elements in the corresponding places of nums2.
#
# The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, return -1 for this number.
# Example 1:
#
# Input: nums1 = [4,1,2], nums2 = [1,3,4,2]
# Output: [-1,3,-1]
#
# Explanation:
# For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
# For number 1 in the first array, the next greater number for it in the second array is 3.
# For number 2 in the first array, there is no next greater number for it in the second array, so output -1.
#
# Example 2:
#
# Input: nums1 = [2,4], nums2 = [1,2,3,4]
# Output: [3,-1]
#
# Explanation:
# For number 2 in the first array, the next greater number for it in the second array is 3.
# For number 4 in the first array, there is no next greater number for it in the second array, so output -1.
#
# Approach: Brute Force
#
# Complexity Analysis
#
# Time complexity: O(m*n). The complete nums1 array (of size n) needs to be scanned for all the m elements of nums2 in the worst case.
# Space complexity: O(1). No additional space since we're swapping elements in nums1 and returning the input array.
# @param {Integer[]} nums1
# @param {Integer[]} nums2
# @return {Integer[]}
def next_greater_element(nums1, nums2)
nums1.each_with_index do |nums1_value, pointer1|
max = 0
pos_nums2 = nums2.find_index(nums1_value)
nums2[pos_nums2..nums2.count].each do |nums2_value|
if nums2_value > nums1_value
max = nums2_value
break
end
end
nums1[pointer1] = (nums1_value < max ? max : -1)
end
nums1
end
nums1 = [4, 1, 2]
nums2 = [1, 3, 4, 2]
print next_greater_element(nums1, nums2)
# Output: [-1,3,-1]
nums1 = [2, 4]
nums2 = [1, 2, 3, 4]
print next_greater_element(nums1, nums2)
# Output: [3,-1]

View file

@ -0,0 +1,33 @@
# Shortest Word Distance
# Given a list of words and two words word1 and word2,
# return the shortest distance between these two words in the list.
# @param {String[]} words
# @param {String} word1
# @param {String} word2
# @return {Integer}
def shortest_distance(words, word1, word2)
return 0 if word1 == word2
return 0 unless words.include?(word1) && words.include?(word2)
minimum_distance = words.length
words.each_with_index do |outer_value, outer_index|
words.each_with_index do |inner_value, inner_index|
if ((inner_value == word1 && outer_value == word2) || (inner_value == word2 && outer_value == word1)) && (minimum_distance > (outer_index - inner_index).abs)
minimum_distance = (outer_index - inner_index).abs
end
end
end
minimum_distance
end
words = %w[practice makes perfect coding makes]
word1 = 'coding'
word2 = 'practice'
puts(shortest_distance(words, word1, word2))
# Output: 3
words = %w[practice makes perfect coding makes]
word1 = 'makes'
word2 = 'coding'
puts(shortest_distance(words, word1, word2))
# Output: 1

View file

@ -0,0 +1,67 @@
# Given three integer arrays arr1, arr2 and arr3 sorted in strictly increasing order, return a sorted array of only the integers that appeared in all three arrays.
#
# Example 1:
#
# Input: arr1 = [1,2,3,4,5], arr2 = [1,2,5,7,9], arr3 = [1,3,4,5,8]
# Output: [1,5]
# Explanation: Only 1 and 5 appeared in the three arrays.
#
# Example 2:
#
# Input: arr1 = [197,418,523,876,1356], arr2 = [501,880,1593,1710,1870], arr3 = [521,682,1337,1395,1764]
# Output: []
#
#
#
# Approach: Two-pointers
#
# Complexity Analysis
#
# Time Complexity: O(n), where n is the total length of all of the
# input arrays.
# Space Complexity: O(1), as we only initiate three integer variables
# using constant space.
# @param {Integer[]} arr1
# @param {Integer[]} arr2
# @param {Integer[]} arr3
# @return {Integer[]}
def sorted_arrays_intersection(arr1, arr2, arr3)
result = []
# prepare three pointers to iterate through three arrays
# p1, p2, and p3 point to the beginning of arr1, arr2, and arr3 accordingly
p1 = p2 = p3 = 0
while (p1 < arr1.count) && (p2 < arr2.count) && (p3 < arr3.count)
if arr1[p1] == arr2[p2] && arr1[p1] == arr3[p3]
result.push(arr1[p1])
p1 += 1
p2 += 1
p3 += 1
elsif arr1[p1] < arr2[p2]
p1 += 1
elsif arr2[p2] < arr3[p3]
p2 += 1
else
p3 += 1
end
end
result
end
arr1 = [1, 2, 3, 4, 5]
arr2 = [1, 2, 5, 7, 9]
arr3 = [1, 3, 4, 5, 8]
print(sorted_arrays_intersection(arr1, arr2, arr3))
# Output: [1,5]
arr1 = [197, 418, 523, 876, 1356]
arr2 = [501, 880, 1593, 1710, 1870]
arr3 = [521, 682, 1337, 1395, 1764]
print(sorted_arrays_intersection(arr1, arr2, arr3))
# Output: []

View file

@ -15,7 +15,7 @@
# @return {Boolean}
#
# Approach 1: Sort and Compare
# Approach: Sort and Compare
#
# Complexity analysis:
#

View file

@ -0,0 +1,127 @@
# Challenge name: Valid Palindrome
#
# Given a string s, determine if it is a palindrome,
# considering only alphanumeric characters and ignoring cases.
#
# Example 1:
# Input: s = "A man, a plan, a canal: Panama"
# Output: true
# Explanation: "amanaplanacanalpanama" is a palindrome.
#
# Example 2:
# Input: s = "race a car"
# Output: false
# Explanation: "raceacar" is not a palindrome.
#
# Constraints:
# 1 <= s.length <= 2 * 105
# s consists only of printable ASCII characters.
# @param {String} s
# @return {Boolean}
#
# Approach 1: Using Ruby method .reverse
#
# Time Complexity: O(n)
#
def is_palindrome(s)
letters_only = s.downcase.gsub(/[^0-9a-z]/i, '')
letters_only.reverse == letters_only
end
s = 'A man, a plan, a canal: Panama'
puts is_palindrome(s)
# Output: true
# Explanation: "amanaplanacanalpanama" is a palindrome.
s = 'race a car'
puts is_palindrome(s)
# Output: false
# Explanation: "raceacar" is not a palindrome.
s = 'ab_a'
puts is_palindrome(s)
# Output: true
# Explanation: "aba" is a palindrome.
#
# Approach 2: Reversed array
#
# Complexity Analysis:
#
# Time Complexity: O(n), in length n of the string.
#
# We need to iterate through the string: When we filter out non-alphanumeric characters and convert the remaining
# characters to lower-case. When we reverse the string. When we compare the original and the reversed strings.
# Each iteration runs linearly in time (since each character operation completes in constant time).
# Thus, the effective run-time complexity is linear.
#
# Space Complexity: O(n), in length n of the string. We need O(n) additional
# space to store the filtered string and the reversed string.
#
def is_palindrome(s)
letters_only_array = s.downcase.gsub(/[^0-9a-z]/i, '').split('')
reversed_array = []
letters_only_array.each do |letter|
reversed_array.unshift(letter)
end
letters_only_array == reversed_array
end
s = 'A man, a plan, a canal: Panama'
puts is_palindrome(s)
# Output: true
# Explanation: "amanaplanacanalpanama" is a palindrome.
s = 'race a car'
puts is_palindrome(s)
# Output: false
# Explanation: "raceacar" is not a palindrome.
s = 'ab_a'
puts is_palindrome(s)
# Output: true
# Explanation: "aba" is a palindrome.
#
# Approach 2: Two Pointers
#
#
# Complexity Analysis:
#
# Time Complexity: O(n), in length n of the string. We traverse over each
# character at most once until the two pointers meet in the middle, or when
# we break and return early.
# Space Complexity: O(1). No extra space required, at all.
#
def is_palindrome(s)
letters_only = s.downcase.gsub(/[^0-9a-z]/i, '')
p1 = 0
p2 = letters_only.length - 1
while p1 < p2
if letters_only[p1] == letters_only[p2]
p1 += 1
p2 -= 1
else
return false
end
end
true
end
s = 'A man, a plan, a canal: Panama'
puts is_palindrome(s)
# Output: true
# Explanation: "amanaplanacanalpanama" is a palindrome.
s = 'race a car'
puts is_palindrome(s)
# Output: false
# Explanation: "raceacar" is not a palindrome.
s = 'ab_a'
puts is_palindrome(s)
# Output: true
# Explanation: "aba" is a palindrome.

View file

@ -0,0 +1,292 @@
# Challenge name: Valid Sudoku
# Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
# Each row must contain the digits 1-9 without repetition.
# Each column must contain the digits 1-9 without repetition.
# Each of the nine 3 x 3 sub-boxes of the grid must contain the digits 1-9 without repetition.
# @param {Character[][]} board
# @return {Boolean}
#
# Approach 1: Hash & Brute Force
#
def is_valid_sudoku(board)
rows = []
columns = []
grids = []
# make each row into a hash to track for duplicated values
board.each do |row|
row_hash = Hash.new(0)
row.each do |num|
next if num == "."
row_hash[num] += 1
end
rows << row_hash
end
# check each row hash for duplicated value
rows.each do |row|
row.each do |k, v|
if v > 1
return false
end
end
end
# make each column into a hash to track for duplicated values
(0..8).each do |i|
column_hash = Hash.new(0)
board.each do |row|
next if row[i] == "."
column_hash[row[i]] += 1
columns << column_hash
end
end
# check each column hash for duplicated value
columns.each do |column|
column.each do |k, v|
if v > 1
return false
end
end
end
# make each 3x3 grid into a hash to track for duplicated values
(0..2).each do |i|
grid_hash = Hash.new(0)
board.first(3).each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
board[3..5].each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
board.each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
end
(3..5).each do |i|
grid_hash = Hash.new(0)
board.first(3).each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
board[3..5].each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
board.each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
end
(6..8).last(3).each do |i|
grid_hash = Hash.new(0)
board.first(3).each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
board[3..5].each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
board.each do |row|
next if row[i] == "."
grid_hash[row[i]] += 1
grids << grid_hash
end
end
# check each grid hash for duplicated value
grids.each do |grid|
grid.each do |k, v|
if v > 1
return false
end
end
end
true
end
board = [["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]
print(is_valid_sudoku(board))
# => true
board = [["8","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]
print(is_valid_sudoku(board))
# => false
# explanation: duplicated value in column
board = [["8","3",".",".","7",".","3",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]
print(is_valid_sudoku(board))
# => false
# explanation: duplicated value in row
board = [["8","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
[".",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]
print(is_valid_sudoku(board))
# => false
# explanation: duplicated value in 3x3 grid
#
# Approach 2: Sets
#
require 'set'
def is_valid_sudoku(board)
return false unless check_rows(board)
return false unless check_cols(board)
row = -3
while (row += 3) < 9
col = - 3
while (col += 3) < 9
start_point = [row, col]
return false unless check_grid(board, start_point)
end
end
true
end
def check_grid(board, start_point)
row = start_point[0]
col = start_point[1]
ss = Set.new
(row..(row + 2)).each do |cur_row|
(col..(col + 2)).each do |cur_col|
next if board[cur_row][cur_col] == "."
return false if ss.member?(board[cur_row][cur_col])
ss.add board[cur_row][cur_col]
end
end
true
end
def check_col(board, col)
ss = Set.new
(0..8).each do |row|
next if board[row][col] == "."
return false if ss.member?(board[row][col])
ss.add board[row][col]
end
true
end
def check_row(board, row)
ss = Set.new
(0..8).each do |col|
next if board[row][col] == "."
return false if ss.member?(board[row][col])
ss.add board[row][col]
end
true
end
def check_rows(board)
(0..8).each do |row|
return false unless check_row(board, row)
end
true
end
def check_cols(board)
(0..8).each do |col|
return false unless check_col(board, col)
end
true
end
board = [["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]
print(is_valid_sudoku(board))
# => true
board = [["8","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]
print(is_valid_sudoku(board))
# => false
# explanation: duplicated value in column
board = [["8","3",".",".","7",".","3",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]
print(is_valid_sudoku(board))
# => false
# explanation: duplicated value in row
board = [["8","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
[".",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]
print(is_valid_sudoku(board))
# => false
# explanation: duplicated value in 3x3 grid

View file

@ -0,0 +1,161 @@
# Challenge name: Is anagram
#
# Given two strings s and t , write a function to determine
# if t is an anagram of s.
#
# Note:
# You may assume the string contains only lowercase alphabets.
#
# Follow up:
# What if the inputs contain unicode characters?
# How would you adapt your solution to such case?
#
# @param {String} s
# @param {String} t
# @return {Boolean}
#
# Approach: Hash table
#
# Complexity analysis:
#
# Time complexity: O(n). Time complexity is O(n) since accessing the counter
# table is a constant time operation.
# Space complexity: O(1). Although we do use extra space,
# the space complexity is O(1) because the table's size stays constant no
# matter how large n is.
#
def is_anagram(s, t)
s_length = s.length
t_length = t.length
counter = Hash.new(0)
return false unless s_length == t_length
(0...s_length).each do |i|
counter[s[i]] += 1
counter[t[i]] -= 1
end
counter.each do |k, v|
return false unless v == 0
end
true
end
s = 'anagram'
t = 'nagaram'
puts(is_anagram(s, t))
# => true
s = 'rat'
t = 'car'
puts(is_anagram(s, t))
# => false
s = 'a'
t = 'ab'
puts(is_anagram(s, t))
# => false
#
# Approach 2: Hash table
#
# Algorithm: we could also first increment the counter for s,
# then decrement the counter for t. If at any point the counter
# drops below zero, we know that t contains an extra letter,
# not in s, and return false immediately.
# Complexity analysis:
#
# Time complexity: O(n).
# Space complexity: O(1).
#
def is_anagram(s, t)
s_length = s.length
t_length = t.length
counter = Hash.new(0)
return false unless s_length == t_length
(0...s_length).each do |i|
counter[s[i]] += 1
end
(0...s_length).each do |i|
counter[t[i]] -= 1
return false if counter[t[i]] < 0
end
true
end
s = 'anagram'
t = 'nagaram'
puts(is_anagram(s, t))
# => true
s = 'rat'
t = 'car'
puts(is_anagram(s, t))
# => false
s = 'a'
t = 'ab'
puts(is_anagram(s, t))
# => false
#
# Approach 3: populate 2 hashes and compare them
#
def is_anagram(s, t)
s = s.chars
t = t.chars
return false if s.count != t.count
hash1 = {}
s.each do |value|
hash1[value] = if hash1[value]
hash1[value] + 1
else
1
end
end
hash2 = {}
t.each do |value|
hash2[value] = if hash2[value]
hash2[value] + 1
else
1
end
end
hash1.keys.each do |key|
return false if hash2[key] != hash1[key]
end
true
end
s = 'anagram'
t = 'nagaram'
puts(is_anagram(s, t))
# => true
s = 'rat'
t = 'car'
puts(is_anagram(s, t))
# => false
s = 'a'
t = 'ab'
puts(is_anagram(s, t))
# => false

View file

@ -0,0 +1,56 @@
# Given three integer arrays arr1, arr2 and arr3 sorted in strictly increasing order, return a sorted array of only the integers that appeared in all three arrays.
#
# Example 1:
#
# Input: arr1 = [1,2,3,4,5], arr2 = [1,2,5,7,9], arr3 = [1,3,4,5,8]
# Output: [1,5]
# Explanation: Only 1 and 5 appeared in the three arrays.
#
# Example 2:
#
# Input: arr1 = [197,418,523,876,1356], arr2 = [501,880,1593,1710,1870], arr3 = [521,682,1337,1395,1764]
# Output: []
#
#
#
# Approach: Hash table
#
# Complexity Analysis
# Time Complexity: O(n) - n is the total length of
# all of the input arrays.
# Space Complexity: O(n) - n is the total length of all of the
# input arrays. This is because we adopted a Hash table to store all
# numbers and their number of appearances as values.
def arrays_intersection(arr1, arr2, arr3)
hash = Hash.new(0)
add_to_hash(arr1, hash)
add_to_hash(arr2, hash)
add_to_hash(arr3, hash)
hash.select { |key, value| value == 3 }.keys
end
def add_to_hash(arr, hash)
arr.count.times do |pointer|
value = arr[pointer]
hash[value] += 1
end
end
arr1 = [1, 2, 3, 4, 5]
arr2 = [1, 2, 5, 7, 9]
arr3 = [1, 3, 4, 5, 8]
print arrays_intersection(arr1, arr2, arr3)
# Output: [1,5]
# Explanation: Only 1 and 5 appeared in the three arrays.
arr1 = [197, 418, 523, 876, 1356]
arr2 = [501, 880, 1593, 1710, 1870]
arr3 = [521, 682, 1337, 1395, 1764]
print arrays_intersection(arr1, arr2, arr3)
# Output: []

View file

@ -0,0 +1,43 @@
# Challenge name: Number of good pairs
#
# Given an array of integers nums.
# A pair (i,j) is called good if nums[i] == nums[j] and i < j.
# Return the number of good pairs.
#
# @param {Integer[]} nums
# @return {Integer}
#
#
# Approach 1: Hash
#
# Time Complexity: O(n)
def num_identical_pairs(nums)
hash = Hash.new(0)
nums.each do |num|
hash[num] = hash[num] + 1
end
counter = 0
# Count how many times each number appears.
# If a number appears n times, then n * (n 1) / 2 good pairs
# can be made with this number.
hash.values.each do |val|
counter += (val * (val - 1) / 2)
end
counter
end
nums = [1, 2, 3, 1, 1, 3]
puts(num_identical_pairs(nums))
# Output: 4
nums = [1, 1, 1, 1]
puts(num_identical_pairs(nums))
# Output: 6
nums = [1, 2, 3]
puts(num_identical_pairs(nums))
# Output: 0

View file

@ -0,0 +1,48 @@
# Challenge name: Uncommon words from two sentences
#
# We are given two sentences A and B.
# (A sentence is a string of space separated words.
# Each word consists only of lowercase letters.)
#
# A word is uncommon if it appears exactly once in one of the sentences,
# and does not appear in the other sentence.
#
# Return a list of all uncommon words.
# You may return the list in any order.
#
# Example 1:
# Input: A = "this apple is sweet", B = "this apple is sour"
# Output: ["sweet","sour"]
#
# Example 2:
# Input: A = "apple apple", B = "banana"
# Output: ["banana"]
#
# Approach 1: Hash
#
# Time Complexitiy: O(n)
def find_uncommon_words(strA, strB)
array = strA.concat(" ", strB).split(" ")
hash = Hash.new(0)
result = []
array.each do |word|
hash[word] += 1
end
hash.each do |k, v|
if v < 2
result.push(k)
end
end
result
end
puts find_uncommon_words("this apple is sweet", "this apple is sour")
# => ["sweet", "sour"]
puts find_uncommon_words("apple apple", "banana")
# => ["banana"]

View file

@ -0,0 +1,88 @@
# Challenge name: Circular Queue
#
# Design the implementation of a circular queue.
# The circular queue is a linear data structure in which the operations are performed based on FIFO (First In First Out) principle and
# the last position is connected back to the first position to make a circle. It is also called "Ring Buffer".
#
#
# Complexity Analysis
#
# Time complexity: O(1).
# All of the methods in our circular data structure are of constant time complexity.
#
# Space Complexity: O(N).
# The overall space complexity of the data structure is linear, where N is the pre-assigned capacity of the queue.
# However, it is worth mentioning that the memory consumption of the data structure remains as its pre-assigned capacity during its entire life cycle.
class CircularQueue
def initialize(max_size)
@max_size = max_size
@queue = Array.new(max_size, nil)
@front = 0
@back = 0
@size = 0
end
attr_accessor :front, :back, :size
attr_reader :max_size, :queue
def empty?
size == 0
end
def peek
return nil if empty?
queue[front]
end
def add(x)
raise "Queue is at max capacity" if size == max_size
queue[back] = x
@back = (back + 1) % max_size
@size += 1
end
def pop
raise "Queue is empty" if size == 0
temp = queue[front]
queue[front] = nil
@front = (front + 1) % max_size
@size -= 1
temp
end
end
queue = CircularQueue.new(3)
begin
queue.pop
rescue => e
puts e.message
end
queue.add(1)
queue.add(2)
queue.add(3)
begin
queue.add(4)
rescue => e
puts e.message
end
puts queue.inspect
# => #<CircularQueue:0x00007fea23876cd8 @max_size=3, @queue=[1, 2, 3], @front=0, @back=0, @size=3>
puts queue.peek
# => 1
queue.pop
puts queue.peek
# => 2

View file

@ -0,0 +1,91 @@
# Challenge name: Count Sorted Vowel Strings
#
# Given an integer n, return the number of strings of length n that consist only
# of vowels (a, e, i, o, u) and are lexicographically sorted.
#
# A string s is lexicographically sorted if for all valid i, s[i] is the same as
# or comes before s[i+1] in the alphabet.
#
#
# Example 1:
#
# Input: n = 1
# Output: 5
# Explanation: The 5 sorted strings that consist of vowels only are ["a","e","i","o","u"].
#
# Example 2:
#
# Input: n = 2
# Output: 15
# Explanation: The 15 sorted strings that consist of vowels only are
# ["aa","ae","ai","ao","au","ee","ei","eo","eu","ii","io","iu","oo","ou","uu"].
# Note that "ea" is not a valid string since 'e' comes after 'a' in the alphabet.
#
# Example 3:
#
# Input: n = 33
# Output: 66045
#
# Approach: Using Recursion + Memoization, Top Down Dynamic Programming
#
#
# Algorithm: Dynamic Programming state transition.
#
# F(0) = 1
# F(n)a = F(n-1)a + F(n-1)e + F(n-1)i + F(n-1)o +F(n-1)u
# F(n)e = F(n-1)e + F(n-1)i + F(n-1)o + F(n-1)u
# F(n)i = F(n-1)i + F(n-1)o +F(n-1)u
# F(n)o = F(n-1)o + F(n-1)u
# F(n)u = F(n-1)u
#
# @param {Integer} n
# @return {Integer}
def count_vowel_strings(n, letter = 'a')
return 1 if n < 1
@h ||= {}
key = [n, letter]
return @h[key] if @h[key]
result = case letter
when 'a'
count_vowel_strings(n - 1, letter = 'a') +
count_vowel_strings(n - 1, letter = 'e') +
count_vowel_strings(n - 1, letter = 'i') +
count_vowel_strings(n - 1, letter = 'o') +
count_vowel_strings(n - 1, letter = 'u')
when 'e'
count_vowel_strings(n - 1, letter = 'e') +
count_vowel_strings(n - 1, letter = 'i') +
count_vowel_strings(n - 1, letter = 'o') +
count_vowel_strings(n - 1, letter = 'u')
when 'i'
count_vowel_strings(n - 1, letter = 'i') +
count_vowel_strings(n - 1, letter = 'o') +
count_vowel_strings(n - 1, letter = 'u')
when 'o'
count_vowel_strings(n - 1, letter = 'o') +
count_vowel_strings(n - 1, letter = 'u')
when 'u'
count_vowel_strings(n - 1, letter = 'u')
end
@h[key] = result
@h[key]
end
n = 33
puts count_vowel_strings(n)
# Output: 66045
n = 2
puts count_vowel_strings(n)
# Output: 15
n = 1
puts count_vowel_strings(n)
# Output: 5

30
maths/abs_max.rb Normal file
View file

@ -0,0 +1,30 @@
# A ruby program to find absolute maximum
# Mathematical representation of abs max = ((a + b + absoulte(a - b)) / 2)
def abs_max(x, y)
num = x - y
max_value = ((x + y + num.abs()) / 2)
"The Abs Max of #{x} and #{y} is #{max_value}."
rescue
"Error: Provide number only!"
end
# Valid inputs
puts abs_max(10, 20)
# The Abs Max of 10 and 20 is 20.
puts abs_max(-10, -1)
# The Abs Max of -10 and -1 is -1.
puts abs_max(9, -121)
# The Abs Max of 9 and -121 is 9.
# Invalid inputs
puts abs_max(2, "-1")
# Error: Provide number only!
puts abs_max("3", "5")
# Error: Provide number only!
puts abs_max("a", "5")
# Error: Provide number only!

34
maths/abs_min.rb Normal file
View file

@ -0,0 +1,34 @@
# A ruby program to find absolute minimum
# Mathematical representation of abs min = ((a + b - absoulte(a - b)) / 2)
def abs_min(x, y)
num = x - y
min_value = ((x + y - num.abs()) / 2)
"The Abs Min of #{x} and #{y} is #{min_value}."
rescue
"Error: Provide number only!"
end
#
# Valid inputs
#
puts abs_min(10, 20)
# The Abs Min of 10 and 20 is 10.
puts abs_min(-10, -1)
# The Abs Min of -10 and -1 is -10.
puts abs_min(9, -121)
# The Abs Min of 9 and -121 is -121.
#
# Invalid inputs
#
puts abs_min(2, "-1")
# Error: Provide number only!
puts abs_min("3", "5")
# Error: Provide number only!
puts abs_min("a", "5")
# Error: Provide number only!

34
maths/add.rb Normal file
View file

@ -0,0 +1,34 @@
# A ruby program to add numbers
# Addition or sum of numbers means adding each and every element of the inputs
# Sum or addition of 1 and 3 is 1 + 3 = 4
def add(*array)
sum = 0
array.each { |a| sum+=a }
puts "The sum of following elements #{array} is #{sum}"
rescue
puts "Error: Please provide number only!"
end
#
# Valid inputs
#
puts add(1)
# The sum of following elements [1] is 1
puts add(2, 5, -4)
# The sum of following elements [2, 5, -4] is 3
puts add(25, 45)
# The sum of following elements [25, 45] is 70
#
# Invalid inputs
#
puts add("1", 2, 3)
# Error: Please provide number only!
puts add("a", 1)
# Error: Please provide number only!

57
maths/armstrong_number.rb Normal file
View file

@ -0,0 +1,57 @@
# A ruby program to determine whether a given number is an Armstrong number
# Wiki url: https://en.wikipedia.org/wiki/Narcissistic_number
# other resources: https://pages.mtu.edu/~shene/COURSES/cs201/NOTES/chap04/arms.html
#
# Examples: -> 153 = (1 * 1 * 1) + (5 * 5 * 5) + (3 * 3 * 3) [Armstrong number] and -> 125 != (1 * 1 * 1) + (2 * 2 * 2) + (5 * 5 * 5)
# -> 1634 = (1 * 1 * 1 * 1) + (6 * 6 * 6 * 6) + (3 * 3 * 3 * 3) + (4 * 4 * 4 * 4)
#
def armstrong_number(number)
num = number
sum = 0
len = number.digits.count
while(number != 0)
remainder = number % 10
sum += remainder ** len
number /= 10
end
if num == sum
"The number #{num} is an Armstrong number."
else
"The number #{num} is not an Armstrong number."
end
rescue
"Error: Please provide number only!"
end
#
# Valid inputs
#
puts armstrong_number(153)
# The number 153 is an Armstrong number.
puts armstrong_number(0)
# The number 0 is an Armstrong number.
puts armstrong_number(370)
# The number 370 is an Armstrong number.
puts armstrong_number(10)
# The number 10 is not an Armstrong number.
puts armstrong_number(1634)
# The number 1634 is an Armstrong number.
puts armstrong_number(123)
# The number 123 is not an Armstrong number.
#
# Invalid inputs
#
puts armstrong_number("153")
# Error: Please provide number only!
puts armstrong_number("a")
# Error: Please provide number only!

28
maths/average_mean.rb Normal file
View file

@ -0,0 +1,28 @@
# A ruby program for finding average mean
module AverageMean
# Average mean = sum of elements / total number of elements
def self.average_mean(n, *array)
if n.instance_of? Integer
if n == array.size
puts "The average mean of the following elements #{array} is #{array.sum/array.size}."
else
puts "Provide the required #{n} elements properly!"
end
else
raise
end
rescue
puts "Error: Please provide number only!"
end
end
# Valid inputs
AverageMean.average_mean(2, 3, 1)
AverageMean.average_mean(5, 1, 2, 3, 4, 5)
AverageMean.average_mean(3, 2, 2, 2)
# Invalid inputs
AverageMean.average_mean(2, 3, 1, 5)
AverageMean.average_mean(2, 3, "a")
AverageMean.average_mean("a", 1, 2)

60
maths/average_median.rb Normal file
View file

@ -0,0 +1,60 @@
# A ruby program to find average median
# Reference: https://dev.to/colerau/how-to-find-the-median-and-mean-of-an-array-in-ruby-4f04
module AverageMedian
def self.average_median(n, *array)
if n.instance_of? Integer
if n == array.size
array.sort
if array.size % 2 == 0
mid_element_1 = array.size/2
mid_element_2 = mid_element_1 + 1
puts "The average median of the following elements #{array} is #{(array[mid_element_1 - 1] + array[mid_element_2 - 1]) / 2}."
else
mid_element = (array.size + 1) / 2
puts "The average median of the following elements #{array} is #{array[mid_element - 1]}."
end
else
puts "Provide the required #{n} elements properly!"
end
else
raise
end
rescue
puts "Error: Please provide number only!"
end
end
#
# Valid inputs
#
puts AverageMedian.average_median(2, 3, 1)
# The average median of the following elements [3, 1] is 2.
puts AverageMedian.average_median(5, 1, 2, 3, 4, 5)
# The average median of the following elements [1, 2, 3, 4, 5] is 3.
puts AverageMedian.average_median(3, 2, 2, 2)
# The average median of the following elements [2, 2, 2] is 2.
puts AverageMedian.average_median(1, 5)
# The average median of the following elements [5] is 5.
#
# Invalid inputs
#
puts AverageMedian.average_median(2, 3, 1, 5)
# Provide the required 2 elements properly!
puts AverageMedian.average_median(2, 3, "a")
# Traceback (most recent call last):
# 4: from /Users/voliveira/.rvm/rubies/ruby-2.7.0/bin/irb:23:in `<main>'
# 3: from /Users/voliveira/.rvm/rubies/ruby-2.7.0/bin/irb:23:in `load'
# 2: from /Users/voliveira/.rvm/rubies/ruby-2.7.0/lib/ruby/gems/2.7.0/gems/irb-1.2.1/exe/irb:11:in `<top (required)>'
# 1: from (irb):30
# NameError (undefined local variable or method `verageMedian' for main:Object)
puts AverageMedian.average_median("a", 1, 2)
# Error: Please provide number only!

View file

@ -0,0 +1,65 @@
# Challenge name: Count Sorted Vowel Strings
#
# Given an integer n, return the number of strings of length n that consist only
# of vowels (a, e, i, o, u) and are lexicographically sorted.
#
# A string s is lexicographically sorted if for all valid i, s[i] is the same as
# or comes before s[i+1] in the alphabet.
#
#
# Example 1:
#
# Input: n = 1
# Output: 5
# Explanation: The 5 sorted strings that consist of vowels only are ["a","e","i","o","u"].
#
# Example 2:
#
# Input: n = 2
# Output: 15
# Explanation: The 15 sorted strings that consist of vowels only are
# ["aa","ae","ai","ao","au","ee","ei","eo","eu","ii","io","iu","oo","ou","uu"].
# Note that "ea" is not a valid string since 'e' comes after 'a' in the alphabet.
#
# Example 3:
#
# Input: n = 33
# Output: 66045
#
# Approach: Math
#
#
# Intuition and Algorithm
#
# The problem is a variant of finding Combinations.
# Mathematically, the problem can be described as,
# given 5 vowels (let k = 5), we want to find the
# number of combinations using only n vowels. Also,
# we can repeat each of those vowels multiple times.
#
# Complexity Analysis
#
# Time Complexity: O(1), as the approach runs in constant time.
# Space Complexity: O(1), as the approach uses constant extra space.
# @param {Integer} n
# @return {Integer}
def count_vowel_strings(n)
(n + 4) * (n + 3) * (n + 2) * (n + 1) / 24
end
n = 33
puts count_vowel_strings(n)
# Output: 66045
n = 2
puts count_vowel_strings(n)
# Output: 15
n = 1
puts count_vowel_strings(n)
# Output: 5

31
maths/factorial.rb Normal file
View file

@ -0,0 +1,31 @@
=begin
A ruby program calculate factorial of a given number.
Mathematical Explanation: The factorial of a number is the product of all the integers from 1 to that number.
i.e: n! = n*(n-1)*(n-2)......*2*1
=end
#
# Approach: Interative
#
def factorial(n)
return nil if n < 0
fac = 1
while n > 0
fac *= n
n -= 1
end
fac
end
puts '4! = ' + factorial(4).to_s
# 4! = 24
puts '0! = ' + factorial(0).to_s
# 0! = 1
puts '10! = ' + factorial(10).to_s
# 10! = 3628800

View file

@ -0,0 +1,43 @@
# A ruby program to find factorial of a given integer
# Factorial of a given integer is defined as the product of all the positive integers less than or equal to the given integer
# Mathematical representation: n! = n * (n - 1) * (n - 2) * ... * 1
#
# Non-recursive and non-iterative approach
#
def factorial(number)
if number < 0
"Please check your input number! The given number is a negative number."
elsif number == 0
"The factorial of #{number} is 1."
else
result = (1..number).inject(:*)
"The factorial of #{number} is #{result}."
end
rescue
"Error: Please provide integer only!"
end
# Valid inputs
puts factorial(0)
# The factorial of 0 is 1.
puts factorial(4)
# The factorial of 4 is 24.
puts factorial(10)
# The factorial of 10 is 3628800.
puts factorial(1)
# The factorial of 1 is 1.
puts factorial(-5)
# Please check your input number! The given number is a negative number.
# Invalid inputs
puts factorial("a")
# Error: Please provide integer only!
puts factorial("2")
# Error: Please provide integer only!

64
maths/find_max.rb Normal file
View file

@ -0,0 +1,64 @@
# A ruby program to find max from a set of elements
# This find_max method will return the max element out of the array
def find_max(*array)
max = array[0]
array.each do |a|
if a >= max
max = a
end
end
"The Max of the following elements #{array} is #{max}."
rescue
"Error: Please provide number only!"
end
# Max method will return the maximum element from the set of input elements provided
def predefined_max(*array)
"The Max of the following elements #{array} is #{array.max}."
rescue
"Error: Please provide number only!"
end
# Sort method will sort the elements in ascending order. Last method will return the end element out of the array
def predefined_sort_last_max(*array)
"The Max of the following elements #{array} is #{array.sort.last}."
rescue
"Error: Please provide number only!"
end
# Using find_max
# Valid inputs
puts find_max(11, 29, 33)
# The Max of the following elements [11, 29, 33] is 33.
puts find_max(-221, -852, -1100, -10)
# The Max of the following elements [-221, -852, -1100, -10] is -10.
# Invalid inputs
puts find_max(5, "95", 2)
# Error: Please provide number only!
# Using predefined_max
# Valid inputs
puts predefined_max(51, 82, 39)
# The Max of the following elements [51, 82, 39] is 82.
puts predefined_max(-11, -51, -10, -10)
# The Max of the following elements [-11, -51, -10, -10] is -10.
# Invalid inputs
puts predefined_max("x", 5, 95, 2)
# Error: Please provide number only!
# Using predefined_sort_last_max
# Valid inputs
puts predefined_sort_last_max(1, 2, 3)
# The Max of the following elements [1, 2, 3] is 3.
puts predefined_sort_last_max(-21, -52, -100, -1)
# The Max of the following elements [-21, -52, -100, -1] is -1.
# Invalid inputs
puts predefined_sort_last_max(5, 95, 2, "a")
# Error: Please provide number only!

64
maths/find_min.rb Normal file
View file

@ -0,0 +1,64 @@
# A ruby program to find min from a set of elements
# This find_min method will return the min element out of the array
def find_min(*array)
min = array[0]
array.each do |a|
if a <= min
min = a
end
end
"The Min of the following elements #{array} is #{min}."
rescue
"Error: Please provide number only!"
end
# Min method will return the minimum element from the set of input elements provided
def predefined_min(*array)
"The Min of the following elements #{array} is #{array.min}."
rescue
"Error: Please provide number only!"
end
# Sort method will sort the elements in ascending order. First method will return the beginning element out of the array
def predefined_sort_first_min(*array)
"The Min of the following elements #{array} is #{array.sort.first}."
rescue
"Error: Please provide number only!"
end
# Using find_min
# Valid inputs
puts find_min(11, 29, 33)
# The Min of the following elements [11, 29, 33] is 33.
puts find_min(-221, -852, -1100, -10)
# The Min of the following elements [-221, -852, -1100, -10] is -10.
# Invalid inputs
puts find_min(5, "95", 2)
# Error: Please provide number only!
# Using predefined_min
# Valid inputs
puts predefined_min(51, 82, 39)
# The Min of the following elements [51, 82, 39] is 82.
puts predefined_min(-11, -51, -10, -10)
# The Min of the following elements [-11, -51, -10, -10] is -10.
# Invalid inputs
puts predefined_min("x", 5, 95, 2)
# Error: Please provide number only!
# Using predefined_sort_first_min
# Valid inputs
puts predefined_sort_first_min(1, 2, 3)
# The Min of the following elements [1, 2, 3] is 3.
puts predefined_sort_first_min(-21, -52, -100, -1)
# The Min of the following elements [-21, -52, -100, -1] is -1.
# Invalid inputs
puts predefined_sort_first_min(5, 95, 2, "a")
# Error: Please provide number only!

31
maths/lucas_series.rb Normal file
View file

@ -0,0 +1,31 @@
# A ruby program for Lucas series
#
# The Lucas numbers, commonly denoted L(n) form a sequence,
# called the Lucas series, such that each number is the sum
# of the two preceding ones, starting from 2 and 1. That is,
#
# L(0) = 2, L(1) = 1
# L(n) = L(n - 1) + L(n - 2), for n > 1.
#
# Given n, calculate L(n).
# Example: 2 1 3 4 7 11 18...
# Resource: https://en.wikipedia.org/wiki/Lucas_number
def lucas(number)
golden_ratio = (1 + 5**0.5) / 2
((golden_ratio**number).round()).to_i
rescue
"Error: Provide number only!"
end
puts lucas(4)
# 7
puts lucas(3)
# 4
puts lucas("3")
# Error: Provide number only!
puts lucas(2)
# 3

96
maths/roman_to_integer.rb Normal file
View file

@ -0,0 +1,96 @@
# Challenge name: Roman to Integer
#
# Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.
#
# Symbol Value
# I 1
# V 5
# X 10
# L 50
# C 100
# D 500
# M 1000
#
# For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.
#
# Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:
#
# I can be placed before V (5) and X (10) to make 4 and 9.
# X can be placed before L (50) and C (100) to make 40 and 90.
# C can be placed before D (500) and M (1000) to make 400 and 900.
# Given a roman numeral, convert it to an integer.
#
#
# Approach 1: Left-to-Right Pass
#
# Complexity Analysis
#
# Let n be the length of the input string (the total number of symbols in it).
#
# Time complexity: O(1).
# As there is a finite set of roman numerals.
#
# Space complexity: O(1).
# Because only a constant number of single-value variables are used, the space complexity is O(1).
ROM_NUMS = {
"I" => 1,
"V" => 5,
"X" => 10,
"L" => 50,
"C" => 100,
"D" => 500,
"M" => 1000
}
# Now, recall that each symbol adds its own value, except for when a smaller
# valued symbol is before a larger valued symbol. In those cases, instead of
# adding both symbols to the total, we need to subtract the large from the
# small, adding that instead.
# Therefore, the simplest algorithm is to use a pointer to scan through the
# string, at each step deciding whether to add the current symbol and
# go forward 1 place, or add the difference of the next 2 symbols and
# go forward 2 places.
def roman_to_int(s)
res = 0
temp = 0
s.chars.each_with_index do |el, i|
# subtractive case: if at least 2 symbols remaining AND value of s[i] < value of s[i + 1]
if ROM_NUMS[s[i + 1]] && ROM_NUMS[el] < ROM_NUMS[s[i+1]]
temp = ROM_NUMS[el]
else
# Else this is NOT the subtractive case.
res += (ROM_NUMS[el] - temp)
temp = 0
end
end
res
end
s = "III"
puts roman_to_int(s)
# Output: 3
s = "IV"
puts roman_to_int(s)
# Output: 4
s = "IX"
puts roman_to_int(s)
# Output: 9
s = "LVIII"
puts roman_to_int(s)
# Output: 58
# Explanation: L = 50, V= 5, III = 3.
s = "MCMXCIV"
puts roman_to_int(s)
# Output: 1994
# Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

View file

@ -9,17 +9,20 @@ def binary_search(array, key)
if key < array[middle]
back = middle - 1
else
else
front = middle + 1
end
end
end
nil
end
puts "Enter a sorted space-separated list:"
arr = gets.chomp.split(' ').map(&:to_i)
puts "Enter the value to be searched:"
value = gets.chomp.to_i
puts if binary_search(arr, value) != nil
"Found at index #{binary_search(arr, value)}"
else

24
sorting/bead_sort.rb Normal file
View file

@ -0,0 +1,24 @@
class Array
def columns
x = map(&:length).max
Array.new(x) do |row|
Array.new(length) { |column| self[column][row] }.compact
end
end
end
def bead_sort(array)
array
.map { |element| [1] * element }
.columns
.columns
.map(&:length)
.reverse
end
if $0 == __FILE__
puts 'Enter a list of numbers separated by space'
list = gets.split.map(&:to_i)
p bead_sort(list)
end

11
sorting/bead_sort_test.rb Normal file
View file

@ -0,0 +1,11 @@
require 'minitest/autorun'
require_relative './sort_tests'
require_relative './bead_sort'
class TestInsertionSort < Minitest::Test
include SortTests
def sort(input)
bead_sort(input)
end
end

24
sorting/cocktail_sort.rb Normal file
View file

@ -0,0 +1,24 @@
def cocktail_sort(array)
start = 0
finish = array.length - 1
way = 1
loop do
swapped = false
start.step(finish - way, way) do |i|
if (array[i] <=> array[i + way]) == way
array[i], array[i + way] = array[i + way], array[i]
swapped = i
end
end
break unless swapped
start, finish, way = swapped, start, -way
end
array
end
if $0 == __FILE__
puts 'Enter a list of numbers separated by space'
list = gets.split.map(&:to_i)
p cocktail_sort(list)
end

View file

@ -0,0 +1,12 @@
require 'minitest/autorun'
require_relative './sort_tests'
require_relative './cocktail_sort'
class TestInsertionSort < Minitest::Test
include SortTests
def sort(input)
cocktail_sort(input)
end
end

22
sorting/comb_sort.rb Normal file
View file

@ -0,0 +1,22 @@
def comb_sort(array)
gap = array.length
swaps = true
while gap > 1 or swaps
gap = [1, (gap / 1.25).to_i].max
swaps = false
0.upto(array.length - gap - 1) do |i|
if array[i] > array[i + gap]
array[i], array[i + gap] = array[i + gap], array[i]
swaps = true
end
end
end
array
end
if $0 == __FILE__
puts 'Enter a list of numbers separated by space'
list = gets.split.map(&:to_i)
p insertion_sort(list)
end

11
sorting/comb_sort_test.rb Normal file
View file

@ -0,0 +1,11 @@
require 'minitest/autorun'
require_relative './sort_tests'
require_relative './comb_sort'
class TestInsertionSort < Minitest::Test
include SortTests
def sort(input)
comb_sort(input)
end
end

18
sorting/pancake_sort.rb Normal file
View file

@ -0,0 +1,18 @@
def pancake_sort(array)
return array if array.length <= 1
(array.length - 1).downto(1) do |index|
max_index = array[0..index].index(array[0..index].max)
next if max_index == index
array[0..max_index] = array[0..max_index].reverse if max_index > 0
array[0..index] = array[0..index].reverse
end
array
end
if $0 == __FILE__
puts 'Enter a list of numbers separated by space'
list = gets.split.map(&:to_i)
p pancake_sort(list)
end

View file

@ -0,0 +1,11 @@
require 'minitest/autorun'
require_relative './sort_tests'
require_relative './pancake_sort'
class TestInsertionSort < Minitest::Test
include SortTests
def sort(input)
pancake_sort(input)
end
end

65
sorting/sort_color.rb Normal file
View file

@ -0,0 +1,65 @@
# Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.
#
# We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.
#
# Example 1:
#
# Input: nums = [2,0,2,1,1,0]
# Output: [0,0,1,1,2,2]
#
# Example 2:
#
# Input: nums = [2,0,1]
# Output: [0,1,2]
#
# Example 3:
#
# Input: nums = [0]
# Output: [0]
#
# Example 4:
#
# Input: nums = [1]
# Output: [1]
# @param {Integer[]} nums
# @return {Void} Do not return anything, modify nums in-place instead.
def sort_colors(nums)
bubble_sort(nums)
end
def bubble_sort(array)
array_length = array.size
return array if array_length <= 1
loop do
swapped = false
(array_length - 1).times do |i|
if array[i] > array[i + 1]
array[i], array[i + 1] = array[i + 1], array[i]
swapped = true
end
end
break unless swapped
end
array
end
nums = [2, 0, 2, 1, 1, 0]
puts sort_colors(nums)
# Output: [0,0,1,1,2,2]
nums = [2, 0, 1]
puts sort_colors(nums)
# Output: [0,1,2]
nums = [0]
puts sort_colors(nums)
# Output: [0]
nums = [1]
puts sort_colors(nums)
# Output: [1]