Ruby Coding Problems Interview Questions and Answers
Practice commonly asked Ruby coding problems with detailed solutions. Covers arrays, strings, hashes, and algorithms with time complexity analysis.
📋 Jump to Question
Ruby Coding Interview Questions - Beginner to Intermediate
Table of Contents
- Array Flattening
- Hash Flattening
- Nil Removal
- Array Reversal
- Finding Maximum Elements
- Finding Second Largest
- Duplicate Removal
- Array Merging
- Array Rotation
- Finding Pairs
- Moving Zeroes
- Array Intersection
- Frequency Counting
- Additional Array Problems
- String Problems
- Hash Problems
- Number Problems
1. Array Flattening
Q1: Flatten a nested array without using the built-in flatten method
Explanation: This recursive solution traverses the array and flattens any nested arrays it encounters. The base case is when an element is not an array - we simply add it to the result. When we encounter an array, we recursively flatten it and concatenate the results.
def custom_flatten(array)
result = []
array.each do |element|
if element.is_a?(Array)
# Recursively flatten the nested array and add all its elements
result += custom_flatten(element)
else
# Add non-array elements directly
result << element
end
end
result
end
# Example usage:
nested_array = [1, [2, [3, 4], 5], 6]
puts custom_flatten(nested_array).inspect #=> [1, 2, 3, 4, 5, 6]
# Test with different nesting levels
puts custom_flatten([1, [2, 3], [[4, 5], 6]]).inspect #=> [1, 2, 3, 4, 5, 6]
puts custom_flatten([]).inspect #=> []
puts custom_flatten([1, 2, 3]).inspect #=> [1, 2, 3]
Time Complexity: O(n) where n is total number of elements Space Complexity: O(n) for the result array
Q2: Flatten an array iteratively (without recursion)
Explanation: An iterative approach using a stack. This avoids recursion depth limitations for very deeply nested arrays.
def iterative_flatten(array)
result = []
stack = array.dup
while !stack.empty?
element = stack.shift
if element.is_a?(Array)
# Prepend array elements to stack (to maintain order)
stack = element + stack
else
result << element
end
end
result
end
puts iterative_flatten([1, [2, [3, 4], 5], 6]).inspect #=> [1, 2, 3, 4, 5, 6]
2. Hash Flattening
Q3: Flatten a nested hash with dot notation for keys
Explanation: This recursive solution traverses a nested hash and creates a flat hash where nested keys are represented with dot notation (e.g., "parent.child.grandchild").
def flatten_hash(hash, parent_key = nil, result = {})
hash.each do |key, value|
current_key = parent_key ? "#{parent_key}.#{key}" : key.to_s
if value.is_a?(Hash)
# Recursively flatten nested hash
flatten_hash(value, current_key, result)
else
# Store non-hash values with their flattened key
result[current_key] = value
end
end
result
end
# Example usage:
nested_hash = {a: 1, b: {c: 2, d: {e: 3}}}
puts flatten_hash(nested_hash).inspect
#=> {"a"=>1, "b.c"=>2, "b.d.e"=>3}
# More complex example
complex_hash = {
user: {
name: "John",
address: {
city: "NYC",
zip: 10001
},
contacts: {
email: "john@example.com",
phone: "123-456-7890"
}
},
meta: { version: 1 }
}
puts flatten_hash(complex_hash).inspect
#=> {"user.name"=>"John", "user.address.city"=>"NYC", "user.address.zip"=>10001,
# "user.contacts.email"=>"john@example.com", "user.contacts.phone"=>"123-456-7890",
# "meta.version"=>1}
Time Complexity: O(n) where n is total number of key-value pairs Space Complexity: O(n) for the result hash
Q4: Flatten hash with custom delimiter
Explanation: Enhanced version that allows custom delimiter between nested keys.
def flatten_hash_with_delimiter(hash, parent_key = nil, delimiter = '.', result = {})
hash.each do |key, value|
current_key = parent_key ? "#{parent_key}#{delimiter}#{key}" : key.to_s
if value.is_a?(Hash)
flatten_hash_with_delimiter(value, current_key, delimiter, result)
else
result[current_key] = value
end
end
result
end
puts flatten_hash_with_delimiter(nested_hash, nil, '/').inspect
#=> {"a"=>1, "b/c"=>2, "b/d/e"=>3}
3. Nil Removal
Q5: Remove nil values from an array without using compact
Explanation: Several approaches to filter out nil values from an array.
# Method 1: Using each_with_object
def remove_nils(array)
array.each_with_object([]) do |element, result|
result << element unless element.nil?
end
end
# Method 2: Using reject (elegant, but uses built-in)
def remove_nils_reject(array)
array.reject { |x| x.nil? }
end
# Method 3: Manual iteration
def remove_nils_manual(array)
result = []
array.each { |element| result << element if element }
result
end
# Method 4: Using select with non-nil condition
def remove_nils_select(array)
array.select { |x| !x.nil? }
end
# Example usage:
array_with_nils = [1, nil, 2, nil, 3, nil, nil, 4]
puts remove_nils(array_with_nils).inspect #=> [1, 2, 3, 4]
# Compact version (for comparison)
puts array_with_nils.compact.inspect #=> [1, 2, 3, 4]
Time Complexity: O(n) Space Complexity: O(n)
Q6: Remove nil and false values
Explanation: Sometimes we want to remove both nil and false values.
def remove_nil_and_false(array)
array.select { |element| element != nil && element != false }
end
# Or more concisely
def remove_falsy(array)
array.select { |element| element }
end
mixed_array = [1, nil, false, 2, true, 3, nil]
puts remove_falsy(mixed_array).inspect #=> [1, 2, true, 3]
4. Array Reversal
Q7: Reverse an array without using built-in reverse
Explanation: Multiple approaches to reverse an array manually.
# Method 1: Using unshift
def reverse_array_manual(arr)
reversed = []
arr.each { |element| reversed.unshift(element) }
reversed
end
# Method 2: Using indices
def reverse_array_indices(arr)
reversed = []
(arr.length - 1).downto(0) do |i|
reversed << arr[i]
end
reversed
end
# Method 3: In-place reversal
def reverse_in_place!(arr)
left = 0
right = arr.length - 1
while left < right
arr[left], arr[right] = arr[right], arr[left]
left += 1
right -= 1
end
arr
end
# Method 4: Using inject
def reverse_inject(arr)
arr.inject([]) { |reversed, element| reversed.unshift(element) }
end
# Example usage:
original = [1, 2, 3, 4, 5]
puts reverse_array_manual(original).inspect #=> [5, 4, 3, 2, 1]
puts reverse_array_indices(original).inspect #=> [5, 4, 3, 2, 1]
# In-place modifies original
arr = [1, 2, 3, 4, 5]
reverse_in_place!(arr)
puts arr.inspect #=> [5, 4, 3, 2, 1]
Time Complexity: O(n) Space Complexity: O(n) for new array methods, O(1) for in-place
5. Finding Maximum Elements
Q8: Find the maximum element without using max
Explanation: Manual approaches to find the maximum value in an array.
# Method 1: Simple iteration
def find_max_manual(arr)
return nil if arr.empty?
max = arr.first
arr.each { |num| max = num if num > max }
max
end
# Method 2: Using reduce
def find_max_reduce(arr)
arr.reduce { |max, num| num > max ? num : max }
end
# Method 3: Using sort (inefficient but possible)
def find_max_sort(arr)
arr.sort.last
end
# Example usage:
numbers = [3, 7, 2, 9, 1, 5]
puts find_max_manual(numbers) #=> 9
puts find_max_reduce(numbers) #=> 9
puts find_max_sort(numbers) #=> 9
# Edge cases
puts find_max_manual([]).inspect #=> nil
puts find_max_manual([5]).inspect #=> 5
Time Complexity: O(n) Space Complexity: O(1)
Q9: Find maximum and minimum simultaneously
Explanation: Finding both max and min in a single pass.
def find_min_max(arr)
return [nil, nil] if arr.empty?
min = max = arr.first
arr.each do |num|
min = num if num < min
max = num if num > max
end
[min, max]
end
numbers = [3, 7, 2, 9, 1, 5]
min, max = find_min_max(numbers)
puts "Min: #{min}, Max: #{max}" #=> Min: 1, Max: 9
6. Finding Second Largest
Q10: Find the second largest number without sorting
Explanation: Multiple approaches to find the second largest element.
# Method 1: Using uniq and sort (simple)
def second_largest_sort(arr)
return nil if arr.size < 2
arr.uniq.sort[-2]
end
# Method 2: Single pass (more efficient)
def second_largest_manual(arr)
return nil if arr.size < 2
largest = -Float::INFINITY
second = -Float::INFINITY
arr.each do |num|
if num > largest
second = largest
largest = num
elsif num > second && num < largest
second = num
end
end
second == -Float::INFINITY ? nil : second
end
# Method 3: With negative numbers handling
def second_largest_with_negatives(arr)
return nil if arr.size < 2
arr = arr.uniq
return nil if arr.size < 2
arr.sort[-2]
end
# Example usage:
numbers = [3, 7, 2, 9, 1, 5]
puts second_largest_manual(numbers) #=> 7
puts second_largest_sort(numbers) #=> 7
# With duplicates
numbers_with_dupes = [5, 5, 5, 3, 3, 8]
puts second_largest_manual(numbers_with_dupes) #=> 5
puts second_largest_sort(numbers_with_dupes) #=> 5
Time Complexity: O(n) for manual, O(n log n) for sort Space Complexity: O(1) for manual, O(n) for sort with uniq
Q11: Find nth largest element
Explanation: Generalized solution for finding the nth largest element.
def nth_largest(arr, n)
return nil if arr.size < n || n < 1
arr.uniq.sort[-n]
end
puts nth_largest([3, 7, 2, 9, 1, 5], 3) #=> 5 (3rd largest)
puts nth_largest([3, 7, 2, 9, 1, 5], 1) #=> 9 (1st largest)
puts nth_largest([3, 7, 2, 9, 1, 5], 6) #=> 1 (6th largest)
7. Duplicate Removal
Q12: Remove duplicates without using uniq
Explanation: Manual approaches to remove duplicate elements.
# Method 1: Using a hash (most efficient)
def remove_duplicates_hash(arr)
result = []
seen = {}
arr.each do |element|
unless seen[element]
result << element
seen[element] = true
end
end
result
end
# Method 2: Using array inclusion (slower for large arrays)
def remove_duplicates_include(arr)
result = []
arr.each do |element|
result << element unless result.include?(element)
end
result
end
# Method 3: Using Set
require 'set'
def remove_duplicates_set(arr)
arr.to_set.to_a
end
# Example usage:
duplicates = [1, 2, 2, 3, 4, 4, 4, 5]
puts remove_duplicates_hash(duplicates).inspect #=> [1, 2, 3, 4, 5]
puts remove_duplicates_include(duplicates).inspect #=> [1, 2, 3, 4, 5]
# Maintain order of first occurrence
mixed = [3, 1, 2, 1, 3, 4]
puts remove_duplicates_hash(mixed).inspect #=> [3, 1, 2, 4]
Time Complexity: O(n) for hash method, O(n²) for include method Space Complexity: O(n)
Q13: Remove duplicates while keeping count
Explanation: Not just removing duplicates but tracking how many times each appeared.
def remove_duplicates_with_count(arr)
counts = Hash.new(0)
arr.each { |element| counts[element] += 1 }
{
unique_elements: counts.keys,
element_counts: counts,
duplicates: counts.select { |_, count| count > 1 }.keys
}
end
result = remove_duplicates_with_count([1, 2, 2, 3, 3, 3, 4])
puts result[:unique_elements].inspect #=> [1, 2, 3, 4]
puts result[:element_counts].inspect #=> {1=>1, 2=>2, 3=>3, 4=>1}
puts result[:duplicates].inspect #=> [2, 3]
8. Array Merging
Q14: Merge two sorted arrays
Explanation: Multiple approaches to merge sorted arrays.
# Method 1: Simple concatenation and sort (not optimal for large arrays)
def merge_sorted_simple(arr1, arr2)
(arr1 + arr2).sort
end
# Method 2: Manual merge (O(n+m) - optimal for sorted inputs)
def merge_sorted_manual(arr1, arr2)
merged = []
i = j = 0
while i < arr1.length && j < arr2.length
if arr1[i] <= arr2[j]
merged << arr1[i]
i += 1
else
merged << arr2[j]
j += 1
end
end
# Add remaining elements
merged.concat(arr1[i..-1]) if i < arr1.length
merged.concat(arr2[j..-1]) if j < arr2.length
merged
end
# Method 3: Using built-in merge (if we could use Ruby's features)
def merge_sorted_builtin(arr1, arr2)
arr1.merge(arr2) # Only works with hashes, not arrays
end
# Example usage:
arr1 = [1, 3, 5, 7]
arr2 = [2, 4, 6, 8]
puts merge_sorted_manual(arr1, arr2).inspect #=> [1, 2, 3, 4, 5, 6, 7, 8]
# With duplicates
arr3 = [1, 2, 3]
arr4 = [2, 3, 4]
puts merge_sorted_manual(arr3, arr4).inspect #=> [1, 2, 2, 3, 3, 4]
Time Complexity: O(n+m) for manual merge Space Complexity: O(n+m)
Q15: Merge multiple sorted arrays
Explanation: Extending to merge any number of sorted arrays.
def merge_multiple_sorted(arrays)
# Flatten and sort is simple but not optimal
arrays.flatten.sort
# More efficient would be to use a priority queue
# This is a simplified version
result = []
indices = [0] * arrays.length
loop do
# Find minimum among current elements
min_val = nil
min_idx = nil
arrays.each_with_index do |arr, i|
next if indices[i] >= arr.length
current = arr[indices[i]]
if min_val.nil? || current < min_val
min_val = current
min_idx = i
end
end
break if min_idx.nil?
result << min_val
indices[min_idx] += 1
end
result
end
arrays = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
puts merge_multiple_sorted(arrays).inspect #=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
9. Array Rotation
Q16: Rotate array left by k positions
Explanation: Multiple approaches to rotate an array.
# Method 1: Using built-in rotate
def rotate_left(arr, k)
arr.rotate(k)
end
# Method 2: Manual rotation
def rotate_left_manual(arr, k)
k = k % arr.length # Handle k > array length
arr[k..-1] + arr[0...k]
end
# Method 3: In-place rotation
def rotate_left_in_place!(arr, k)
k = k % arr.length
return arr if k == 0
# Reverse entire array
reverse!(arr, 0, arr.length - 1)
# Reverse first part
reverse!(arr, 0, arr.length - k - 1)
# Reverse second part
reverse!(arr, arr.length - k, arr.length - 1)
arr
end
def reverse!(arr, start, finish)
while start < finish
arr[start], arr[finish] = arr[finish], arr[start]
start += 1
finish -= 1
end
end
# Example usage:
arr = [1, 2, 3, 4, 5]
puts rotate_left_manual(arr, 2).inspect #=> [3, 4, 5, 1, 2]
puts rotate_left_manual(arr, 7).inspect #=> [3, 4, 5, 1, 2] (7 % 5 = 2)
# In-place rotation
arr2 = [1, 2, 3, 4, 5]
rotate_left_in_place!(arr2, 2)
puts arr2.inspect #=> [3, 4, 5, 1, 2]
Time Complexity: O(n) Space Complexity: O(n) for new array, O(1) for in-place
Q17: Rotate array right by k positions
Explanation: Right rotation is the complement of left rotation.
def rotate_right(arr, k)
k = k % arr.length
arr[-k..-1] + arr[0...-k]
end
arr = [1, 2, 3, 4, 5]
puts rotate_right(arr, 2).inspect #=> [4, 5, 1, 2, 3]
# Using left rotation
def rotate_right_via_left(arr, k)
k = k % arr.length
rotate_left_manual(arr, arr.length - k)
end
puts rotate_right_via_left(arr, 2).inspect #=> [4, 5, 1, 2, 3]
10. Finding Pairs
Q18: Find all pairs that sum to a target
Explanation: Multiple approaches to find pairs with a given sum.
# Method 1: Using combination (simple but O(n²))
def find_pairs_combination(arr, target)
arr.combination(2).select { |a, b| a + b == target }
end
# Method 2: Using hash set (more efficient)
def find_pairs_hash(arr, target)
pairs = []
seen = {}
arr.each do |num|
complement = target - num
if seen[complement]
pairs << [complement, num]
end
seen[num] = true
end
pairs
end
# Method 3: Find all unique pairs
def find_unique_pairs(arr, target)
arr.combination(2)
.select { |a, b| a + b == target }
.map(&:sort)
.uniq
end
# Example usage:
numbers = [1, 2, 3, 4, 5]
puts find_pairs_hash(numbers, 6).inspect #=> [[1, 5], [2, 4]]
# With duplicates
numbers_with_dupes = [1, 1, 2, 3, 3, 4]
puts find_unique_pairs(numbers_with_dupes, 5).inspect #=> [[1, 4], [2, 3]]
Time Complexity: O(n) with hash, O(n²) with combination Space Complexity: O(n)
Q19: Find pairs with difference k
Explanation: Finding pairs with a specific difference.
def pairs_with_difference(arr, k)
pairs = []
seen = {}
arr.each do |num|
# Check for num + k
if seen[num + k]
pairs << [num, num + k]
end
# Check for num - k
if seen[num - k]
pairs << [num - k, num]
end
seen[num] = true
end
pairs.uniq
end
numbers = [1, 3, 5, 7, 9]
puts pairs_with_difference(numbers, 2).inspect #=> [[1, 3], [3, 5], [5, 7], [7, 9]]
11. Moving Zeroes
Q20: Move all zeroes to the end while maintaining order
Explanation: Multiple approaches to move zeroes to the end.
# Method 1: Partition approach
def move_zeroes(arr)
non_zeroes = arr.reject { |x| x == 0 }
zeroes = Array.new(arr.length - non_zeroes.length, 0)
non_zeroes + zeroes
end
# Method 2: In-place movement
def move_zeroes_in_place!(arr)
non_zero_index = 0
# Move all non-zero elements forward
arr.each_with_index do |num, i|
if num != 0
arr[non_zero_index] = num
non_zero_index += 1
end
end
# Fill remaining positions with zeros
(non_zero_index...arr.length).each do |i|
arr[i] = 0
end
arr
end
# Method 3: Using partition
def move_zeroes_partition(arr)
arr.partition { |x| x != 0 }.flatten
end
# Example usage:
numbers = [1, 0, 3, 0, 5, 0, 7]
puts move_zeroes(numbers).inspect #=> [1, 3, 5, 7, 0, 0, 0]
# In-place modification
arr = [1, 0, 3, 0, 5]
move_zeroes_in_place!(arr)
puts arr.inspect #=> [1, 3, 5, 0, 0]
Time Complexity: O(n) Space Complexity: O(n) for new array, O(1) for in-place
Q21: Move zeroes to the beginning
Explanation: Variation where zeroes go to the front.
def move_zeroes_to_front(arr)
zeroes = arr.select { |x| x == 0 }
non_zeroes = arr.reject { |x| x == 0 }
zeroes + non_zeroes
end
numbers = [1, 0, 3, 0, 5]
puts move_zeroes_to_front(numbers).inspect #=> [0, 0, 1, 3, 5]
12. Array Intersection
Q22: Find intersection of two arrays
Explanation: Multiple approaches to find common elements.
# Method 1: Using & operator (built-in)
def array_intersection(arr1, arr2)
arr1 & arr2
end
# Method 2: Manual using hash
def intersection_manual(arr1, arr2)
result = []
seen = {}
arr1.each { |element| seen[element] = true }
arr2.each { |element| result << element if seen[element] }
result.uniq
end
# Method 3: Preserve order from first array
def intersection_preserve_order(arr1, arr2)
set2 = arr2.to_set
arr1.select { |element| set2.include?(element) }.uniq
end
require 'set'
def intersection_with_set(arr1, arr2)
set1 = arr1.to_set
set2 = arr2.to_set
(set1 & set2).to_a
end
# Example usage:
arr1 = [1, 2, 3, 4, 5]
arr2 = [4, 5, 6, 7, 8]
puts array_intersection(arr1, arr2).inspect #=> [4, 5]
Time Complexity: O(n+m) with hash Space Complexity: O(min(n,m))
Q23: Find union of two arrays
Explanation: Combining elements from both arrays without duplicates.
def array_union(arr1, arr2)
(arr1 + arr2).uniq
end
def union_manual(arr1, arr2)
result = []
seen = {}
(arr1 + arr2).each do |element|
unless seen[element]
result << element
seen[element] = true
end
end
result
end
arr1 = [1, 2, 3]
arr2 = [3, 4, 5]
puts array_union(arr1, arr2).inspect #=> [1, 2, 3, 4, 5]
13. Frequency Counting
Q24: Count frequency of each element
Explanation: Multiple approaches to count element frequencies.
# Method 1: Using tally (Ruby 2.7+)
def count_frequency_tally(arr)
arr.tally
end
# Method 2: Manual using hash
def count_frequency_manual(arr)
frequency = Hash.new(0)
arr.each { |element| frequency[element] += 1 }
frequency
end
# Method 3: With element ordering
def count_frequency_ordered(arr)
arr.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
end
# Example usage:
elements = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
puts count_frequency_manual(elements).inspect
#=> {1=>1, 2=>2, 3=>3, 4=>4}
# With strings
words = %w[a b a c a b]
puts count_frequency_manual(words).inspect #=> {"a"=>3, "b"=>2, "c"=>1}
Time Complexity: O(n) Space Complexity: O(n)
Q25: Find most frequent element
Explanation: Finding the element with highest frequency.
def most_frequent(arr)
return nil if arr.empty?
freq = arr.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
max_freq = freq.values.max
freq.select { |_, count| count == max_freq }.keys
end
def most_frequent_single(arr)
freq = arr.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
freq.max_by { |_, count| count }.first
end
numbers = [1, 2, 2, 3, 3, 3, 4]
puts most_frequent(numbers).inspect #=> [3]
puts most_frequent_single(numbers) #=> 3
# With tie
numbers_with_tie = [1, 1, 2, 2, 3]
puts most_frequent(numbers_with_tie).inspect #=> [1, 2]
14. Additional Array Problems
Q26: Check if array is palindrome
Explanation: Determine if an array reads the same forwards and backwards.
def palindrome?(arr)
arr == arr.reverse
end
def palindrome_manual?(arr)
left = 0
right = arr.length - 1
while left < right
return false if arr[left] != arr[right]
left += 1
right -= 1
end
true
end
puts palindrome?([1, 2, 3, 2, 1]) #=> true
puts palindrome?([1, 2, 3, 4, 5]) #=> false
Q27: Find missing number in sequence
Explanation: Given an array containing n-1 numbers from 1 to n, find the missing number.
def find_missing_number(arr)
n = arr.length + 1
expected_sum = n * (n + 1) / 2
actual_sum = arr.sum
expected_sum - actual_sum
end
def find_missing_number_xor(arr)
n = arr.length + 1
xor_all = (1..n).reduce(:^)
xor_arr = arr.reduce(:^)
xor_all ^ xor_arr
end
numbers = [1, 2, 4, 5, 6] # missing 3
puts find_missing_number(numbers) #=> 3
puts find_missing_number_xor(numbers) #=> 3
Q28: Find duplicates in array
Explanation: Find elements that appear more than once.
def find_duplicates(arr)
seen = {}
duplicates = []
arr.each do |element|
if seen[element]
duplicates << element unless duplicates.include?(element)
else
seen[element] = true
end
end
duplicates
end
def find_all_duplicates(arr)
arr.group_by { |e| e }
.select { |_, v| v.size > 1 }
.keys
end
numbers = [1, 2, 3, 2, 4, 3, 5]
puts find_duplicates(numbers).inspect #=> [2, 3]
Q29: Find the first non-repeating element
Explanation: Find the first element that appears only once.
def first_non_repeating(arr)
freq = arr.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
arr.find { |element| freq[element] == 1 }
end
numbers = [4, 5, 1, 2, 0, 4, 5, 1]
puts first_non_repeating(numbers) #=> 2
Q30: Find the longest consecutive sequence
Explanation: Find the length of the longest consecutive elements sequence.
def longest_consecutive(nums)
return 0 if nums.empty?
num_set = nums.to_set
longest = 0
num_set.each do |num|
# Only start counting if this is the beginning of a sequence
if !num_set.include?(num - 1)
current_num = num
current_length = 1
while num_set.include?(current_num + 1)
current_num += 1
current_length += 1
end
longest = [longest, current_length].max
end
end
longest
end
numbers = [100, 4, 200, 1, 3, 2]
puts longest_consecutive(numbers) #=> 4 (1,2,3,4)
15. String Problems
Q31: Reverse a string without using reverse
Explanation: Multiple approaches to reverse a string manually.
def reverse_string(str)
reversed = ""
str.each_char { |c| reversed = c + reversed }
reversed
end
def reverse_string_indices(str)
result = ""
(str.length - 1).downto(0) { |i| result << str[i] }
result
end
def reverse_string_array(str)
str.chars.inject([]) { |arr, c| arr.unshift(c) }.join
end
puts reverse_string("hello") #=> "olleh"
puts reverse_string_indices("ruby") #=> "ybur"
Q32: Check if string is palindrome
Explanation: Determine if a string reads the same forwards and backwards.
def palindrome_string?(str)
str == str.reverse
end
def palindrome_manual?(str)
left = 0
right = str.length - 1
while left < right
return false if str[left] != str[right]
left += 1
right -= 1
end
true
end
def palindrome_ignore_case?(str)
cleaned = str.downcase.gsub(/[^a-z0-9]/, '')
cleaned == cleaned.reverse
end
puts palindrome_string?("racecar") #=> true
puts palindrome_string?("hello") #=> false
puts palindrome_ignore_case?("A man, a plan, a canal: Panama") #=> true
Q33: Count vowels and consonants
Explanation: Count vowels and consonants in a string.
def count_vowels_consonants(str)
vowels = 'aeiouAEIOU'
counts = { vowels: 0, consonants: 0 }
str.each_char do |char|
if char =~ /[a-zA-Z]/
if vowels.include?(char)
counts[:vowels] += 1
else
counts[:consonants] += 1
end
end
end
counts
end
result = count_vowels_consonants("Hello World")
puts "Vowels: #{result[:vowels]}, Consonants: #{result[:consonants]}"
#=> Vowels: 3, Consonants: 7
16. Hash Problems
Q34: Merge two hashes with conflict resolution
Explanation: Merge hashes with custom handling for duplicate keys.
def merge_hashes(hash1, hash2)
result = hash1.dup
hash2.each do |key, value|
if result.key?(key)
# Handle conflict - here we choose the larger value
result[key] = [result[key], value].max
else
result[key] = value
end
end
result
end
def merge_with_block(hash1, hash2, &block)
result = hash1.dup
hash2.each do |key, value|
if result.key?(key)
result[key] = block.call(key, result[key], value)
else
result[key] = value
end
end
result
end
h1 = {a: 1, b: 2, c: 3}
h2 = {b: 5, d: 4}
puts merge_hashes(h1, h2).inspect #=> {:a=>1, :b=>5, :c=>3, :d=>4}
# Custom conflict resolution - sum values
merged = merge_with_block(h1, h2) { |key, v1, v2| v1 + v2 }
puts merged.inspect #=> {:a=>1, :b=>7, :c=>3, :d=>4}
Q35: Invert a hash (swap keys and values)
Explanation: Swap keys and values, handling duplicate values.
def invert_hash(hash)
hash.invert
end
def invert_hash_manual(hash)
result = {}
hash.each { |key, value| result[value] = key }
result
end
def invert_hash_handle_duplicates(hash)
result = {}
hash.each do |key, value|
if result[value]
result[value] = [result[value]] unless result[value].is_a?(Array)
result[value] << key
else
result[value] = key
end
end
result
end
original = {a: 1, b: 2, c: 2}
puts invert_hash_handle_duplicates(original).inspect
#=> {1=>:a, 2=>[:b, :c]}
17. Number Problems
Q36: Check if number is prime
Explanation: Determine if a number is prime.
def prime?(n)
return false if n <= 1
return true if n <= 3
return false if n % 2 == 0 || n % 3 == 0
i = 5
while i * i <= n
return false if n % i == 0 || n % (i + 2) == 0
i += 6
end
true
end
puts prime?(17) #=> true
puts prime?(15) #=> false
Q37: Find factorial
Explanation: Calculate factorial recursively and iteratively.
def factorial_recursive(n)
return 1 if n <= 1
n * factorial_recursive(n - 1)
end
def factorial_iterative(n)
result = 1
(2..n).each { |i| result *= i }
result
end
puts factorial_iterative(5) #=> 120
Q38: Fibonacci sequence
Explanation: Generate Fibonacci sequence.
def fibonacci_recursive(n)
return n if n <= 1
fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)
end
def fibonacci_iterative(n)
return n if n <= 1
a, b = 0, 1
(2..n).each do
a, b = b, a + b
end
b
end
def fibonacci_sequence(length)
return [] if length <= 0
return [0] if length == 1
result = [0, 1]
(2...length).each do
result << result[-1] + result[-2]
end
result
end
puts fibonacci_sequence(10).inspect #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Quick Reference Cheat Sheet
| Problem | Best Approach | Time | Space | |---------|--------------|------|-------| | Flatten array | Recursive | O(n) | O(n) | | Remove nils | select/reject | O(n) | O(n) | | Reverse array | Two pointers | O(n) | O(1) | | Find max | Single pass | O(n) | O(1) | | Second largest | Single pass | O(n) | O(1) | | Remove duplicates | Hash | O(n) | O(n) | | Merge sorted arrays | Two pointers | O(n+m) | O(n+m) | | Rotate array | Slice | O(n) | O(n) | | Find pairs | Hash | O(n) | O(n) | | Move zeroes | Partition | O(n) | O(1) | | Array intersection | Hash set | O(n+m) | O(min(n,m)) | | Frequency count | Hash | O(n) | O(n) |
# Ruby Coding Interview Questions - Simple but Commonly Asked
## Table of Contents
1. [String Basics](#1-string-basics)
2. [Number Operations](#2-number-operations)
3. [Array Basics](#3-array-basics)
4. [Hash Basics](#4-hash-basics)
5. [Conditionals and Loops](#5-conditionals-and-loops)
6. [Simple Algorithms](#6-simple-algorithms)
7. [Common Ruby Methods](#7-common-ruby-methods)
8. [Object Oriented Basics](#8-object-oriented-basics)
9. [Error Handling](#9-error-handling)
10. [File Operations](#10-file-operations)
---
## 1. String Basics
### Q1: Check if a string is empty or nil
**Explanation:**
Very common check in Ruby applications. Need to handle both nil and empty string cases.
```ruby
def blank?(str)
str.nil? || str.empty?
end
# Ruby's built-in method
def blank_rails?(str)
str.blank? # Rails method - true for nil, false, empty
end
# Examples
puts blank?(nil) #=> true
puts blank?("") #=> true
puts blank?("hello") #=> false
Q2: Convert string to integer safely
Explanation: Handle cases where string might not be a valid number.
def safe_to_int(str)
Integer(str) rescue nil
end
def to_int_with_default(str, default = 0)
Integer(str) rescue default
end
puts safe_to_int("123") #=> 123
puts safe_to_int("abc") #=> nil
puts to_int_with_default("abc", -1) #=> -1
Q3: Capitalize first letter of each word
Explanation: Title case conversion - common for formatting names, titles.
def title_case(sentence)
sentence.split.map(&:capitalize).join(' ')
end
def title_case_except_articles(sentence)
articles = ['a', 'an', 'the', 'and', 'but', 'or', 'for', 'nor', 'on', 'at', 'to', 'by']
sentence.split.each_with_index.map do |word, i|
if i == 0 || !articles.include?(word.downcase)
word.capitalize
else
word.downcase
end
end.join(' ')
end
puts title_case("hello world") #=> "Hello World"
puts title_case_except_articles("the lord of the rings") #=> "The Lord of the Rings"
Q4: Remove whitespace from string
Explanation: Different ways to remove whitespace depending on requirements.
# Remove leading/trailing whitespace
def trim(str)
str.strip
end
# Remove all whitespace
def remove_all_spaces(str)
str.gsub(/\s+/, '')
end
# Remove extra spaces (single space between words)
def normalize_spaces(str)
str.gsub(/\s+/, ' ').strip
end
text = " Hello World ! "
puts trim(text) #=> "Hello World !"
puts remove_all_spaces(text) #=> "HelloWorld!"
puts normalize_spaces(text) #=> "Hello World !"
Q5: Check if string contains only digits
Explanation: Validate numeric strings for further processing.
def numeric?(str)
str.match?(/\A\d+\z/)
end
def integer?(str)
str.match?(/\A-?\d+\z/)
end
def decimal?(str)
str.match?(/\A-?\d+(\.\d+)?\z/)
end
puts numeric?("123") #=> true
puts numeric?("12.3") #=> false
puts integer?("-123") #=> true
puts decimal?("123.45") #=> true
Q6: Count occurrences of a character
Explanation: Count how many times a specific character appears.
def count_char(str, char)
str.count(char)
end
def count_char_manual(str, char)
str.chars.count { |c| c == char }
end
def count_char_regex(str, char)
str.scan(/#{char}/).length
end
text = "hello world"
puts count_char(text, 'l') #=> 3
puts count_char_manual(text, 'o') #=> 2
Q7: Reverse words in a sentence
Explanation: Reverse the order of words, not the characters.
def reverse_words(sentence)
sentence.split.reverse.join(' ')
end
def reverse_words_manual(sentence)
words = sentence.split
reversed = []
(words.length - 1).downto(0) do |i|
reversed << words[i]
end
reversed.join(' ')
end
puts reverse_words("Hello World Ruby") #=> "Ruby World Hello"
Q8: Check if two strings are anagrams
Explanation: Determine if two strings use the same letters.
def anagrams?(str1, str2)
str1.downcase.chars.sort == str2.downcase.chars.sort
end
def anagrams_manual?(str1, str2)
return false if str1.length != str2.length
str1.downcase.each_char do |char|
return false unless str2.downcase.include?(char)
str2 = str2.sub(char, '')
end
true
end
puts anagrams?("listen", "silent") #=> true
puts anagrams?("hello", "world") #=> false
2. Number Operations
Q9: Check if number is even or odd
Explanation: Basic parity check - very common in conditional logic.
def even?(num)
num % 2 == 0
end
def odd?(num)
num % 2 != 0
end
# Using bitwise AND
def even_bitwise?(num)
num & 1 == 0
end
puts even?(4) #=> true
puts odd?(5) #=> true
puts even?(7) #=> false
Q10: Find sum of digits in a number
Explanation: Break down number and add individual digits.
def sum_of_digits(num)
num.to_s.chars.map(&:to_i).sum
end
def sum_of_digits_manual(num)
sum = 0
num.abs.to_s.each_char { |digit| sum += digit.to_i }
sum
end
def sum_of_digits_math(num)
num = num.abs
sum = 0
while num > 0
sum += num % 10
num /= 10
end
sum
end
puts sum_of_digits(123) #=> 6 (1+2+3)
puts sum_of_digits_math(456) #=> 15 (4+5+6)
Q11: Generate multiplication table
Explanation: Simple table generation - tests loops and formatting.
def multiplication_table(num, upto = 10)
(1..upto).map { |i| "#{num} × #{i} = #{num * i}" }
end
def print_table(num, upto = 10)
multiplication_table(num, upto).each { |line| puts line }
end
puts multiplication_table(5)
#=> ["5 × 1 = 5", "5 × 2 = 10", "5 × 3 = 15", ...]
print_table(7, 5)
# Output:
# 7 × 1 = 7
# 7 × 2 = 14
# 7 × 3 = 21
# 7 × 4 = 28
# 7 × 5 = 35
Q12: Check if a number is positive, negative, or zero
Explanation: Basic number classification.
def number_type(num)
if num > 0
"positive"
elsif num < 0
"negative"
else
"zero"
end
end
# Using case statement
def number_type_case(num)
case num <=> 0
when 1 then "positive"
when -1 then "negative"
else "zero"
end
end
puts number_type(5) #=> "positive"
puts number_type(-3) #=> "negative"
puts number_type(0) #=> "zero"
Q13: Find factorial of a number (simple)
Explanation: Basic factorial calculation - tests recursion or iteration.
def factorial(n)
return 1 if n <= 1
n * factorial(n - 1)
end
def factorial_iterative(n)
result = 1
(2..n).each { |i| result *= i }
result
end
puts factorial(5) #=> 120
puts factorial(0) #=> 1
puts factorial(1) #=> 1
Q14: Generate Fibonacci series up to n
Explanation: Classic sequence generation problem.
def fibonacci_upto(n)
return [] if n <= 0
return [0] if n == 1
fib = [0, 1]
while fib[-1] + fib[-2] <= n
fib << fib[-1] + fib[-2]
end
fib
end
def first_n_fibonacci(n)
return [] if n <= 0
return [0] if n == 1
fib = [0, 1]
(2...n).each { fib << fib[-1] + fib[-2] }
fib
end
puts fibonacci_upto(50).inspect #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
puts first_n_fibonacci(7).inspect #=> [0, 1, 1, 2, 3, 5, 8]
Q15: Find greatest common divisor (GCD)
Explanation: Euclidean algorithm for finding GCD.
def gcd(a, b)
while b != 0
a, b = b, a % b
end
a
end
def gcd_recursive(a, b)
return a if b == 0
gcd_recursive(b, a % b)
end
puts gcd(48, 18) #=> 6
puts gcd(56, 42) #=> 14
puts gcd(17, 19) #=> 1
3. Array Basics
Q16: Check if element exists in array
Explanation: Basic array membership test.
def element_exists?(arr, element)
arr.include?(element)
end
def element_exists_manual?(arr, element)
arr.each { |e| return true if e == element }
false
end
numbers = [1, 2, 3, 4, 5]
puts element_exists?(numbers, 3) #=> true
puts element_exists?(numbers, 6) #=> false
Q17: Get first and last element of array
Explanation: Accessing array boundaries safely.
def first_element(arr)
arr.first
end
def last_element(arr)
arr.last
end
def safe_first(arr, default = nil)
arr.empty? ? default : arr.first
end
def safe_last(arr, default = nil)
arr.empty? ? default : arr.last
end
numbers = [1, 2, 3]
puts first_element(numbers) #=> 1
puts last_element(numbers) #=> 3
puts safe_first([], "empty") #=> "empty"
Q18: Add element to beginning and end
Explanation: Different ways to add elements to arrays.
def add_to_beginning(arr, element)
[element] + arr
end
def add_to_end(arr, element)
arr + [element]
end
def add_to_beginning!(arr, element)
arr.unshift(element)
end
def add_to_end!(arr, element)
arr << element
end
numbers = [2, 3, 4]
puts add_to_beginning(numbers, 1).inspect #=> [1, 2, 3, 4]
puts add_to_end(numbers, 5).inspect #=> [2, 3, 4, 5]
Q19: Remove duplicates (simple version)
Explanation: Basic duplicate removal - different from earlier advanced version.
def remove_duplicates(arr)
arr.uniq
end
def remove_duplicates_manual(arr)
result = []
arr.each { |e| result << e unless result.include?(e) }
result
end
numbers = [1, 2, 2, 3, 3, 3, 4]
puts remove_duplicates(numbers).inspect #=> [1, 2, 3, 4]
Q20: Check if array is empty
Explanation: Simple but essential check.
def array_empty?(arr)
arr.empty?
end
def array_empty_manual?(arr)
arr.length == 0
end
puts array_empty?([]) #=> true
puts array_empty?([1, 2]) #=> false
Q21: Combine two arrays
Explanation: Different ways to combine arrays.
def combine_arrays(arr1, arr2)
arr1 + arr2
end
def combine_without_duplicates(arr1, arr2)
(arr1 + arr2).uniq
end
def combine_alternating(arr1, arr2)
result = []
max_length = [arr1.length, arr2.length].max
(0...max_length).each do |i|
result << arr1[i] if i < arr1.length
result << arr2[i] if i < arr2.length
end
result
end
a1 = [1, 2, 3]
a2 = [4, 5, 6]
puts combine_arrays(a1, a2).inspect #=> [1, 2, 3, 4, 5, 6]
puts combine_alternating([1, 3], [2, 4]).inspect #=> [1, 2, 3, 4]
4. Hash Basics
Q22: Check if key exists in hash
Explanation: Basic hash key lookup.
def key_exists?(hash, key)
hash.key?(key)
end
def key_exists_manual?(hash, key)
hash.each_key { |k| return true if k == key }
false
end
person = { name: "John", age: 30 }
puts key_exists?(person, :name) #=> true
puts key_exists?(person, :city) #=> false
Q23: Get all keys or values from hash
Explanation: Extracting hash components.
def get_keys(hash)
hash.keys
end
def get_values(hash)
hash.values
end
def get_keys_manual(hash)
keys = []
hash.each { |k, _| keys << k }
keys
end
person = { name: "John", age: 30, city: "NYC" }
puts get_keys(person).inspect #=> [:name, :age, :city]
puts get_values(person).inspect #=> ["John", 30, "NYC"]
Q24: Create hash from two arrays
Explanation: Zip arrays into key-value pairs.
def arrays_to_hash(keys, values)
Hash[keys.zip(values)]
end
def arrays_to_hash_manual(keys, values)
hash = {}
keys.each_with_index do |key, i|
hash[key] = values[i] if i < values.length
end
hash
end
keys = [:name, :age, :city]
values = ["John", 30, "NYC"]
puts arrays_to_hash(keys, values).inspect
#=> {:name=>"John", :age=>30, :city=>"NYC"}
Q25: Merge two hashes (simple)
Explanation: Combining hashes with basic conflict handling.
def merge_hashes(h1, h2)
h1.merge(h2)
end
def merge_hashes_manual(h1, h2)
result = h1.dup
h2.each { |k, v| result[k] = v }
result
end
h1 = {a: 1, b: 2}
h2 = {b: 3, c: 4}
puts merge_hashes(h1, h2).inspect #=> {:a=>1, :b=>3, :c=>4}
Q26: Count frequency of words (simple)
Explanation: Basic word counting in a sentence.
def word_frequency(sentence)
words = sentence.downcase.split
frequency = {}
words.each do |word|
if frequency[word]
frequency[word] += 1
else
frequency[word] = 1
end
end
frequency
end
sentence = "the cat and the dog"
puts word_frequency(sentence).inspect
#=> {"the"=>2, "cat"=>1, "and"=>1, "dog"=>1}
5. Conditionals and Loops
Q27: FizzBuzz (classic)
Explanation: The classic interview problem - tests basic logic flow.
def fizzbuzz(n)
(1..n).map do |i|
if i % 15 == 0
"FizzBuzz"
elsif i % 3 == 0
"Fizz"
elsif i % 5 == 0
"Buzz"
else
i
end
end
end
puts fizzbuzz(15).inspect
#=> [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14, "FizzBuzz"]
Q28: Print numbers 1 to 10 with different loops
Explanation: Demonstrates various looping constructs.
# Using each
def print_with_each
(1..10).each { |n| puts n }
end
# Using for loop
def print_with_for
for i in 1..10
puts i
end
end
# Using while
def print_with_while
i = 1
while i <= 10
puts i
i += 1
end
end
# Using until
def print_with_until
i = 1
until i > 10
puts i
i += 1
end
end
# Using times
def print_with_times
10.times { |i| puts i + 1 }
end
Q29: Sum of numbers in range
Explanation: Calculate sum using different approaches.
def sum_range(start, finish)
(start..finish).sum
end
def sum_range_manual(start, finish)
sum = 0
(start..finish).each { |n| sum += n }
sum
end
def sum_range_formula(start, finish)
n = finish - start + 1
n * (start + finish) / 2
end
puts sum_range(1, 10) #=> 55
puts sum_range_formula(1, 10) #=> 55
Q30: Check if number is in range
Explanation: Range inclusion test.
def in_range?(num, min, max)
num.between?(min, max)
end
def in_range_manual?(num, min, max)
num >= min && num <= max
end
puts in_range?(5, 1, 10) #=> true
puts in_range?(15, 1, 10) #=> false
6. Simple Algorithms
Q31: Find minimum and maximum in array (simple)
Explanation: Basic min/max without using built-in methods.
def find_min(arr)
return nil if arr.empty?
min = arr.first
arr.each { |n| min = n if n < min }
min
end
def find_max(arr)
return nil if arr.empty?
max = arr.first
arr.each { |n| max = n if n > max }
max
end
numbers = [3, 7, 2, 9, 1, 5]
puts find_min(numbers) #=> 1
puts find_max(numbers) #=> 9
Q32: Count even and odd numbers
Explanation: Simple classification and counting.
def count_even_odd(arr)
even_count = 0
odd_count = 0
arr.each do |n|
if n.even?
even_count += 1
else
odd_count += 1
end
end
{ even: even_count, odd: odd_count }
end
numbers = [1, 2, 3, 4, 5, 6]
puts count_even_odd(numbers).inspect #=> {:even=>3, :odd=>3}
Q33: Reverse a number
Explanation: Reverse digits of a number.
def reverse_number(num)
num.to_s.reverse.to_i
end
def reverse_number_math(num)
reversed = 0
while num > 0
reversed = reversed * 10 + num % 10
num /= 10
end
reversed
end
puts reverse_number(12345) #=> 54321
puts reverse_number_math(123) #=> 321
Q34: Check if year is leap year
Explanation: Leap year calculation - tests nested conditions.
def leap_year?(year)
if year % 400 == 0
true
elsif year % 100 == 0
false
elsif year % 4 == 0
true
else
false
end
end
# More concise
def leap_year_compact?(year)
(year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)
end
puts leap_year?(2000) #=> true
puts leap_year?(1900) #=> false
puts leap_year?(2024) #=> true
Q35: Generate random password
Explanation: Simple string generation with character sets.
def random_password(length = 8)
chars = [('a'..'z'), ('A'..'Z'), (0..9)].map(&:to_a).flatten
(0...length).map { chars[rand(chars.length)] }.join
end
def simple_password(length = 8)
('a'..'z').to_a.sample(length).join
end
puts random_password #=> "kL9mN2pQ"
puts simple_password #=> "fgkmpqrs"
7. Common Ruby Methods
Q36: Implement times method
Explanation:
Recreate Ruby's built-in times method.
def my_times(n, &block)
i = 0
while i < n
block.call(i)
i += 1
end
n
end
# Usage
my_times(3) { |i| puts "Hello #{i}" }
# Output:
# Hello 0
# Hello 1
# Hello 2
Q37: Implement each method for array
Explanation: Basic iterator implementation.
def my_each(array, &block)
i = 0
while i < array.length
block.call(array[i])
i += 1
end
array
end
my_each([1, 2, 3]) { |n| puts n * 2 }
# Output: 2, 4, 6
Q38: Implement select method
Explanation: Filtering array based on condition.
def my_select(array, &block)
result = []
array.each { |element| result << element if block.call(element) }
result
end
numbers = [1, 2, 3, 4, 5]
evens = my_select(numbers) { |n| n.even? }
puts evens.inspect #=> [2, 4]
Q39: Implement map method
Explanation: Transforming array elements.
def my_map(array, &block)
result = []
array.each { |element| result << block.call(element) }
result
end
numbers = [1, 2, 3]
doubled = my_map(numbers) { |n| n * 2 }
puts doubled.inspect #=> [2, 4, 6]
8. Object Oriented Basics
Q40: Create a simple Person class
Explanation: Basic class with attributes and methods.
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def introduce
"Hi, I'm #{@name} and I'm #{@age} years old"
end
def birthday!
@age += 1
end
def older_than?(other)
@age > other.age
end
end
person1 = Person.new("Alice", 25)
person2 = Person.new("Bob", 30)
puts person1.introduce #=> "Hi, I'm Alice and I'm 25 years old"
person1.birthday!
puts person1.age #=> 26
puts person1.older_than?(person2) #=> false
Q41: Create a simple Bank Account class
Explanation: Class with state and validation.
class BankAccount
attr_reader :balance, :account_number
def initialize(initial_balance = 0)
@balance = initial_balance
@account_number = rand(10000..99999)
end
def deposit(amount)
if amount > 0
@balance += amount
true
else
false
end
end
def withdraw(amount)
if amount > 0 && amount <= @balance
@balance -= amount
true
else
false
end
end
def display
"Account ##{@account_number}: $#{@balance}"
end
end
account = BankAccount.new(100)
account.deposit(50)
account.withdraw(30)
puts account.display #=> "Account #12345: $120"
Q42: Create a simple Counter class
Explanation: Class with class and instance variables.
class Counter
@@total_count = 0
def initialize
@count = 0
@@total_count += 1
end
def increment
@count += 1
end
def decrement
@count -= 1 if @count > 0
end
def value
@count
end
def self.total_instances
@@total_count
end
end
c1 = Counter.new
c2 = Counter.new
c1.increment
c1.increment
c2.increment
puts c1.value #=> 2
puts c2.value #=> 1
puts Counter.total_instances #=> 2
9. Error Handling
Q43: Safe division with error handling
Explanation: Handle division by zero gracefully.
def safe_divide(a, b)
begin
a / b
rescue ZeroDivisionError
"Cannot divide by zero"
end
end
def safe_divide_with_default(a, b, default = nil)
a / b
rescue ZeroDivisionError
default
end
puts safe_divide(10, 2) #=> 5
puts safe_divide(10, 0) #=> "Cannot divide by zero"
puts safe_divide_with_default(10, 0, 0) #=> 0
Q44: Convert to integer with error handling
Explanation: Handle conversion errors.
def to_integer(value)
Integer(value)
rescue ArgumentError, TypeError
nil
end
def to_integer_with_default(value, default = 0)
Integer(value)
rescue ArgumentError, TypeError
default
end
puts to_integer("123") #=> 123
puts to_integer("abc") #=> nil
puts to_integer_with_default("abc", -1) #=> -1
10. File Operations
Q45: Read a file line by line
Explanation: Basic file reading operations.
def read_file(filename)
File.readlines(filename) if File.exist?(filename)
rescue Errno::ENOENT
"File not found"
end
def print_file(filename)
File.foreach(filename) { |line| puts line } if File.exist?(filename)
end
# Count lines in file
def count_lines(filename)
return 0 unless File.exist?(filename)
File.foreach(filename).count
end
Q46: Write to a file
Explanation: Basic file writing operations.
def write_to_file(filename, content)
File.write(filename, content)
true
rescue IOError => e
puts "Error writing file: #{e.message}"
false
end
def append_to_file(filename, content)
File.open(filename, 'a') { |f| f.puts(content) }
true
rescue IOError => e
puts "Error appending to file: #{e.message}"
false
end
Q47: Check if file exists
Explanation: File existence check.
def file_exists?(filename)
File.exist?(filename)
end
def file_readable?(filename)
File.readable?(filename)
end
def file_writable?(filename)
File.writable?(filename)
end
puts file_exists?("test.txt") #=> true/false
Quick Reference - Common Patterns
| Pattern | Code |
|---------|------|
| Safe nil check | value.nil? ? default : value |
| Safe method call | object&.method |
| Default value | variable ||= default |
| Ternary operator | condition ? true_value : false_value |
| Loop with index | array.each_with_index { \|item, i\| ... } |
| Transform array | array.map { \|x\| x * 2 } |
| Filter array | array.select { \|x\| x > 5 } |
| Find element | array.find { \|x\| x == target } |
| Group by | array.group_by { \|x\| x % 2 } |
| Sum array | array.sum or array.reduce(:+) |
Most Commonly Asked One-Liners
# Check if string is numeric
string.match?(/\A\d+\z/)
# Convert string to array of characters
string.chars
# Convert array to string with delimiter
array.join(', ')
# Get unique elements
array.uniq
# Sort array
array.sort
# Reverse string/array
string.reverse / array.reverse
# Check if all elements meet condition
array.all? { |x| x > 0 }
# Check if any element meets condition
array.any? { |x| x.even? }
# Get first n elements
array.first(n)
# Get last n elements
array.last(n)
# Remove nil values
array.compact
# Flatten one level
array.flatten(1)