iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Exercises

Six Ruby exercises with self-check answers. Strings, collections, blocks, classes, error handling.

Ruby — exercises

EXAMPLE
# ===== Exercise 1: word count =====
# Given a string, return a Hash mapping each word to its count (case-insensitive).
# Example: "the cat sat on the mat" -> { "the" => 2, "cat" => 1, "sat" => 1, "on" => 1, "mat" => 1 }

def word_count(s)
  s.downcase.split.each_with_object(Hash.new(0)) { |w, h| h[w] += 1 }
end

p word_count('the cat sat on the mat')

# ===== Exercise 2: prime sieve =====
# Return all primes up to n using Sieve of Eratosthenes.
# Example: primes(20) -> [2, 3, 5, 7, 11, 13, 17, 19]

def primes(n)
  return [] if n < 2
  sieve = Array.new(n + 1, true)
  sieve[0] = sieve[1] = false
  (2..Math.sqrt(n)).each do |i|
    next unless sieve[i]
    (i*i..n).step(i) { |j| sieve[j] = false }
  end
  sieve.each_with_index.select { |b, _| b }.map(&:last)
end

p primes(20)

# ===== Exercise 3: group anagrams =====
# Given an array of strings, group anagrams together.
# Example: ['eat', 'tea', 'tan', 'ate', 'nat', 'bat'] -> [['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]

def group_anagrams(words)
  words.group_by { |w| w.chars.sort.join }.values
end

p group_anagrams(%w[eat tea tan ate nat bat])

# ===== Exercise 4: rectangle area class =====
# Build a Rectangle class with width, height, area, perimeter. Frozen (immutable).

class Rectangle
  attr_reader :width, :height

  def initialize(width:, height:)
    raise ArgumentError, 'positive only' if width <= 0 || height <= 0
    @width = width
    @height = height
    freeze
  end

  def area = width * height
  def perimeter = 2 * (width + height)

  def to_s = "Rectangle(#{width}x#{height})"
end

r = Rectangle.new(width: 3, height: 4)
p r.area
p r.perimeter
# r.instance_variable_set(:@width, 99)  # FrozenError

# ===== Exercise 5: safe divide =====
# Implement divide(a, b) returning either an Integer result or a String error.
# Don't raise; return data.

def divide(a, b)
  return 'divide by zero' if b.zero?
  return 'not numeric' unless [a, b].all?(Numeric)
  a / b
end

p divide(10, 2)
p divide(10, 0)
p divide('a', 2)

# ===== Exercise 6: retry with backoff =====
# Implement a method that retries a block up to n times with exponential backoff.

def with_retry(max_attempts: 3, base_delay: 0.1)
  attempt = 0
  begin
    attempt += 1
    yield
  rescue StandardError => e
    raise if attempt >= max_attempts
    sleep(base_delay * (2 ** (attempt - 1)))
    retry
  end
end

i = 0
result = with_retry { i += 1; raise 'flaky' if i < 3; 'ok' }
p result  # 'ok' (after 3 attempts)

# ===== Patterns to internalise =====
# - each_with_object for accumulator-style iteration
# - Hash.new(0) for default-zero counts
# - group_by for partitioning
# - keyword args for clarity
# - freeze for immutable value objects

# ===== Pitfalls =====
# - Using inject without initial value -> error on empty
# - Mutating shared state from blocks
# - Forgetting Math.sqrt is Float (use to_i if you need Int)
# - Method definitions inside other methods (not idiomatic; use procs/lambdas)

Why it matters

Six Ruby exercises drill the daily reflexes: each_with_object, Hash defaults, group_by, frozen value classes, error-as-data, retry with backoff. Ship them as your warm-up before any Ruby interview or refactor session.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
# Fill in: def add(a, b) = a ____ b
Try it Yourself »

Discussion

Loading…