diff --git a/solutions/ruby_basics/10_basic_enumerables/.rspec b/solutions/ruby_basics/10_basic_enumerables/.rspec new file mode 100644 index 0000000000..279bfd9e99 --- /dev/null +++ b/solutions/ruby_basics/10_basic_enumerables/.rspec @@ -0,0 +1 @@ +--require spec_helper --format documentation --color diff --git a/solutions/ruby_basics/10_basic_enumerables/exercises/basic_enumerable_exercises.rb b/solutions/ruby_basics/10_basic_enumerables/exercises/basic_enumerable_exercises.rb new file mode 100644 index 0000000000..67b8ca659a --- /dev/null +++ b/solutions/ruby_basics/10_basic_enumerables/exercises/basic_enumerable_exercises.rb @@ -0,0 +1,38 @@ +def display_current_inventory(inventory_list) + # use #each to iterate through each item of the inventory_list (a hash) + # use puts to output each list item ", quantity: " to console + inventory_list.each do |key, value| + puts "#{key}, quantity: #{value}" + end +end + +def display_guess_order(guesses) + # use #each_with_index to iterate through each item of the guesses (an array) + # use puts to output each list item "Guess # is " to console + # hint: the number should start with 1 + guesses.each_with_index do |guess, index| + puts "Guess ##{index + 1} is #{guess}" + end +end + +def find_absolute_values(numbers) + # use #map to iterate through each item of the numbers (an array) + # return an array of absolute values of each number + numbers.map { |number| number.abs } +end + +def find_low_inventory(inventory_list) + # use #select to iterate through each item of the inventory_list (a hash) + # return a hash of items with values less than 4 + inventory_list.select { |_key, value| value < 4 } +end + +def find_word_lengths(word_list) + # use #reduce to iterate through each item of the word_list (an array) + # return a hash with each word as the key and its length as the value + # hint: look at the documentation and review the reduce examples in basic enumerable lesson + word_list.reduce(Hash.new) do |length_hash, word| + length_hash[word] = word.length # This adds the word as the key & its length as the value + length_hash # This is the required return value for each iteration + end +end diff --git a/solutions/ruby_basics/10_basic_enumerables/spec/basic_enumerable_exercises_spec.rb b/solutions/ruby_basics/10_basic_enumerables/spec/basic_enumerable_exercises_spec.rb new file mode 100644 index 0000000000..a0e39bd5a1 --- /dev/null +++ b/solutions/ruby_basics/10_basic_enumerables/spec/basic_enumerable_exercises_spec.rb @@ -0,0 +1,87 @@ +require 'spec_helper' +require_relative '../exercises/basic_enumerable_exercises' + +RSpec.describe 'Basic Enumerable Exercises' do + + describe 'display current inventory exercise' do + + it 'outputs each inventory item' do + expect($stdout).to receive(:puts).with("apples, quantity: 1") + expect($stdout).to receive(:puts).with("bananas, quantity: 3") + expect($stdout).to receive(:puts).with("oranges, quantity: 7") + fruit = { apples: 1, bananas: 3, oranges: 7 } + display_current_inventory(fruit) + end + + # remove the 'x' from the line below to unskip the test + it 'outputs item without quantity when value is nil' do + expect($stdout).to receive(:puts).with("pineapples, quantity: ") + fruit = { pineapples: nil } + display_current_inventory(fruit) + end + end + + describe 'display guess order exercise' do + + it 'outputs each guess of strings in order' do + expect($stdout).to receive(:puts).with("Guess #1 is cookies") + expect($stdout).to receive(:puts).with("Guess #2 is cake") + expect($stdout).to receive(:puts).with("Guess #3 is ice cream") + guesses = ['cookies', 'cake', 'ice cream'] + display_guess_order(guesses) + end + + it 'outputs each guess of integers in order' do + expect($stdout).to receive(:puts).with("Guess #1 is 553") + expect($stdout).to receive(:puts).with("Guess #2 is 554") + expect($stdout).to receive(:puts).with("Guess #3 is 555") + guesses = [553, 554, 555] + display_guess_order(guesses) + end + end + + describe 'find absolute values exercise' do + + it 'returns an array of positive integers' do + numbers = [0, -7, 14, -21] + result = [0, 7, 14, 21] + expect(find_absolute_values(numbers)).to eq(result) + end + + it 'returns an array of positive floating point numbers' do + numbers = [-3.14, 6.28, -9.42] + result = [3.14, 6.28, 9.42] + expect(find_absolute_values(numbers)).to eq(result) + end + end + + describe 'find low inventory exercise' do + + it 'returns a hash with integer values' do + fruit = { apples: 1, peaches: 4, bananas: 3, oranges: 7 } + result = { apples: 1, bananas: 3 } + expect(find_low_inventory(fruit)).to eq(result) + end + + it 'returns a hash with floating point number values' do + cakes = { chocolate_cake: 2.5, vanilla_cake: 4.25, carrot_cake: 3.75 } + result = { chocolate_cake: 2.5, carrot_cake: 3.75 } + expect(find_low_inventory(cakes)).to eq(result) + end + end + + describe 'find word length exercise' do + + it 'returns a hash with rocket syntax when using strings' do + animals = ['cat', 'horse', 'rabbit', 'deer'] + result = { 'cat' => 3, 'horse' => 5, 'rabbit' => 6, 'deer' => 4 } + expect(find_word_lengths(animals)).to eq(result) + end + + it 'returns a hash with symbols syntax when using symbols' do + animals = [:cat, :horse, :rabbit, :deer] + result = { cat: 3, horse: 5, rabbit: 6, deer: 4 } + expect(find_word_lengths(animals)).to eq(result) + end + end +end diff --git a/solutions/ruby_basics/10_basic_enumerables/spec/spec_helper.rb b/solutions/ruby_basics/10_basic_enumerables/spec/spec_helper.rb new file mode 100644 index 0000000000..71b90cde10 --- /dev/null +++ b/solutions/ruby_basics/10_basic_enumerables/spec/spec_helper.rb @@ -0,0 +1,18 @@ +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups +end + +module FormatterOverrides + def dump_pending(_) + end +end + +RSpec::Core::Formatters::DocumentationFormatter.prepend FormatterOverrides diff --git a/solutions/ruby_basics/11_predicate_enumerables/.rspec b/solutions/ruby_basics/11_predicate_enumerables/.rspec new file mode 100644 index 0000000000..279bfd9e99 --- /dev/null +++ b/solutions/ruby_basics/11_predicate_enumerables/.rspec @@ -0,0 +1 @@ +--require spec_helper --format documentation --color diff --git a/solutions/ruby_basics/11_predicate_enumerables/exercises/predicate_enumerable_exercises.rb b/solutions/ruby_basics/11_predicate_enumerables/exercises/predicate_enumerable_exercises.rb new file mode 100644 index 0000000000..f40dc08792 --- /dev/null +++ b/solutions/ruby_basics/11_predicate_enumerables/exercises/predicate_enumerable_exercises.rb @@ -0,0 +1,24 @@ +def coffee_drink?(drink_list) + # use #include? to return true when the drink_list (array) contains the string "coffee" or "espresso" + drink_list.include?("coffee") || drink_list.include?("espresso") +end + +def correct_guess?(guess_list, answer) + # use #any? to return true when any element of the guess_list (array) equals the answer (number) + guess_list.any?(answer) +end + +def twenty_first_century_years?(year_list) + # use #all? to return true when all of the years in the year_list (array) are between 2001 and 2100 + year_list.all? { |year| year.between?(2001, 2100) } +end + +def correct_format?(word_list) + # use #none? to return true when none of the words in the word_list (array) are in upcase + word_list.none? { |word| word == word.upcase } +end + +def valid_scores?(score_list, perfect_score) + # use #one? to return true when only one value in the score_list (hash) is equal to the perfect_score (number) + score_list.one? { |_key, value| value == perfect_score } +end diff --git a/solutions/ruby_basics/11_predicate_enumerables/spec/predicate_enumerable_exercises_spec.rb b/solutions/ruby_basics/11_predicate_enumerables/spec/predicate_enumerable_exercises_spec.rb new file mode 100644 index 0000000000..85786b8745 --- /dev/null +++ b/solutions/ruby_basics/11_predicate_enumerables/spec/predicate_enumerable_exercises_spec.rb @@ -0,0 +1,107 @@ +require 'spec_helper' +require_relative '../exercises/predicate_enumerable_exercises' + +RSpec.describe 'Predicate Enumerable Exercises' do + + describe 'coffee drink exercise' do + + it 'returns true when coffee is included' do + drink_list = ["coffee", "water", "tea"] + expect(coffee_drink?(drink_list)).to be true + end + + # remove the 'x' from the line below to unskip the test + it 'returns true when espresso is included' do + drink_list = ["milk", "juice", "espresso"] + expect(coffee_drink?(drink_list)).to be true + end + + it 'returns false when coffee or espresso is not included' do + drink_list = ["tea", "water", "milk"] + expect(coffee_drink?(drink_list)).to be false + end + + it 'returns false when the list is empty' do + drink_list = [] + expect(coffee_drink?(drink_list)).to be false + end + end + + describe 'correct guess exercise' do + + it 'returns true when the list contains the answer' do + guess_list = [2, 3, 4, 5] + answer = 5 + expect(correct_guess?(guess_list, answer)).to be true + end + + it 'returns false when the list does not contain the answer' do + guess_list = [6, 7, 8, 9] + answer = 5 + expect(correct_guess?(guess_list, answer)).to be false + end + + it 'returns false when the list is empty' do + guess_list = [] + answer = 5 + expect(correct_guess?(guess_list, answer)).to be false + end + end + + describe 'twenty-first century years exercise' do + + it 'returns true when all of the years are between 2001 and 2100' do + year_list = [2001, 2002, 2099, 2100] + expect(twenty_first_century_years?(year_list)).to be true + end + + it 'returns false when some of the years are not between 2001 and 2100' do + year_list = [2000, 2042, 2084, 2101] + expect(twenty_first_century_years?(year_list)).to be false + end + + it 'returns true when the list is empty' do + year_list = [] + expect(twenty_first_century_years?(year_list)).to be true + end + end + + describe 'correct format exercise' do + + it 'returns true when none of the words in the list are in upcase' do + word_list = ["Pepsi", "Coke", "Dr. Pepper"] + expect(correct_format?(word_list)).to be true + end + + it 'returns false when at least one word in the list is in upcase' do + word_list = ["PEPSI", "Coke", "Dr. Pepper"] + expect(correct_format?(word_list)).to be false + end + + it 'returns true when the list is empty' do + word_list = [] + expect(correct_format?(word_list)).to be true + end + end + + describe 'valid scores exercise' do + + it 'returns true when only one score is a 10' do + score_list = { easy_to_read: 10, uses_best_practices: 8, clever: 7 } + perfect_score = 10 + expect(valid_scores?(score_list, perfect_score)).to be true + end + + it 'returns false when more than one score is a 10' do + score_list = { easy_to_read: 10, uses_best_practices: 10, clever: 9 } + perfect_score = 10 + expect(valid_scores?(score_list, perfect_score)).to be false + end + + it 'returns false when the list is empty' do + score_list = {} + perfect_score = 10 + expect(valid_scores?(score_list, perfect_score)).to be false + end + end +end diff --git a/solutions/ruby_basics/11_predicate_enumerables/spec/spec_helper.rb b/solutions/ruby_basics/11_predicate_enumerables/spec/spec_helper.rb new file mode 100644 index 0000000000..71b90cde10 --- /dev/null +++ b/solutions/ruby_basics/11_predicate_enumerables/spec/spec_helper.rb @@ -0,0 +1,18 @@ +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups +end + +module FormatterOverrides + def dump_pending(_) + end +end + +RSpec::Core::Formatters::DocumentationFormatter.prepend FormatterOverrides diff --git a/solutions/ruby_basics/12_nested_collections/.rspec b/solutions/ruby_basics/12_nested_collections/.rspec new file mode 100644 index 0000000000..279bfd9e99 --- /dev/null +++ b/solutions/ruby_basics/12_nested_collections/.rspec @@ -0,0 +1 @@ +--require spec_helper --format documentation --color diff --git a/solutions/ruby_basics/12_nested_collections/exercises/nested_array_exercises.rb b/solutions/ruby_basics/12_nested_collections/exercises/nested_array_exercises.rb new file mode 100644 index 0000000000..b87444b399 --- /dev/null +++ b/solutions/ruby_basics/12_nested_collections/exercises/nested_array_exercises.rb @@ -0,0 +1,68 @@ +def blank_seating_chart(number_of_rows, seats_per_row) + # return a 2d array to represent a seating chart that contains + # number_of_rows nested arrays, each with seats_per_row entries of nil to + # represent that each seat is empty. + + # Example: blank_seating_chart(2, 3) should return: + # [ + # [nil, nil, nil], + # [nil, nil, nil] + # ] + + # NOTE: if one of the nested arrays is changed, the others should **not** + # change with it + Array.new(number_of_rows) { Array.new(seats_per_row) } +end + +def add_seat_to_row(chart, row_index, seat_to_add) + # take a chart (2d array) and add seat_to_add to the end of the row that is + # at row_index index of the chart, then return the chart + chart[row_index].push(seat_to_add) + chart +end + +def add_another_row(chart, row_to_add) + # take a chart and add row_to_add to the end of the chart, + # then return the chart. + chart << row_to_add +end + +def delete_seat_from_row(chart, row_index, seat_index) + # take a chart and delete the seat at seat_index of the row at row_index of + # the chart, then return the chart + + # Hint: explore the ruby docs to find a method for deleting from an array! + chart[row_index].delete_at(seat_index) + chart +end + +def delete_row_from_chart(chart, row_index) + # take a chart and delete the row at row_index of the chart, + # then return the chart + chart.delete_at(row_index) + chart +end + +def count_empty_seats(chart) + # take a chart and return the number of empty (nil) seats in it + + # NOTE: `chart` should **not** be mutated + chart.flatten.count(nil) +end + +def find_favorite(array_of_hash_objects) + # take an array_of_hash_objects and return the hash which has the key/value + # pair :is_my_favorite? => true. If no hash returns the value true to the key + # :is_my_favorite? it should return nil + + # array_of_hash_objects will look something like this: + # [ + # { name: 'Ruby', is_my_favorite?: true }, + # { name: 'JavaScript', is_my_favorite?: false }, + # { name: 'HTML', is_my_favorite?: false } + # ] + + # TIP: there will only be a maximum of one hash in the array that will + # return true to the :is_my_favorite? key + array_of_hash_objects.find { |hash| hash[:is_my_favorite?] } +end diff --git a/solutions/ruby_basics/12_nested_collections/exercises/nested_hash_exercises.rb b/solutions/ruby_basics/12_nested_collections/exercises/nested_hash_exercises.rb new file mode 100644 index 0000000000..f2c52a6e50 --- /dev/null +++ b/solutions/ruby_basics/12_nested_collections/exercises/nested_hash_exercises.rb @@ -0,0 +1,66 @@ +def find_language_information(languages, language_name) + # Take languages (a nested hash) and language_name as a symbol, return the + # value for the language_name key (which will be another hash!) + + # the languages hash will look something like this: + # { + # ruby: { initial_release: 'December 25, 1996', is_beautiful?: true }, + # javascript: { initial_release: 'December 4, 1995', is_beautiful?: false } + # } + languages[language_name] +end + +def add_information_about_language(languages, language_name, info_key, info_value) + # Take languages and add the key/value pair info_key/info_value to the nested + # hash of language_name, then return the updated languages hash + languages[language_name][info_key] = info_value + languages +end + +def add_language(languages, language_name, language_info_value) + # Take languages and add the key/value pair language_name/language_info_value + # to it, then return languages + languages[language_name] = language_info_value + languages +end + +def delete_information_about_language(languages, language_name, info_key) + # Take languages and delete the key/value pair with key info_key from + # language_name, then return languages + languages[language_name].delete(info_key) + languages +end + +def delete_language(languages, language_name) + # Take languages and delete the language_name key/value pair, then return + # languages + languages.delete(language_name) + languages +end + +def find_beautiful_languages(languages) + # Take languages and return a hash containing only languages which have the + # key/value pair { is_beautiful?: true } listed in their information + languages.select do |key, value| + value[:is_beautiful?] == true + end +end + +def find_language_facts(languages, language_name, fact_index = 0) + # Take languages (now with additional facts added to each language with the + # key :facts and value of an array of strings) and return the fact + # language_name has at fact_index of its facts array, or at index 0 if this + # argument is not given + + # the revised languages hash will look something like this: + # { + # ruby: { facts: ['fact 0', 'fact 1'], + # initial_release: 'December 25, 1996', + # is_beautiful?: true }, + + # javascript: { facts: ['fact 0', 'fact 1'], + # initial_release: 'December 4, 1995', + # is_beautiful?: false } + # } + languages.dig(language_name, :facts, fact_index) +end diff --git a/solutions/ruby_basics/12_nested_collections/spec/nested_array_exercises_spec.rb b/solutions/ruby_basics/12_nested_collections/spec/nested_array_exercises_spec.rb new file mode 100644 index 0000000000..a171b41f21 --- /dev/null +++ b/solutions/ruby_basics/12_nested_collections/spec/nested_array_exercises_spec.rb @@ -0,0 +1,137 @@ +require 'spec_helper' +require_relative '../exercises/nested_array_exercises' + +RSpec.describe 'Nested Array Exercises' do + describe 'blank seating chart creation exercise' do + it 'returns a 2d array (chart) containing 2 rows, each containing nil 3 times' do + expected_output = [[nil, nil, nil], [nil, nil, nil]] + expect(blank_seating_chart(2, 3)).to eq(expected_output) + end + + # remove the 'x' from the line below to unskip the test + it 'returns a 2d array (chart) containing 4 arrays, each containing nil 2 times' do + expected_output = [[nil, nil], [nil, nil], [nil, nil], [nil, nil]] + expect(blank_seating_chart(4, 2)).to eq(expected_output) + end + + context 'when one of the rows are changed' do + it "doesn't change the other rows" do + my_array = blank_seating_chart(4, 2) + my_array[2][1] = true + + expect(my_array).to eq([[nil, nil], [nil, nil], [nil, true], [nil, nil]]) + end + end + end + + describe 'add seat to row exercise' do + let(:array) { [[nil, 'Bob', 'Joe'], [nil, nil, 'Bill']] } + + it "returns the array with 'Jack' added to the end of the second row" do + expected_output = [[nil, 'Bob', 'Joe'], [nil, nil, 'Bill', 'Jack']] + expect(add_seat_to_row(array, 1, 'Jack')).to eq(expected_output) + end + + it "returns the array with 'Diane' added to the end of the first row" do + expected_output = [[nil, 'Bob', 'Joe', 'Diane'], [nil, nil, 'Bill']] + expect(add_seat_to_row(array, 0, 'Diane')).to eq(expected_output) + end + end + + describe 'add another row exercise' do + let(:array) { [[nil, 'Bob', 'Joe'], [nil, nil, 'Bill']] } + + it "returns the array with ['Bo', nil, 'Kim'] added as a third row" do + expected_output = [[nil, 'Bob', 'Joe'], [nil, nil, 'Bill'], ['Bo', nil, 'Kim']] + expect(add_another_row(array, ['Bo', nil, 'Kim'])).to eq(expected_output) + end + + it "returns the array with ['Tim', 'Joe', nil] added as a third row" do + expected_output = [[nil, 'Bob', 'Joe'], [nil, nil, 'Bill'], ['Tim', 'Joe', nil]] + expect(add_another_row(array, ['Tim', 'Joe', nil])).to eq(expected_output) + end + end + + describe 'delete seat from row exercise' do + let(:array) { [[nil, 'Bob', 'Joe'], [nil, nil, 'Bill']] } + + it 'returns the array with the second item in the first row deleted' do + expected_output = [[nil, 'Joe'], [nil, nil, 'Bill']] + expect(delete_seat_from_row(array, 0, 1)).to eq(expected_output) + end + + it 'returns the array with the first item in the second row deleted' do + expected_output = [[nil, 'Bob', 'Joe'], [nil, 'Bill']] + expect(delete_seat_from_row(array, 1, 0)).to eq(expected_output) + end + end + + describe 'delete row from chart exercise' do + let(:array) { [[nil, 'Bob'], ['Joe', nil], [nil, 'Bill']] } + + it 'returns the array with the second row deleted' do + expected_output = [[nil, 'Bob'], [nil, 'Bill']] + expect(delete_row_from_chart(array, 1)).to eq(expected_output) + end + + it 'returns the array with the first row deleted' do + expected_output = [['Joe', nil], [nil, 'Bill']] + expect(delete_row_from_chart(array, 0)).to eq(expected_output) + end + end + + describe 'count empty seats exercise' do + let(:array) { [[nil, 'Bob', 'Joe'], [nil, nil, 'Bill']] } + + context "when there are three nil's in the given array" do + it 'returns the number 3' do + expect(count_empty_seats(array)).to eq(3) + end + end + + context "when there are four nil's in the given array" do + let(:array) { [[nil, 'Bob', nil], [nil, nil, 'Bill']] } + + it 'returns the number 4' do + expect(count_empty_seats(array)).to eq(4) + end + end + + it 'does not mutate the original array' do + count_empty_seats(array) + expect(array).to eq([[nil, 'Bob', 'Joe'], [nil, nil, 'Bill']]) + end + end + + describe 'find favorite exercise' do + context 'when Ruby is the favorite' do + let(:array) do + [ + { name: 'JavaScript', is_my_favorite?: false }, + { name: 'Ruby', is_my_favorite?: true }, + { name: 'HTML', is_my_favorite?: false } + ] + end + + it 'returns the hash with the name Ruby' do + expected_output = { name: 'Ruby', is_my_favorite?: true } + expect(find_favorite(array)).to eq(expected_output) + end + end + + context 'when there is no favorite' do + let(:array) do + [ + { name: 'Python', is_my_favorite?: false }, + { name: 'JavaScript', is_my_favorite?: false }, + { name: 'HTML', is_my_favorite?: false } + ] + end + + it 'returns nil' do + expected_output = nil + expect(find_favorite(array)).to eq(expected_output) + end + end + end +end diff --git a/solutions/ruby_basics/12_nested_collections/spec/nested_hash_exercises_spec.rb b/solutions/ruby_basics/12_nested_collections/spec/nested_hash_exercises_spec.rb new file mode 100644 index 0000000000..a2799d70db --- /dev/null +++ b/solutions/ruby_basics/12_nested_collections/spec/nested_hash_exercises_spec.rb @@ -0,0 +1,198 @@ +require 'spec_helper' +require_relative '../exercises/nested_hash_exercises' + +RSpec.describe 'Nested hash exercises' do + describe 'find language information exercise' do + let(:hash) do + { + ruby: { initial_release: 'December 25, 1996', is_beautiful?: true }, + javascript: { initial_release: 'December 4, 1995', is_beautiful?: false } + } + end + + context 'when the given language name is ruby' do + it 'returns the information for ruby' do + expected_output = { initial_release: 'December 25, 1996', is_beautiful?: true } + expect(find_language_information(hash, :ruby)).to eq(expected_output) + end + end + + context 'when the given language name is javascript' do + # remove the 'x' from the line below to unskip the test + it 'returns the information for javascript' do + expected_output = { initial_release: 'December 4, 1995', is_beautiful?: false } + expect(find_language_information(hash, :javascript)).to eq(expected_output) + end + end + end + + describe 'add information about language exercise' do + let(:hash) do + { + ruby: { initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false } + } + end + + it 'adds is_beautiful?: true k/v pair to the ruby nested hash' do + expected_output = { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false } + } + expect(add_information_about_language(hash, :ruby, :is_beautiful?, true)).to eq(expected_output) + end + + it "adds initial_release: 'December 4, 1995', k/v pair to the javascript nested hash" do + expected_output = { + ruby: { initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' } + } + expect(add_information_about_language(hash, :javascript, :initial_release, 'December 4, 1995')).to eq(expected_output) + end + end + + describe 'add language exercise' do + let(:hash) do + { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' } + } + end + + it 'adds a hash about java with the included kv pairs' do + key_to_add = :java + value_to_add = { is_beautiful?: false, initial_release: 'May 23, 1995' } + expected_output = { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' }, + java: { is_beautiful?: false, initial_release: 'May 23, 1995' } + } + expect(add_language(hash, key_to_add, value_to_add)).to eq(expected_output) + end + + it 'adds a hash about python with the included kv pairs' do + key_to_add = :python + value_to_add = { is_beautiful?: false, initial_release: 'Feb 20, 1991' } + expected_output = { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' }, + python: { is_beautiful?: false, initial_release: 'Feb 20, 1991' } + } + expect(add_language(hash, key_to_add, value_to_add)).to eq(expected_output) + end + end + + describe 'delete information about language exercise' do + let(:hash) do + { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' } + } + end + + it 'removes the is_beautiful? k/v pair from the ruby nested hash' do + expected_output = { + ruby: { initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' } + } + expect(delete_information_about_language(hash, :ruby, :is_beautiful?)).to eq(expected_output) + end + + it 'removes the initial_release k/v pair from the javascript nested hash' do + expected_output = { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false } + } + expect(delete_information_about_language(hash, :javascript, :initial_release)).to eq(expected_output) + end + end + + describe 'delete language hash' do + let(:hash) do + { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' } + } + end + + it 'removes the ruby hash' do + expected_output = { + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' } + } + expect(delete_language(hash, :ruby)).to eq(expected_output) + end + + it 'removes the javascript hash' do + expected_output = { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' } + } + expect(delete_language(hash, :javascript)).to eq(expected_output) + end + end + + describe 'find beautiful languages exercise' do + context 'when only ruby is beautiful' do + let(:hash) do + { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: false, initial_release: 'December 4, 1995' }, + python: { is_beautiful?: false, initial_release: 'Feb 20, 1991' } + } + end + + it 'returns a hash with only ruby' do + expected_output = { + ruby: { is_beautiful?: true, initial_release: 'December 25, 1996' } + } + expect(find_beautiful_languages(hash)).to eq(expected_output) + end + end + + context 'when only javascript and python are beautiful (never but lets pretend)' do + let(:hash) do + { + ruby: { is_beautiful?: false, initial_release: 'December 25, 1996' }, + javascript: { is_beautiful?: true, initial_release: 'December 4, 1995' }, + python: { is_beautiful?: true, initial_release: 'Feb 20, 1991' } + } + end + + it 'returns the hash with only javascript and python' do + expected_output = { + javascript: { is_beautiful?: true, initial_release: 'December 4, 1995' }, + python: { is_beautiful?: true, initial_release: 'Feb 20, 1991' } + } + expect(find_beautiful_languages(hash)).to eq(expected_output) + end + end + end + + describe 'find language facts exercise' do + let(:hash) do + { + ruby: { facts: ['was made for programmer happiness', 'its code is beautiful'], + initial_release: 'December 25, 1996', + is_beautiful?: true }, + + javascript: { facts: ['you have to use semicolons everywhere', "its real name isn't even javascript"], + initial_release: 'December 4, 1995', + is_beautiful?: false } + } + end + + it 'returns the first fact for ruby' do + expected_output = 'was made for programmer happiness' + expect(find_language_facts(hash, :ruby)).to eq(expected_output) + end + + it 'returns the second fact for javascript' do + expected_output = "its real name isn't even javascript" + expect(find_language_facts(hash, :javascript, 1)).to eq(expected_output) + end + + it 'returns nil for python' do + expected_output = nil + expect(find_language_facts(hash, :python, 1)).to eq(expected_output) + end + end +end diff --git a/solutions/ruby_basics/12_nested_collections/spec/spec_helper.rb b/solutions/ruby_basics/12_nested_collections/spec/spec_helper.rb new file mode 100644 index 0000000000..71b90cde10 --- /dev/null +++ b/solutions/ruby_basics/12_nested_collections/spec/spec_helper.rb @@ -0,0 +1,18 @@ +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups +end + +module FormatterOverrides + def dump_pending(_) + end +end + +RSpec::Core::Formatters::DocumentationFormatter.prepend FormatterOverrides diff --git a/solutions/ruby_basics/1_data_types/.rspec b/solutions/ruby_basics/1_data_types/.rspec new file mode 100644 index 0000000000..279bfd9e99 --- /dev/null +++ b/solutions/ruby_basics/1_data_types/.rspec @@ -0,0 +1 @@ +--require spec_helper --format documentation --color diff --git a/solutions/ruby_basics/1_data_types/exercises/numbers_exercises.rb b/solutions/ruby_basics/1_data_types/exercises/numbers_exercises.rb new file mode 100644 index 0000000000..c23305d05a --- /dev/null +++ b/solutions/ruby_basics/1_data_types/exercises/numbers_exercises.rb @@ -0,0 +1,44 @@ +def add(a, b) + # return the result of adding a and b + a + b +end + +def subtract(a, b) + # return the result of subtracting b from a + a - b +end + +def multiply(a, b) + # return the result of multiplying a times b + a * b +end + +def divide(a, b) + # return the result of dividing a by b + a / b +end + +def remainder(a, b) + # return the remainder of dividing a by b using the modulo operator + a % b +end + +def float_division(a, b) + # return the result of dividing a by b as a float, rather than an integer + (a / b).to_f +end + +def string_to_number(string) + # return the result of converting a string into an integer + string.to_i +end + +def even?(number) + # return true if the number is even (hint: use integer's even? method) + number.even? +end + +def odd?(number) + # return true if the number is odd (hint: use integer's odd? method) + number.odd? +end diff --git a/solutions/ruby_basics/1_data_types/exercises/string_exercises.rb b/solutions/ruby_basics/1_data_types/exercises/string_exercises.rb new file mode 100644 index 0000000000..d40690bdd9 --- /dev/null +++ b/solutions/ruby_basics/1_data_types/exercises/string_exercises.rb @@ -0,0 +1,49 @@ +def concatenate_example(string) + # use concatenation to format the result to be "Classic " + "Classic " << string +end + +def concatenate(string) + # use concatenation to format the result to be "Hello !" + "Hello " + string + "!" +end + +def substrings(word) + # return the first 4 letters from the word using substrings + word[0, 4] +end + +def capitalize(word) + # capitalize the first letter of the word + word.capitalize +end + +def uppercase(string) + # uppercase all letters in the string + string.upcase +end + +def downcase(string) + # downcase all letters in the string + string.downcase +end + +def empty_string(string) + # return true if the string is empty + string.empty? +end + +def string_length(string) + # return the length of the string + string.length +end + +def reverse(string) + # return the same string, with all of its characters reversed + string.reverse +end + +def space_remover(string) + # remove all the spaces in the string using gsub + string.gsub(' ', '') +end diff --git a/solutions/ruby_basics/1_data_types/spec/numbers_exercises_spec.rb b/solutions/ruby_basics/1_data_types/spec/numbers_exercises_spec.rb new file mode 100644 index 0000000000..56f2d52fa6 --- /dev/null +++ b/solutions/ruby_basics/1_data_types/spec/numbers_exercises_spec.rb @@ -0,0 +1,90 @@ +require 'spec_helper' +require_relative '../exercises/numbers_exercises' + +RSpec.describe 'Numbers Exercises' do + + describe 'addition exercise' do + + it 'adds two positive numbers' do + expect(add(1, 2)).to eq(3) + end + + it 'adds two negative numbers' do + expect(add(-2, -3)).to eq(-5) + end + end + + describe 'subtraction exercise' do + + it 'subtracts two numbers' do + expect(subtract(5, 3)).to eq(2) + end + end + + describe 'multiplication exercise' do + + # remove the 'x' from the line below to unskip the test + it 'multiplies two numbers' do + expect(multiply(5, 5)).to eq(25) + end + end + + describe 'division exercise' do + + it 'divides two numbers' do + expect(divide(25, 5)).to eq(5) + end + end + + describe 'modulus exercise' do + + it 'returns the remainder using modulo' do + expect(remainder(25, 5)).to eq(0) + end + + it 'returns the remainder when it is not 0' do + expect(remainder(13, 5)).to eq(3) + end + end + + describe 'float exercise' do + + it 'returns a float' do + expect(float_division(10, 2)).to eql(5.0) + end + end + + describe 'string to number exercise' do + + it 'returns an integer from a string' do + expect(string_to_number('1')).to eq(1) + end + + it 'returns a negative integer from a string' do + expect(string_to_number('-5')).to eq(-5) + end + end + + describe 'even exercise' do + + it 'returns true when the number is even' do + expect(even?(6)).to eq(true) + end + + it 'returns false when the number is not even' do + expect(even?(5)).to eq(false) + end + end + + describe 'odd exercise' do + + it 'returns true when the number is odd' do + expect(odd?(9)).to eq(true) + end + + it 'returns false when the number is not odd' do + expect(odd?(6)).to eq(false) + end + + end +end diff --git a/solutions/ruby_basics/1_data_types/spec/spec_helper.rb b/solutions/ruby_basics/1_data_types/spec/spec_helper.rb new file mode 100644 index 0000000000..71b90cde10 --- /dev/null +++ b/solutions/ruby_basics/1_data_types/spec/spec_helper.rb @@ -0,0 +1,18 @@ +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups +end + +module FormatterOverrides + def dump_pending(_) + end +end + +RSpec::Core::Formatters::DocumentationFormatter.prepend FormatterOverrides diff --git a/solutions/ruby_basics/1_data_types/spec/strings_exercises_spec.rb b/solutions/ruby_basics/1_data_types/spec/strings_exercises_spec.rb new file mode 100644 index 0000000000..b850112130 --- /dev/null +++ b/solutions/ruby_basics/1_data_types/spec/strings_exercises_spec.rb @@ -0,0 +1,112 @@ +require 'spec_helper' +require_relative '../exercises/string_exercises' + +RSpec.describe 'String Exercises' do + + describe 'concatenation example exercise' do + + it 'returns "Classic Ruby"' do + expect(concatenate_example('Ruby')).to eq('Classic Ruby') + end + end + + describe 'concatenation exercise' do + + it 'returns "Hello world!"' do + expect(concatenate('world')).to eq('Hello world!') + end + + it 'returns "Hello universe!"' do + expect(concatenate('universe')).to eq('Hello universe!') + end + end + + describe 'substrings exercise' do + + it 'returns the first 4 letters of the word' do + expect(substrings('chocolate')).to eq('choc') + end + end + + describe 'capitalizing exercise' do + + it 'capitalizes a word' do + expect(capitalize('paris')).to eq('Paris') + end + + it 'only capitalizes the first word if there are multiple words' do + expect(capitalize('miami in the summer')).to eq('Miami in the summer') + end + + it 'leaves an already capitalized word as is' do + expect(capitalize('London')).to eq('London') + end + end + + describe 'uppercasing exercise' do + + it 'uppercases a word' do + expect(uppercase('small')).to eq('SMALL') + end + + it 'uppercases multiple words' do + expect(uppercase('make me bigger')).to eq('MAKE ME BIGGER') + end + end + + + describe 'downcasing exercise' do + + it 'downcases a word' do + expect(downcase('LARGE')).to eq('large') + end + + it 'downcases multiple words' do + expect(downcase('MAKE ME SMALLER')).to eq('make me smaller') + end + end + + describe 'empty exercise' do + + it 'returns true if string is empty' do + expect(empty_string('')).to eq(true) + end + + it 'returns false if string is not empty' do + expect(empty_string('wow')).to eq(false) + end + end + + describe 'length exercise' do + + it 'returns the length of a word' do + expect(string_length('longitude')).to eq(9) + end + + it 'returns the length of a string with multiple words' do + expect(string_length('i am quite long')).to eq(15) + end + end + + describe 'reverse exercise' do + + it 'reverses a word' do + expect(reverse('desrever')).to eq('reversed') + end + + it 'reverses multiple words' do + expect(reverse('dnuora kcab')).to eq('back around') + end + end + + describe 'remove spaces exercise' do + + it 'removes a single space' do + expect(space_remover('white space')).to eq('whitespace') + end + + it 'removes multiple spaces' do + expect(space_remover('many white spaces')).to eq('manywhitespaces') + end + end +end diff --git a/solutions/ruby_basics/6_arrays/.rspec b/solutions/ruby_basics/6_arrays/.rspec new file mode 100644 index 0000000000..279bfd9e99 --- /dev/null +++ b/solutions/ruby_basics/6_arrays/.rspec @@ -0,0 +1 @@ +--require spec_helper --format documentation --color diff --git a/solutions/ruby_basics/6_arrays/exercises/array_exercises.rb b/solutions/ruby_basics/6_arrays/exercises/array_exercises.rb new file mode 100644 index 0000000000..90232375a9 --- /dev/null +++ b/solutions/ruby_basics/6_arrays/exercises/array_exercises.rb @@ -0,0 +1,73 @@ +def nil_array(number) + # return an array containing `nil` the given number of times + Array.new(number) +end + +def first_element(array) + # return the first element of the array + array.first +end + +def third_element(array) + # return the third element of the array + array[2] +end + +def last_three_elements(array) + # return the last 3 elements of the array + array.last(3) +end + +def add_element(array) + # add an element (of any value) to the array + array << "ruby" +end + +def remove_last_element(array) + # Step 1: remove the last element from the array + array.pop + # Step 2: return the array (because Step 1 returns the value of the element removed) + array +end + +def remove_first_three_elements(array) + # Step 1: remove the first three elements + array.shift(3) + # Step 2: return the array (because Step 1 returns the values of the elements removed) + array +end + +def array_concatenation(original, additional) + # return an array adding the original and additional array together + original + additional +end + +def array_difference(original, comparison) + # return an array of elements from the original array that are not in the comparison array + original - comparison +end + +def empty_array?(array) + # return true if the array is empty + array.empty? +end + +def reverse(array) + # return the reverse of the array + array.reverse +end + +def array_length(array) + # return the length of the array + array.length +end + +def include?(array, value) + # return true if the array includes the value + array.include?(value) +end + +def join(array, separator) + # return the result of joining the array with the separator + array.join(separator) +end diff --git a/solutions/ruby_basics/6_arrays/spec/array_exercises_spec.rb b/solutions/ruby_basics/6_arrays/spec/array_exercises_spec.rb new file mode 100644 index 0000000000..a9ff4c5ecb --- /dev/null +++ b/solutions/ruby_basics/6_arrays/spec/array_exercises_spec.rb @@ -0,0 +1,161 @@ +require 'spec_helper' +require_relative '../exercises/array_exercises' + +RSpec.describe 'Array Exercises' do + describe 'nil array exercise' do + + it 'returns an array containing 5 nil values' do + expect(nil_array(5)).to eq([nil, nil, nil, nil, nil]) + end + + # remove the 'x' from the line below to unskip the test + it 'returns an array containing 2 nil values' do + expect(nil_array(2)).to eq([nil, nil]) + end + end + + describe 'first element exercise' do + + it 'returns the first element of an array of numbers' do + expect(first_element([2, 4, 6, 8, 10])).to eq(2) + end + + it 'returns the first element of an array of strings' do + expect(first_element(['foo', 'bar'])).to eq('foo') + end + end + + describe 'third element exercise' do + + it 'returns the third element of an array of numbers' do + expect(third_element([2, 4, 6, 8, 10])).to eq(6) + end + + it 'returns nil if the array does not have a third element' do + expect(third_element(['foo', 'bar'])).to eq(nil) + end + end + + describe 'last three elements exercise' do + + it 'returns an array of the last three elements' do + expect(last_three_elements([2, 4, 6, 8, 10])).to eq([6, 8, 10]) + end + + it 'returns all of the elements when there are less than 3 elements' do + expect(last_three_elements(['foo', 'bar'])).to eq(['foo', 'bar']) + end + end + + describe 'add element exercise' do + + it 'increases the length of an array by 1' do + numbers = [1, 2, 3, 4] + expect { add_element(numbers) }.to change { numbers.length }.by(1) + end + + it 'increases the length of an empty array by 1' do + data = [] + expect { add_element(data) }.to change { data.length }.by(1) + end + end + + describe 'remove last element exercise' do + + it 'returns the array without the last element' do + expect(remove_last_element([1, 3, 5])).to eq([1, 3]) + end + + it 'returns an empty array when the array only has one element' do + expect(remove_last_element(['foo'])).to eq([]) + end + end + + describe 'remove first three elements exercise' do + + it 'returns the array without the first three elements' do + expect(remove_first_three_elements([1, 3, 5, 7, 9])).to eq([7, 9]) + end + + it 'returns an empty array when the array has less than 3 elements' do + expect(remove_first_three_elements(['foo', 'bar'])).to eq([]) + end + end + + describe 'array concatenation exercise' do + + it 'returns an array adding two arrays of numbers together' do + expect(array_concatenation([1, 3, 5], [2, 4, 6])).to eq([1, 3, 5, 2, 4, 6]) + end + + it 'returns an array adding arrays of strings and numbers together' do + expect(array_concatenation(['a', 'b', 'c'], [1, 2, 3])).to eq(['a', 'b', 'c', 1, 2, 3]) + end + end + + describe 'array difference exercise' do + + it 'returns an array subtracting two arrays of numbers' do + expect(array_difference([0, 1, 1, 2, 3, 5], [0, 1, 2])).to eq([3, 5]) + end + + it 'returns an array subtracting two arrays of strings' do + expect(array_difference(['foo', 'bar', 'baz'], ['bar','hello'])).to eq(['foo', 'baz']) + end + end + + describe 'empty array exercise' do + + it 'returns true when the array is empty' do + expect(empty_array?([])).to be true + end + + it 'returns false when the array is not empty' do + expect(empty_array?([1, 2, 3])).to be false + end + end + + describe 'reverse exercise' do + + it 'returns an array containing the elements in reverse order' do + expect(reverse([0, 1, 1, 2, 3, 5])).to eq([5, 3, 2, 1, 1, 0]) + end + + it 'returns an array containing the element when there is only one' do + expect(reverse(['foo'])).to eq(['foo']) + end + end + + describe 'array length exercise' do + + it 'returns the length of the array' do + expect(array_length([0, 1, 1, 2, 3, 5])).to eq(6) + end + + it 'returns zero when the array is empty' do + expect(array_length([])).to eq(0) + end + end + + describe 'include exercise' do + + it 'returns true when the array contains the specified value' do + expect(include?([0, 1, 1, 2, 3, 5], 3)).to be true + end + + it 'returns false when the array does not contain the specified value' do + expect(include?([0, 1, 1, 2, 3, 5], 8)).to be false + end + end + + describe 'join exercise' do + + it 'returns a string joining an array of numbers with " + "' do + expect(join([0, 1, 1, 2, 3, 5], ' + ')).to eq('0 + 1 + 1 + 2 + 3 + 5') + end + + it 'returns a string joining an array of strings with " "' do + expect(join(['foo', 'bar', 'baz'], ' ')).to eq('foo bar baz') + end + end +end diff --git a/solutions/ruby_basics/6_arrays/spec/spec_helper.rb b/solutions/ruby_basics/6_arrays/spec/spec_helper.rb new file mode 100644 index 0000000000..71b90cde10 --- /dev/null +++ b/solutions/ruby_basics/6_arrays/spec/spec_helper.rb @@ -0,0 +1,18 @@ +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups +end + +module FormatterOverrides + def dump_pending(_) + end +end + +RSpec::Core::Formatters::DocumentationFormatter.prepend FormatterOverrides diff --git a/solutions/ruby_basics/7_hashes/.rspec b/solutions/ruby_basics/7_hashes/.rspec new file mode 100644 index 0000000000..279bfd9e99 --- /dev/null +++ b/solutions/ruby_basics/7_hashes/.rspec @@ -0,0 +1 @@ +--require spec_helper --format documentation --color diff --git a/solutions/ruby_basics/7_hashes/exercises/hash_exercises.rb b/solutions/ruby_basics/7_hashes/exercises/hash_exercises.rb new file mode 100644 index 0000000000..74173924d9 --- /dev/null +++ b/solutions/ruby_basics/7_hashes/exercises/hash_exercises.rb @@ -0,0 +1,45 @@ +def create_favorite_hash(color, number) + # return a hash with the following key/value pairs: + # key of color (as a symbol) with value of the color argument + # key of number (as a symbol) with the value of the number argument + { color: color, number: number } +end + +def favorite_color(favorite_list) + # return the value of the color key + favorite_list[:color] +end + +def favorite_number(favorite_list) + # use #fetch to return the value of the number key or 42 if the key is not found + favorite_list.fetch(:number, 42) +end + +def update_favorite_movie(favorite_list, movie) + # Step 1: add/update the key of movie (as a symbol) + favorite_list[:movie] = movie + # Step 2: return the hash (because Step 1 returns the value of the movie key) + favorite_list +end + +def remove_favorite_number(favorite_list) + # Step 1: delete the number data + favorite_list.delete(:number) + # Step 2: return the hash (because Step 1 returns the value of the number key) + favorite_list +end + +def favorite_categories(favorite_list) + # return the keys of favorite_list + favorite_list.keys +end + +def favorite_items(favorite_list) + # return the values of favorite_list + favorite_list.values +end + +def merge_favorites(original_list, additional_list) + # merge the two hashes: original_list and additional_list + original_list.merge(additional_list) +end diff --git a/solutions/ruby_basics/7_hashes/spec/hash_exercises_spec.rb b/solutions/ruby_basics/7_hashes/spec/hash_exercises_spec.rb new file mode 100644 index 0000000000..0154279221 --- /dev/null +++ b/solutions/ruby_basics/7_hashes/spec/hash_exercises_spec.rb @@ -0,0 +1,140 @@ +require 'spec_helper' +require_relative '../exercises/hash_exercises' + +RSpec.describe 'Hash Exercises' do + describe 'create favorite hash exercise' do + + it 'returns result with a string and integer' do + favorite = create_favorite_hash('blue', 65) + result = { color: 'blue', number: 65 } + expect(favorite).to eq(result) + end + + # remove the 'x' from the line below to unskip the test + it 'returns result with an array and hash' do + favorite = create_favorite_hash(['orange', 'green'], { lucky: 7 }) + result = { color: ['orange', 'green'], number: { lucky: 7 } } + expect(favorite).to eq(result) + end + end + + describe 'favorite color exercise' do + + it 'returns a string' do + my_favorites = { color: 'blue', number: 65 } + expect(favorite_color(my_favorites)).to eq('blue') + end + + it 'returns an array' do + my_favorites = { color: ['orange', 'green'], number: { lucky: 7 } } + expect(favorite_color(my_favorites)).to eq(['orange', 'green']) + end + + it 'returns nil when the key is not found' do + my_favorites = { number: 21, movie: 'Avengers: Endgame' } + expect(favorite_color(my_favorites)).to eq(nil) + end + end + + describe 'favorite number exercise' do + + it 'returns an integer' do + my_favorites = { color: 'blue', number: 65 } + expect(favorite_number(my_favorites)).to eq(65) + end + + it 'returns a hash' do + my_favorites = { color: ['orange', 'green'], number: { lucky: 7 } } + expect(favorite_number(my_favorites)).to eq({ lucky: 7 }) + end + + it 'returns the default number when the key is not found' do + my_favorites = { color: ['orange', 'green'], movie: 'Avengers: Endgame' } + expect(favorite_number(my_favorites)).to eq(42) + end + end + + describe 'update favorite movie exercise' do + + it 'returns hash with a new key/value pair when not included' do + my_favorites = { color: 'blue', number: 65 } + result = { color: 'blue', number: 65, movie: 'Avengers: Endgame' } + expect(update_favorite_movie(my_favorites, 'Avengers: Endgame')).to eq(result) + end + + it 'returns hash with an updated key/value pair when included' do + my_favorites = { color: 'emerald green', movie: 'Avengers: Endgame' } + result = { color: 'emerald green', movie: 'Avengers: Infinity War' } + expect(update_favorite_movie(my_favorites, 'Avengers: Infinity War')).to eq(result) + end + end + + describe 'remove favorite number exercise' do + + it 'returns hash without key/value pair when included' do + my_favorites = { color: 'blue', number: 65, movie: 'Avengers: Endgame' } + result = { color: 'blue', movie: 'Avengers: Endgame' } + expect(remove_favorite_number(my_favorites)).to eq(result) + end + + it 'returns hash when key/value pair is not included' do + my_favorites = { color: 'blue', movie: 'Avengers: Endgame' } + expect(remove_favorite_number(my_favorites)).to eq(my_favorites) + end + end + + describe 'favorite categories exercise' do + + it 'returns an array of the keys' do + my_favorites = { color: 'blue', number: 65, movie: 'Avengers: Endgame' } + expect(favorite_categories(my_favorites)).to eq([:color, :number, :movie]) + end + + it 'returns an empty array when hash is empty' do + my_favorites = {} + expect(favorite_categories(my_favorites)).to eq([]) + end + end + + describe 'favorite items exercise' do + + it 'returns an array with the string and integer values' do + my_favorites = { color: 'blue', number: 65, movie: 'Avengers: Endgame' } + expect(favorite_items(my_favorites)).to eq(['blue', 65, 'Avengers: Endgame']) + end + + it 'returns an array with the array and hash values' do + my_favorites = { color: ['orange', 'green'], number: { lucky: 7 } } + expect(favorite_items(my_favorites)).to eq([['orange', 'green'], { lucky: 7 }]) + end + + it 'returns an empty array when hash is empty' do + my_favorites = {} + expect(favorite_items(my_favorites)).to eq([]) + end + end + + describe 'merge favorites exercise' do + + it 'returns a hash with all key/value pairs when there is not a duplicate' do + my_favorites = { color: 'blue', number: 65 } + favorite_movie = { movie: 'Avengers: Endgame' } + result = { color: 'blue', number: 65, movie: 'Avengers: Endgame' } + expect(merge_favorites(my_favorites, favorite_movie)).to eq(result) + end + + it 'returns a hash with an updated value when there is duplicate' do + my_favorites = { color: 'emerald green', movie: 'Avengers: Endgame' } + favorite_movie = { movie: 'Avengers: Infinity War' } + result = { color: 'emerald green', movie: 'Avengers: Infinity War' } + expect(merge_favorites(my_favorites, favorite_movie)).to eq(result) + end + + it 'returns a hash with all key/value pairs and an updated value when there is duplicate' do + my_favorites = { color: 'teal', number: 65 } + new_favorites = { number: 42, movie: "The Hitchhiker's Guide to the Galaxy" } + result = { color: 'teal', number: 42, movie: "The Hitchhiker's Guide to the Galaxy" } + expect(merge_favorites(my_favorites, new_favorites)).to eq(result) + end + end +end diff --git a/solutions/ruby_basics/7_hashes/spec/spec_helper.rb b/solutions/ruby_basics/7_hashes/spec/spec_helper.rb new file mode 100644 index 0000000000..71b90cde10 --- /dev/null +++ b/solutions/ruby_basics/7_hashes/spec/spec_helper.rb @@ -0,0 +1,18 @@ +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups +end + +module FormatterOverrides + def dump_pending(_) + end +end + +RSpec::Core::Formatters::DocumentationFormatter.prepend FormatterOverrides diff --git a/solutions/ruby_basics/8_methods/.rspec b/solutions/ruby_basics/8_methods/.rspec new file mode 100644 index 0000000000..279bfd9e99 --- /dev/null +++ b/solutions/ruby_basics/8_methods/.rspec @@ -0,0 +1 @@ +--require spec_helper --format documentation --color diff --git a/solutions/ruby_basics/8_methods/exercises/method_exercises.rb b/solutions/ruby_basics/8_methods/exercises/method_exercises.rb new file mode 100644 index 0000000000..3e79bff66f --- /dev/null +++ b/solutions/ruby_basics/8_methods/exercises/method_exercises.rb @@ -0,0 +1,77 @@ +# Since lesson #8 is on methods, you will be writing the entire method. +# To gain more familiarity, look up the documentation for each hint. +# Remember to unskip the corresponding tests one at a time. + +# method name: #ascii_translator +# parameter: number (an integer) +# return value: the number's ASCII character (https://www.ascii-code.com/) +# hint: use Integer#chr +def ascii_translator(number) + number.chr +end + + +# method name: #common_sports +# parameters: current_sports and favorite_sports (both arrays) +# return value: an array containing items in both arrays +# hint: use Array#intersection +def common_sports(current_sports, favorite_sports) + current_sports.intersection(favorite_sports) +end + +# method name: #alphabetical_list +# parameter: games (an array) +# return value: games, alphabetically sorted and duplicates removed +# hint: chain Array#sort and Array#uniq together +def alphabetical_list(games) + games.sort.uniq +end + + +# method name: #lucky_number +# parameter: number (an integer) with default value of 7 +# return value: a string "Today's lucky number is " +def lucky_number(number = 7) + "Today's lucky number is #{number}" +end + + +# method name: #ascii_code +# parameter: character (a string) +# return value: the character's ordinal number +# explicit return value: 'Input Error' if character's length does not equal 1 +# hint: use String#ord +def ascii_code(character) + unless character.length == 1 + return "Input Error" + end + + character.ord +end + + +# method name: #pet_pun +# parameter: animal (a string) +# return value: nil +# console output: if animal is 'cat', 'Cats are purr-fect!' (perfect) +# console output: if animal is 'dog', 'Dogs are paw-some!' (awesome) +# console output: otherwise, "I think s have pet-tential!" (potential) +# hint: use puts +def pet_pun(animal) + if animal == 'cat' + puts 'Cats are purr-fect!' + elsif animal == 'dog' + puts 'Dogs are paw-some!' + else + puts "I think #{animal}s have pet-tential!" + end +end + + +# method name: #twenty_first_century? +# parameter: year (an integer) +# return value: true if the year is between 2001 - 2100, otherwise return false +# hint: use Comparable#between? +def twenty_first_century?(year) + year.between?(2001, 2100) +end diff --git a/solutions/ruby_basics/8_methods/spec/method_exercises_spec.rb b/solutions/ruby_basics/8_methods/spec/method_exercises_spec.rb new file mode 100644 index 0000000000..1f27e18b29 --- /dev/null +++ b/solutions/ruby_basics/8_methods/spec/method_exercises_spec.rb @@ -0,0 +1,118 @@ +require 'spec_helper' +require_relative '../exercises/method_exercises' + +RSpec.describe 'Method Exercises' do + + describe 'ASCII translator exercise using #chr' do + + it 'returns an uppercase A' do + expect(ascii_translator(65)).to eq('A') + end + + # remove the 'x' from the line below to unskip the test + it 'returns a lowercase z' do + expect(ascii_translator(122)).to eq('z') + end + + it 'returns an exclamation mark' do + expect(ascii_translator(33)).to eq('!') + end + end + + describe 'common sports exercise using #intersection' do + + it 'returns the common sports' do + current = ['tennis', 'football', 'baseball'] + favorite = ['baseball', 'tennis', 'basketball'] + expect(common_sports(current, favorite)).to eq(['tennis', 'baseball']) + end + + it 'returns an empty array when there are no common sports' do + current = ['tennis', 'football', 'wrestling'] + favorite = ['baseball', 'basketball'] + expect(common_sports(current, favorite)).to eq([]) + end + end + + describe 'alphabetical list exercise using #sort and #uniq chained' do + + it 'returns an sorted array removing one duplicate' do + games = ['Chess', 'Scrabble', 'Othello', 'Chess'] + expect(alphabetical_list(games)).to eq(['Chess', 'Othello', 'Scrabble']) + end + + it 'returns an sorted array removing multiple duplicates' do + games = ['Monopoly', 'Checkers', 'Risk', 'Checkers', 'Risk', 'Checkers'] + expect(alphabetical_list(games)).to eq(['Checkers', 'Monopoly', 'Risk']) + end + end + + describe 'lucky number exercise using a default parameter' do + + it 'returns a string with the provided argument' do + expect(lucky_number(42)).to eq("Today's lucky number is 42") + end + + it 'returns a string with the default parameter' do + expect(lucky_number).to eq("Today's lucky number is 7") + end + end + + describe 'ASCII code exercise using implicit and explicit return' do + + it 'returns number for uppercase letter' do + expect(ascii_code('A')).to eq(65) + end + + it 'returns number for lowercase letter' do + expect(ascii_code('z')).to eq(122) + end + + it 'returns input error when there is less than one character' do + expect(ascii_code('')).to eq('Input Error') + end + + it 'returns input error when there is more than one character' do + expect(ascii_code('word')).to eq('Input Error') + end + end + + describe 'pet pun exercise using console output' do + + it 'returns nil' do + allow($stdout).to receive(:puts).with("Cats are purr-fect!") + expect(pet_pun('cat')).to be nil + end + + it 'outputs the cat pun' do + expect { pet_pun('cat') }.to output("Cats are purr-fect!\n").to_stdout + end + + it 'outputs the dog pun' do + expect { pet_pun('dog') }.to output("Dogs are paw-some!\n").to_stdout + end + + it 'outputs the default pet pun' do + expect { pet_pun('rabbit') }.to output("I think rabbits have pet-tential!\n").to_stdout + end + end + + describe 'twenty-first century predicate exercise' do + + it 'returns true when the year is between 2001 - 2100' do + expect(twenty_first_century?(2024)).to be true + end + + it 'returns true when the year is 2001' do + expect(twenty_first_century?(2001)).to be true + end + + it 'returns true when the year is 2100' do + expect(twenty_first_century?(2100)).to be true + end + + it 'returns false when the year is not between 2001 - 2100' do + expect(twenty_first_century?(1999)).to be false + end + end +end diff --git a/solutions/ruby_basics/8_methods/spec/spec_helper.rb b/solutions/ruby_basics/8_methods/spec/spec_helper.rb new file mode 100644 index 0000000000..71b90cde10 --- /dev/null +++ b/solutions/ruby_basics/8_methods/spec/spec_helper.rb @@ -0,0 +1,18 @@ +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups +end + +module FormatterOverrides + def dump_pending(_) + end +end + +RSpec::Core::Formatters::DocumentationFormatter.prepend FormatterOverrides diff --git a/solutions/ruby_basics/9_debugging/.rspec b/solutions/ruby_basics/9_debugging/.rspec new file mode 100644 index 0000000000..80dda815b9 --- /dev/null +++ b/solutions/ruby_basics/9_debugging/.rspec @@ -0,0 +1 @@ +--require spec_helper --format documentation --color \ No newline at end of file diff --git a/solutions/ruby_basics/9_debugging/exercises/debugging_exercises.rb b/solutions/ruby_basics/9_debugging/exercises/debugging_exercises.rb new file mode 100644 index 0000000000..cb303853b0 --- /dev/null +++ b/solutions/ruby_basics/9_debugging/exercises/debugging_exercises.rb @@ -0,0 +1,58 @@ +require 'pry-byebug' + +# First, we're going to practice reading the Stack Trace +# Don't look at this method prior to running the test +# Type 'rspec' into the terminal to run Rspec +# Once this test fails, have a look at the Stack Trace +# Try to see if you can work your way from the last line, the bottom of the stack +# To the top, the first line, where the error occured, and ONLY THEN fix the error + +def decrement_smallest_value(nested_array) + smallest_value = nested_array.flatten.max + nested_array.each do |array| + array.each do |current_value| + if smallest_value > current_value + smallest_value = current_value + end + end + end + smallest_value -= 1 +end + +# use the stack trace to debug the following method +# Don't look at this method prior to running the test +# Run rspec, let the test fail, and go through the stack trace again +def increment_greatest_value(nested_array) + greatest_value = nested_array.flatten.min + nested_array.each do |array| + array.each do |current_value| + if greatest_value < current_value + greatest_value = current_value + end + end + end + greatest_value += 1 +end + +# This next exercise might look familiar +# Use p and puts in order to find what's wrong with our method + +def isogram?(string) + original_length = string.length + string_array = string.downcase.split('') + unique_length = string_array.uniq.length + original_length == unique_length +end + +# Can you guess what's next? +# That's right! The final exercise from the lesson, which we'll debug with pry-byebug +# Try to avoid looking at the problem too much, let's rely on pry to fix it +# First, include require 'pry-byebug' at the top of this page +# Next insert plenty of breakpoints, and see if you can tell where things break +# Once you find the error, fix it and get the test to pass + +def yell_greeting(string) + name = string + name = name.upcase + greeting = "WASSAP, #{name}!" +end diff --git a/solutions/ruby_basics/9_debugging/spec/debugging_exercises_spec.rb b/solutions/ruby_basics/9_debugging/spec/debugging_exercises_spec.rb new file mode 100644 index 0000000000..ae900c166a --- /dev/null +++ b/solutions/ruby_basics/9_debugging/spec/debugging_exercises_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' +require_relative '../exercises/debugging_exercises' + +RSpec.describe 'Debugging Exercises' do + describe 'decrement_smallest_value' do + + # remove the 'x' from the line below to unskip the test + it 'Returns 0 after you use the stack trace to find and fix the error' do + nested_array = [[3, 4], [1, 2]] + + smallest_value_decremented = decrement_smallest_value(nested_array) + + expect(smallest_value_decremented).to eq(0) + end + end + + describe 'increment_greatest_value' do + + # remove the 'x' from the line below to unskip the test + it 'Returns 5 after you use the stack trace to find and fix the error' do + nested_array = [[3, 4], [1, 2]] + + greatest_value_incremented = increment_greatest_value(nested_array) + + expect(greatest_value_incremented).to eq(5) + end + end + + describe 'isogram' do + + # remove the 'x' from the line below to unskip the test + it 'Returns true after you use puts to fix the method, since Odin is an isogram' do + + expect(isogram?("Odin")).to be true + end + end + + describe 'yell_greeting' do + + # remove the 'x' from the line below to unskip the test + it 'Returns "WASSAP, BOB!" after you use pry-byebug to fix the method' do + + expect(yell_greeting("Bob")).to eq("WASSAP, BOB!") + end + end +end diff --git a/solutions/ruby_basics/9_debugging/spec/spec_helper.rb b/solutions/ruby_basics/9_debugging/spec/spec_helper.rb new file mode 100644 index 0000000000..a7dcad1238 --- /dev/null +++ b/solutions/ruby_basics/9_debugging/spec/spec_helper.rb @@ -0,0 +1,20 @@ + +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups +end + +module FormatterOverrides + def dump_pending(_) + end +end + +RSpec::Core::Formatters::DocumentationFormatter.prepend FormatterOverrides \ No newline at end of file diff --git a/solutions/ruby_basics/README.md b/solutions/ruby_basics/README.md new file mode 100644 index 0000000000..9896d50579 --- /dev/null +++ b/solutions/ruby_basics/README.md @@ -0,0 +1,50 @@ +# Ruby Basics Exercises +These exercises are designed to complement the [Ruby Basic lessons](https://www.theodinproject.com/paths/full-stack-ruby-on-rails/courses/ruby#basic-ruby) on [The Odin Project](https://www.theodinproject.com/). Each folder contains exercises and specs (tests) for the lessons in the Ruby Basics section. + +### Usage + +1. First change directory into the lesson directory, for example `cd 1_data_types`. +2. Run the tests for an exercise file, for example `bundle exec rspec spec/numbers_exercises_spec.rb`. The first test will fail and the rest will be skipped. +3. Open that corresponding exercise file in your text editor, in this case the `exercises/numbers_exercises.rb` file. +4. Write the code to get the failing test to pass in the exercise file and run the tests again to verify it passes. +5. Each `exercises` folder has a corresponding `spec` folder with matching test files. For instance, you can find the tests for `exercises/numbers_exercises.rb` in `spec/numbers_exercises_spec.rb`. Find and open the matching spec file. +6. Unskip the next test by removing the `x` from `xit`. +7. Run your tests again `bundle exec rspec spec/numbers_exercises_spec.rb` the second test should now be failing. +8. Repeat the steps from step 2 until no more tests are skipped and all are passing. + +**TIP**: When there is only one exercise file in a directory (such as in `6_arrays`) you can omit the path to the file and just enter `bundle exec rspec` to run the tests in that file. + +### Contents + +#### 1.Basic Data Types + +- [ ] Numbers Exercises +- [ ] Strings Exercises + +#### 6.Arrays + +- [ ] Array Exercises + +#### 7.Hashes + +- [ ] Hash Exercises + +#### 8.Methods + +- [ ] Method Exercises + +#### 9.Debugging + +- [ ] Debugging Exercises + +#### 10.Basic Enumerables + +- [ ] Basic Enumerable Exercises + +#### 11.Predicate Enumerables + +- [ ] Predicate Enumerable Exercises + +#### 12.Nested Collections + +- [ ] Nested Collection Exercises