├── .gitignore ├── .rspec ├── .vscode └── launch.json ├── Gemfile ├── Gemfile.lock ├── README.md ├── category_generator.rb ├── practice_test_generator.rb ├── problems ├── anagrams.rb ├── base_converter.rb ├── binary_search.rb ├── bubble_sort.rb ├── caesar_cipher.rb ├── deep_dup.rb ├── digital_root.rb ├── doubler.rb ├── dups.rb ├── eight_queens.rb ├── exponent.rb ├── factorials_rec.rb ├── factors.rb ├── fibs_sum.rb ├── first_even_numbers_sum.rb ├── jumble_sort.rb ├── longest_palindrome.rb ├── make_better_change.rb ├── median.rb ├── merge_sort.rb ├── my_all.rb ├── my_any.rb ├── my_each.rb ├── my_each_hash.rb ├── my_each_with_index.rb ├── my_flatten.rb ├── my_inject.rb ├── my_join.rb ├── my_merge.rb ├── my_reject.rb ├── my_reverse.rb ├── my_rotate.rb ├── my_select.rb ├── my_zip.rb ├── permutations.rb ├── pig_latinify.rb ├── prime_factorization.rb ├── primes.rb ├── quicksort.rb ├── real_words_in_string.rb ├── rec_sum.rb ├── string_include_key.rb ├── subsets.rb ├── symmetric_substrings.rb ├── titleize.rb └── two_sum.rb ├── resources ├── README.md └── list.csv ├── solutions ├── anagrams_solution.rb ├── base_converter_solution.rb ├── binary_search_solution.rb ├── bubble_sort_solution.rb ├── caesar_cipher_solution.rb ├── deep_dup_solution.rb ├── digital_root_solution.rb ├── doubler_solution.rb ├── dups_solution.rb ├── eight_queens_solution.rb ├── exponent_solution.rb ├── factorials_rec_solution.rb ├── factors_solution.rb ├── fibs_sum_solution.rb ├── first_even_numbers_sum_solution.rb ├── jumble_sort_solution.rb ├── longest_palindrome_solution.rb ├── make_better_change_solution.rb ├── median_solution.rb ├── merge_sort_solution.rb ├── my_all_solution.rb ├── my_any_solution.rb ├── my_each_hash_solution.rb ├── my_each_solution.rb ├── my_each_with_index_solution.rb ├── my_flatten_solution.rb ├── my_inject_solution.rb ├── my_join_solution.rb ├── my_merge_solution.rb ├── my_reject_solution.rb ├── my_reverse_solution.rb ├── my_rotate_solution.rb ├── my_select_solution.rb ├── my_zip_solution.rb ├── permutations_solution.rb ├── pig_latinify_solution.rb ├── prime_factorization_solution.rb ├── primes_solution.rb ├── quicksort_solution.rb ├── real_words_in_string_solution.rb ├── rec_sum_solution.rb ├── string_include_key_solution.rb ├── subsets_solution.rb ├── symmetric_substrings_solution.rb ├── titleize_solution.rb └── two_sum_solution.rb └── specs ├── anagrams_spec.rb ├── base_converter_spec.rb ├── binary_search_spec.rb ├── bubble_sort_spec.rb ├── caesar_cipher_spec.rb ├── deep_dup_spec.rb ├── digital_root_spec.rb ├── doubler_spec.rb ├── dups_spec.rb ├── eight_queens_spec.rb ├── exponent_spec.rb ├── factorials_rec_spec.rb ├── factors_spec.rb ├── fibs_sum_spec.rb ├── first_even_numbers_sum_spec.rb ├── jumble_sort_spec.rb ├── longest_palindrome_spec.rb ├── make_better_change_spec.rb ├── median_spec.rb ├── merge_sort_spec.rb ├── my_all_spec.rb ├── my_any_spec.rb ├── my_each_hash_spec.rb ├── my_each_spec.rb ├── my_each_with_index_spec.rb ├── my_flatten_spec.rb ├── my_inject_spec.rb ├── my_join_spec.rb ├── my_merge_spec.rb ├── my_reject_spec.rb ├── my_reverse_spec.rb ├── my_rotate_spec.rb ├── my_select_spec.rb ├── my_zip_spec.rb ├── permutations_spec.rb ├── pig_latinify_spec.rb ├── prime_factorization_spec.rb ├── primes_spec.rb ├── quicksort_spec.rb ├── real_words_in_string_spec.rb ├── rec_sum_spec.rb ├── string_include_key_spec.rb ├── subsets_spec.rb ├── symmetric_substrings_spec.rb ├── titleize_spec.rb └── two_sum_spec.rb /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore generated test files 2 | practice_assessment/ 3 | category_assessment/ 4 | practice_test.rb 5 | solution.rb 6 | spec.rb -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --order=default 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${file}" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # A sample Gemfile 3 | source "https://rubygems.org" 4 | 5 | gem 'rspec', "~> 3.1.0" 6 | 7 | gem 'byebug' 8 | 9 | gem 'colorize' 10 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | byebug (11.0.1) 5 | colorize (0.8.1) 6 | diff-lcs (1.3) 7 | rspec (3.1.0) 8 | rspec-core (~> 3.1.0) 9 | rspec-expectations (~> 3.1.0) 10 | rspec-mocks (~> 3.1.0) 11 | rspec-core (3.1.7) 12 | rspec-support (~> 3.1.0) 13 | rspec-expectations (3.1.2) 14 | diff-lcs (>= 1.2.0, < 2.0) 15 | rspec-support (~> 3.1.0) 16 | rspec-mocks (3.1.3) 17 | rspec-support (~> 3.1.0) 18 | rspec-support (3.1.2) 19 | 20 | PLATFORMS 21 | ruby 22 | 23 | DEPENDENCIES 24 | byebug 25 | colorize 26 | rspec (~> 3.1.0) 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # a/A Ruby 1 Practice Test Generator 2 | 3 | This is a practice test generator to prepare for the Ruby 1 Assessment, your 4 | first assessment at App Academy. This repo is forked from 5 | [Mallory Bulkley](https://github.com/mallorybulkley), an App Academy alum who 6 | created this when she was a student. The purpose of this tool is to allow you to 7 | get comfortable with the types of problems that could pop up on an assessment. 8 | Note that the purpose is **NOT TO MEMORIZE SOLUTIONS** - the problems included 9 | in this generator are _not_ an exhaustive list of what could show up on the 10 | assessment. Choosing to memorize solutions without understanding them may get 11 | you by in the short-term, but will never be worth it in the long run. Practice 12 | thinking and struggling through these problems so that you are agile and 13 | prepared for anything come assessment day. 14 | 15 | ## How to use this repo 16 | 17 | 1. Clone this repo onto your local machine. 18 | 19 | 2. Navigate to your local repo directory in terminal, run `bundle install`, and 20 | then run one of the following generators (detailed in below section): 21 | 22 | - `ruby practice_test_generator.rb` - Generates a practice test in a folder 23 | called `practice_assessment` 24 | - `ruby category_generator.rb` - Generates a test by category, based on how 25 | many problems of each category you want in a folder called 26 | `category_assessment` (requires following a prompt) 27 | 28 | 3. Navigate to the directory that was generated from running one of the above 29 | commands. Run `bundle install` and then `bundle exec rspec` to test your 30 | answers against the spec as you work through `practice_test.rb`. 31 | 32 | 4. Check your solutions against those in `solution.rb`. 33 | 34 | **Note**: Do not modify anything in the `problems`, `solutions`, or `specs` 35 | directories - the files in these directories are used to generate practice 36 | assessments. Instead, run one of the generators listed below and work on 37 | problems in the test directory created by the generator. 38 | 39 | ## Generators 40 | 41 | All of the practice problems are listed and categorized in `list.csv`. 42 | Categories include: recursion, sorting, enumerable, array, string, and bonus. 43 | Bonus problems will not appear on the assessment but are good to practice and 44 | can help you gain a deeper understanding of some of the more complex problems, 45 | especially with regards to recursion. There are two different generators 46 | included in this repo - they are detailed below. 47 | 48 | ### Practice Assessment Generator 49 | 50 | **Command**: `ruby practice_test_generator.rb` 51 | 52 | Generates a random practice assessment including problems across all categories 53 | (except for bonus). Test files will be generated inside of a directory called 54 | `practice_assessment`. 55 | 56 | ### Problems by Category Generator 57 | 58 | **Command**: `ruby category_generator.rb` (must follow prompt after) 59 | 60 | Prompts you for your desired number of questions from each category, and uses 61 | your input and the CSV file to generate a test of randomly selected practice 62 | problems from each category specified. Test files will be generated inside of a 63 | directory called `category_assessment`. 64 | 65 | **Generate assessment with all problems** - Input `all` when prompted 66 | 67 | **Generate assessment with all problems, except bonus** - Input 68 | `all, except: bonus` when prompted 69 | 70 | --- 71 | 72 | For both generators, 3 files will be created inside the generated folder as 73 | follows: 74 | 75 | - `practice_test.rb` contains the problems to be solved 76 | 77 | - `spec.rb` combines the specs for the chosen problems into one file for easy 78 | testing 79 | 80 | - `solution.rb` combines the solutions for each problem 81 | 82 | **Warning**: If you run the generator again, it will re-write the previously 83 | generated files and erase your previous work. If you wish to save your previous 84 | work, you will need to rename the files. This applies to both generators. 85 | -------------------------------------------------------------------------------- /category_generator.rb: -------------------------------------------------------------------------------- 1 | require 'csv' 2 | require 'colorize' 3 | require 'fileutils' 4 | 5 | # Instructions 6 | system("clear") 7 | puts "Welcome to a/A's Practice Assessment Generator".cyan 8 | puts "This generator will create a practice test based on your input. " \ 9 | "You can choose how many problems from each category to include in your test. " 10 | puts "This program will generate 3 files in this folder: practice_test, spec, and solution. " \ 11 | "Complete the practice_test file, running the spec file to check your answers. " \ 12 | "When your time is up (you are timing yourself, right?), compare your answers to the solutions." 13 | puts "Good luck!" 14 | 15 | # read in csv with test info 16 | tests = CSV.read('resources/list.csv', headers: true, header_converters: :symbol, converters: :all) 17 | 18 | # list possible categories 19 | categories = Array.new 20 | tests.each do |test| 21 | categories << test[1] 22 | end 23 | categories = categories.uniq 24 | puts "Possible categories: #{categories.join(", ")}".magenta 25 | puts 26 | 27 | # get user request 28 | puts "Input your requests, separated by commas and spaces please" 29 | puts "Example input: " + "array: 2, recursion: 1, sort: 1".yellow 30 | puts "If you would like ALL problems from ALL categories, input: " + "all".yellow 31 | puts "If you'd like all problems, EXCEPT bonus problems, input: " + "all, except: bonus".yellow 32 | input = gets.chomp.split(", ") 33 | 34 | system("clear") 35 | puts "I am generating a practice assessment that will be saved" 36 | puts "as 'category_assessment/' in your current directory" 37 | 38 | if input == ["all"] 39 | input = categories.map { |cat| cat += ": 20" } 40 | end 41 | 42 | if input == ["all", "except: bonus"] 43 | no_bonus_categories = categories.reject {|cat| cat == "bonus"} 44 | input = no_bonus_categories.map { |cat| cat += ": 20" } 45 | end 46 | 47 | categoryrequests = Hash.new(0) 48 | input.each do |request| 49 | req = request.downcase.split(": ") 50 | categoryrequests[req[0]] = req[1].to_i 51 | end 52 | 53 | # make test array for each category 54 | master = Array.new 55 | categories.each do |category| 56 | problems_in_category = Array.new 57 | tests.each do |test| 58 | if category == test[1] 59 | problems_in_category << test 60 | end 61 | end 62 | 63 | # pick tests at random from each category 64 | n = categoryrequests[category] 65 | master = master.concat(problems_in_category.sample(n)) 66 | end 67 | 68 | # Create new test, spec and solution files 69 | FileUtils.rm_r("category_assessment") if File.directory?("category_assessment") 70 | Dir.mkdir("category_assessment") 71 | Dir.mkdir("category_assessment/lib") 72 | Dir.mkdir("category_assessment/spec") 73 | Dir.mkdir("category_assessment/solution") 74 | practice_test = File.open("category_assessment/lib/practice_test.rb", "w") 75 | spec = File.open("category_assessment/spec/practice_test_spec.rb", "w") 76 | solution = File.open("category_assessment/solution/solution.rb", "w") 77 | gemfile = File.open("category_assessment/Gemfile", "w") 78 | rspec = File.open("category_assessment/.rspec", "w") 79 | 80 | # require rspec and the practice_test in the spec 81 | spec << "gem 'rspec'" << "\n" 82 | spec << "require 'practice_test'" << "\n" << "\n" 83 | 84 | # .rspec file add formatting and color for better readability. 85 | rspec << "--format documentation" << "\n" 86 | rspec << "--color" << "\n" 87 | rspec << "--order=default" << "\n" 88 | 89 | # Add rspec, byebug, and colorize gems to Gemfile 90 | gemfile << "source 'https://rubygems.org'" << "\n" 91 | gemfile << "gem 'rspec'" << "\n" 92 | gemfile << "gem 'byebug'" << "\n" 93 | gemfile << "gem 'colorize'" << "\n" 94 | 95 | # loop through master tests and add text to the new files 96 | master.each do |test| 97 | practice_test << File.read(test[2]) << "\n" 98 | spec << File.read(test[3]) << "\n" 99 | solution << File.read(test[4]) << "\n" 100 | end 101 | 102 | # close the files that were just created 103 | practice_test.close 104 | spec.close 105 | solution.close 106 | 107 | sleep(0.5) 108 | puts 109 | puts "Done!" 110 | -------------------------------------------------------------------------------- /practice_test_generator.rb: -------------------------------------------------------------------------------- 1 | require 'csv' 2 | require 'colorize' 3 | require 'fileutils' 4 | 5 | # Instructions 6 | system("clear") 7 | puts "I am generating a practice assessment that will be saved" 8 | puts "as 'practice_assessment/' in your current directory" 9 | 10 | # Read in csv with problem info 11 | problems = CSV.read( 12 | 'resources/list.csv', 13 | headers: true, 14 | header_converters: :symbol, 15 | converters: :all 16 | ) 17 | 18 | # Define number of each category problem 19 | categories = { 20 | recursion: 2, 21 | array: 1, 22 | string: 1, 23 | enumerable: 1, 24 | sort: 1 25 | } 26 | 27 | # Grab appropriate problems for each category 28 | master = [] 29 | 30 | categories.each do |category, num| 31 | problems_in_category = [] 32 | problems.each do |problem| 33 | problems_in_category << problem if category.to_s == problem[1] 34 | end 35 | 36 | # my_each should be on every test, so if the category is enumerable we add 37 | # it in here, delete it, and then lower will add a random problem from 38 | # remaining enumerables 39 | if category == :enumerable 40 | my_each = problems_in_category.find { |el| el[0] == 'my_each' } 41 | master << my_each 42 | problems_in_category.delete(my_each) 43 | end 44 | 45 | if category == :string 46 | pig_latinify = problems_in_category.find { |el| el[0] == 'pig_latinify' } 47 | problems_in_category.delete(pig_latinify) 48 | end 49 | 50 | master.concat(problems_in_category.sample(num)) 51 | end 52 | 53 | # Remove old practice assessment if it exists 54 | FileUtils.rm_r("practice_assessment") if File.directory?("practice_assessment") 55 | 56 | # Create relevant directories for practice assessment 57 | Dir.mkdir("practice_assessment") 58 | Dir.mkdir("practice_assessment/lib") 59 | Dir.mkdir("practice_assessment/spec") 60 | Dir.mkdir("practice_assessment/solution") 61 | 62 | # Create new problem, spec and solution files 63 | practice_test = File.open("practice_assessment/lib/practice_test.rb", "w") 64 | spec = File.open("practice_assessment/spec/practice_test_spec.rb", "w") 65 | solution = File.open("practice_assessment/solution/solution.rb", "w") 66 | gemfile = File.open("practice_assessment/Gemfile", "w") 67 | rspec = File.open("practice_assessment/.rspec", "w") 68 | 69 | # Copy README into practice directory 70 | FileUtils.cp("./resources/README.md", "./practice_assessment/") 71 | 72 | # Require rspec and the practice_test in the spec 73 | spec << "gem 'rspec'" << "\n" 74 | spec << "require 'practice_test'" << "\n" 75 | 76 | # .rspec file add formatting and color for better readability. 77 | rspec << "--format documentation" << "\n" 78 | rspec << "--color" << "\n" 79 | rspec << "--order=default" << "\n" 80 | 81 | # Add rspec, byebug, and colorize gems to Gemfile 82 | gemfile << "source 'https://rubygems.org'" << "\n" 83 | gemfile << "gem 'rspec'" << "\n" 84 | gemfile << "gem 'byebug'" << "\n" 85 | gemfile << "gem 'colorize'" << "\n" 86 | 87 | # Loop through master problems and add text to the new files 88 | master.each do |problem| 89 | practice_test << File.read(problem[2]) << "\n" 90 | spec << File.read(problem[3]) << "\n" 91 | solution << File.read(problem[4]) << "\n" 92 | end 93 | 94 | # Close the files that were just created 95 | practice_test.close 96 | spec.close 97 | solution.close 98 | gemfile.close 99 | 100 | puts "Beep." 101 | puts "Bop." 102 | puts "Boop." 103 | puts "Beep." 104 | puts "Done!" -------------------------------------------------------------------------------- /problems/anagrams.rb: -------------------------------------------------------------------------------- 1 | # Write a function `anagrams(str1, str2)` that takes in two words and returns a 2 | # boolean indicating whether or not the words are anagrams. Anagrams are words 3 | # that contain the same characters but not necessarily in the same order. Solve 4 | # this without using `Array#sort` or `Array#sort_by`. 5 | 6 | def anagrams(str1, str2) 7 | 8 | end 9 | -------------------------------------------------------------------------------- /problems/base_converter.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that takes in a base 10 number n and 2 | # converts it to a base b number. Return the new number as a string 3 | # 4 | # E.g. base_converter(5, 2) == "101" 5 | # base_converter(31, 16) == "1f" 6 | 7 | def base_converter(num, b) 8 | 9 | end 10 | -------------------------------------------------------------------------------- /problems/binary_search.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write a monkey patch of binary search: 3 | # E.g. [1, 2, 3, 4, 5, 7].my_bsearch(5) => 4 4 | # **Do NOT use the built in `Array#index` `Array#find_index`, `Array#include?`, 5 | # or `Array#member` methods in your implementation.** 6 | 7 | # NB: YOU MUST WRITE THIS RECURSIVELY (searching half of the array every time). 8 | # We will not give you points if you visit every element in the array every 9 | # time you search. 10 | 11 | # For example, given the array [1, 2, 3, 4], you should NOT be checking 12 | # 1 first, then 2, then 3, then 4. 13 | def my_bsearch(target) 14 | 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /problems/bubble_sort.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an Array method that returns a bubble-sorted copy of an array. 3 | # Do NOT call the built-in `Array#sort` or `Array#sort_by` methods in 4 | # your implementation. 5 | 6 | def bubble_sort(&prc) 7 | 8 | end 9 | 10 | # You are not required to implement this; it's here as a suggestion :-) 11 | def bubble_sort!(&prc) 12 | 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /problems/caesar_cipher.rb: -------------------------------------------------------------------------------- 1 | # Back in the good old days, you used to be able to write a darn near 2 | # uncrackable code by simply taking each letter of a message and incrementing it 3 | # by a fixed number, so "abc" by 2 would look like "cde", wrapping around back 4 | # to "a" when you pass "z". Write a function, `caesar_cipher(str, shift)` which 5 | # will take a message and an increment amount and outputs the encoded message. 6 | # Assume lowercase and no punctuation. Preserve spaces. 7 | # 8 | # To get an array of letters "a" to "z", you may use `("a".."z").to_a`. To find 9 | # the position of a letter in the array, you may use `Array#find_index`. 10 | 11 | def caesar_cipher(str, shift) 12 | 13 | end 14 | -------------------------------------------------------------------------------- /problems/deep_dup.rb: -------------------------------------------------------------------------------- 1 | # Using recursion and the `is_a?` method, write an `Array#deep_dup` method that 2 | # will perform a "deep" duplication of the interior arrays. 3 | 4 | def deep_dup(arr) 5 | 6 | end 7 | -------------------------------------------------------------------------------- /problems/digital_root.rb: -------------------------------------------------------------------------------- 1 | # Write a method, `digital_root(num)`. It should Sum the digits of a positive 2 | # integer. If it is greater than 9 (i.e. more than one digit), sum the digits of 3 | # the resulting number. Keep repeating until there is only one digit in the 4 | # result, called the "digital root". **Do NOT use the built in `Integer#to_s` 5 | # or `Integer#digits` methods in your implementation.** 6 | # 7 | # You may wish to use a helper function, `digital_root_step(num)` which performs 8 | # one step of the process. 9 | 10 | def digital_root(num) 11 | 12 | end 13 | -------------------------------------------------------------------------------- /problems/doubler.rb: -------------------------------------------------------------------------------- 1 | # Write a method that doubles each element in an array. Assume all elements of 2 | # the array are integers. 3 | 4 | def doubler(array) 5 | 6 | end 7 | -------------------------------------------------------------------------------- /problems/dups.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#dups` method that will return a hash containing the indices 3 | # of all duplicate elements. The keys are the duplicate elements; the values 4 | # are arrays of their indices in ascending order. 5 | # e.g. [1, 3, 4, 3, 0, 3, 0].dups => { 3 => [1, 3, 5], 0 => [4, 6] } 6 | 7 | def dups 8 | 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /problems/eight_queens.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that generates the number of possible unique ways to 2 | # place eight queens on a chess board such that no two queens are in 3 | # the row, column, or diagonal. A skeleton for a possible solution is 4 | # provided. Feel free to create your own solution from scratch. 5 | 6 | class EightQueens 7 | attr_accessor :rows, :diags1, :diags2 8 | 9 | def initialize 10 | @rows = Array.new(8, false) 11 | @diags1 = Array.new(14, false) 12 | @diags2 = Array.new(14, false) 13 | end 14 | 15 | def backtrack(row = 0, count = 0) 16 | end 17 | 18 | def is_not_under_attack(row, col) 19 | end 20 | 21 | def place_queen(row, col) 22 | end 23 | 24 | def remove_queen(row, col) 25 | end 26 | end 27 | 28 | eight_queens = EightQueens.new() 29 | eight_queens.backtrack 30 | -------------------------------------------------------------------------------- /problems/exponent.rb: -------------------------------------------------------------------------------- 1 | # Write a method that returns b^n recursively. Your solution should accept 2 | # negative values for n. 3 | 4 | def exponent(b, n) 5 | 6 | end 7 | -------------------------------------------------------------------------------- /problems/factorials_rec.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that returns the first "num" factorial numbers in 2 | # ascending order. Note that the 1st factorial number is 0!, which equals 1. 3 | # The 2nd factorial is 1!, the 3rd factorial is 2!, etc. 4 | 5 | def factorials_rec(num) 6 | 7 | end 8 | -------------------------------------------------------------------------------- /problems/factors.rb: -------------------------------------------------------------------------------- 1 | # Write a method that returns the factors of a number in ascending order. 2 | 3 | def factors(num) 4 | 5 | end 6 | -------------------------------------------------------------------------------- /problems/fibs_sum.rb: -------------------------------------------------------------------------------- 1 | # Write a method that finds the sum of the first n fibonacci numbers recursively. 2 | # Assume n > 0. 3 | 4 | def fibs_sum(n) 5 | 6 | end 7 | -------------------------------------------------------------------------------- /problems/first_even_numbers_sum.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that returns the sum of the first n even numbers 2 | # recursively. Assume n > 0. 3 | 4 | def first_even_numbers_sum(n) 5 | 6 | end 7 | -------------------------------------------------------------------------------- /problems/jumble_sort.rb: -------------------------------------------------------------------------------- 1 | # Write a method that takes a string and an alphabet. It returns a copy of the string 2 | # with the letters re-ordered according to their positions in the alphabet. If 3 | # no alphabet is passed in, it defaults to normal alphabetical order (a-z). 4 | # **Do NOT use `Array#sort` or `Array#sort_by`.** 5 | 6 | # Example: 7 | # `jumble_sort("hello")` => "ehllo" 8 | # `jumble_sort("hello", ['o', 'l', 'h', 'e'])` => 'ollhe' 9 | 10 | def jumble_sort(str, alphabet = nil) 11 | 12 | end 13 | -------------------------------------------------------------------------------- /problems/longest_palindrome.rb: -------------------------------------------------------------------------------- 1 | # A palindrome is a word or sequence of words that reads the same backwards as 2 | # forwards. Write a method that returns the length of the longest palindrome in 3 | # a given string. If there is no palindrome longer than two letters, return false. 4 | 5 | def longest_palindrome(string) 6 | 7 | end 8 | -------------------------------------------------------------------------------- /problems/make_better_change.rb: -------------------------------------------------------------------------------- 1 | # See question here: http://web.archive.org/web/20130215052843/http://rubyquiz.com/quiz154.html 2 | # Write a recursive method to solve `make_better_change`. 3 | 4 | # HINT: To make_better_change, we only take one coin at a time and 5 | # never rule out denominations that we've already used. 6 | # This allows each coin to be available each time we get a new remainder. 7 | # By iterating over the denominations and continuing to search 8 | # for the best change, we assure that we test for 'non-greedy' uses 9 | # of each denomination. 10 | 11 | # `make_better_change(24, [10,7,1])` should return [10,7,7] 12 | 13 | def make_better_change(value, coins) 14 | 15 | end 16 | -------------------------------------------------------------------------------- /problems/median.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#median` method that returns the median element in an array. 3 | # If the length is even, return the average of the middle two elements. 4 | 5 | def median 6 | 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /problems/merge_sort.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#merge_sort` method; it should not modify the original array. 3 | # **Do NOT use `Array#sort` or `Array#sort_by` in your implementation.** 4 | 5 | def merge_sort(&prc) 6 | 7 | end 8 | 9 | private 10 | def self.merge(left, right, &prc) 11 | 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /problems/my_all.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_all?(&prc)` method. This method should return true if 3 | # every element in the array satisfies the block, otherwise return false. 4 | # **Do NOT use `Array#all?` in your implementation.** 5 | 6 | # Examples: 7 | # `[1,2,3].my_all? { |n| n.even? }` => false 8 | # `[2,4,6].my_all? { |n| n.even? }` => true 9 | 10 | def my_all?(&prc) 11 | 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /problems/my_any.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_any?(&prc)` method. This method should return true if any 3 | # of the Array elements satisfy the block, otherwise it should return false. 4 | 5 | # Examples: 6 | # `[1,2,3].my_any? { |n| n.even? }` => true 7 | # `[1,3,5].my_any? { |n| n.even? }` => false 8 | 9 | def my_any?(&prc) 10 | 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /problems/my_each.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_each(&prc)` method that calls a proc on each element. 3 | # **Do NOT use the built-in `Array#each`, `Array#each_with_index`, or 4 | # `Array#map` methods in your implementation.** 5 | 6 | def my_each(&prc) 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/my_each_hash.rb: -------------------------------------------------------------------------------- 1 | class Hash 2 | # Write a `Hash#my_each(&prc)` that calls a proc on each key, value pair. 3 | # **Do NOT use the built-in `Hash#each`, `Hash#map`, `Hash#each_with_index` 4 | # methods in your implementation.** 5 | 6 | def my_each(&prc) 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/my_each_with_index.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_each_with_index(&prc)` method that calls a proc on each 3 | # element with its index. **Do NOT use the built-in `Array#each`, `Array#map` 4 | # or `Array#each_with_index` methods in your implementation.** 5 | 6 | def my_each_with_index(&prc) 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/my_flatten.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_flatten` method that akes a multi-dimentional array and 3 | # returns a single array of all the elements. 4 | # 5 | # Example: `[1,[2,3], [4,[5]]].my_flatten` => [1,2,3,4,5] 6 | 7 | def my_flatten 8 | 9 | end 10 | 11 | # Write an `Array#my_controlled_flatten(n)` method that only flattens n levels 12 | # of an array. For example, if you have an array with 3 levels of nested 13 | # arrays, and run `arr.my_flatten(1)`, you should return an array with 1 14 | # level of nested arrays flattened. 15 | # 16 | # Example: `[1,[2,3], [4,[5]]].my_controlled_flatten(1)` => [1,2,3,4,[5]] 17 | 18 | def my_controlled_flatten(n) 19 | 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /problems/my_inject.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_inject` method. If my_inject receives no argument, then 3 | # use the first element of the array as the default accumulator. 4 | # **Do NOT use the built-in `Array#inject` or `Array#reduce` methods in your 5 | # implementation.** 6 | 7 | def my_inject(accumulator = nil, &prc) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/my_join.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_join` method. If my_join receives no argument, then use 3 | # an empty string to join the array together. 4 | # **Do NOT use the built-in `Array#join` method in your implementation.** 5 | # 6 | # Examples. 7 | # `[1,2,3].my_join` => '123' 8 | # `[1,2,3].my_join('$')` => '1$2$3' 9 | 10 | def my_join(separator = "") 11 | 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /problems/my_merge.rb: -------------------------------------------------------------------------------- 1 | class Hash 2 | # Write a `Hash#my_merge(other_hash)` method. This should NOT modify the 3 | # original hash and return a combined version of both hashes. 4 | # **Do NOT use the built-in `Hash#merge` method in your implementation.** 5 | 6 | def my_merge(other_hash) 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/my_reject.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_reject(&prc)` method. This method should return a new 3 | # array excluding all the elements in the original array that satisfy the proc. 4 | # **Do NOT use the built-in `Array#reject` or `Array#select` methods in your 5 | # implementation.** 6 | 7 | # Example: `[1,2,3].my_reject {|n| n.even?}` => [1,3] 8 | 9 | def my_reject(&prc) 10 | 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /problems/my_reverse.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_reverse` method that reverses the order in which elements 3 | # appear within the array. **Do NOT use the built-in `Array#reverse` method 4 | # in your implementation.** 5 | 6 | def my_reverse 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/my_rotate.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#my_rotate(positions)` that rotates the elements 3 | # correctly based on the argument provided. The work for positive and 4 | # negative integer arguments. You CANNOT use Ruby's `Array#rotate` or 5 | # `Array#rotate!`. 6 | 7 | def my_rotate(positions) 8 | 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /problems/my_select.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#my_select(&prc)` that correctly returns an array of 3 | # selected elements according to the block. **Do NOT use the built-in 4 | # `Array#select` or `Array#reject` in your implementation.** 5 | 6 | def my_select(&prc) 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/my_zip.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#my_zip(*arrays)` that merges elements from the 3 | # receiver with the corresponding elements from each provided argument. You 4 | # CANNOT use Ruby's built-in `Array#zip` method 5 | 6 | # example => [1,2,3].my_zip([4,5,6], [7,8,9]) 7 | # should return => [[1,4,7], [2,5,8], [3,6,9]] 8 | 9 | def my_zip(*arrays) 10 | 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /problems/permutations.rb: -------------------------------------------------------------------------------- 1 | # Define a recursive method `permutations(array)` that returns all of the 2 | # permutations of an array 3 | 4 | # example => permutations([1,2,3]) 5 | # should return => [ 6 | # [1, 2, 3], 7 | # [1, 3, 2], 8 | # [2, 1, 3], 9 | # [2, 3, 1], 10 | # [3, 1, 2], 11 | # [3, 2, 1] 12 | # ] 13 | 14 | # You CANNOT use call Ruby's built-in `Array#permutation` method. 15 | 16 | def permutations(array) 17 | 18 | end 19 | -------------------------------------------------------------------------------- /problems/pig_latinify.rb: -------------------------------------------------------------------------------- 1 | # **THIS PROBLEM WILL NOT SHOW UP ON A REAL ASSESSMENT** 2 | # If you are a non-native English speaker and find it difficult to understand 3 | # this problem, do not spend too much time on it. Focus on other problems instead. 4 | 5 | # Define a method `pig_latinify(sentence)` that translates a sentence into pig 6 | # latin. You may want a helper method. 7 | 8 | ## Rules 9 | # In the English language, vowels are the following letters: 10 | # ['a', 'e', 'i', 'o', 'u'] Consonants are all other letters. 11 | 12 | # Pig latin translation uses the following rules: 13 | # 1. If the word begins with a vowel, simply append `ay` onto the end. 14 | # ex. 'apple' => 'appleay' 15 | # 2. If the word begins with a consonant, move the starting consonants to the 16 | # end of the word and then append `ay` 17 | # ex1. 'pearl' => 'earlpay' 18 | # ex2. `school` => `oolschay` 19 | # 3. Treat `qu` at the start of a word as a singular consonant. 20 | # ex1. `queen` => `eenquay` 21 | # ex2. `square` => `aresquay` 22 | 23 | def pig_latinify(sentence) 24 | 25 | end 26 | -------------------------------------------------------------------------------- /problems/prime_factorization.rb: -------------------------------------------------------------------------------- 1 | # It is sometimes necessary to be able to break down a number into its prime 2 | # factors. The process is called prime factorization. We can use a factor tree 3 | # to determine the prime factorization of a number: 4 | 5 | # 12 6 | # / \ 7 | # / \ 8 | # 4 3 9 | # / \ 10 | # 2 2 11 | 12 | # Define a method `prime_factorization(n)` that breaks a number down into it's 13 | # prime factors. 14 | 15 | # example: prime_factorization(12) => [2,2,3] 16 | 17 | def prime_factorization(num) 18 | 19 | end 20 | -------------------------------------------------------------------------------- /problems/primes.rb: -------------------------------------------------------------------------------- 1 | # Define a method `primes(num)` that returns an array of the first "num" primes. 2 | # You may wish to use an `is_prime?` helper method. 3 | 4 | def primes(num) 5 | 6 | end 7 | -------------------------------------------------------------------------------- /problems/quicksort.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#quick_sort` that implements the quick sort method. 3 | # The method should be able to accept a block. **Do NOT use the built-in 4 | # `Array#sort` or `Array#sort_by` methods in your implementation.** 5 | 6 | def my_quick_sort(&prc) 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/real_words_in_string.rb: -------------------------------------------------------------------------------- 1 | class String 2 | # Define a method `String#real_words_in_string(dictionary)` that returns an 3 | # array of all the subwords of the string that appear in the dictionary 4 | # argument. The method should NOT return any duplicates. 5 | 6 | def real_words_in_string(dictionary) 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /problems/rec_sum.rb: -------------------------------------------------------------------------------- 1 | # Define a method `rec_sum(nums)` that returns the sum of all elements in an 2 | # array recursively 3 | 4 | def rec_sum(nums) 5 | 6 | end 7 | -------------------------------------------------------------------------------- /problems/string_include_key.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method `string_include_key?(string, key)` that takes in a 2 | # string to search and a key string. Return true if the string contains all of 3 | # the characters in the key in the same order that they appear in the key. 4 | 5 | # example_1: string_include_key?("cadbpc", "abc") => true 6 | # example_2: string_include_key("cba", "abc") => false 7 | 8 | def string_include_key?(string, key) 9 | 10 | end 11 | -------------------------------------------------------------------------------- /problems/subsets.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method `subsets(array)` that returns all of the subsets of 2 | # an array 3 | 4 | # example => subsets([1,2,3]) 5 | # should return => [ 6 | # [], 7 | # [1], 8 | # [2], 9 | # [1, 2], 10 | # [3], 11 | # [1, 3], 12 | # [2, 3], 13 | # [1, 2, 3] 14 | # ] 15 | 16 | def subsets(array) 17 | 18 | end 19 | -------------------------------------------------------------------------------- /problems/symmetric_substrings.rb: -------------------------------------------------------------------------------- 1 | class String 2 | # Define a method `String#symmetric_substrings` that returns an array of 3 | # substrings that are palindromes. Only include substrings of length > 1. 4 | 5 | # example: "cool".symmetric_substrings => ["oo"] 6 | 7 | def symmetric_substrings 8 | 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /problems/titleize.rb: -------------------------------------------------------------------------------- 1 | # Define a method `titleize(title)` that capitalizes each word in a string like 2 | # a book title. First word in a title should always be capitalized. Do not 3 | # capitalize words like 'a', 'and', 'of', 'over' or 'the'. 4 | 5 | def titleize(title) 6 | 7 | end 8 | -------------------------------------------------------------------------------- /problems/two_sum.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#two_sum`, that finds all pairs of positions where the 3 | # elements at those positions sum to zero. The method should return a nested 4 | # array of positions. 5 | 6 | # Ordering matters. We want each of the pairs to be sorted smaller index 7 | # before bigger index. We want the array of pairs to be sorted "dictionary-wise": 8 | # [0, 2] before [1, 2] (smaller first elements come first) 9 | # [0, 1] before [0, 2] (then smaller second elements come first) 10 | 11 | def two_sum 12 | 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /resources/README.md: -------------------------------------------------------------------------------- 1 | # Assessment Ruby 01 Instructions 2 | 3 | **Do not share this repo or post it publicly. We will take violations very 4 | seriously.** 5 | 6 | - We will take 45 minutes for this assessment. 7 | 8 | - Don't worry if you can't pass every spec in the time limit; do the best you 9 | can. 10 | 11 | - Instructions for each problem are included in the `practice_test.rb` file. 12 | 13 | - Run the specs as you solve the assessment. 14 | 15 | - To run the specs, run `bundle exec rspec spec.rb` from the assessment 16 | directory. 17 | 18 | - You will be evaluated based on the number of specs passed. It is in your 19 | interest to tackle easier problems first; this will help you pass specs 20 | earlier. 21 | 22 | - Look at the title of the spec to see why it failed; you can also read the 23 | spec code for more information. 24 | 25 | - Please ask your TAs any questions. If you get stuck or don't know why 26 | something is failing, ask. TAs will let you know whether they can answer 27 | your question, so ask anything. 28 | 29 | - Do not use the internet or prior notes. 30 | -------------------------------------------------------------------------------- /resources/list.csv: -------------------------------------------------------------------------------- 1 | Name,Category,ProblemFile,SpecFile,SolutionFile 2 | anagrams,string,problems/anagrams.rb,specs/anagrams_spec.rb,solutions/anagrams_solution.rb 3 | base_converter,bonus,problems/base_converter.rb,specs/base_converter_spec.rb,solutions/base_converter_solution.rb 4 | binary_search,sort,problems/binary_search.rb,specs/binary_search_spec.rb,solutions/binary_search_solution.rb 5 | bubble_sort,sort,problems/bubble_sort.rb,specs/bubble_sort_spec.rb,solutions/bubble_sort_solution.rb 6 | caesar_cipher,bonus,problems/caesar_cipher.rb,specs/caesar_cipher_spec.rb,solutions/caesar_cipher_solution.rb 7 | deep_dup,recursion,problems/deep_dup.rb,specs/deep_dup_spec.rb,solutions/deep_dup_solution.rb 8 | digital_root,recursion,problems/digital_root.rb,specs/digital_root_spec.rb,solutions/digital_root_solution.rb 9 | doubler,array,problems/doubler.rb,specs/doubler_spec.rb,solutions/doubler_solution.rb 10 | dups,array,problems/dups.rb,specs/dups_spec.rb,solutions/dups_solution.rb 11 | eight_queens,bonus,problems/eight_queens.rb,specs/eight_queens_spec.rb,solutions/eight_queens_solution.rb 12 | exponent,recursion,problems/exponent.rb,specs/exponent_spec.rb,solutions/exponent_solution.rb 13 | factorials_rec,recursion,problems/factorials_rec.rb,specs/factorials_rec_spec.rb,solutions/factorials_rec_solution.rb 14 | factors,array,problems/factors.rb,specs/factors_spec.rb,solutions/factors_solution.rb 15 | fibs_sum,recursion,problems/fibs_sum.rb,specs/fibs_sum_spec.rb,solutions/fibs_sum_solution.rb 16 | first_even_numbers_sum,recursion,problems/first_even_numbers_sum.rb,specs/first_even_numbers_sum_spec.rb,solutions/first_even_numbers_sum_solution.rb 17 | jumble_sort,sort,problems/jumble_sort.rb,specs/jumble_sort_spec.rb,solutions/jumble_sort_solution.rb 18 | longest_palindrome,string,problems/longest_palindrome.rb,specs/longest_palindrome_spec.rb,solutions/longest_palindrome_solution.rb 19 | make_better_change,bonus,problems/make_better_change.rb,specs/make_better_change_spec.rb,solutions/make_better_change_solution.rb 20 | median,array,problems/median.rb,specs/median_spec.rb,solutions/median_solution.rb 21 | merge_sort,sort,problems/merge_sort.rb,specs/merge_sort_spec.rb,solutions/merge_sort_solution.rb 22 | my_all,enumerable,problems/my_all.rb,specs/my_all_spec.rb,solutions/my_all_solution.rb 23 | my_any,enumerable,problems/my_any.rb,specs/my_any_spec.rb,solutions/my_any_solution.rb 24 | my_each,enumerable,problems/my_each.rb,specs/my_each_spec.rb,solutions/my_each_solution.rb 25 | my_each_hash,enumerable,problems/my_each_hash.rb,specs/my_each_hash_spec.rb,solutions/my_each_hash_solution.rb 26 | my_each_with_index,enumerable,problems/my_each_with_index.rb,specs/my_each_with_index_spec.rb,solutions/my_each_with_index_solution.rb 27 | my_flatten,array,problems/my_flatten.rb,specs/my_flatten_spec.rb,solutions/my_flatten_solution.rb 28 | my_inject,enumerable,problems/my_inject.rb,specs/my_inject_spec.rb,solutions/my_inject_solution.rb 29 | my_join,array,problems/my_join.rb,specs/my_join_spec.rb,solutions/my_join_solution.rb 30 | my_merge,array,problems/my_merge.rb,specs/my_merge_spec.rb,solutions/my_merge_solution.rb 31 | my_reject,enumerable,problems/my_reject.rb,specs/my_reject_spec.rb,solutions/my_reject_solution.rb 32 | my_reverse,array,problems/my_reverse.rb,specs/my_reverse_spec.rb,solutions/my_reverse_solution.rb 33 | my_rotate,array,problems/my_rotate.rb,specs/my_rotate_spec.rb,solutions/my_rotate_solution.rb 34 | my_select,enumerable,problems/my_select.rb,specs/my_select_spec.rb,solutions/my_select_solution.rb 35 | my_zip,array,problems/my_zip.rb,specs/my_zip_spec.rb,solutions/my_zip_solution.rb 36 | permutations,bonus,problems/permutations.rb,specs/permutations_spec.rb,solutions/permutations_solution.rb 37 | pig_latinify,bonus,problems/pig_latinify.rb,specs/pig_latinify_spec.rb,solutions/pig_latinify_solution.rb 38 | prime_factorization,bonus,problems/prime_factorization.rb,specs/prime_factorization_spec.rb,solutions/prime_factorization_solution.rb 39 | primes,array,problems/primes.rb,specs/primes_spec.rb,solutions/primes_solution.rb 40 | quicksort,sort,problems/quicksort.rb,specs/quicksort_spec.rb,solutions/quicksort_solution.rb 41 | real_words_in_string,string,problems/real_words_in_string.rb,specs/real_words_in_string_spec.rb,solutions/real_words_in_string_solution.rb 42 | rec_sum,recursion,problems/rec_sum.rb,specs/rec_sum_spec.rb,solutions/rec_sum_solution.rb 43 | string_include_key,recursion,problems/string_include_key.rb,specs/string_include_key_spec.rb,solutions/string_include_key_solution.rb 44 | subsets,bonus,problems/subsets.rb,specs/subsets_spec.rb,solutions/subsets_solution.rb 45 | symmetric_substrings,string,problems/symmetric_substrings.rb,specs/symmetric_substrings_spec.rb,solutions/symmetric_substrings_solution.rb 46 | titleize,string,problems/titleize.rb,specs/titleize_spec.rb,solutions/titleize_solution.rb 47 | two_sum,array,problems/two_sum.rb,specs/two_sum_spec.rb,solutions/two_sum_solution.rb -------------------------------------------------------------------------------- /solutions/anagrams_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a function `anagrams(str1, str2)` that takes in two words and returns a 2 | # boolean indicating whether or not the words are anagrams. Anagrams are words 3 | # that contain the same characters but not necessarily in the same order. Solve 4 | # this without using `Array#sort` or `Array#sort_by`. 5 | 6 | def anagrams(str1, str2) 7 | letters = Hash.new(0) 8 | 9 | str1.split('').each do |char| 10 | letters[char] += 1 11 | end 12 | 13 | str2.split('').each do |char| 14 | letters[char] -= 1 15 | end 16 | 17 | letters.all? { |_, v| v.zero? } 18 | end 19 | -------------------------------------------------------------------------------- /solutions/base_converter_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that takes in a base 10 number n and 2 | # converts it to a base b number. Return the new number as a string 3 | # 4 | # E.g. base_converter(5, 2) == "101" 5 | # base_converter(31, 16) == "1f" 6 | 7 | def base_converter(num, b) 8 | return num.to_s if [0,1].include?(num) 9 | 10 | digits = %w(0 1 2 3 4 5 6 7 8 9 a b c d e f) 11 | base_converter(num/b, b) + digits[num % b] 12 | end 13 | -------------------------------------------------------------------------------- /solutions/binary_search_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write a monkey patch of binary search: 3 | # E.g. [1, 2, 3, 4, 5, 7].my_bsearch(5) => 4 4 | # **Do NOT use the built in `Array#index` `Array#find_index`, `Array#include?`, 5 | # or `Array#member` methods in your implementation.** 6 | 7 | def my_bsearch(target) 8 | return nil if size == 0 9 | mid = size/2 10 | 11 | case self[mid] <=> target 12 | when 0 13 | return mid 14 | when 1 15 | return self.take(mid).my_bsearch(target) 16 | else 17 | search_res = self.drop(mid+1).my_bsearch(target) 18 | search_res.nil? ? nil : mid + 1 + search_res 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /solutions/bubble_sort_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an Array method that returns a bubble-sorted copy of an array. 3 | # Do NOT call the built-in `Array#sort` or `Array#sort_by` methods in 4 | # your implementation. 5 | 6 | def bubble_sort! 7 | # Without a proc 8 | sorted = false 9 | until sorted 10 | sorted = true 11 | 12 | self.each_with_index do |el, i| 13 | next if i + 1 == self.length 14 | j = i + 1 15 | if self[i] > self[j] 16 | sorted = false 17 | self[i], self[j] = self[j], self[i] 18 | end 19 | end 20 | end 21 | 22 | self 23 | end 24 | 25 | def bubble_sort!(&prc) 26 | # With a proc 27 | prc ||= Proc.new { |x, y| x <=> y } 28 | 29 | sorted = false 30 | until sorted 31 | sorted = true 32 | 33 | self.each_with_index do |el, i| 34 | next if i + 1 == self.length 35 | j = i + 1 36 | if prc.call(self[i], self[j]) == 1 37 | sorted = false 38 | self[i], self[j] = self[j], self[i] 39 | end 40 | end 41 | end 42 | 43 | self 44 | end 45 | 46 | def bubble_sort(&prc) 47 | self.dup.bubble_sort!(&prc) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /solutions/caesar_cipher_solution.rb: -------------------------------------------------------------------------------- 1 | # Back in the good old days, you used to be able to write a darn near 2 | # uncrackable code by simply taking each letter of a message and incrementing it 3 | # by a fixed number, so "abc" by 2 would look like "cde", wrapping around back 4 | # to "a" when you pass "z". Write a function, `caesar_cipher(str, shift)` which 5 | # will take a message and an increment amount and outputs the encoded message. 6 | # Assume lowercase and no punctuation. Preserve spaces. 7 | # 8 | # To get an array of letters "a" to "z", you may use `("a".."z").to_a`. To find 9 | # the position of a letter in the array, you may use `Array#find_index`. 10 | 11 | def caesar_cipher(str, shift) 12 | letters = ("a".."z").to_a 13 | 14 | encoded_str = "" 15 | str.split('').each do |char| 16 | if char == " " 17 | encoded_str << " " 18 | next 19 | end 20 | 21 | old_idx = letters.find_index(char) 22 | new_idx = (old_idx + shift) % letters.count 23 | 24 | encoded_str << letters[new_idx] 25 | end 26 | 27 | encoded_str 28 | end 29 | -------------------------------------------------------------------------------- /solutions/deep_dup_solution.rb: -------------------------------------------------------------------------------- 1 | # Using recursion and the `is_a?` method, write an `Array#deep_dup` method that 2 | # will perform a "deep" duplication of the interior arrays. 3 | 4 | def deep_dup(arr) 5 | arr.map{ |el| el.is_a?(Array) ? deep_dup(el) : el } 6 | end 7 | -------------------------------------------------------------------------------- /solutions/digital_root_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a method, `digital_root(num)`. It should Sum the digits of a positive 2 | # integer. If it is greater than 9 (i.e. more than one digit), sum the digits of 3 | # the resulting number. Keep repeating until there is only one digit in the 4 | # result, called the "digital root". **Do NOT use the built in `Integer#to_s` 5 | # or `Integer#digits` methods in your implementation.** 6 | # 7 | # You may wish to use a helper function, `digital_root_step(num)` which performs 8 | # one step of the process. 9 | 10 | def digital_root(num) 11 | while num >= 10 12 | num = digital_root_step(num) 13 | end 14 | 15 | num 16 | end 17 | 18 | def digital_root_step(num) 19 | root = 0 20 | while num > 0 21 | root += (num % 10) 22 | 23 | num /= 10 24 | end 25 | 26 | root 27 | end 28 | 29 | # Alternate Solution 30 | def digital_root(num) 31 | digits = [] 32 | 33 | while num > 0 34 | digits << num % 10 35 | num /= 10 36 | end 37 | 38 | digit_sum = digits.inject(&:+) 39 | 40 | digit_sum >= 10 ? digital_root(digit_sum) : digit_sum 41 | end 42 | 43 | # Magical one-line solution 44 | def digital_root(num) 45 | num < 10 ? num : digital_root(digital_root(num / 10) + (num % 10)) 46 | end 47 | -------------------------------------------------------------------------------- /solutions/doubler_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a method that doubles each element in an array. Assume all elements of 2 | # the array are integers. 3 | 4 | def doubler(array) 5 | array.map { |num| num * 2 } 6 | end 7 | -------------------------------------------------------------------------------- /solutions/dups_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#dups` method that will return a hash containing the indices 3 | # of all duplicate elements. The keys are the duplicate elements; the values 4 | # are arrays of their indices in ascending order. 5 | # e.g. [1, 3, 4, 3, 0, 3, 0].dups => { 3 => [1, 3, 5], 0 => [4, 6] } 6 | 7 | def dups 8 | positions = Hash.new { |h, k| h[k] = [] } 9 | 10 | self.each_with_index do |item, index| 11 | positions[item] << index 12 | end 13 | 14 | positions.select { |key, val| val.count > 1 } 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /solutions/eight_queens_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that generates the number of possible unique ways to 2 | # place eight queens on a chess board such that no two queens are in 3 | # the row, column, or diagonal. A skeleton for a possible solution is 4 | # provided. Feel free to create your own solution from scratch. 5 | 6 | class EightQueens 7 | attr_accessor :rows, :diags1, :diags2 8 | 9 | def initialize 10 | @rows = Array.new(8, false) 11 | @diags1 = Array.new(14, false) 12 | @diags2 = Array.new(14, false) 13 | end 14 | 15 | def backtrack(row = 0, count = 0) 16 | (0...8).each do |col| 17 | if is_not_under_attack(row, col) 18 | place_queen(row, col) 19 | if row + 1 == 8 20 | count += 1 21 | else 22 | count = backtrack(row + 1, count) 23 | end 24 | remove_queen(row, col) 25 | end 26 | end 27 | count 28 | end 29 | 30 | def is_not_under_attack(row, col) 31 | return !(rows[col] || diags1[row - col] || diags2[row + col]) 32 | end 33 | 34 | def place_queen(row, col) 35 | rows[col] = true 36 | diags1[row - col] = true 37 | diags2[row + col] = true 38 | end 39 | 40 | def remove_queen(row, col) 41 | rows[col] = false 42 | diags1[row - col] = false 43 | diags2[row + col] = false 44 | end 45 | end 46 | 47 | eight_queens = EightQueens.new() 48 | eight_queens.backtrack 49 | -------------------------------------------------------------------------------- /solutions/exponent_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a method that returns b^n recursively. Your solution should accept 2 | # negative values for n. 3 | 4 | def exponent(b, n) 5 | return 1 if n == 0 6 | if n > 0 7 | b * exponent(b, n - 1) 8 | else 9 | 1.0/b * exponent(b, n + 1) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /solutions/factorials_rec_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that returns the first "num" factorial numbers in 2 | # ascending order. Note that the 1st factorial number is 0!, which equals 1. 3 | # The 2nd factorial is 1!, the 3rd factorial is 2!, etc. 4 | 5 | def factorials_rec(num) 6 | return [1] if num == 1 7 | facs = factorials_rec(num - 1) 8 | facs << facs.last * (num - 1) 9 | facs 10 | end 11 | -------------------------------------------------------------------------------- /solutions/factors_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a method that returns the factors of a number in ascending order. 2 | 3 | def factors(num) 4 | return nil if num <= 0 5 | return [1] if num == 0 6 | (1..num).select { |i| (num % i) == 0 } 7 | end 8 | -------------------------------------------------------------------------------- /solutions/fibs_sum_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a method that finds the sum of the first n fibonacci numbers recursively. 2 | # Assume n > 0. 3 | 4 | def fibs_sum(n) 5 | return 0 if n == 0 6 | return 1 if n == 1 7 | 8 | fibs_sum(n-1) + fibs_sum(n-2) + 1 9 | end 10 | -------------------------------------------------------------------------------- /solutions/first_even_numbers_sum_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that returns the sum of the first n even numbers 2 | # recursively. Assume n > 0. 3 | 4 | def first_even_numbers_sum(n) 5 | return 2 if n == 1 6 | 2 * n + first_even_numbers_sum(n-1) 7 | end 8 | -------------------------------------------------------------------------------- /solutions/jumble_sort_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a method that takes a string and an alphabet. It returns a copy of the string 2 | # with the letters re-ordered according to their positions in the alphabet. If 3 | # no alphabet is passed in, it defaults to normal alphabetical order (a-z). 4 | # **Do NOT use `Array#sort` or `Array#sort_by`.** 5 | 6 | # Example: 7 | # `jumble_sort("hello")` => "ehllo" 8 | # `jumble_sort("hello", ['o', 'l', 'h', 'e'])` => 'ollhe' 9 | 10 | def jumble_sort(str, alphabet = nil) 11 | alphabet ||= ('a'..'z').to_a 12 | 13 | sorted = false 14 | until sorted 15 | sorted = true 16 | (0...str.length - 1).to_a.each do |i| 17 | if alphabet.index(str[i]) > alphabet.index(str[i + 1]) 18 | str[i], str[i + 1] = str[i + 1], str[i] 19 | sorted = false 20 | end 21 | end 22 | end 23 | str 24 | end 25 | -------------------------------------------------------------------------------- /solutions/longest_palindrome_solution.rb: -------------------------------------------------------------------------------- 1 | # A palindrome is a word or sequence of words that reads the same backwards as 2 | # forwards. Write a method that returns the length of the longest palindrome in 3 | # a given string. If there is no palindrome longer than two letters, return false. 4 | 5 | def longest_palindrome(string) 6 | longest_palindrome = false 7 | i = 0 8 | 9 | while i < string.length - 1 10 | j = i + 1 11 | 12 | while j < string.length 13 | curr_string = string[i..j] 14 | len = curr_string.length 15 | 16 | if is_palindrome?(curr_string) 17 | longest_palindrome = len if !longest_palindrome || len > longest_palindrome 18 | end 19 | 20 | j += 1 21 | end 22 | 23 | i += 1 24 | end 25 | 26 | longest_palindrome 27 | end 28 | 29 | def is_palindrome?(str) 30 | str == str.reverse 31 | end 32 | -------------------------------------------------------------------------------- /solutions/make_better_change_solution.rb: -------------------------------------------------------------------------------- 1 | # See question here: http://web.archive.org/web/20130215052843/http://rubyquiz.com/quiz154.html 2 | # Write a recursive method to solve `make_better_change`. 3 | 4 | # HINT: To make_better_change, we only take one coin at a time and 5 | # never rule out denominations that we've already used. 6 | # This allows each coin to be available each time we get a new remainder. 7 | # By iterating over the denominations and continuing to search 8 | # for the best change, we assure that we test for 'non-greedy' uses 9 | # of each denomination. 10 | 11 | # `make_better_change(24, [10,7,1])` should return [10,7,7] 12 | 13 | def make_better_change(value, coins) 14 | return nil if coins.empty? 15 | return [] if value == 0 16 | 17 | change = [] 18 | coins = coins.sort.reverse.select{|coin| coin <= value} 19 | coins.each do |coin| 20 | remainder = value - coin 21 | if remainder > 0 22 | best_remainder = make_better_change(remainder, coins) 23 | change << [coin] + best_remainder unless best_remainder.nil? 24 | else 25 | change << [coin] 26 | end 27 | end 28 | change.sort_by!{|arr| arr.size}.first 29 | end 30 | -------------------------------------------------------------------------------- /solutions/median_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#median` method that returns the median element in an array. 3 | # If the length is even, return the average of the middle two elements. 4 | 5 | def median 6 | return nil if empty? 7 | sorted = self.sort 8 | if length.odd? 9 | sorted[length / 2] 10 | else 11 | (sorted[length / 2] + sorted[length / 2 - 1]).fdiv(2) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /solutions/merge_sort_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#merge_sort` method; it should not modify the original array. 3 | # **Do NOT use `Array#sort` or `Array#sort_by` in your implementation.** 4 | 5 | def merge_sort(&prc) 6 | # See how I create a Proc if no block was given; this eliminates 7 | # having to later have two branches of logic, one for a block and 8 | # one for no block. 9 | prc ||= Proc.new { |x, y| x <=> y } 10 | 11 | return self if self.count <= 1 12 | 13 | midpoint = self.count / 2 14 | sorted_left = self.take(midpoint).merge_sort(&prc) 15 | sorted_right = self.drop(midpoint).merge_sort(&prc) 16 | 17 | Array.merge(sorted_left, sorted_right, &prc) 18 | 19 | end 20 | 21 | private 22 | def self.merge(left, right, &prc) 23 | merged = [] 24 | 25 | until left.empty? || right.empty? 26 | case prc.call(left.first, right.first) 27 | when -1 28 | merged << left.shift 29 | when 0 30 | merged << left.shift 31 | when 1 32 | merged << right.shift 33 | end 34 | end 35 | 36 | merged.concat(left) 37 | merged.concat(right) 38 | 39 | merged 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /solutions/my_all_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_all?(&prc)` method. This method should return true if 3 | # every element in the array satisfies the block, otherwise return false. 4 | # **Do NOT use `Array#all?` in your implementation.** 5 | 6 | # Examples: 7 | # `[1,2,3].my_all? { |n| n.even? }` => false 8 | # `[2,4,6].my_all? { |n| n.even? }` => true 9 | 10 | def my_all?(&prc) 11 | self.each { |el| return false unless prc.call(el) } 12 | true 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /solutions/my_any_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_any?(&prc)` method. This method should return true if any 3 | # of the Array elements satisfy the block, otherwise it should return false. 4 | 5 | # Examples: 6 | # `[1,2,3].my_any? { |n| n.even? }` => true 7 | # `[1,3,5].my_any? { |n| n.even? }` => false 8 | 9 | def my_any?(&prc) 10 | self.each { |el| return true if prc.call(el) } 11 | false 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /solutions/my_each_hash_solution.rb: -------------------------------------------------------------------------------- 1 | class Hash 2 | # Write a `Hash#my_each(&prc)` that calls a proc on each key, value pair. 3 | # **Do NOT use the built-in `Hash#each`, `Hash#map`, `Hash#each_with_index` 4 | # methods in your implementation.** 5 | 6 | def my_each(&prc) 7 | i = 0 8 | while i < keys.length 9 | prc.call(keys[i], self[keys[i]]) 10 | i += 1 11 | end 12 | self 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /solutions/my_each_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_each(&prc)` method that calls a proc on each element. 3 | # **Do NOT use the built-in `Array#each`, `Array#each_with_index`, or 4 | # `Array#map` methods in your implementation.** 5 | 6 | def my_each(&prc) 7 | i = 0 8 | while i < self.length 9 | prc.call(self[i]) 10 | i += 1 11 | end 12 | self 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /solutions/my_each_with_index_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_each_with_index(&prc)` method that calls a proc on each 3 | # element with its index. **Do NOT use the built-in `Array#each`, `Array#map` 4 | # or `Array#each_with_index` methods in your implementation.** 5 | 6 | def my_each_with_index(&prc) 7 | i = 0 8 | while i < self.length 9 | prc.call(self[i], i) 10 | i += 1 11 | end 12 | self 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /solutions/my_flatten_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_flatten` method that akes a multi-dimentional array and 3 | # returns a single array of all the elements. 4 | # 5 | # Example: `[1,[2,3], [4,[5]]].my_flatten` => [1,2,3,4,5] 6 | 7 | def my_flatten 8 | flattened = [] 9 | self.each do |el| 10 | el.is_a?(Array) ? flattened += el.my_flatten : flattened << el 11 | end 12 | flattened 13 | end 14 | 15 | # Write an `Array#my_controlled_flatten(n)` method that only flattens n levels 16 | # of an array. For example, if you have an array with 3 levels of nested 17 | # arrays, and run `arr.my_flatten(1)`, you should return an array with 1 18 | # level of nested arrays flattened. 19 | # 20 | # Example: `[1,[2,3], [4,[5]]].my_controlled_flatten(1)` => [1,2,3,4,[5]] 21 | 22 | def my_controlled_flatten(level = nil) 23 | flattened = [] 24 | 25 | self.each do |ele| 26 | if ele.is_a?(Array) && level != 0 27 | flattened += (level.nil? ? ele.my_controlled_flatten : ele.my_controlled_flatten(level - 1)) 28 | else 29 | flattened << ele 30 | end 31 | end 32 | 33 | flattened 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /solutions/my_inject_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_inject` method. If my_inject receives no argument, then 3 | # use the first element of the array as the default accumulator. 4 | # **Do NOT use the built-in `Array#inject` or `Array#reduce` methods in your 5 | # implementation.** 6 | 7 | def my_inject(accumulator = nil, &prc) 8 | arr = self 9 | 10 | if accumulator.nil? 11 | accumulator = self.first 12 | arr = self.drop(1) 13 | end 14 | 15 | arr.each do |el| 16 | accumulator = prc.call(accumulator, el) 17 | end 18 | 19 | accumulator 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /solutions/my_join_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_join` method. If my_join receives no argument, then use 3 | # an empty string to join the array together. 4 | # **Do NOT use the built-in `Array#join` method in your implementation.** 5 | # 6 | # Examples. 7 | # `[1,2,3].my_join` => '123' 8 | # `[1,2,3].my_join('$')` => '1$2$3' 9 | 10 | def my_join(separator = "") 11 | joined_str = "" 12 | i = 0 13 | self.each do |el| 14 | joined_str << el.to_s 15 | joined_str << separator unless i == self.length - 1 16 | i += 1 17 | end 18 | 19 | joined_str 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /solutions/my_merge_solution.rb: -------------------------------------------------------------------------------- 1 | class Hash 2 | # Write a `Hash#my_merge(other_hash)` method. This should NOT modify the 3 | # original hash and return a combined version of both hashes. 4 | # **Do NOT use the built-in `Hash#merge` method in your implementation.** 5 | 6 | def my_merge(other_hash) 7 | duped_hash = self.dup 8 | 9 | other_hash.each do |k, v| 10 | duped_hash[k] = v 11 | end 12 | 13 | duped_hash 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /solutions/my_reject_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_reject(&prc)` method. This method should return a new 3 | # array excluding all the elements in the original array that satisfy the proc. 4 | # **Do NOT use the built-in `Array#reject` or `Array#select` methods in your 5 | # implementation.** 6 | 7 | # Example: `[1,2,3].my_reject {|n| n.even?}` => [1,3] 8 | 9 | def my_reject(&prc) 10 | arr = [] 11 | self.each do |el| 12 | arr << el unless prc.call(el) 13 | end 14 | arr 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /solutions/my_reverse_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Write an `Array#my_reverse` method that reverses the order in which elements 3 | # appear within the array. **Do NOT use the built-in `Array#reverse` method 4 | # in your implementation.** 5 | 6 | def my_reverse 7 | reversed = [] 8 | 9 | self.each do |el| 10 | reversed.unshift(el) 11 | end 12 | 13 | reversed 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /solutions/my_rotate_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#my_rotate(positions)` that rotates the elements 3 | # correctly based on the argument provided. The work for positive and 4 | # negative integer arguments. You CANNOT use Ruby's `Array#rotate` or 5 | # `Array#rotate!`. 6 | 7 | def my_rotate(positions = 1) 8 | split_idx = positions % self.length 9 | 10 | self.drop(split_idx) + self.take(split_idx) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /solutions/my_select_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#my_select(&prc)` that correctly returns an array of 3 | # selected elements according to the block. **Do NOT use the built-in 4 | # `Array#select` or `Array#reject` in your implementation.** 5 | 6 | def my_select(&prc) 7 | selects = [] 8 | 9 | self.each do |item| 10 | selects << item if prc.call(item) 11 | end 12 | 13 | selects 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /solutions/my_zip_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#my_zip(*arrays)` that merges elements from the 3 | # receiver with the corresponding elements from each provided argument. You 4 | # CANNOT use Ruby's built-in `Array#zip` method 5 | 6 | # example => [1,2,3].my_zip([4,5,6], [7,8,9]) 7 | # should return => [[1,4,7], [2,5,8], [3,6,9]] 8 | 9 | def my_zip(*arrays) 10 | zipped = [] 11 | 12 | self.length.times do |i| 13 | subzip = [self[i]] 14 | 15 | arrays.each do |array| 16 | subzip << array[i] 17 | end 18 | 19 | zipped << subzip 20 | end 21 | 22 | zipped 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /solutions/permutations_solution.rb: -------------------------------------------------------------------------------- 1 | # Define a recursive method `permutations(array)` that returns all of the 2 | # permutations of an array 3 | 4 | # example => permutations([1,2,3]) 5 | # should return => [ 6 | # [1, 2, 3], 7 | # [1, 3, 2], 8 | # [2, 1, 3], 9 | # [2, 3, 1], 10 | # [3, 1, 2], 11 | # [3, 2, 1] 12 | # ] 13 | 14 | # You CANNOT use call Ruby's built-in `Array#permutation` method. 15 | 16 | def permutations(array) 17 | return [array] if array.length <= 1 18 | 19 | # Similar to the subsets problem, we observe that to get the permutations of 20 | # [1, 2, 3] we can look at the permutations of [1, 2] which are [1, 2] and 21 | # [2, 1] and add the last element to every possible index getting [3, 1, 2], 22 | # [1, 3, 2], [1, 2, 3], [3, 2, 1], [2, 3, 1], [2, 1, 3] 23 | 24 | # pop off the last element 25 | first = array.shift 26 | 27 | # make the recursive call 28 | perms = permutations(array) 29 | 30 | # we will need an array to store all our different permutations 31 | total_permutations = [] 32 | 33 | # Now we iterate over the result of our recusive call say [[1, 2], [2, 1]] 34 | # and for each permutation add first into every index. This new subarray 35 | # gets added to total_permutations. 36 | perms.each do |perm| 37 | (0..perm.length).to_a.each do |i| 38 | total_permutations << perm[0...i] + [first] + perm[i..-1] 39 | end 40 | end 41 | 42 | total_permutations 43 | end 44 | -------------------------------------------------------------------------------- /solutions/pig_latinify_solution.rb: -------------------------------------------------------------------------------- 1 | # **THIS PROBLEM WILL NOT SHOW UP ON A REAL ASSESSMENT** 2 | # If you are a non-native English speaker and find it difficult to understand 3 | # this problem, do not spend too much time on it. Focus on other problems instead. 4 | 5 | # Define a method `pig_latinify(sentence)` that translates a sentence into pig 6 | # latin. You may want a helper method. 7 | 8 | ## Rules 9 | # In the English language, vowels are the following letters: 10 | # ['a', 'e', 'i', 'o', 'u'] Consonants are all other letters. 11 | 12 | # Pig latin translation uses the following rules: 13 | # 1. If the word begins with a vowel, simply append `ay` onto the end. 14 | # ex. 'apple' => 'appleay' 15 | # 2. If the word begins with a consonant, move the starting consonants to the 16 | # end of the word and then append `ay` 17 | # ex1. 'pearl' => 'earlpay' 18 | # ex2. `school` => `oolschay` 19 | # 3. Treat `qu` at the start of a word as a singular consonant. 20 | # ex1. `queen` => `eenquay` 21 | # ex2. `square` => `aresquay` 22 | 23 | def pig_latinify(sentence) 24 | translated_words = sentence.split(" ").map do |word| 25 | translate_word(word) 26 | end 27 | translated_words.join(" ") 28 | end 29 | 30 | def translate_word(word) 31 | vowels = %w(a e i o u) 32 | if vowels.include?(word[0]) 33 | "#{word}ay" 34 | else 35 | phoneme_end = 0 36 | until vowels.include?(word[phoneme_end]) 37 | phoneme_end += 1 38 | end 39 | phoneme_end += 1 if word[phoneme_end - 1] == "q" && word[phoneme_end] == "u" 40 | "#{word[phoneme_end..-1]}#{word[0...phoneme_end]}ay" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /solutions/prime_factorization_solution.rb: -------------------------------------------------------------------------------- 1 | # It is sometimes necessary to be able to break down a number into its prime 2 | # factors. The process is called prime factorization. We can use a factor tree 3 | # to determine the prime factorization of a number: 4 | 5 | # 12 6 | # / \ 7 | # / \ 8 | # 4 3 9 | # / \ 10 | # 2 2 11 | 12 | # Define a method `prime_factorization(n)` that breaks a number down into it's 13 | # prime factors. 14 | 15 | # example: prime_factorization(12) => [2,2,3] 16 | 17 | def prime_factorization(num) 18 | # Base case - 1 is not a prime so we return an empty array here 19 | return [] if num == 1 20 | 21 | # initialize i to 2, since it is the first prime # 22 | i = 2 23 | 24 | # increment i until we find a prime factor 25 | i += 1 until is_prime?(i) && num % i == 0 26 | 27 | # Add i to prime factors and make recursive call to find rest 28 | [i] + prime_factorization(num / i) 29 | end 30 | 31 | def is_prime?(num) 32 | return false if num < 2 33 | (2...num).none? { |n| num % n == 0 } 34 | end 35 | 36 | # Alternative, optimized solution 37 | def prime_factorization(num) 38 | return [] if num == 1 39 | 40 | # Only iterating up to the square root of num is an optimization, so that we 41 | # don't check the same numbers again. This is because any factor greater than 42 | # the square root would have a complementary factor below the square root. 43 | 44 | # Example: The square root of 144 is 12. Factors of 144 below 12 include 45 | # [1, 2, 3, 6]. The only factors greater than 12, are the complements of these 46 | # factors => [144, 72, 48, 24]. Therefore it is not necessary to iterate past 47 | # the square root, since if a factor existed we would have already found it by 48 | # then. 49 | 50 | # We also do not need to explicitly check that the factor is prime, because 51 | # by starting at 2, we ensure that the first factor we find is prime. Any 52 | # factor that is not prime, will itself have factors that are also factors of 53 | # the number we are evaluating. This will continue to be true until we in fact 54 | # reach the prime factors. 55 | (2..Math.sqrt(num).ceil).to_a.each do |i| 56 | if num % i == 0 57 | return [i] + prime_factorization(num/i) 58 | end 59 | end 60 | 61 | return [num] 62 | end 63 | -------------------------------------------------------------------------------- /solutions/primes_solution.rb: -------------------------------------------------------------------------------- 1 | # Define a method `primes(num)` that returns an array of the first "num" primes. 2 | # You may wish to use an `is_prime?` helper method. 3 | 4 | def is_prime?(num) 5 | return false if num < 2 6 | (2...num).none? { |factor| num % factor == 0 } 7 | end 8 | 9 | def primes(count) 10 | primes = [] 11 | 12 | i = 2 13 | until primes.count >= count 14 | primes << i if is_prime?(i) 15 | 16 | i += 1 17 | end 18 | 19 | primes 20 | end 21 | -------------------------------------------------------------------------------- /solutions/quicksort_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#quick_sort` that implements the quick sort method. 3 | # The method should be able to accept a block. Do NOT use the built-in 4 | # `Array#sort` or `Array#sort_by` methods in your implementation. 5 | 6 | def my_quick_sort(&prc) 7 | prc ||= proc {|a, b| a<=>b} 8 | return self if size < 2 9 | 10 | pivot = first 11 | left = self[1..-1].select{|el| prc.call(el, pivot) == -1} 12 | right = self[1..-1].select{|el| prc.call(el, pivot) != -1} 13 | left.my_quick_sort(&prc) + [pivot] + right.my_quick_sort(&prc) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /solutions/real_words_in_string_solution.rb: -------------------------------------------------------------------------------- 1 | class String 2 | # Define a method `String#real_words_in_string(dictionary)` that returns an 3 | # array of all the subwords of the string that appear in the dictionary 4 | # argument. The method should NOT return any duplicates. 5 | 6 | def real_words_in_string(dictionary) 7 | real_words = [] 8 | 9 | (0...self.length).each do |idx| 10 | (idx...self.length).each do |jdx| 11 | curr_word = self[idx..jdx] 12 | next if real_words.include?(curr_word) 13 | 14 | real_words << curr_word if dictionary.include?(curr_word) 15 | end 16 | end 17 | 18 | real_words 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /solutions/rec_sum_solution.rb: -------------------------------------------------------------------------------- 1 | # Define a method `rec_sum(nums)` that returns the sum of all elements in an 2 | # array recursively 3 | 4 | def rec_sum(nums) 5 | return 0 if nums.empty? 6 | 7 | nums[0] + rec_sum(nums.drop(1)) 8 | end 9 | -------------------------------------------------------------------------------- /solutions/string_include_key_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method `string_include_key?(string, key)` that takes in a 2 | # string to search and a key string. Return true if the string contains all of 3 | # the characters in the key in the same order that they appear in the key. 4 | 5 | # example_1: string_include_key?("cadbpc", "abc") => true 6 | # example_2: string_include_key("cba", "abc") => false 7 | 8 | def string_include_key?(string, key) 9 | return true if key.length == 0 10 | 11 | next_key_char = key.chars.first 12 | key_index = string.index(next_key_char) 13 | 14 | return false if key_index.nil? 15 | string_include_key?(string[key_index+1..-1], key[1..-1]) 16 | end 17 | -------------------------------------------------------------------------------- /solutions/subsets_solution.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method `subsets(array)` that returns all of the subsets of 2 | # an array 3 | 4 | # example => subsets([1,2,3]) 5 | # should return => [ 6 | # [], 7 | # [1], 8 | # [2], 9 | # [1, 2], 10 | # [3], 11 | # [1, 3], 12 | # [2, 3], 13 | # [1, 2, 3] 14 | # ] 15 | 16 | def subsets(array) 17 | return [[]] if array.empty? 18 | 19 | subs = subsets(array[0..-2]) 20 | subs.concat(subs.map{|el| el += [array.last]}) 21 | end 22 | -------------------------------------------------------------------------------- /solutions/symmetric_substrings_solution.rb: -------------------------------------------------------------------------------- 1 | class String 2 | # Define a method `String#symmetric_substrings` that returns an array of 3 | # substrings that are palindromes. Only include substrings of length > 1. 4 | 5 | # example: "cool".symmetric_substrings => ["oo"] 6 | 7 | def symmetric_substrings 8 | symm_subs = [] 9 | 10 | self.length.times do |start_pos| 11 | (2..(self.length - start_pos)).to_a.each do |end_pos| 12 | substr = self[start_pos...(start_pos + end_pos)] 13 | symm_subs << substr if substr == substr.reverse 14 | end 15 | end 16 | 17 | symm_subs 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /solutions/titleize_solution.rb: -------------------------------------------------------------------------------- 1 | # Define a method `titleize(title)` that capitalizes each word in a string like 2 | # a book title. First word in a title should always be capitalized. Do not 3 | # capitalize words like 'a', 'and', 'of', 'over' or 'the'. 4 | 5 | LITTLE_WORDS = [ 6 | "a", 7 | "and", 8 | "of", 9 | "over", 10 | "the" 11 | ].freeze 12 | 13 | def titleize(title) 14 | words = title.split(" ") 15 | result_words = [] 16 | idx = 0 17 | words.each do |word| 18 | if idx > 0 && LITTLE_WORDS.include?(word) 19 | result_words << word.downcase 20 | else 21 | result_words << word.capitalize 22 | end 23 | idx += 1 24 | end 25 | 26 | result_words.join(" ") 27 | end 28 | -------------------------------------------------------------------------------- /solutions/two_sum_solution.rb: -------------------------------------------------------------------------------- 1 | class Array 2 | # Define a method `Array#two_sum`, that finds all pairs of positions where the 3 | # elements at those positions sum to zero. The method should return a nested 4 | # array of positions. 5 | 6 | # Ordering matters. We want each of the pairs to be sorted smaller index 7 | # before bigger index. We want the array of pairs to be sorted "dictionary-wise": 8 | # [0, 2] before [1, 2] (smaller first elements come first) 9 | # [0, 1] before [0, 2] (then smaller second elements come first) 10 | 11 | def two_sum 12 | pairs = [] 13 | 14 | self.each_index do |i| 15 | ((i + 1)...self.length).to_a.each do |j| 16 | pairs << [i, j] if self[i] + self[j] == 0 17 | end 18 | end 19 | 20 | pairs 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /specs/anagrams_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#anagrams" do 2 | before(:each) do 3 | expect_any_instance_of(Array).not_to receive(:sort) 4 | expect_any_instance_of(Array).not_to receive(:sort!) 5 | expect_any_instance_of(Array).not_to receive(:sort_by) 6 | expect_any_instance_of(Array).not_to receive(:sort_by!) 7 | end 8 | 9 | it "returns true if words are anagrams" do 10 | expect(anagrams('abc', 'cba')).to be true 11 | end 12 | 13 | it "returns false if words are not anagrams" do 14 | expect(anagrams('abc', 'aba')).to be false 15 | end 16 | 17 | it "does not count words with same letters but varying lengths as anagrams" do 18 | expect(anagrams('abc', 'cbaa')).to be false 19 | end 20 | 21 | it "can handle large words with letters extremely scrambled" do 22 | expect(anagrams('aiuwehfxzxcvmneowieurahsde', 'nsewceaerihfawzueouxdihmxv')).to be true 23 | expect(anagrams('aiuwehfxzxcvmneowieurahsde', 'nsewceaerihfawzueouxdihmxw')).to be false 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /specs/base_converter_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#base_converter" do 2 | it "converts a small number in binary" do 3 | expect(base_converter(5, 2)).to eq("101") 4 | end 5 | 6 | it "converts a large number into base 16" do 7 | expect(base_converter(1239449, 16)).to eq("12e999" || "12E999") 8 | end 9 | 10 | it "returns 0 if the number is 0, regardless of base" do 11 | expect(base_converter(0, 16)).to eq("0") 12 | expect(base_converter(0, 2)).to eq("0") 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /specs/binary_search_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'Array#my_bsearch' do 2 | # create a method that performs a binary search in an array for 3 | # an element and returns its index 4 | let(:arr) { [11, 22, 33, 44, 66] } 5 | 6 | disallowed_methods = [ 7 | :index, :find_index, :include?, :member?, :dup 8 | ] 9 | 10 | before(:each) do 11 | disallowed_methods.each do |method| 12 | expect(arr).not_to receive(method) 13 | end 14 | expect_any_instance_of(Array).not_to receive(:index) 15 | end 16 | 17 | it "returns nil if the array is empty" do 18 | expect([].my_bsearch(11)).to be_nil 19 | end 20 | 21 | it "returns the index of a target" do 22 | expect(arr.my_bsearch(33)).to eq(2) 23 | end 24 | 25 | it "returns the index of a target that's less than the midpoint" do 26 | expect(arr.my_bsearch(22)).to eq(1) 27 | end 28 | 29 | it "returns the index of a target that's greater than the midpoint" do 30 | expect(arr.my_bsearch(66)).to eq(4) 31 | end 32 | 33 | it "returns nil if the target isn't found" do 34 | # Properly returns nil searching left half 35 | expect(arr.my_bsearch(5)).to be_nil 36 | # Properly returns nil searching right half 37 | expect(arr.my_bsearch(80)).to be_nil 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /specs/bubble_sort_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#bubble_sort" do 2 | let(:array) { [1, 2, 3, 4, 5].shuffle } 3 | 4 | before(:each) do 5 | expect_any_instance_of(Array).not_to receive(:sort) 6 | expect_any_instance_of(Array).not_to receive(:sort!) 7 | expect_any_instance_of(Array).not_to receive(:sort_by!) 8 | end 9 | 10 | it "works with an empty array" do 11 | expect([].bubble_sort).to eq([]) 12 | end 13 | 14 | it "works with an array of one item" do 15 | expect([1].bubble_sort).to eq([1]) 16 | end 17 | 18 | it "sorts numbers" do 19 | expect(array.bubble_sort).to eq([1, 2, 3, 4, 5]) 20 | end 21 | 22 | it "will use block if given" do 23 | sorted = array.bubble_sort do |num1, num2| 24 | # order numbers based on descending sort of their squares 25 | num2**2 <=> num1**2 26 | end 27 | 28 | expect(sorted).to eq([5, 4, 3, 2, 1]) 29 | end 30 | 31 | it "does not modify original" do 32 | duped_array = array.dup 33 | duped_array.bubble_sort 34 | expect(duped_array).to eq(array) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /specs/caesar_cipher_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#caesar_cipher" do 2 | it "encodes a simple word" do 3 | expect(caesar_cipher("aaa", 11)).to eq("lll") 4 | end 5 | 6 | it "wraps around the alphabet" do 7 | expect(caesar_cipher("zzz", 1)).to eq("aaa") 8 | end 9 | 10 | it "encodes multiple words" do 11 | expect(caesar_cipher("catz hatz", 2)).to eq("ecvb jcvb") 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /specs/deep_dup_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#deep_dup" do 2 | subject(:robot_parts) do [ 3 | ["nuts", "bolts", "washers"], 4 | ["capacitors", "resistors", "inductors"] 5 | ] 6 | end 7 | let(:copy) { deep_dup(robot_parts) } 8 | 9 | it "makes a copy of the original array" do 10 | expect(copy).to eq(robot_parts) 11 | expect(copy).not_to be(robot_parts) 12 | end 13 | 14 | it "deeply copies arrays" do 15 | expect(copy[0]).to eq(robot_parts[0]) 16 | expect(copy[0]).not_to be(robot_parts[0]) 17 | 18 | copy[1] << "LEDs" 19 | expect(robot_parts[1]).to eq(["capacitors", "resistors", "inductors"]) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /specs/digital_root_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#digital_root" do 2 | before(:each) do 3 | expect_any_instance_of(Integer).to_not receive(:to_s) 4 | expect_any_instance_of(Integer).to_not receive(:digits) 5 | end 6 | 7 | it "calculates the digital root of a single-digit number" do 8 | expect(digital_root(9)).to eq(9) 9 | end 10 | 11 | it "calculates the digital root of a multi-digit number" do 12 | expect(digital_root(125)).to eq(8) 13 | end 14 | 15 | it "calculates the digital root of a larger number" do 16 | expect(digital_root(4322)).to eq(2) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /specs/doubler_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#doubler" do 2 | subject(:array) { [1, 2, 3] } 3 | 4 | it "doubles the elements of the array" do 5 | expect(doubler(array)).to eq([2, 4, 6]) 6 | end 7 | 8 | it "does not modify the original array" do 9 | duped_array = array.dup 10 | doubler(array) 11 | 12 | expect(array).to eq(duped_array) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /specs/dups_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#dups" do 2 | it "solves a simple example" do 3 | expect([1, 3, 0, 1].dups).to eq({ 1 => [0, 3] }) 4 | end 5 | 6 | it "finds two dups" do 7 | expect([1, 3, 0, 3, 1].dups).to eq({ 1 => [0, 4], 3 => [1, 3] }) 8 | end 9 | 10 | it "finds multi-dups" do 11 | expect([1, 3, 4, 3, 0, 3].dups).to eq({ 3 => [1, 3, 5] }) 12 | end 13 | 14 | it "returns {} when no dups found" do 15 | expect([1, 3, 4, 5].dups).to eq({}) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /specs/eight_queens_spec.rb: -------------------------------------------------------------------------------- 1 | describe "EightQueens" do 2 | eight_queens = EightQueens.new() 3 | 4 | it "returns the correct number" do 5 | expect(eight_queens.backtrack).to eq(92) 6 | end 7 | 8 | it "calls itself recursively" do 9 | expect(eight_queens).to receive(:backtrack).exactly(1965).times.and_call_original 10 | eight_queens.backtrack 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /specs/exponent_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#exponent" do 2 | it "returns the correct answer for positive exponents" do 3 | expect(exponent(5,3)).to eq(125) 4 | end 5 | 6 | it "returns the correct answer for negative exponents" do 7 | expect(exponent(2, -3)).to eq(1/8.0) 8 | end 9 | 10 | it "returns the correct answer when n is 0" do 11 | expect(exponent(2, 0)).to eq(1) 12 | end 13 | 14 | it "calls itself recursively" do 15 | expect(self).to receive(:exponent).at_least(:twice).and_call_original 16 | exponent(2, 3) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /specs/factorials_rec_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#factorials_rec" do 2 | it "returns first factorial number" do 3 | expect(factorials_rec(1)).to eq([1]) 4 | end 5 | 6 | it "returns first two factorial numbers" do 7 | expect(factorials_rec(2)).to eq([1, 1]) 8 | end 9 | 10 | it "returns many factorials numbers" do 11 | expect(factorials_rec(6)).to eq([1, 1, 2, 6, 24, 120]) 12 | end 13 | 14 | it "calls itself recursively" do 15 | expect(self).to receive(:factorials_rec).at_least(:twice).and_call_original 16 | factorials_rec(6) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /specs/factors_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#factors" do 2 | it "returns the factors of 10 in order" do 3 | expect(factors(10)).to eq([1, 2, 5, 10]) 4 | end 5 | 6 | it "returns just two factors for primes" do 7 | expect(factors(13)).to eq([1, 13]) 8 | end 9 | 10 | it "returns nil for numbers less than zero" do 11 | expect(factors(-5)).to eq(nil) 12 | end 13 | 14 | it "returns [1] when finding factors of 1" do 15 | expect(factors(1)).to eq([1]) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /specs/fibs_sum_spec.rb: -------------------------------------------------------------------------------- 1 | describe '#fibs_sum' do 2 | it 'returns the sum of the first fibonacci number' do 3 | expect(fibs_sum(1)).to eq(1) 4 | end 5 | 6 | it 'returns the sum of the first 2 fibonacci numbers' do 7 | expect(fibs_sum(2)).to eq(2) 8 | end 9 | 10 | it 'returns the sum of the first 6 fibonacci numbers' do 11 | expect(fibs_sum(6)).to eq(20) 12 | end 13 | 14 | it "calls itself recursively" do 15 | expect(self).to receive(:fibs_sum).at_least(:twice).and_call_original 16 | fibs_sum(6) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /specs/first_even_numbers_sum_spec.rb: -------------------------------------------------------------------------------- 1 | # Write a recursive method that returns the sum of the first n even numbers 2 | # recursively. Assume n > 0. 3 | describe '#first_even_numbers_sum' do 4 | it "returns the sum of the first even number" do 5 | expect(first_even_numbers_sum(1)).to eq(2) 6 | end 7 | 8 | it "returns the sum of the first n even numbers" do 9 | expect(first_even_numbers_sum(6)).to eq(42) 10 | end 11 | 12 | it "calls itself recursively" do 13 | expect(self).to receive(:first_even_numbers_sum).at_least(:twice).and_call_original 14 | first_even_numbers_sum(6) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /specs/jumble_sort_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#jumble_sort" do 2 | before(:each) do 3 | expect_any_instance_of(Array).not_to receive(:sort) 4 | expect_any_instance_of(Array).not_to receive(:sort!) 5 | expect_any_instance_of(Array).not_to receive(:sort_by!) 6 | end 7 | 8 | it "defaults to alphabetical order" do 9 | expect(jumble_sort("hello")).to eq("ehllo") 10 | end 11 | 12 | it "takes an alphabet array and sorts by that order" do 13 | alph = ("a".."z").to_a 14 | hello = "hello".chars.uniq 15 | alph -= hello 16 | alphabet = (hello += alph) 17 | 18 | expect(jumble_sort("hello", alphabet)).to eq("hello") 19 | end 20 | 21 | it "sorts by a reversed alphabet" do 22 | reverse = ("a".."z").to_a.reverse 23 | expect(jumble_sort("hello", reverse)).to eq("ollhe") 24 | end 25 | 26 | it "works with an empty string" do 27 | expect(jumble_sort("")).to eq("") 28 | end 29 | 30 | it "works with a string of one item" do 31 | expect(jumble_sort("g")).to eq("g") 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /specs/longest_palindrome_spec.rb: -------------------------------------------------------------------------------- 1 | describe '#longest_palindrome' do 2 | it 'returns false if there is no palindrome longer than two letters' do 3 | expect(longest_palindrome("palindrome")).to eq(false) 4 | end 5 | 6 | it 'returns the correct length of the palindrome' do 7 | expect(longest_palindrome("181847117432")).to eq(6) 8 | end 9 | 10 | it 'returns the correct length for the longest palindrome in the string' do 11 | expect(longest_palindrome("noonminimum")).to eq(5) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /specs/make_better_change_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#make_better_change" do 2 | it "returns the smallest possible array of coins I" do 3 | expect(make_better_change(24, [10,7,1])).to match_array([10,7,7]) 4 | end 5 | 6 | it "returns the smallest possible array of coins II" do 7 | expect(make_better_change(25, [10,7,1])).to match_array([10,7,7,1]) 8 | end 9 | 10 | it "returns the smallest possible array of coins III" do 11 | expect(make_better_change(25, [10,8,7,1])).to match_array([10,8,7]) 12 | end 13 | 14 | it "calls itself recursively" do 15 | expect(self).to receive(:make_better_change).at_least(:twice).and_call_original 16 | make_better_change(25, [10,8,7,1]) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /specs/median_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#median" do 2 | let(:even_array) { [3, 2, 6, 7] } 3 | let(:odd_array) { [3, 2, 6, 7, 1] } 4 | 5 | it "returns nil for the empty array" do 6 | expect([].median).to be_nil 7 | end 8 | 9 | it "returns the element for an array of length 1" do 10 | expect([1].median).to eq(1) 11 | end 12 | 13 | it "returns the median of an odd-length array" do 14 | expect(odd_array.median).to eq(3) 15 | end 16 | 17 | it "returns the median of an even-length array" do 18 | expect(even_array.median).to eq(4.5) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /specs/merge_sort_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#merge_sort" do 2 | let(:array) { [1, 2, 3, 4, 5].shuffle } 3 | 4 | it "works with an empty array" do 5 | expect([].merge_sort).to eq([]) 6 | end 7 | 8 | it "works with an array of one item" do 9 | expect([1].merge_sort).to eq([1]) 10 | end 11 | 12 | before(:each) do 13 | expect_any_instance_of(Array).not_to receive(:sort) 14 | expect_any_instance_of(Array).not_to receive(:sort!) 15 | expect_any_instance_of(Array).not_to receive(:sort_by!) 16 | end 17 | 18 | it "sorts numbers" do 19 | expect(array.merge_sort).to eq([1,2,3,4,5]) 20 | end 21 | 22 | it "will use block if given" do 23 | reversed = array.merge_sort do |num1, num2| 24 | # reverse order 25 | num2 <=> num1 26 | end 27 | expect(reversed).to eq([5, 4, 3, 2, 1]) 28 | end 29 | 30 | it "does not modify original" do 31 | duped_array = array.dup 32 | duped_array.merge_sort 33 | expect(duped_array).to eq(array) 34 | end 35 | 36 | it "calls the merge helper method" do 37 | expect(Array).to receive(:merge).at_least(:once).and_call_original 38 | array.merge_sort 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /specs/my_all_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'Array#my_all' do 2 | let(:arr) { [1,2,3] } 3 | 4 | before(:each) do 5 | expect(arr).not_to receive(:all?) 6 | expect(arr).not_to receive(:dup) 7 | end 8 | 9 | it "returns true if all elements match the block" do 10 | expect(arr.my_all? { |num| num > 0 }).to eq(true) 11 | end 12 | 13 | it "returns false if not all elements match the block" do 14 | expect(arr.my_all? { |num| num > 1 }).to eq(false) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /specs/my_any_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'Array#my_any' do 2 | let(:arr) { [1,2,3] } 3 | 4 | before(:each) do 5 | expect(arr).not_to receive(:any?) 6 | expect(arr).not_to receive(:dup) 7 | end 8 | 9 | it "returns true if any number matches the block" do 10 | expect(arr.my_any? { |num| num > 2 }).to eq(true) 11 | end 12 | 13 | it "returns false if no elementes match the block" do 14 | expect(arr.my_any? { |num| num == 4 }).to eq(false) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /specs/my_each_hash_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Hash#my_each" do 2 | let(:a) { {"a"=> 1, "b" => 2, "c" => 3} } 3 | let(:res) { Array.new } 4 | 5 | before(:each) do 6 | expect(a).not_to receive(:each) 7 | expect(a).not_to receive(:dup) 8 | expect(a).not_to receive(:slice) 9 | expect_any_instance_of(Hash).not_to receive(:each_with_index) 10 | expect_any_instance_of(Hash).not_to receive(:map) 11 | expect_any_instance_of(Hash).not_to receive(:map!) 12 | end 13 | 14 | it "should call the proc on each key value pair" do 15 | a.my_each{ |key, v| v.times{res << key} } 16 | expect(res.sort).to eq(["a","b","b","c","c","c"]) 17 | end 18 | 19 | it "should not modify the hash" do 20 | a.my_each { |key, v| v.times { res << key } } 21 | expect(a).to eq({ "a"=> 1, "b" => 2, "c" => 3 }) 22 | end 23 | 24 | it "should return the original hash" do 25 | expect(a.my_each{ |key, v| v.times { res << key } }).to eq(a) 26 | end 27 | 28 | it "should be chainable" do 29 | a.my_each do |k,v| 30 | v.times { res << k } 31 | end.my_each do |k,v| 32 | v.times { res << k } 33 | end 34 | expect(res).to eq(["a","b","b","c","c","c","a","b","b","c","c","c"]) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /specs/my_each_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_each" do 2 | let(:arr) { [1,2,3] } 3 | let(:res) { Array.new } 4 | 5 | before(:each) do 6 | expect(arr).not_to receive(:each) 7 | expect(arr).not_to receive(:map) 8 | expect(arr).not_to receive(:dup) 9 | expect(arr).not_to receive(:slice) 10 | expect_any_instance_of(Array).not_to receive(:each_with_index) 11 | expect_any_instance_of(Array).not_to receive(:map!) 12 | end 13 | 14 | it "works for blocks" do 15 | arr.my_each { |el| res << 2 * el } 16 | expect(res).to eq([2,4,6]) 17 | end 18 | 19 | it "does not modify original array" do 20 | arr.my_each { |el| res << 2 * el } 21 | expect(arr).to eq([1,2,3]) 22 | end 23 | 24 | it "should return the original array" do 25 | return_val = arr.my_each { |el| el } 26 | expect(return_val).to eq(arr) 27 | end 28 | 29 | it "should be chainable" do 30 | arr.my_each do |el| 31 | res << 2 * el 32 | end.my_each do |el| 33 | res << 3 * el 34 | end 35 | 36 | expect(res).to eq([2,4,6,3,6,9]) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /specs/my_each_with_index_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_each_with_index" do 2 | let(:arr) { [1,2,3] } 3 | let(:res) { Array.new } 4 | 5 | before(:each) do 6 | expect(arr).not_to receive(:each) 7 | expect(arr).not_to receive(:map) 8 | expect(arr).not_to receive(:dup) 9 | expect(arr).not_to receive(:slice) 10 | expect_any_instance_of(Array).not_to receive(:each_with_index) 11 | expect_any_instance_of(Array).not_to receive(:map!) 12 | end 13 | 14 | it "works for blocks that use both the index and element" do 15 | arr.my_each_with_index { |el, i| res << 2 * el + i } 16 | expect(res).to eq([2,5,8]) 17 | end 18 | 19 | it "does not modify the original array" do 20 | arr.my_each_with_index { |el, i| res << el * 2 + i } 21 | expect(arr).to eq([1,2,3]) 22 | end 23 | 24 | it "should return the original array" do 25 | return_val = arr.my_each_with_index { |el, i| el + i } 26 | expect(return_val).to eq(arr) 27 | end 28 | 29 | it "should be chainable" do 30 | arr.my_each_with_index do |el, i| 31 | res << el * 2 + i 32 | end.my_each_with_index do |el, i| 33 | res << el * 2 + i 34 | end 35 | 36 | expect(res).to eq([2,5,8,2,5,8]) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /specs/my_flatten_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_flatten" do 2 | let(:arr) { [1, 2, 3, [4, [5, 6]], [[[7]], 8]] } 3 | 4 | before(:each) do 5 | expect(arr).not_to receive(:flatten) 6 | expect(arr).not_to receive(:flatten!) 7 | end 8 | 9 | it 'flattens arrays correctly' do 10 | expect(arr.my_flatten).to eq([1, 2, 3, 4, 5, 6, 7, 8]) 11 | end 12 | 13 | it 'works on one dimensional arrays' do 14 | expect([1,2,3,4,5].my_flatten).to eq([1,2,3,4,5]) 15 | end 16 | end 17 | 18 | describe "Array#my_controlled_flatten" do 19 | let(:arr) { [1,[2,3], [4,[5]], [[6,[7]]]] } 20 | 21 | before(:each) do 22 | expect(arr).not_to receive(:flatten) 23 | expect(arr).not_to receive(:flatten!) 24 | end 25 | 26 | it "flattens an array the specified number of levels" do 27 | expect(arr.my_controlled_flatten(1)).to eq([1,2,3,4,[5], [6, [7]]]) 28 | end 29 | 30 | it "returns a one dimensional array when invoked without an argument" do 31 | expect(arr.my_controlled_flatten).to eq([1, 2, 3, 4, 5, 6, 7]) 32 | end 33 | 34 | it "works on one dimensional arrays" do 35 | expect([1,2,3,4,5].my_controlled_flatten).to eq([1,2,3,4,5]) 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /specs/my_inject_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'Array#my_inject' do 2 | let(:arr) { [1, 2, 3] } 3 | 4 | before(:each) do 5 | expect_any_instance_of(Array).not_to receive(:inject) 6 | expect_any_instance_of(Array).not_to receive(:reduce) 7 | end 8 | 9 | it 'calls the block passed to it' do 10 | expect do |block| 11 | ["test array"].my_inject(:dummy, &block) 12 | end.to yield_control.once 13 | end 14 | 15 | it 'makes the first element the accumulator if no default is given' do 16 | expect do |block| 17 | ["el1", "el2", "el3"].my_inject(&block) 18 | end.to yield_successive_args(["el1", "el2"], [nil, "el3"]) 19 | end 20 | 21 | it 'yields the accumulator and each element to the block' do 22 | expect do |block| 23 | [1, 2, 3].my_inject(100, &block) 24 | end.to yield_successive_args([100, 1], [nil, 2], [nil, 3]) 25 | end 26 | 27 | it 'with accumulator, it correctly injects and returns answer' do 28 | expect([1, 2, 3].my_inject(1) { |acc, x| acc + x }).to eq(7) 29 | expect([3, 3].my_inject(3) { |acc, x| acc * x }).to eq(27) 30 | end 31 | 32 | it 'without accumulator, it correctly injects and returns answer' do 33 | expect([1, 2, 3].my_inject { |acc, x| acc + x }).to eq(6) 34 | expect([3, 3].my_inject { |acc, x| acc * x }).to eq(9) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /specs/my_join_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_join" do 2 | let(:array) { [ "a", "b", "c", "d" ] } 3 | 4 | before(:each) do 5 | expect_any_instance_of(Array).not_to receive(:join) 6 | end 7 | 8 | it "joins an array if no argument is passed" do 9 | expect(array.my_join).to eq("abcd") 10 | end 11 | 12 | it "joins an array if an argument is passed" do 13 | expect(array.my_join("$")).to eq("a$b$c$d") 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /specs/my_merge_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Hash#my_merge" do 2 | let(:hash1) { {a: 1, b: 2, c: 3} } 3 | let(:hash2) { {d: 4, e: 5} } 4 | let(:hash3) { {c: 33, d: 4, e: 5} } 5 | 6 | before(:each) do 7 | expect(hash1).not_to receive(:merge) 8 | expect(hash1).not_to receive(:merge!) 9 | end 10 | 11 | it "merges 2 hashes and returns a hash" do 12 | expect(hash1.my_merge(hash2)).to eq({ a: 1, b: 2, c: 3, d: 4, e: 5 }) 13 | end 14 | 15 | it "prioritizes values from the hash being merged in" do 16 | expect(hash1.my_merge(hash3)).to eq({ a: 1, b: 2, c: 33, d: 4, e: 5 }) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /specs/my_reject_spec.rb: -------------------------------------------------------------------------------- 1 | describe 'Array#my_reject' do 2 | let(:arr) { [1, 2, 3] } 3 | 4 | before(:each) do 5 | expect(arr).not_to receive(:dup) 6 | expect(arr).not_to receive(:select) 7 | expect_any_instance_of(Array).not_to receive(:reject) 8 | expect_any_instance_of(Array).not_to receive(:reject!) 9 | expect_any_instance_of(Array).not_to receive(:select!) 10 | end 11 | 12 | it 'It correctly selects elements that do not match the passed in block' do 13 | expect(arr.my_reject { |num| num > 1 }).to eq([1]) 14 | end 15 | 16 | it 'It returns all elements if no elements match the block' do 17 | expect(arr.my_reject { |num| num == 4 }).to eq([1,2,3]) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /specs/my_reverse_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_reverse" do 2 | let(:array) { [ "a", "b", "c", "d" ] } 3 | 4 | before(:each) do 5 | expect_any_instance_of(Array).not_to receive(:reverse!) 6 | expect(array).not_to receive(:reverse) 7 | expect(array).not_to receive(:dup) 8 | expect(array).not_to receive(:slice) 9 | expect(array).not_to receive(:slice!) 10 | end 11 | 12 | it "reverses an array" do 13 | expect(array.my_reverse).to eq(["d", "c", "b", "a"]) 14 | end 15 | 16 | it "works on an array of length one" do 17 | expect([1].my_reverse).to eq([1]) 18 | end 19 | 20 | it "works on an empty array" do 21 | expect([].my_reverse).to eq([]) 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /specs/my_rotate_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_rotate" do 2 | let(:arr) {[ "a", "b", "c", "d" ]} 3 | 4 | before (:each) do 5 | expect_any_instance_of(Array).not_to receive(:rotate) 6 | expect_any_instance_of(Array).not_to receive(:rotate!) 7 | end 8 | 9 | it "Rotates the elements 1 position if no argument is passed in" do 10 | expect(arr.my_rotate).to eq(["b", "c", "d", "a"]) 11 | end 12 | 13 | it "Rotates the elements correctly if an argument is passed in" do 14 | expect(arr.my_rotate(2)).to eq(["c", "d", "a", "b"]) 15 | end 16 | 17 | it "Rotates the elements correctly if a negative argument is passed in" do 18 | expect(arr.my_rotate(-3)).to eq(["b", "c", "d", "a"]) 19 | end 20 | 21 | it "Rotates the elements correctly for a large argument" do 22 | expect(arr.my_rotate(15)).to eq(["d", "a", "b", "c"]) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /specs/my_select_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_select" do 2 | let(:arr) { [1, 2, 3] } 3 | 4 | before(:each) do 5 | expect(arr).not_to receive(:select) 6 | expect(arr).not_to receive(:dup) 7 | expect(arr).not_to receive(:slice) 8 | expect_any_instance_of(Array).not_to receive(:select!) 9 | expect_any_instance_of(Array).not_to receive(:reject) 10 | expect_any_instance_of(Array).not_to receive(:reject!) 11 | end 12 | 13 | it "It correctly selects elements according to the passed in block" do 14 | expect(arr.my_select { |num| num > 1 }).to eq([2, 3]) 15 | end 16 | 17 | it "It returns an empty array if there are no matches" do 18 | expect(arr.my_select { |num| num == 4 }).to eq([]) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /specs/my_zip_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_zip" do 2 | let(:arr1) { [ 4, 5, 6 ] } 3 | let(:arr2) { [ 7, 8, 9 ] } 4 | 5 | before(:each) do 6 | expect_any_instance_of(Array).not_to receive(:zip) 7 | end 8 | 9 | it "Zips arrays of the same size" do 10 | expect([1, 2, 3].my_zip(arr1, arr2)).to eq([[1, 4, 7], [2, 5, 8], [3, 6, 9]]) 11 | end 12 | 13 | it "Zips arrays of differnet sizes and adds nil appropriately" do 14 | expect(arr1.my_zip([1,2], [8])).to eq([[4, 1, 8], [5, 2, nil], [6, nil, nil]]) 15 | end 16 | 17 | let(:arr3) { [10, 11, 12] } 18 | let(:arr4) { [13, 14, 15] } 19 | 20 | it "Zips arrays with more elements than the original" do 21 | expect([1, 2].my_zip(arr1, arr2, arr3, arr4)).to eq([[1, 4, 7, 10, 13], [2, 5, 8, 11, 14]]) 22 | expect([].my_zip(arr1, arr2, arr3, arr4)).to eq([]) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /specs/permutations_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#permutations" do 2 | let(:arr) { [1, 2, 3] } 3 | let(:perms) { [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] } 4 | 5 | before(:each) do 6 | expect_any_instance_of(Array).not_to receive(:permutation) 7 | end 8 | 9 | it "works for an empty array" do 10 | expect(permutations([])).to match_array([[]]) 11 | end 12 | 13 | it "works for an array of one item" do 14 | expect(permutations([1])).to match_array([[1]]) 15 | end 16 | 17 | it "returns all permutations of an array" do 18 | expect(permutations(arr)).to match_array(perms) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /specs/pig_latinify_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#pig_latinify" do 2 | it "translates a word beginning with a vowel" do 3 | s = pig_latinify("apple") 4 | expect(s).to eq("appleay") 5 | end 6 | 7 | it "translates a word beginning with a consonant" do 8 | s = pig_latinify("banana") 9 | expect(s).to eq("ananabay") 10 | end 11 | 12 | it "translates a word beginning with two consonants" do 13 | s = pig_latinify("cherry") 14 | expect(s).to eq("errychay") 15 | end 16 | 17 | it "translates two words" do 18 | s = pig_latinify("eat pie") 19 | expect(s).to eq("eatay iepay") 20 | end 21 | 22 | it "translates a word beginning with three consonants" do 23 | expect(pig_latinify("three")).to eq("eethray") 24 | end 25 | 26 | it "counts 'qu' as a single phoneme" do 27 | s = pig_latinify("quiet") 28 | expect(s).to eq("ietquay") 29 | end 30 | 31 | it "counts 'qu' as a consonant even when it's preceded by a consonant" do 32 | s = pig_latinify("square") 33 | expect(s).to eq("aresquay") 34 | end 35 | 36 | it "translates many words" do 37 | s = pig_latinify("the quick brown fox") 38 | expect(s).to eq("ethay ickquay ownbray oxfay") 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /specs/prime_factorization_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#prime_factorization" do 2 | it "handles an input of 2" do 3 | expect(prime_factorization(2)).to eq([2]) 4 | end 5 | 6 | it "correctly calculates the prime factorization of a number" do 7 | expect(prime_factorization(12).sort).to eq([2,2,3]) 8 | end 9 | 10 | it "correctly calculates the prime factorization of a large number" do 11 | expect(prime_factorization(600851475143).sort).to eq([71,839,1471,6857]) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /specs/primes_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#primes" do 2 | it "returns first five primes in order" do 3 | expect(primes(5)).to eq([2, 3, 5, 7, 11]) 4 | end 5 | 6 | it "returns an empty array when asked for zero primes" do 7 | expect(primes(0)).to eq([]) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /specs/quicksort_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#my_quick_sort" do 2 | let(:array) { [1, 2, 3, 4, 5, 6, 7].shuffle } 3 | let(:sorted) { [1, 2, 3, 4, 5, 6, 7] } 4 | 5 | before(:each) do 6 | expect_any_instance_of(Array).not_to receive(:sort) 7 | expect_any_instance_of(Array).not_to receive(:sort!) 8 | expect_any_instance_of(Array).not_to receive(:sort_by!) 9 | end 10 | 11 | it "works with an empty array" do 12 | expect([].my_quick_sort).to eq([]) 13 | end 14 | 15 | it "works with an array of one number" do 16 | expect([5].my_quick_sort).to eq([5]) 17 | end 18 | 19 | it "sorts numbers" do 20 | expect(array.my_quick_sort).to eq(sorted) 21 | end 22 | 23 | it "sorts arrays with duplicates" do 24 | expect([17,10,10,9,3,3,2].my_quick_sort).to eq([2,3,3,9,10,10,17]) 25 | end 26 | 27 | it "will use block if given" do 28 | reversed = array.my_quick_sort do |num1, num2| 29 | num2 <=> num1 30 | end 31 | expect(reversed).to eq([7, 6, 5, 4, 3, 2, 1]) 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /specs/real_words_in_string_spec.rb: -------------------------------------------------------------------------------- 1 | describe "String#real_words_in_string" do 2 | it "finds a simple word" do 3 | words = "asdfcatqwer".real_words_in_string(["cat", "car"]) 4 | expect(words).to eq(["cat"]) 5 | end 6 | 7 | it "doesn't find words not in the dictionary" do 8 | words = "batcabtarbrat".real_words_in_string(["cat", "car"]) 9 | expect(words).to be_empty 10 | end 11 | 12 | it "finds words within words" do 13 | dictionary = ["bears", "ear", "a", "army"] 14 | words = "erbearsweatmyajs".real_words_in_string(dictionary) 15 | expect(words).to match_array(["bears", "ear", "a"]) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /specs/rec_sum_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#rec_sum" do 2 | it "returns the sum of all elements in an array" do 3 | arr = [1,2,3,4] 4 | expect(rec_sum(arr)).to eq(10) 5 | end 6 | 7 | it "returns the sum of all elements in an array" do 8 | expect(rec_sum([-6, 6, 5, 4])).to eq(9) 9 | end 10 | 11 | it "returns 0 if the array is empty" do 12 | expect(rec_sum([])).to eq(0) 13 | end 14 | 15 | it "calls itself recursively" do 16 | expect(self).to receive(:rec_sum).exactly(4).times.and_call_original 17 | rec_sum([1,2,3]) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /specs/string_include_key_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#string_include_key" do 2 | it "returns true for the same string" do 3 | expect(string_include_key?("adblfci", "abc")).to eq(true) 4 | end 5 | 6 | it "handles keys with duplicate characters: case 1" do 7 | expect(string_include_key?("adbblfci", "abbc")).to eq(true) 8 | end 9 | 10 | it "handles keys with duplicate characters: case 2" do 11 | expect(string_include_key?("adbclfci", "abbc")).to eq(false) 12 | end 13 | 14 | it "returns false if the key characters are in the wrong order" do 15 | expect(string_include_key?("dblfcia", "abc")).to eq(false) 16 | end 17 | 18 | it "returns false if the string doesn't contain the key" do 19 | expect(string_include_key?("db", "abc")).to eq(false) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /specs/subsets_spec.rb: -------------------------------------------------------------------------------- 1 | describe '#subsets' do 2 | it "works for an empty array" do 3 | expect(subsets([])).to match_array([[]]) 4 | end 5 | 6 | it "works for an array of one item" do 7 | expect(subsets([1])).to match_array([[], [1]]) 8 | end 9 | 10 | it "returns all subsets of an array" do 11 | expect(subsets([1, 2, 3])).to match_array([[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /specs/symmetric_substrings_spec.rb: -------------------------------------------------------------------------------- 1 | describe "String#symmetric_substrings" do 2 | it "handles a simple example" do 3 | expect("aba".symmetric_substrings).to match_array(["aba"]) 4 | end 5 | 6 | it "handles two substrings" do 7 | expect("aba1cdc".symmetric_substrings).to match_array(["aba", "cdc"]) 8 | end 9 | 10 | it "handles nested substrings" do 11 | expect("xabax".symmetric_substrings).to match_array(["aba", "xabax"]) 12 | end 13 | 14 | it "handles no symmetrical substrings" do 15 | expect("abcd".symmetric_substrings).to match_array([]) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /specs/titleize_spec.rb: -------------------------------------------------------------------------------- 1 | describe "#titleize" do 2 | it "capitalizes a word" do 3 | expect(titleize("jaws")).to eq("Jaws") 4 | end 5 | 6 | it "capitalizes every word (aka title case)" do 7 | expect(titleize("david copperfield")).to eq("David Copperfield") 8 | end 9 | 10 | it "doesn't capitalize 'little words' in a title" do 11 | expect(titleize("war and peace")).to eq("War and Peace") 12 | end 13 | 14 | it "does capitalize 'little words' at the start of a title" do 15 | expect(titleize("the bridge over the river kwai")).to eq("The Bridge over the River Kwai") 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /specs/two_sum_spec.rb: -------------------------------------------------------------------------------- 1 | describe "Array#two_sum" do 2 | it "returns positions of pairs of numbers that add to zero" do 3 | expect([5, 1, -7, -5].two_sum).to eq([[0, 3]]) 4 | end 5 | 6 | it "finds multiple pairs" do 7 | expect([5, -1, -5, 1].two_sum).to eq([[0, 2], [1, 3]]) 8 | end 9 | 10 | it "finds pairs with same element" do 11 | expect([5, -5, -5].two_sum).to eq([[0, 1], [0, 2]]) 12 | end 13 | 14 | it "returns [] when no pair is found" do 15 | expect([5, 5, 3, 1].two_sum).to eq([]) 16 | end 17 | 18 | it "won't find spurious zero pairs" do 19 | expect([0, 1, 2, 3].two_sum).to eq([]) 20 | end 21 | 22 | it "will find real zero pairs" do 23 | expect([0, 1, 2, 0].two_sum).to eq([[0, 3]]) 24 | end 25 | end 26 | --------------------------------------------------------------------------------