Added first algorithms in Ruby programming language

pull/1217/head
Marcio Oliveira 2023-07-01 14:08:41 -03:00
parent d3c2184af8
commit b982662efb
13 changed files with 386 additions and 0 deletions

40
.github/workflows/ruby.yml vendored 100644
View File

@ -0,0 +1,40 @@
name: Ruby
on:
push:
branches: [ main ]
paths: '**.rb'
pull_request:
branches: [ main ]
paths: '**.rb'
permissions:
contents: read
jobs:
lint:
name: Run Ruby linter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2.2'
bundler-cache: true
- name: Install dependencies
run: bundle install
- name: Run RuboCop
run: bundle exec rubocop
test:
name: Run Ruby tests
needs: [ lint ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2.2'
bundler-cache: true
- name: Install dependencies
run: bundle install
- name: Run tests
run: bundle exec rspec **/*.rb

21
.gitignore vendored
View File

@ -15,3 +15,24 @@ Thumbs.db
# Visual Studio Code # Visual Studio Code
.vscode/ .vscode/
# Ruby
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/
/.yardoc/
/_yardoc/
/doc/
/rdoc/
/.bundle/
/vendor/bundle
/lib/bundler/man/
.rvmrc

View File

@ -5,6 +5,7 @@
[![Python](https://github.com/MakeContributions/DSA/actions/workflows/python.yml/badge.svg)](https://github.com/MakeContributions/DSA/actions/workflows/python.yml) [![Python](https://github.com/MakeContributions/DSA/actions/workflows/python.yml/badge.svg)](https://github.com/MakeContributions/DSA/actions/workflows/python.yml)
[![codespell](https://github.com/MakeContributions/DSA/actions/workflows/codespell.yml/badge.svg)](https://github.com/MakeContributions/DSA/actions/workflows/codespell.yml) [![codespell](https://github.com/MakeContributions/DSA/actions/workflows/codespell.yml/badge.svg)](https://github.com/MakeContributions/DSA/actions/workflows/codespell.yml)
[![CodeQL](https://github.com/MakeContributions/DSA/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/MakeContributions/DSA/actions/workflows/codeql-analysis.yml) [![CodeQL](https://github.com/MakeContributions/DSA/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/MakeContributions/DSA/actions/workflows/codeql-analysis.yml)
[![Ruby](https://github.com/MakeContributions/DSA/actions/workflows/ruby.yml/badge.svg)](https://github.com/MakeContributions/DSA/actions/workflows/ruby.yml)
[![Discord](https://img.shields.io/discord/863049619734790185?color=7389D8&logo=discord&logoColor=ffffff&label=&labelColor=6A7EC2)](https://discord.gg/ydWxdqbTyK) [![Discord](https://img.shields.io/discord/863049619734790185?color=7389D8&logo=discord&logoColor=ffffff&label=&labelColor=6A7EC2)](https://discord.gg/ydWxdqbTyK)
# Data Structures and Algorithm # Data Structures and Algorithm
@ -102,6 +103,7 @@ It can be any of the following ones
- **JavaScript**: `package.json` and `package-lock.json` - **JavaScript**: `package.json` and `package-lock.json`
- **Rust**: `Cargo.toml` and `Cargo.lock` - **Rust**: `Cargo.toml` and `Cargo.lock`
- **Go**: `go.mod` - **Go**: `go.mod`
- **Ruby**: `Gemfile`
#### Source Code File #### Source Code File
@ -127,6 +129,7 @@ The programming should keep the naming convention rule of each programming langu
| Go | @ayo-ajayi | | Go | @ayo-ajayi |
| Python | @Arsenic-ATG, @sridhar-5 | | Python | @Arsenic-ATG, @sridhar-5 |
| JavaScript | @ming-tsai | | JavaScript | @ming-tsai |
| Ruby | @oliveiramarcio |
## Contributors ## Contributors

View File

@ -0,0 +1,16 @@
require:
- rubocop-rspec
Bundler/OrderedGems:
Exclude:
- 'Gemfile'
AllCops:
DisplayCopNames: true
DisplayStyleGuide: true
TargetRubyVersion: 3.2.2
NewCops: enable
Style/FrozenStringLiteralComment:
Exclude:
- 'Gemfile'

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
# Given an integer array nums, return true if any value appears at least,
# twice in the array and return false if every element is distinct.
# Example:
# Input: nums = [1, 2, 3, 1]
# Output: true
# Time: O(n)
# Space: O(n)
module Arrays
def self.contains_duplicate(nums)
!nums.uniq!.nil?
end
end
RSpec.describe Arrays do
describe '.contains_duplicate(nums)' do
it 'returns true if any value appears at least twice in the array' do
expect(Arrays.contains_duplicate([1, 2, 3, 1])).to be true
end
it 'returns false if every element is distinct' do
expect(Arrays.contains_duplicate([1, 2, 3, 4])).to be false
end
it 'returns false for an empty array' do
expect(Arrays.contains_duplicate([])).to be false
end
end
end

View File

@ -0,0 +1,57 @@
# frozen_string_literal: true
# Given an array nums of size n, return the majority element.
# The majority element appears more than n/2 times
# Time: O(n)
# Space: O(1)
module Arrays
def self.majority_element(nums)
candidate, count = find_candidate(nums)
count.positive? ? candidate : nil
end
def self.find_candidate(nums)
candidate = nil
count = 0
nums.each do |num|
candidate, count = update_candidate(candidate, count, num)
end
[candidate, count]
end
def self.update_candidate(candidate, count, num)
if count.zero?
candidate = num
count = 1
elsif candidate == num
count += 1
else
count -= 1
end
[candidate, count]
end
end
RSpec.describe Arrays do
describe '.majority_element' do
it 'returns the majority element in the array' do
expect(Arrays.majority_element([3, 2, 3])).to eq(3)
expect(Arrays.majority_element([2, 2, 1, 1, 1, 2, 2])).to eq(2)
end
it 'handles different input sizes' do
expect(Arrays.majority_element([1])).to eq(1)
expect(Arrays.majority_element([1, 1])).to eq(1)
expect(Arrays.majority_element([1, 2, 2])).to eq(2)
expect(Arrays.majority_element([3, 3, 4, 2, 4, 4, 2, 4, 4])).to eq(4)
end
it 'handles negative numbers' do
expect(Arrays.majority_element([-1, -1, -1, 2, 2, 2, -1, -1])).to eq(-1)
expect(Arrays.majority_element([-3, -2, -3, -3])).to eq(-3)
end
end
end

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
# Algorithm Name: Max Sum of Sub Array
# Time: O(n)
# Space: O(n)
module Arrays
def self.max_subarray_sum(arr)
arr_size = arr.length
max_sum = arr[0]
max_sum_curr = arr[0]
(1...arr_size).each do |i|
max_sum_curr = [arr[i], max_sum_curr + arr[i]].max
max_sum = [max_sum, max_sum_curr].max
end
max_sum
end
end
RSpec.describe Arrays do
describe '.max_subarray_sum' do
it 'returns the max subarray sum for positive numbers' do
expect(Arrays.max_subarray_sum([1, 2, 3, 4])).to eq(10)
end
it 'returns the max subarray sum for negative numbers' do
expect(Arrays.max_subarray_sum([-2, -3, -4, -1, -2, -1, -5, -3])).to eq(-1)
end
it 'returns the max subarray sum for a mix of positive and negative numbers' do
expect(Arrays.max_subarray_sum([3, 2, -4, 9])).to eq(10)
end
it 'returns the max subarray sum for an array with a single element' do
expect(Arrays.max_subarray_sum([5])).to eq(5)
end
end
end

View File

@ -0,0 +1,24 @@
# frozen_string_literal: true
# Description: This program reverses array elements by swapping the first half part of the array
# Time Complexity : O(n/2), where n is the array size
# Auxiliary Space : O(1)
module Arrays
def self.reverse_array(arr)
n = arr.length
mid = n / 2
(0...mid).each { |i| arr[i], arr[n - i - 1] = arr[n - i - 1], arr[i] }
arr
end
end
RSpec.describe Arrays do
describe '.reverse_array' do
it 'reverses the elements of an array' do
expect(Arrays.reverse_array([1, 2, 3, 4, 5])).to eq([5, 4, 3, 2, 1])
expect(Arrays.reverse_array([1, 2, 3, 4])).to eq([4, 3, 2, 1])
expect(Arrays.reverse_array([1])).to eq([1])
expect(Arrays.reverse_array([])).to eq([])
end
end
end

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
# Given a non-empty array of int, every element appears twice except for 1. Find that element.
# Time: O(n)
# Space: O(n)
module Arrays
def self.single_number(arr)
frequency = Hash.new(0)
arr.each do |num|
frequency[num] += 1
end
frequency.each do |num, count|
return num if count == 1
end
nil
end
end
RSpec.describe Arrays do
describe '.single_number' do
it 'returns the single number in the array' do
expect(Arrays.single_number([1])).to eq(1)
expect(Arrays.single_number([1, 2, 2])).to eq(1)
expect(Arrays.single_number([1, 2, 1])).to eq(2)
expect(Arrays.single_number([4, 2, 2, 3, 4, 1, 1])).to eq(3)
expect(Arrays.single_number([5, 5, 6, 6, 7, 7, 8])).to eq(8)
end
it 'returns nil when no single number is found' do
expect(Arrays.single_number([1, 1, 2, 2, 3, 3])).to be_nil
expect(Arrays.single_number([1, 1, 2, 2, 3, 3, 4, 4])).to be_nil
end
end
end

View File

@ -0,0 +1,43 @@
# frozen_string_literal: true
# Problem Statement: given an array of integers nums and an integer target,
# return indices of the two numbers such that they add up to target.
#
# You may assume that each input would have exactly one solution,
# and you may not use the same element twice.
#
# Input: An array of integers and a target (int)
# Output: array of indexes of len(2) with sum of element at that index equal to target or nil
#
# Time: O(n)
# Space: O(n)
module Arrays
def self.two_sum(nums, target)
complement_hash = {}
nums.each_with_index do |num, index|
complement = target - num
return [complement_hash[complement], index] if complement_hash.key?(complement)
complement_hash[num] = index
end
nil
end
end
RSpec.describe Arrays do
describe '.two_sum' do
it 'returns the correct indices' do
expect(Arrays.two_sum([2, 7, 11, 15], 9)).to eq([0, 1])
expect(Arrays.two_sum([3, 2, 4], 6)).to eq([1, 2])
expect(Arrays.two_sum([3, 3], 6)).to eq([0, 1])
end
it 'returns nil if no solution is found' do
expect(Arrays.two_sum([1, 2, 3, 4], 9)).to be_nil
expect(Arrays.two_sum([], 5)).to be_nil
end
end
end

View File

@ -0,0 +1,5 @@
source 'https://rubygems.org'
gem 'rspec'
gem 'rubocop'
gem 'rubocop-rspec'

View File

@ -0,0 +1,62 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
diff-lcs (1.5.0)
json (2.6.3)
language_server-protocol (3.17.0.3)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
racc (1.7.1)
rainbow (3.1.1)
regexp_parser (2.8.1)
rexml (3.2.5)
rspec (3.12.0)
rspec-core (~> 3.12.0)
rspec-expectations (~> 3.12.0)
rspec-mocks (~> 3.12.0)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-mocks (3.12.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-support (3.12.1)
rubocop (1.53.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.3)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
rubocop-capybara (2.18.0)
rubocop (~> 1.41)
rubocop-factory_bot (2.23.1)
rubocop (~> 1.33)
rubocop-rspec (2.22.0)
rubocop (~> 1.33)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0)
unicode-display_width (2.4.2)
PLATFORMS
arm64-darwin-22
DEPENDENCIES
rspec
rubocop
rubocop-rspec
BUNDLED WITH
2.4.15

View File

@ -0,0 +1,9 @@
# Ruby
## Arrays
- [Contains Duplicate](arrays/contains_duplicate.rb)
- [Majority Element](arrays/majority_element.rb)
- [Maximum subarray sum (Kadane's Algorithm)](arrays/maximum-subarray-sum.rb)
- [Reverse Array](arrays/reverse-array.rb)
- [Single Number](arrays/single-number.rb)
- [Two Sum](arrays/two-sum.rb)