Merge branch 'TheAlgorithms:master' into master

This commit is contained in:
Sahil Afrid Farookhi 2021-06-01 00:10:05 +05:30
commit 62333e03c7
24 changed files with 1208 additions and 1 deletions

View file

@ -3,7 +3,13 @@
* [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)
@ -19,10 +25,12 @@
* [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)
@ -32,6 +40,7 @@
* [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
@ -43,13 +52,16 @@
* [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)
* [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)
@ -63,6 +75,7 @@
## 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
@ -79,9 +92,10 @@
* [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 and Non-iterative](https://github.com/TheAlgorithms/Ruby/blob/master/maths/factorial_non_recursive_non_iterative.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)
@ -89,6 +103,7 @@
* [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)
@ -127,18 +142,26 @@
* [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)

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,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,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,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,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

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

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.

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