minor changes

This commit is contained in:
Vitor Oliveira 2021-02-06 23:12:37 -08:00
commit 1fe4dead1b
72 changed files with 1887 additions and 489 deletions

10
.github/CODEOWNERS vendored Normal file
View file

@ -0,0 +1,10 @@
# This is a comment.
# Each line is a file pattern followed by one or more owners.
# More details are here: https://help.github.com/articles/about-codeowners/
# The '*' pattern is global owners.
# Order is important. The last matching pattern has the most precedence.
/.* @vbrazo @vzvu3k6k

60
.github/stale.yml vendored Normal file
View file

@ -0,0 +1,60 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 30
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 7
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- "Status: on hold"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
pulls:
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This pull request has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale Pull Request.
closeComment: >
Please reopen this pull request once you commit the changes requested
or make improvements on the code. If this is not the case and you need
some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms)
or ping one of the reviewers. Thank you for your contributions!
issues:
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale Issue.
closeComment: >
Please reopen this issue once you add more information and updates here.
If this is not the case and you need some help, feel free to seek help
from our [Gitter](https://gitter.im/TheAlgorithms) or ping one of the
reviewers. Thank you for your contributions!

12
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,12 @@
name: test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: ruby/setup-ruby@master
with:
ruby-version: '3.0'
- name: Run tests
run: rake test

View file

@ -0,0 +1,59 @@
name: update_directory_md
on: [push]
jobs:
update_directory_md:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/setup-python@master
- name: update_directory_md
shell: python
run: |
import os
from typing import Iterator
URL_BASE = "https://github.com/TheAlgorithms/Ruby/blob/master"
g_output = []
def good_filepaths(top_dir: str = ".") -> Iterator[str]:
for dirpath, dirnames, filenames in os.walk(top_dir):
dirnames[:] = [d for d in dirnames if d[0] not in "._"]
for filename in filenames:
if os.path.splitext(filename)[1].lower() == ".rb":
yield os.path.join(dirpath, filename).lstrip("./")
def md_prefix(i):
return f"{i * ' '}*" if i else "\n##"
def print_path(old_path: str, new_path: str) -> str:
global g_output
old_parts = old_path.split(os.sep)
for i, new_part in enumerate(new_path.split(os.sep)):
if i + 1 > len(old_parts) or old_parts[i] != new_part:
if new_part:
g_output.append(f"{md_prefix(i)} {new_part.replace('_', ' ').title()}")
return new_path
def build_directory_md(top_dir: str = ".") -> str:
global g_output
old_path = ""
for filepath in sorted(good_filepaths(), key=str.lower):
filepath, filename = os.path.split(filepath)
if filepath != old_path:
old_path = print_path(old_path, filepath)
indent = (filepath.count(os.sep) + 1) if filepath else 0
url = "/".join((URL_BASE, filepath, filename)).replace(" ", "%20")
filename = os.path.splitext(filename.replace("_", " ").title())[0]
g_output.append(f"{md_prefix(indent)} [{filename}]({url})")
return "\n".join(g_output)
with open("DIRECTORY.md", "w") as out_file:
out_file.write(build_directory_md(".") + "\n")
- name: Update DIRECTORY.md
run: |
cat DIRECTORY.md
git config --global user.name github-actions
git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com'
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY
git add DIRECTORY.md
git commit -am "updating DIRECTORY.md" || true
git push --force origin HEAD:$GITHUB_REF || true

67
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,67 @@
# Contributing guidelines
## Before contributing
Welcome to [TheAlgorithms/Ruby](https://github.com/TheAlgorithms/Ruby)! Before sending your pull requests, make sure that you **read the whole guidelines**. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Ruby/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms).
## Contributing
### Contributor
We are very happy that you consider implementing algorithms and data structure for others! This repository is referenced and used by learners from all over the globe. Being one of our contributors, you agree and confirm that:
- You did your work - no plagiarism allowed
- Any plagiarized work will not be merged.
- Your work will be distributed under [MIT License](LICENSE.md) once your pull request is merged
- You submitted work fulfils or mostly fulfils our styles and standards
**New implementation** is welcome! For example, new solutions for a problem, different representations for a graph data structure or algorithm designs with different complexity but **identical implementation** of an existing implementation is not allowed. Please check whether the solution is already implemented or not before submitting your pull request.
**Improving comments** and **writing proper tests** are also highly welcome.
### Contribution
We appreciate any contribution, from fixing a grammar mistake in a comment to implementing complex algorithms. Please read this section if you are contributing your work.
Your contribution will be tested by our [automated testing on Travis CI](https://travis-ci.org/TheAlgorithms/Ruby/pull_requests) to save time and mental energy. After you have submitted your pull request, you should see the Travis tests start to run at the bottom of your submission page. If those tests fail, then click on the ___details___ button try to read through the Travis output to understand the failure. If you do not understand, please leave a comment on your submission page and a community member will try to help.
Please help us keep our issue list small by adding fixes: #{$ISSUE_NO} to the commit message of pull requests that resolve open issues. GitHub will use this tag to auto close the issue when the PR is merged.
#### What is an Algorithm?
An Algorithm is one or more functions (or classes) that:
* take one or more inputs,
* perform some internal calculations or data manipulations,
* return one or more outputs,
* have minimal side effects.
Algorithms should be packaged in a way that would make it easy for readers to put them into larger programs.
Algorithms should:
* have intuitive class and function names that make their purpose clear to readers
* use Ruby naming conventions and intuitive variable names to ease comprehension
* be flexible to take different input values
* have Ruby type hints for their input parameters and return values
* raise Ruby exceptions on erroneous input values
* return all calculation results instead of printing or plotting them
Algorithms in this repo should not be how-to examples for existing Ruby packages. Instead, they should perform internal calculations or manipulations to convert input values into different output values. Those calculations or manipulations can use data types, classes, or functions of existing Ruby packages but each algorithm in this repo should add unique value.
#### Other Requirements for Submissions
- If you are submitting code in the `project_euler/` directory, please also read [the dedicated Guideline](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/README.md) before contributing to our Project Euler library.
- Strictly use snake_case (underscore_separated) in your file_name, as it will be easy to parse in future using scripts.
- Please avoid creating new directories if at all possible. Try to fit your work into the existing directory structure.
- If possible, follow the standard *within* the folder you are submitting to.
- If you have modified/added code work, make sure the code compiles before submitting.
- If you have modified/added documentation work, ensure your language is concise and contains no grammar errors.
- Do not update the `README.md` or `DIRECTORY.md` file which will be periodically autogenerated by our Travis CI processes.
- Add a corresponding explanation to [Algorithms-Explanation](https://github.com/TheAlgorithms/Algorithms-Explanation) (Optional but recommended).
- Most importantly,
- **Be consistent in the use of these guidelines when submitting.**
- **Join** [Gitter](https://gitter.im/TheAlgorithms) **now!**
- Happy coding!
Writer [@vbrazo](https://github.com/vbrazo), Dec 2020.

89
DIRECTORY.md Normal file
View file

@ -0,0 +1,89 @@
## Ciphers
* [Merkle Hellman Cryptosystem](https://github.com/TheAlgorithms/Ruby/blob/master/ciphers/merkle_hellman_cryptosystem.rb)
## Data Structures
* Arrays
* [Get Products Of All Other Elements](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/get_products_of_all_other_elements.rb)
* Binary Trees
* [Inorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/inorder_traversal.rb)
* [Invert](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/invert.rb)
* [Postorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/postorder_traversal.rb)
* [Preorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/preorder_traversal.rb)
* Linked Lists
* [Double List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/double_list.rb)
* [Single List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/single_list.rb)
* Queues
* [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)
* Tries
* [Trie](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/tries/trie.rb)
## Discrete Mathematics
* [Euclidean Gcd](https://github.com/TheAlgorithms/Ruby/blob/master/discrete_mathematics/euclidean_gcd.rb)
* [Exteded Euclidean Algorithm](https://github.com/TheAlgorithms/Ruby/blob/master/discrete_mathematics/exteded_euclidean_algorithm.rb)
* [Lcm](https://github.com/TheAlgorithms/Ruby/blob/master/discrete_mathematics/lcm.rb)
## Maths
* [Abs](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs.rb)
* [Abs Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs_test.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)
* [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)
* [Number Of Digits](https://github.com/TheAlgorithms/Ruby/blob/master/maths/number_of_digits.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)
## Other
* [Fisher Yates](https://github.com/TheAlgorithms/Ruby/blob/master/other/fisher_yates.rb)
## Project Euler
* Problem 1
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_1/sol1.rb)
* Problem 2
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_2/sol1.rb)
* Problem 20
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_20/sol1.rb)
* Problem 21
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_21/sol1.rb)
* Problem 22
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_22/sol1.rb)
* Problem 3
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_3/sol1.rb)
* [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_3/sol2.rb)
* Problem 4
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_4/sol1.rb)
* [Sol2](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_4/sol2.rb)
* Problem 5
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_5/sol1.rb)
## 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)
## Searches
* [Jump Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/jump_search.rb)
## Searches
* [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
* [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)
* [Bucket Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bucket_sort.rb)
* [Heap Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/heap_sort.rb)
* [Insertion Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/insertion_sort.rb)
* [Merge Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/merge_sort.rb)
* [Quicksort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/quicksort.rb)
* [Radix Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/radix_sort.rb)
* [Selection Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/selection_sort.rb)
* [Shell Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/shell_sort.rb)

21
LICENSE.md Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 The Algorithms
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,87 +1,20 @@
# The Algorithms - Ruby
# The Algorithms - Ruby
[![Gitter chat](https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square)](https://gitter.im/TheAlgorithms) 
[![contributions welcome](https://img.shields.io/static/v1.svg?label=Contributions&message=Welcome&color=0059b3&style=flat-square)](https://github.com/TheAlgorithms/Ruby/blob/master/CONTRIBUTING.md) 
![](https://img.shields.io/github/repo-size/TheAlgorithms/Ruby.svg?label=Repo%20size&style=flat-square) 
### All algorithms implemented in Ruby (for education)
These are for demonstration purposes only.
## Sorting Algorithms
These implementations are for learning purposes only. Therefore they may be less efficient than the implementations in the Ruby standard library.
### Bogo Sort
![alt text][bogo-image]
## Contribution Guidelines
From [Wikipedia][bogo-wiki]: Bogo sort is a highly ineffective sorting function based on the generate and test paradigm. The function successively generates permutations of its input until it finds one that is sorted. It is not useful for sorting, but may be used for educational purposes, to contrast it with more efficient algorithms.
Read our [Contribution Guidelines](CONTRIBUTING.md) before you contribute.
__Properties__
* Unbounded (randomized version), O((n+1)!) (deterministic version)
* Best case performance O(n)
* Average case performance O((n+1)!)
## Community Channel
### Bubble Sort
![alt text][bubble-image]
We're on [Gitter](https://gitter.im/TheAlgorithms)! Please join us.
From [Wikipedia][bubble-wiki]: Bubble sort, sometimes referred to as sinking sort, is a simple sorting algorithm that repeatedly steps through the list to be sorted, compares each pair of adjacent items and swaps them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, which indicates that the list is sorted.
## List of Algorithms
__Properties__
* Worst case performance O(n^2)
* Best case performance O(n)
* Average case performance O(n^2)
###### View the algorithm in [action][bubble-toptal]
### Insertion Sort
![alt text][insertion-image]
From [Wikipedia][insertion-wiki]: Insertion sort is a simple sorting algorithm that builds the final sorted array (or list) one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort.
__Properties__
* Worst case performance O(n^2)
* Best case performance O(n)
* Average case performance O(n^2)
###### View the algorithm in [action][insertion-toptal]
### Selection Sort
![alt text][selection-image]
From [Wikipedia][selection-wiki]: The algorithm divides the input list into two parts: the sublist of items already sorted, which is built up from left to right at the front (left) of the list, and the sublist of items remaining to be sorted that occupy the rest of the list. Initially, the sorted sublist is empty and the unsorted sublist is the entire input list. The algorithm proceeds by finding the smallest (or largest, depending on sorting order) element in the unsorted sublist, exchanging (swapping) it with the leftmost unsorted element (putting it in sorted order), and moving the sublist boundaries one element to the right.
__Properties__
* Worst case performance O(n^2)
* Best case performance O(n^2)
* Average case performance O(n^2)
###### View the algorithm in [action][selection-toptal]
### Shell Sort
![alt text][shell-image]
From [Wikipedia][shell-wiki]: Shellsort, also known as Shell sort or Shell's method, is an in-place comparison sort. It can be seen as either a generalization of sorting by exchange (bubble sort) or sorting by insertion (insertion sort).[3] The method starts by sorting pairs of elements far apart from each other, then progressively reducing the gap between elements to be compared. Starting with far apart elements, it can move some out-of-place elements into position faster than a simple nearest neighbor exchange. Donald Shell published the first version of this sort in 1959.[4][5] The running time of Shellsort is heavily dependent on the gap sequence it uses. For many practical variants, determining their time complexity remains an open problem.
__Properties__
* Worst case performance O(n^2)
* Best case performance O(n log n)
* Average case performance depends on gap sequence
###### View the algorithm in [action][shell-toptal]
[selection-toptal]: https://www.toptal.com/developers/sorting-algorithms/selection-sort
[selection-wiki]: https://en.wikipedia.org/wiki/Selection_sort
[selection-image]: https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Selection_sort_animation.gif/250px-Selection_sort_animation.gif "Selection Sort Sort"
[bubble-toptal]: https://www.toptal.com/developers/sorting-algorithms/bubble-sort
[bubble-wiki]: https://en.wikipedia.org/wiki/Bubble_sort
[bubble-image]: https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Bubblesort-edited-color.svg/220px-Bubblesort-edited-color.svg.png "Bubble Sort"
[insertion-toptal]: https://www.toptal.com/developers/sorting-algorithms/insertion-sort
[insertion-wiki]: https://en.wikipedia.org/wiki/Insertion_sort
[insertion-image]: https://upload.wikimedia.org/wikipedia/commons/7/7e/Insertionsort-edited.png "Insertion Sort"
[shell-toptal]: https://www.toptal.com/developers/sorting-algorithms/shell-sort
[shell-wiki]: https://en.wikipedia.org/wiki/Shellsort
[shell-image]: https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Shell_sorting_algorithm_color_bars.svg/267px-Shell_sorting_algorithm_color_bars.svg.png "Shell Sort"
[bogo-wiki]: https://en.wikipedia.org/wiki/Bogosort
[bogo-image]: http://www.siafoo.net/graph/d174e8328044fa36d07b25a4c0ad6631
See our [directory](DIRECTORY.md).

7
Rakefile Normal file
View file

@ -0,0 +1,7 @@
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.test_files = FileList['**/*_test.rb']
end
task default: :test

42
Searches/jump_search.rb Normal file
View file

@ -0,0 +1,42 @@
# Works only on sorted arrays.
# Finding element by creating step in array and jump ahead by fixed steps and finding element using linear search inside that steped array.
# Time Complexity: O(√n)
def jump_search(arr, x)
n = arr.length
# Finding block size to be jumped
step = Math.sqrt(n)
prev = 0
# Finding the block where element is
# present (if it is present)
while arr[[step, n].min - 1] < x
prev = step
step += Math.sqrt(n)
return -1 if prev >= n
end
# Doing a linear search for x in block
# beginning with prev.
while arr[prev] < x
prev += 1
# If we reached next block or end of
# array, element is not present.
return -1 if prev == [step, n].min
end
# If element is found
return prev if arr[prev] == x
-1
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
index = jump_search(arr, value)
puts index == -1 ? 'Element not found' : "Number #{value} is at #{index}"

View file

@ -1,18 +0,0 @@
class Array
def sorted?
### goes thru array and checks if all elements are in order
for i in 1...self.length
return false if self[i-1] > self[i]
end
return true
end
def bogosort
### randomly shuffles until sorted
self.shuffle! until self.sorted?
return self #return sorted array
end
end
puts "Enter a list of numbers seprated by space"
str = gets.chomp.split('')
puts str.bogosort.join('')

View file

@ -1,22 +0,0 @@
def bubble_sort(array)
n = array.length
loop do
swapped = false
(n-1).times do |i|
if array[i] > array[i+1]
array[i], array[i+1] = array[i+1], array[i]
swapped = true
end
end
break if not swapped
end
array
end
puts "Enter a list of numbers seprated by space"
list = gets
bubble_sort(list)
print list

View file

@ -1,34 +0,0 @@
"""
Algorithm: Heap-Sort
Time-Complexity: O(nlogn)
"""
def heap_sort(array)
array_size = array.size
adjusted_array = [nil] + array
(array_size / 2).downto(1) do |i|
adjusted_down(adjusted_array, i, array_size)
end
while array_size > 1
adjusted_array[1], adjusted_array[array_size] = adjusted_array[array_size], adjusted_array[1]
array_size -= 1
adjusted_down(adjusted_array, 1, array_size)
end
adjusted_array.drop(1)
end
#Method to adjust heap in downward manner
def adjusted_down(adjusted_array, parent, limit)
top = adjusted_array[parent]
while (child = 2 * parent) <= limit
child += 1 if child < limit and adjusted_array[child] < adjusted_array[child + 1]
break if top >= adjusted_array[child]
adjusted_array[parent] = adjusted_array[child]
parent = child
end
adjusted_array[parent] = top
end
#Code for testing heapsort
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].shuffle
print heap_sort(array)

View file

@ -1,27 +0,0 @@
def shell_sort(a)
n=a.length
h=1
while (h<n/3) #for computing increment factor "h"
h= (3*h)+1
end
while h>=1
# Logic of insertion sort with inrement steps of "h"
for i in h...n
j=i
while j>=h
if a[j-h]>a[j]
temp=a[j]
a[j]=a[j-h]
a[j-h]=temp
end
j-=h
end
end
h/=3
end
return a
end

View file

@ -0,0 +1,71 @@
require 'openssl'
class MerkleHellman
SMALLEST_KNAPSACK_ITEM = 2**32
STEP = 2**32
def initialize(size)
@size = size
sum = SMALLEST_KNAPSACK_ITEM
@easy_knapsack = size.times.map do |_k|
x = sum + rand(STEP)
sum += x
x
end
@n = sum + rand(STEP)
loop do
@a = rand(0..@n)
break if @a.gcd(@n) == 1
end
@hard_knapsack = @easy_knapsack.map do |x|
(@a * x) % @n
end
end
def encrypt(msg)
raise ArgumentError, "max length is #{@size / 8} characters" if msg.length * 8 > @size
c = 0
msg.each_codepoint.reverse_each.with_index do |ch, i|
7.downto(0) do |j|
wj = ch.>>(j).& 1
c += wj * @hard_knapsack[i * 8 + 7 - j]
end
end
c
end
def decrypt(c)
p = @a.to_bn.mod_inverse(@n).mod_mul(c, @n).to_i
byte = 0
msg = []
@easy_knapsack.reverse_each.with_index do |x, i|
bit = 0
if p >= x
p -= x
bit = 1
end
byte |= (bit << (i % 8))
if i % 8 == 7
msg << byte.chr
byte = 0
end
end
msg.join
end
attr_accessor :hard_knapsack
end
str = 'Hello there, this is my plaintext'
mh = MerkleHellman.new(str.length * 8)
puts "[*] Encrypting \"#{str}\""
c = mh.encrypt(str)
puts "[*] Ciphertext : #{c}"
decrypted = mh.decrypt(c)
puts "[*] after decryption : \"#{decrypted}\""

View file

@ -1,93 +0,0 @@
#Define a node for the list
class Node
attr_accessor :value, :next
def initialize(value)
@value = value
@next = nil
end
end
# Class for circular linked list (last node points to the head node)
class CircularList
attr_accessor :head
def initialize()
@head = nil
end
def insert_end(value)
newNode = Node.new(value)
if (@head == nil)
@head = newNode
@head.next = @head
else
tempNode = @head
while (tempNode.next != @head)
tempNode = tempNode.next
end
newNode.next = @head
tempNode.next = newNode
end
end
def insert_head(value)
newNode = Node.new(value)
if (@head == nil)
@head = newNode
@head.next = head
else
tempNode = @head
while (tempNode.next != @head)
tempNode = tempNode.next
end
newNode.next = @head
tempNode.next = newNode
@head = newNode
end
end
def print_list
print "["
if (@head != nil)
printNode = @head
while (printNode.next != @head)
print "#{printNode.value}"
print ", "
printNode = printNode.next
end
print printNode.value
end
print "]"
STDOUT.flush
end
def delete_head
if (@head != nil) && (@head.next != @head)
newHead = @head.next
tempNode = newHead
while(tempNode.next != @head)
tempNode = tempNode.next
end
tempNode.next = newHead
@head = newHead
elsif (@head != nil) && (@head.next == @head)
@head = nil
end
end
def delete_end
if (@head != nil) && (@head.next != @head)
tempNode = @head
while (tempNode.next.next != @head)
tempNode = tempNode.next
end
tempNode.next = @head
elsif (@head != nil) && (@head.next == @head)
@head = nil
end
end
def isEmpty()
return (@head==nil)
end
end

View file

@ -0,0 +1,87 @@
# Arrays - Get Products of all other elements in Ruby
# Algorithm challenge description:
# Given an array of integers, return a new array such that
# each element at index `i` of the new array is the product of
# all the numbers in the original array except the one at `i`.
#
# 1. Brute force solution
#
def calculate_products_of_all_other_elements(nums)
product_of_other_elements = Array.new(nums.length, 1)
nums.each_with_index do |_num1, i|
nums.each_with_index do |num2, j|
product_of_other_elements[i] = product_of_other_elements[i] * num2 if i != j
end
end
product_of_other_elements
end
puts(calculate_products_of_all_other_elements([1, 2, 3]))
#
# 2. O(n) time and space
# Arrays - Get Products of all other elements in Ruby
#
# Generates prefix products
def build_prefix_products(nums)
prefix_products = []
nums.each do |num|
prefix_products << if prefix_products.count > 0
(prefix_products.last * num)
else
num
end
end
prefix_products
end
# Generates suffix products
def build_suffix_products(nums)
suffix_products = []
nums.reverse.each do |num|
suffix_products << if suffix_products.count > 0
(suffix_products.last * num)
else
num
end
end
suffix_products
end
# Builds output
def output(prefix_products, suffix_products, nums)
result = []
nums.reverse.each_with_index do |_num, index|
result << if index == 0
suffix_products[index + 1]
elsif index == nums.length - 1
prefix_products[index - 1]
else
(prefix_products[index - 1] * suffix_products[index + 1])
end
end
result
end
# Generate result from the product of prefixes and suffixes
def products(nums)
prefix_products = build_prefix_products(nums)
suffix_products = build_suffix_products(nums)
suffix_products = suffix_products.reverse
output(prefix_products, suffix_products, nums)
end
puts(products([1, 2, 3]))
# => [6, 3, 2]

View file

@ -1,23 +1,23 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val)
# @val = val
# @left, @right = nil, nil
# end
# attr_accessor :val, :left, :right
# def initialize(val)
# @val = val
# @left, @right = nil, nil
# end
# end
# @param {TreeNode} root
# @return {Integer[]}
def inorder_traversal(root)
ans = []
def traverse(node, ans)
if node != nil
traverse(node.left, ans)
ans.push(node.val)
traverse(node.right,ans)
end
ans = []
def traverse(node, ans)
unless node.nil?
traverse(node.left, ans)
ans.push(node.val)
traverse(node.right, ans)
end
traverse(root,ans)
return ans
end
end
traverse(root, ans)
ans
end

View file

@ -1,20 +1,19 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val)
# @val = val
# @left, @right = nil, nil
# end
# attr_accessor :val, :left, :right
# def initialize(val)
# @val = val
# @left, @right = nil, nil
# end
# end
# @param {TreeNode} root
# @return {TreeNode}
def invert_tree(root)
if root == nil
return nil
end
temp = root.left
root.left = invert_tree(root.right)
root.right = invert_tree(temp)
return root
end
return nil if root.nil?
temp = root.left
root.left = invert_tree(root.right)
root.right = invert_tree(temp)
root
end

View file

@ -1,23 +1,23 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val)
# @val = val
# @left, @right = nil, nil
# end
# attr_accessor :val, :left, :right
# def initialize(val)
# @val = val
# @left, @right = nil, nil
# end
# end
# @param {TreeNode} root
# @return {Integer[]}
def postorder_traversal(root)
ans = []
def traverse(node, ans)
if node != nil
traverse(node.left, ans)
traverse(node.right,ans)
ans.push(node.val)
end
ans = []
def traverse(node, ans)
unless node.nil?
traverse(node.left, ans)
traverse(node.right, ans)
ans.push(node.val)
end
traverse(root,ans)
return ans
end
end
traverse(root, ans)
ans
end

View file

@ -1,23 +1,23 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val)
# @val = val
# @left, @right = nil, nil
# end
# attr_accessor :val, :left, :right
# def initialize(val)
# @val = val
# @left, @right = nil, nil
# end
# end
# @param {TreeNode} root
# @return {Integer[]}
def preorder_traversal(root)
ans = []
def traverse(node, ans)
if node != nil
ans.push(node.val)
traverse(node.left, ans)
traverse(node.right,ans)
end
ans = []
def traverse(node, ans)
unless node.nil?
ans.push(node.val)
traverse(node.left, ans)
traverse(node.right, ans)
end
traverse(root,ans)
return ans
end
end
traverse(root, ans)
ans
end

View file

@ -0,0 +1,86 @@
# Define a node for the list
class Node
attr_accessor :value, :next
def initialize(value)
@value = value
@next = nil
end
end
# Class for circular linked list (last node points to the head node)
class CircularList
attr_accessor :head
def initialize
@head = nil
end
def insert_end(value)
newNode = Node.new(value)
if @head.nil?
@head = newNode
@head.next = @head
else
tempNode = @head
tempNode = tempNode.next while tempNode.next != @head
newNode.next = @head
tempNode.next = newNode
end
end
def insert_head(value)
newNode = Node.new(value)
if @head.nil?
@head = newNode
@head.next = head
else
tempNode = @head
tempNode = tempNode.next while tempNode.next != @head
newNode.next = @head
tempNode.next = newNode
@head = newNode
end
end
def print_list
print '['
unless @head.nil?
printNode = @head
while printNode.next != @head
print printNode.value.to_s
print ', '
printNode = printNode.next
end
print printNode.value
end
print ']'
STDOUT.flush
end
def delete_head
if !@head.nil? && (@head.next != @head)
newHead = @head.next
tempNode = newHead
tempNode = tempNode.next while tempNode.next != @head
tempNode.next = newHead
@head = newHead
elsif !@head.nil? && (@head.next == @head)
@head = nil
end
end
def delete_end
if !@head.nil? && (@head.next != @head)
tempNode = @head
tempNode = tempNode.next while tempNode.next.next != @head
tempNode.next = @head
elsif !@head.nil? && (@head.next == @head)
@head = nil
end
end
def isEmpty
@head.nil?
end
end

View file

@ -1,6 +1,7 @@
# Define a node in the list
class Node
attr_accessor :value, :next, :prev
def initialize(value)
@value = value
@next = nil
@ -10,15 +11,17 @@ end
# A Class for double linked lists (each element links to the next one, and to the previous one)
class DoubleList
include Enumerable
attr_accessor :head, :tail
def initialize()
def initialize
@head = nil
@tail = nil
end
def insert_tail(value)
new_node = Node.new(value)
if (@head == nil)
if @head.nil?
@head = new_node
@tail = new_node
else
@ -30,7 +33,7 @@ class DoubleList
def insert_head(value)
new_node = Node.new(value)
if (@head == nil)
if @head.nil?
@head = new_node
@tail = new_node
else
@ -40,41 +43,36 @@ class DoubleList
end
end
def delete_tail()
if (@tail != nil)
def delete_tail
until @tail.nil?
@tail = @tail.prev
if (@tail != nil)
@tail.next = nil
end
@tail.next = nil unless @tail.nil?
end
end
def delete_head()
if (@head != nil)
def delete_head
until @head.nil?
@head = @head.next
if (@head != nil)
@head.prev = nil
end
@head.prev = nil unless @head.nil?
end
end
def print_list()
print "["
if (@head != nil)
printNode = @head
while (printNode != nil)
print "#{printNode.value}"
if (printNode != @tail)
print ", "
end
printNode = printNode.next
end
def each
return if @head.nil?
current = @head
until current.nil?
yield current.value
current = current.next
end
print "]"
STDOUT.flush
end
def is_empty()
return (@head==nil)
def print_list
# the to_a method is from Enumerable, will call each to get the values, and return an array
puts '[' + to_a.join(', ') + ']'
end
end
def empty?
@head.nil?
end
end

View file

@ -1,6 +1,7 @@
# Define a node in the list
class Node
attr_accessor :value, :next
def initialize(value)
@value = value
@next = nil
@ -10,27 +11,27 @@ end
# A Class for single linked lists (each element links to the next one, but not to the previous one)
class SingleList
include Enumerable
attr_accessor :head
def initialize()
def initialize
@head = nil
end
def insert_tail(value)
newNode = Node.new(value)
if (@head == nil)
if @head.nil?
@head = newNode
else
tempNode = @head
while (tempNode.next != nil)
tempNode = tempNode.next
end
tempNode = tempNode.next until tempNode.next.nil?
tempNode.next = newNode
end
end
def insert_head(value)
newNode = Node.new(value)
if (@head == nil)
if @head.nil?
@head = newNode
else
newNode.next = @head
@ -38,43 +39,38 @@ class SingleList
end
end
def print_list()
print "["
if (@head != nil)
printNode = @head
while (printNode != nil)
print "#{printNode.value}"
if (printNode.next != nil)
print ", "
end
printNode = printNode.next
end
def each
return if @head.nil?
current = @head
until current.nil?
yield current.value
current = current.next
end
print "]"
STDOUT.flush
end
def print_list
puts '[' + to_a.join(', ') + ']'
end
def delete_head
if (@head != nil) && (@head.next != nil)
if !@head.nil? && !@head.next.nil?
newHead = @head.next
@head = newHead
elsif (@head != nil) && (@head.next == nil)
elsif !@head.nil? && @head.next.nil?
@head = nil
end
end
def delete_tail
if (@head != nil)
tempNode = @head
while (tempNode.next.next != nil)
tempNode = tempNode.next
end
tempNode.next = nil
end
return if @head.nil?
tempNode = @head
tempNode = tempNode.next until tempNode.next.next.nil?
tempNode.next = nil
end
def isEmpty()
return (@head==nil)
def empty?
@head.nil?
end
end
end

View file

@ -0,0 +1,106 @@
# A queue is like a waiting list.
# Imagine you are waiting in line to buy the latest Android product
# or getting a parking ticket. These are queues!
#
#
# 1. An array can behave like a Queue if you use the right methods.
#
# These methods are:
# - unshift: when you unshift, you are adding one item to the queue
# - pop
#
class ArrayQueue
def initialize(queue = [])
@queue = queue
end
attr_accessor :queue
def add(item)
queue.unshift(item)
end
def pop
queue.pop
end
def peek
queue[-1]
end
end
queue = ArrayQueue.new
queue.add(3)
queue.add(4)
queue.add(5)
puts queue.inspect
# => #<ArrayQueue:0x00007fc78200f5e0 @queue=[5, 4, 3]>
queue.pop
puts queue.inspect
# => #<ArrayQueue:0x00007fc78200f5e0 @queue=[5, 4]>
puts(queue.peek)
# => 4
#
#
# 2. Ruby Concurrent Queue
# Ruby has a proper thread-safe, blocking, Queue class.
# You can use this queue for coordinating work in a multi-threaded program.
#
# Reference: https://ruby-doc.org/core-2.5.0/Queue.html
#
queue = Queue.new
queue << 1
queue << 2
queue << 3
queue.pop
# 1
queue.pop
# 2
# If the queue is empty, calling pop will put your current
# thread to sleep & wait until something is added to the queue.
#
#
# 3. How to Use a Ruby SizedQueue
# A sized queue is the same as a regular queue but with a size limit.
#
# Reference: https://ruby-doc.org/core-2.5.0/SizedQueue.html
#
queue = SizedQueue.new(5)
# When the queue is full, the push (same as <<) operation
# will suspend the current thread until an item is taken off the queue.
queue.push(:oranges)
queue.push(:apples)
queue.push(:blue)
queue.push(:orange)
queue.push(:green)
# At this point, the SizedQueue is full
queue.push(:throw_expection)
# data_structures/queues/queue.rb:81:in `push': No live threads left. Deadlock? (fatal)
# 1 threads, 1 sleeps current:0x00007ff54f407130 main thread:0x00007ff54f407130
# * #<Thread:0x00007ff54f86ef38 sleep_forever>
# rb_thread_t:0x00007ff54f407130 native:0x000000010dd24dc0 int:0
# data_structures/queues/queue.rb:81:in `push'
# data_structures/queues/queue.rb:81:in `<main>'
# from data_structures/queues/queue.rb:81:in `<main>'
# You can choose to raise an exception, passing true as an argument as follows:
queue.push(:throw_expection, true)
# data_structures/queues/queue.rb:83:in `push': queue full (ThreadError)
# from data_structures/queues/queue.rb:83:in `<main>'

View file

@ -0,0 +1,87 @@
# A stack is an abstract data type that serves as a collection of
# elements with two principal operations: push() and pop(). push() adds an
# element to the top of the stack, and pop() removes an element from the top
# of a stack. The order in which elements come off of a stack are
# Last In, First Out (LIFO)
class StackOverflowError < StandardError; end
class Stack
def initialize(limit, stack = [])
@stack = stack
@limit = limit
end
attr_accessor :stack, :limit
def push(item)
raise StackOverflowError unless stack.count < limit
stack << item
end
def pop
stack.pop
end
def peek
stack.last
end
def empty?
stack.count.zero?
end
def full?
stack.count == limit
end
def size
stack.count
end
def contains?(item)
stack.include?(item)
end
end
stack = Stack.new(10, [])
puts stack.empty?
# => true
stack.push(3)
stack.push(5)
stack.push(7)
stack.push(9)
puts stack.full?
# => false
puts stack.contains?(5)
# => true
puts stack.pop
# => 9
puts stack.peek
# => 7
puts stack.size
# => 3
puts stack.inspect
# => #<Stack:0x00007fceed83eb40 @stack=[3, 5, 7], @limit=10>
stack.push(13)
stack.push(15)
stack.push(17)
stack.push(19)
stack.push(23)
stack.push(25)
stack.push(27)
# At this point, the stack is full
stack.push(29)
# => data_structures/stacks/stack.rb:18:in `push': StackOverflowError (StackOverflowError)
# from data_structures/stacks/stack.rb:83:in `<main>'

View file

@ -0,0 +1,75 @@
# A Trie (prefix tree) is a kind of search tree used to provide quick lookup
# of words/patterns in a set of words. A basic Trie however has O(n^2)
# space complexity making it impractical in practice.
# It however provides O(max(search_string, length of longest word))
# lookup time making it an optimal approach when space is not an issue.
class Node
attr_reader :value, :next
attr_accessor :word
def initialize(value)
@value = value
@word = false
@next = []
end
end
class Trie
def initialize
@root = Node.new('*')
end
def insert_many(word)
letters = word.chars
base = @root
letters.each do |letter|
base = insert(letter, base.next)
end
end
def include?(word)
letters = word.chars
base = @root
letters.all? do |letter|
base = find(letter, base.next)
end
end
private
# check if it already exists
# if not add character to node
def insert(character, trie)
found = trie.find do |n|
n.value == character
end
add_node(character, trie) unless found
end
def add_node(character, trie)
Node.new(character).tap do |new_node|
trie << new_node
end
end
def find(character, trie)
trie.find do |n|
n.value == character
end
end
end
trie = Trie.new
trie.insert_many('Dogs')
trie.insert_many('South')
trie.insert_many('Cape Town')
puts trie.include?('Cape Town')
# => true
puts trie.include?('not presented')
# => false

View file

@ -1,16 +1,14 @@
#https://en.wikipedia.org/wiki/Euclidean_algorithm
# https://en.wikipedia.org/wiki/Euclidean_algorithm
def euclidean_gcd(a, b)
while b != 0
t = b
b = a % b
a = t
end
return a
while b != 0
t = b
b = a % b
a = t
end
a
end
puts "GCD(3, 5) = " + euclidean_gcd(3, 5).to_s
puts "GCD(3, 6) = " + euclidean_gcd(3, 6).to_s
puts "GCD(6, 3) = " + euclidean_gcd(6, 3).to_s
puts 'GCD(3, 5) = ' + euclidean_gcd(3, 5).to_s
puts 'GCD(3, 6) = ' + euclidean_gcd(3, 6).to_s
puts 'GCD(6, 3) = ' + euclidean_gcd(6, 3).to_s

View file

@ -0,0 +1,30 @@
# https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
def extended_euclidean_gcd(a, b)
x0 = a
x1 = b
s = 1
t = 0
until x1.zero?
q, x2 = x0.divmod(x1)
x0 = x1
x1 = x2
s, t = t, s - q * t
end
x0
end
puts 'GCD(3, 5) = ' + extended_euclidean_gcd(3, 5).to_s
# GCD(3, 5) = 1
puts 'GCD(3, 6) = ' + extended_euclidean_gcd(3, 6).to_s
# GCD(3, 6) = 3
puts 'GCD(6, 3) = ' + extended_euclidean_gcd(6, 3).to_s
# GCD(6, 3) = 3
#
# Dynamic driver code:
#
# a = gets.to_i
# b = gets.to_i
# puts "GCD (#{a}, #{b} ) = #{extended_euclidean_gcd(a, b)}"
#

View file

@ -1,23 +1,23 @@
# LCM (Least Common Multiple) of two numbers is the smallest number which can be divided by both numbers.
p "Least Common Multiple"
p 'Least Common Multiple'
p "Enter first number"
p 'Enter first number'
value_one = gets.chomp.to_i
p "Enter second number"
p 'Enter second number'
value_two = gets.chomp.to_i
def gcd(first, second)
if second != 0
gcd(second, first%second)
gcd(second, first % second)
else
first
end
end
def lcm(first, second)
(first * second)/gcd(first, second)
(first * second) / gcd(first, second)
end
p "Least Common Multiple is: #{lcm(value_one, value_two)}"
p "Least Common Multiple is: #{lcm(value_one, value_two)}"

10
maths/abs.rb Normal file
View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
# Calculates the absolute value of a number
class Abs
def self.call(number)
return -number if number.negative?
number
end
end

18
maths/abs_test.rb Normal file
View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
require 'minitest/autorun'
require_relative './abs'
class AbsTest < Minitest::Test
def test_positive_number
assert_equal Abs.call(4), 4
end
def test_zero
assert_equal Abs.call(0), 0
end
def test_negative_number
assert_equal Abs.call(-9), 9
end
end

21
maths/aliquot_sum.rb Normal file
View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
require_relative './square_root'
require_relative './ceil'
# Calculates the aliquot sum of a number (the sum of all proper divisors of a number)
class AliquotSum
class << self
def call(number)
divisors(number).sum
end
private
def divisors(number)
low_divisors = (1..Ceil.call(SquareRoot.call(number))).select { |num| (number % num).zero? }
high_divisors = low_divisors.map { |div| number / div }
(low_divisors + high_divisors).uniq - [number]
end
end
end

21
maths/aliquot_sum_test.rb Normal file
View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
require 'minitest/autorun'
require_relative './aliquot_sum'
class AliquotSumTest < Minitest::Test
def test_zero
assert_equal AliquotSum.call(0), 0
end
def test_one
assert_equal Abs.call(1), 1
end
def test_many
(2..100).each do |number|
expected_aliquot_sum = (1...number).select { |num| (number % num).zero? }.sum
assert_equal AliquotSum.call(number), expected_aliquot_sum
end
end
end

View file

@ -0,0 +1,24 @@
#
# For any binary number of n digits i.e dn-1 ... d3 d2 d1 d0
# The equivalent decimal number is equal to the sum of binary digits (dn) times their power of 2 (2n):
# decimal = d0×2^0 + d1×2^1 + d2×2^2 + ...
#
def binary_to_decimal(n)
decimal = 0
base = 1
until n.zero?
x = n % 10
n /= 10
decimal += x * base
base *= 2
end
decimal
end
puts 'Decimal value of 110011 is ' + binary_to_decimal(110_011).to_s
# Decimal value of 110011 is 51
puts 'Decimal value of 11110 is ' + binary_to_decimal(11_110).to_s
# Decimal value of 11110 is 30
puts 'Decimal value of 101 is ' + binary_to_decimal(101).to_s
# Decimal value of 101 is 5

11
maths/ceil.rb Normal file
View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
class Ceil
class << self
def call(number)
return number if number.is_a?(Integer) || number == number.to_i
number.to_i + 1
end
end
end

18
maths/ceil_test.rb Normal file
View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
require 'minitest/autorun'
require_relative './ceil'
class CeilTest < Minitest::Test
def test_integer
assert_equal Ceil.call(4), 4
end
def test_float_at_integer
assert_equal Ceil.call(4.0), 4
end
def test_float_not_at_integer
assert_equal Ceil.call(4.01), 5
end
end

22
maths/number_of_digits.rb Normal file
View file

@ -0,0 +1,22 @@
# Given a number, find number of digits in it.
def count_digits(n)
count = 0
temp = n
return 1 if n == 0
until temp.zero?
count += 1
temp /= 10
end
count
end
puts 'Number of digits in 8732 is ' + count_digits(8732).to_s
# Number of digits in 8732 is 4
puts 'Number of digits in 112233 is ' + count_digits(112_233).to_s
# Number of digits in 112233 is 6
puts 'Number of digits in 0 is ' + count_digits(0).to_s
# Number of digits in 0 is 1

26
maths/square_root.rb Normal file
View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
# Calculates the square root of a number
class SquareRoot
class << self
EPSILON = 1E-10
def call(number)
raise DomainError, 'Cannot find square root of negative number' if number.negative?
return 0 if number.zero?
find_root(number)
end
private
def find_root(x0, xn = x0)
xn1 = xn - ((xn * xn - x0) / (2.0 * xn))
return xn1 if (xn1 - xn).abs <= EPSILON
find_root(x0, xn1)
end
end
end
class DomainError < StandardError; end

22
maths/square_root_test.rb Normal file
View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
require 'minitest/autorun'
require_relative './square_root'
class SquareRootTest < Minitest::Test
def test_negative_number
assert_raises DomainError do
SquareRoot.call(-1)
end
end
def test_zero
assert_equal 0, SquareRoot.call(0)
end
def test_all_numbers_below_1024
(1...1024).each do |num|
assert_in_delta SquareRoot.call(num), Math.sqrt(num), 1E-12
end
end
end

19
maths/sum_of_digits.rb Normal file
View file

@ -0,0 +1,19 @@
# Given a number, find sum of its digits.
def digits_sum(n)
a = 0
sum = 0
until n.zero?
a = n % 10
sum += a
n /= 10
end
sum
end
puts 'Sum of digits of 3456 is ' + digits_sum(3456).to_s
# Sum of digits of 3456 is 18
puts 'Sum of digits of 1234 is ' + digits_sum(1234).to_s
# Sum of digits of 1234 is 10
puts 'Sum of digits of 9251321 is ' + digits_sum(9_251_321).to_s
# Sum of digits of 9251321 is 23

View file

@ -1,12 +1,12 @@
# Fisher and Yates Shuffle is one of the simplest and most popular shuffling algorithm
def fisher_yates_shuffle(array)
n = array.length
while n > 0
i = rand(n-=1)
array[i], array[n] = array[n], array[i]
end
return array
n = array.length
while n > 0
i = rand(n -= 1)
array[i], array[n] = array[n], array[i]
end
array
end
arr = [1, 2, 40, 30, 20, 15, 323, 12, 3, 4]
puts fisher_yates_shuffle(arr)
puts fisher_yates_shuffle(arr)

20
project_euler/README.md Normal file
View file

@ -0,0 +1,20 @@
# Project Euler
Problems are taken from https://projecteuler.net/, the Project Euler. [Problems are licensed under CC BY-NC-SA 4.0](https://projecteuler.net/copyright).
Project Euler is a series of challenging mathematical/computer programming problems that require more than just mathematical
insights to solve. Project Euler is ideal for mathematicians who are learning to code.
## Solution Guidelines
Welcome to [TheAlgorithms/Ruby](https://github.com/TheAlgorithms/Ruby)! Before reading the solution guidelines, make sure you read the whole [Contributing Guidelines](https://github.com/TheAlgorithms/Ruby/blob/master/CONTRIBUTING.md) as it won't be repeated in here. If you have any doubt on the guidelines, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Ruby/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms). Be sure to read the [Coding Style](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/README.md#coding-style) before starting solution.
### Coding Style
* Please maintain consistency in project directory and solution file names. Keep the following points in mind:
* Create a new directory only for the problems which do not exist yet.
* Please name the project **directory** as `problem_<problem_number>` where `problem_number` should be filled with 0s so as to occupy 3 digits. Example: `problem_001`, `problem_002`, `problem_067`, `problem_145`, and so on.
* You can have as many helper functions as you want but there should be one main function called `solution` which should satisfy the conditions as stated below:
* It should contain positional argument(s) whose default value is the question input. Example: Please take a look at [Problem 1](https://projecteuler.net/problem=1) where the question is to *Find the sum of all the multiples of 3 or 5 below 1000.* In this case the main solution function will be `solution(limit = 1000)`.
* When the `solution` function is called without any arguments like so: `solution()`, it should return the answer to the problem.

View file

@ -8,7 +8,7 @@ even_fib_sum = 0
fib_first = 1
fib_second = 2
while fib_second < 4000000
while fib_second < 4_000_000
even_fib_sum += fib_second if fib_second.even?
fib_second += fib_first
fib_first = fib_second - fib_first

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
# n! means n x (n - 1) x ... x 3 x 2 x 1
# For example, 10! = 10 x 9 x ... x 3 x 2 x 1 = 3628800,
# and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.
#
# Find the sum of the digits in the number 100!
# method to calculate factorial of a number
def factorial(number)
number.downto(1).reduce(:*)
end
# fetch digits of factorial of `number` and find
# sum of all those digits, and prints the result on the console
number = 100
puts factorial(number).digits.sum

View file

@ -0,0 +1,57 @@
# frozen_string_literal: true
# Let d(n) be defined as the sum of proper divisors of n
# (numbers less than n which divide evenly into n).
# If d(a) = b and d(b) = a, where a & b, then a and b are an amicable pair.
# and each of a and b are called amicable numbers.
#
# For example,
#
# The proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110;
# therefore d(220) = 284.
#
# The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.
#
# Evaluate the sum of all the amicable numbers under 10000.
# get list of all divisors of `number`
def get_divisors(number)
divisors = []
(1..(Math.sqrt(number).to_i)).each do |num|
if (number % num).zero?
divisors << num
divisors << number / num
end
end
divisors
end
# get list of all proper divisors of `number` i.e. removing `number` from
# the list of divisors
def get_proper_divisors(number)
divisors = get_divisors(number)
divisors.delete(number)
divisors
end
# implementation of a method `d` as mentioned in the question
# i.e. finding sum of all proper divisors of `number`
def d(number)
get_proper_divisors(number).sum
end
# given an upper `limit`, this method finds all amicable numbers
# under this `limit`
def find_amicable_numbers(limit)
result = []
(1...limit).each do |a|
b = d(a)
res = d(b)
result.push(a) if (a == res) && (a != b)
end
result
end
# calling `find_amicable_numbers` method and finding sum of all such numbers
# below 10000, and printing the result on the console
puts find_amicable_numbers(10_000).sum

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,40 @@
# frozen_string_literal: true
# Problem 22
# Using names.txt (right click and 'Save Link/Target As...'),
# a 46K text file containing over five-thousand first names,
# begin by sorting it into alphabetical order.
# Then working out the alphabetical value for each name,
# multiply this value by its alphabetical position in the list to obtain a name score.
# For example, when the list is sorted into alphabetical order,
# COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53,
# is the 938th name in the list. So, COLIN would obtain a score of 938 * 53 = 49714.
# What is the total of all the name scores in the file?
# reading the contents of the file
file_contents = File.read('p022_names.txt')
# replacing the occuerance of \" to '' and spliting the result by ','
# to get an array of sorted words
words = file_contents.tr('\"', '').split(',').sort
# this method calculates the worth of a word based on the ASCII
# values of the characters
def word_worth(word)
word.chars.sum { |char| char.ord - 'A'.ord + 1 }
end
# this method takes the words as an input
# calls `word_worth` method on each word
# to that value multiply that with the index of the word in the array
# add the same to the result
def total_rank(words)
result = 0
words.each_with_index { |word, index| result += word_worth(word) * (index + 1) }
result
end
# outputs total rank on the console
puts total_rank(words)

View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
# The prime factors of 13195 are 5, 7, 13 and 29.
# What is the largest prime factor of the number 600851475143
# find all factors of the given number
def get_factors(number)
factors = []
(1..Math.sqrt(number).to_i).each do |num|
if (number % num).zero?
factors << num
factors << number / num
end
end
factors
end
# determine if a given number is a prime number
def prime?(number)
get_factors(number).length == 2
end
# find the largest prime
def largest_prime_factor(number)
prime_factors = get_factors(number).select { |factor| prime?(factor) }
prime_factors.max
end
puts largest_prime_factor(600_851_475_143)

View file

@ -0,0 +1,18 @@
# The prime factors of 13195 are 5, 7, 13 and 29.
# What is the largest prime factor of the number 600851475143 ?
def solution(n)
prime = 1
i = 2
while i * i <= n
while (n % i).zero?
prime = i
n = n.fdiv i
end
i += 1
end
prime = n if n > 1
prime.to_i
end
puts solution(600_851_475_143)

View file

@ -0,0 +1,11 @@
# A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
# Find the largest palindrome made from the product of two 3-digit numbers.
answer = 0
999.downto(99) do |i|
999.downto(99) do |j|
t = (i * j)
answer = i * j if (t.to_s == t.to_s.reverse) && (t > answer) && (t > answer)
end
end
puts answer

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
# A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
# Find the largest palindrome made from the product of two 3-digit numbers.
class Integer
def parindrome?
self == reverse
end
# 123.reverse == 321
# 100.reverse == 1
def reverse
result = 0
n = self
loop do
result = result * 10 + n % 10
break if (n /= 10).zero?
end
result
end
end
factors = (100..999).to_a
products = factors.product(factors).map { _1 * _2 }
puts products.select(&:parindrome?).max

View file

@ -3,7 +3,6 @@
# What is the smallest positive number that is evenly
# divisible by all of the numbers from 1 to 20?
# Euclid's algorithm for the greatest common divisor
def gcd(a, b)
b.zero? ? a : gcd(b, a % b)
@ -20,4 +19,4 @@ result = 1
result = lcm(result, i + 1)
end
p result
p result

View file

@ -1,15 +1,17 @@
=begin
Searches through a list for a value in O(log(n)) time.
The list must be sorted.
=end
# Searches through a list for a value in O(log(n)) time.
# The list must be sorted.
def binary_search(array, key)
front = 0
back = array.length - 1
while front <= back
middle = (front + back) / 2
return middle if array[middle] == key
key < array[middle] ?
back = middle - 1 : front = middle + 1
if key < array[middle]
back = middle - 1
else
front = middle + 1
end
end
nil
end
@ -18,6 +20,8 @@ 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 binary_search(arr, value) != nil ?
"Found at index #{binary_search(arr, value)}" :
puts if binary_search(arr, value) != nil
"Found at index #{binary_search(arr, value)}"
else
"Not found"
end

View file

@ -0,0 +1,53 @@
# @param [Integer] start
# @param [Integer] target
# @param [Array] adjacency_list
# @return [Array] routes
def dfs(start, target, adjacency_list)
is_visited = Hash.new(false)
parent = {}
stack = [start]
loop do
break if stack.empty?
current_node = stack.pop
is_visited[current_node] = true
return get_path(parent, target) if current_node == target
adjacency_list[current_node].each do |neighbor|
next if is_visited[neighbor]
stack << neighbor
is_visited[neighbor] = true
parent[neighbor] = current_node
end
end
[]
end
# @param [Hash] parent
# @param [Integer] dest
# @return [Array] path
def get_path(parent, dest)
iterator = dest
path = [dest]
while parent.has_key?(iterator)
path << parent[iterator]
iterator = parent[iterator]
end
path.reverse
end
def main
adjacency_list = [
[1, 2], # 0
[0, 3], # 1
[0, 3], # 2
[1, 2, 4], # 3
[3, 5], # 4
[4] # 5
]
p dfs(0, 5, adjacency_list)
end
main

View file

@ -0,0 +1,29 @@
# Iterate through the array from both sides to find the index of search_item.
def double_linear_search(array, search_item)
start_ind = 0
end_ind = array.length - 1
while start_ind <= end_ind
return start_ind if array[start_ind] == search_item
return end_ind if array[end_ind] == search_item
start_ind += 1
end_ind -= 1
end
# returns -1 if search_item is not found in array
-1
end
puts(double_linear_search([1, 5, 5, 10], 1))
# => 0
puts(double_linear_search([1, 5, 5, 10], 5))
# => 1
puts(double_linear_search([1, 5, 5, 10], 100))
# => -1
puts(double_linear_search([1, 5, 5, 10], 10))
# => 3

View file

@ -1,18 +1,18 @@
=begin
Looks through array for a value in O(n) time.
Array does not need to be sorted.
=end
# Looks through array for a value in O(n) time.
# Array does not need to be sorted.
def linear_search(array, key)
array.each_with_index do |current, index|
return index if current == key
end
return nil
nil
end
puts "Enter a space-separated list:"
arr = gets.chomp.split(' ').map(&:to_i)
puts "Enter a value to be searched:"
key = gets.chomp.to_i
puts linear_search(arr, key) != nil ?
"Found at index #{linear_search(arr, key)}" :
puts if linear_search(arr, key) != nil
"Found at index #{linear_search(arr, key)}"
else
"Not found"
end

View file

@ -0,0 +1,27 @@
# Iterate through the array to find the index of key using recursion.
def recursive_double_linear_search(data, key, left = 0, right = 0)
right &&= data.length - 1
return -1 if left > right
return left if data[left] == key
return right if data[right] == key
recursive_double_linear_search(data, key, left + 1, right - 1)
end
puts(recursive_double_linear_search([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 5))
# => 5
puts(recursive_double_linear_search([1, 2, 4, 5, 3], 4))
# => 2
puts(recursive_double_linear_search([1, 2, 4, 5, 3], 6))
# => -1
puts(recursive_double_linear_search([5], 5))
# => 0
puts(recursive_double_linear_search([], 1))
# => -1

View file

@ -0,0 +1,25 @@
# A pure Ruby implementation of a recursive linear search algorithm
def rec_linear_search(sequence, low, high, target)
raise Exception('Invalid upper or lower bound!') unless high < sequence.length && low < sequence.length
return -1 if high < low
return low if sequence[low] == target
return high if sequence[high] == target
rec_linear_search(sequence, low + 1, high - 1, target)
end
puts(rec_linear_search([0, 30, 500, 100, 700], 0, 4, 0))
# => 0
puts(rec_linear_search([0, 30, 500, 100, 700], 0, 4, 700))
# => 4
puts(rec_linear_search([0, 30, 500, 100, 700], 0, 4, 30))
# => 1
puts(rec_linear_search([0, 30, 500, 100, 700], 0, 4, -6))
# => -1

View file

@ -0,0 +1,43 @@
# Ternary Search
# -------------------------------
# Ternary search is a searching technique that is used to search the position of a specific value in an array.
# Ternary search is a divide-and-conquer algorithm.
# It is mandatory for the array to be sorted (in which you will search for an element).
# The array is divided into three parts and then we determine in which part the element exists.
# In this search, after each iteration it neglects 1/3 part of the array and repeats the same operations on the remaining ⅔.
# Time Complexity: O(log3 n)
# Space Complexity: O(1)
def ternary_search(l, r, key, arr)
# l is the starting index and r is the ending index of the array/sub-array.
if r >= l
# find mid1 and mid2
mid1 = l + (r - l) / 3
mid2 = r - (r - l) / 3
# check if key is equal to mid1
if arr[mid1] == key
mid1
# check if key is equal to mid2
elsif arr[mid2] == key
mid2
# Since key is not present at mid, check in which region it is present
# then repeat the Search operation in that region
elsif key < arr[mid1]
ternary_search(l, mid1 - 1, key, arr)
elsif key > arr[mid2]
ternary_search(mid2 + 1, r, key, arr)
else
ternary_search(mid1 + 1, mid2 - 1, key, arr)
end
end
end
puts "Enter a space-separated list:"
arr = gets.chomp.split(' ').map(&:to_i)
puts "Enter a value to be searched:"
key = gets.chomp.to_i
puts if ternary_search(0, arr.length - 1, key, arr) != nil
"Found at index #{ternary_search(0, arr.length - 1, key, arr)}"
else
"Not found"
end

21
sorting/bogo_sort.rb Normal file
View file

@ -0,0 +1,21 @@
class Array
def sorted?
### goes thru array and checks if all elements are in order
(1...length).each do |i|
return false if self[i - 1] > self[i]
end
true
end
def bogosort
### randomly shuffles until sorted
shuffle! until sorted?
self # return sorted array
end
end
if $0 == __FILE__
puts 'Enter a list of numbers separated by space'
str = gets.chomp.split('')
puts str.bogosort.join('')
end

16
sorting/bogo_sort_test.rb Normal file
View file

@ -0,0 +1,16 @@
require 'minitest/autorun'
require_relative './bogo_sort'
class TestBogoSort < Minitest::Test
def test_sorted_array
input = [1, 2, 3, 4, 5]
expected = input.dup
assert_equal expected, input.bogosort
end
def test_reversed_array
input = [5, 4, 3, 2, 1]
expected = [1, 2, 3, 4, 5]
assert_equal expected, input.bogosort
end
end

22
sorting/bubble_sort.rb Normal file
View file

@ -0,0 +1,22 @@
def bubble_sort(array)
n = array.length
loop do
swapped = false
(n - 1).times do |i|
if array[i] > array[i + 1]
array[i], array[i + 1] = array[i + 1], array[i]
swapped = true
end
end
break unless swapped
end
array
end
puts 'Enter a list of numbers separated by space'
list = gets
bubble_sort(list)
print list

View file

@ -1,30 +1,29 @@
DEFAULT_BUCKET_SIZE = 5
def bucket_sort(input, bucket_size = DEFAULT_BUCKET_SIZE)
print 'Array is empty' if input.empty?
array = input.split(' ').map(&:to_i)
bucket_count = ((array.max - array.min) / bucket_size).floor + 1
# create buckets
buckets = []
bucket_count.times { buckets.push [] }
# fill buckets
array.each do |item|
buckets[((item - array.min) / bucket_size).floor].push(item)
end
# sort buckets
buckets.each do |bucket|
bucket.sort!
end
buckets.flatten.join(' ')
end
puts "Enter a list of numbers seprated by space"
list = gets
print bucket_sort(list)
DEFAULT_BUCKET_SIZE = 5
def bucket_sort(input, bucket_size = DEFAULT_BUCKET_SIZE)
print 'Array is empty' if input.empty?
array = input.split(' ').map(&:to_i)
bucket_count = ((array.max - array.min) / bucket_size).floor + 1
# create buckets
buckets = []
bucket_count.times { buckets.push [] }
# fill buckets
array.each do |item|
buckets[((item - array.min) / bucket_size).floor].push(item)
end
# sort buckets
buckets.each do |bucket|
bucket.sort!
end
buckets.flatten.join(' ')
end
puts 'Enter a list of numbers separated by space'
list = gets
print bucket_sort(list)

32
sorting/heap_sort.rb Normal file
View file

@ -0,0 +1,32 @@
# Algorithm: Heap-Sort
# Time-Complexity: O(nlogn)
def heap_sort(array)
array_size = array.size
adjusted_array = [nil] + array
(array_size / 2).downto(1) do |i|
adjusted_down(adjusted_array, i, array_size)
end
while array_size > 1
adjusted_array[1], adjusted_array[array_size] = adjusted_array[array_size], adjusted_array[1]
array_size -= 1
adjusted_down(adjusted_array, 1, array_size)
end
adjusted_array.drop(1)
end
# Method to adjust heap in downward manner
def adjusted_down(adjusted_array, parent, limit)
top = adjusted_array[parent]
while (child = 2 * parent) <= limit
child += 1 if (child < limit) && (adjusted_array[child] < adjusted_array[child + 1])
break if top >= adjusted_array[child]
adjusted_array[parent] = adjusted_array[child]
parent = child
end
adjusted_array[parent] = top
end
# Code for testing heapsort
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].shuffle
print heap_sort(array)

View file

@ -1,17 +1,17 @@
def insertion_sort(array)
0.upto(array.length - 1).each do |index|
element = array[index]
position = index
while element < array[position - 1] && position > 0
array[position] = array[position - 1]
array[position - 1] = element
position -= 1
end
end
array
end
puts "Enter a list of numbers seprated by space"
list = gets
insertion_sort(list)
print list
def insertion_sort(array)
0.upto(array.length - 1).each do |index|
element = array[index]
position = index
while element < array[position - 1] && position > 0
array[position] = array[position - 1]
array[position - 1] = element
position -= 1
end
end
array
end
puts 'Enter a list of numbers separated by space'
list = gets
insertion_sort(list)
print list

33
sorting/merge_sort.rb Normal file
View file

@ -0,0 +1,33 @@
def merge_sort(array)
return array if array.length <= 1
mid = array.length / 2
first_array = array.slice(0..mid - 1)
second_array = array.slice(mid..-1)
first_array = merge_sort first_array
second_array = merge_sort second_array
# merge
result = []
until first_array.empty? && second_array.empty?
if first_array.empty?
result.concat(second_array)
second_array.clear
elsif second_array.empty?
result.concat(first_array)
first_array.clear
else
result << if first_array.first < second_array.first
first_array.shift
else
second_array.shift
end
end
end
result
end
puts 'Enter a list of numbers separated by space'
list = gets
print merge_sort list.split(' ').map(&:to_i)

View file

@ -1,15 +1,15 @@
def quicksort
return [] if empty?
def quicksort(arr)
return [] if arr.empty?
# chose a random pivot value
pivot = delete_at(rand(size))
pivot = arr.delete_at(rand(arr.size))
# partition array into 2 arrays and comparing them to each other and eventually returning
# array with the pivot value sorted
left, right = partition(&pivot.method(:>))
left, right = arr.partition(&pivot.method(:>))
# recursively calling the quicksort method on itself
return *left.quicksort, pivot, *right.quicksort
[*quicksort(left), pivot, *quicksort(right)]
end
arr = [34, 2, 1, 5, 3]
p arr.quicksort
p quicksort(arr)

View file

@ -13,6 +13,6 @@ def selection_sort(array)
end
end
arr = ([9,8,3,1,2,55,68,48].shuffle) #We have taken a rondom example and also shuffling it
arr = [9, 8, 3, 1, 2, 55, 68, 48].shuffle # We have taken a rondom example and also shuffling it
selection_sort(arr)
puts "Sorted array is: #{arr.inspect}"

24
sorting/shell_sort.rb Normal file
View file

@ -0,0 +1,24 @@
def shell_sort(a)
n = a.length
h = 1
h = (3 * h) + 1 while h < n / 3
while h >= 1
# Logic of insertion sort with inrement steps of "h"
(h...n).each do |i|
j = i
while j >= h
if a[j - h] > a[j]
temp = a[j]
a[j] = a[j - h]
a[j - h] = temp
end
j -= h
end
end
h /= 3
end
a
end