How to find repeated rows of a matrix in Ruby

1 Answer

0 votes
# Find Repeated Rows in a Matrix
#
# Problem:
# Given a matrix, find all rows that occur more than once.
#
# Approach:
# - Use a Hash to count how many times each row appears.
# - Ruby Arrays can be used directly as Hash keys because they implement
#   proper hashing and equality semantics.
# - After counting, keep only rows with a frequency greater than 1.
#
# Why this approach?
# - Efficient: avoids comparing every row against every other row.
# - Expressive: leverages Ruby's built-in collection methods.
# - Scales well for large matrices.
#
# Time Complexity:
#   O(rows)
#   Assuming row hashing/comparison is efficient for the row size.
#
# More precisely:
#   O(rows * columns)
#
# Space Complexity:
#   O(unique_rows)
#
# Memory Notes:
# - A frequency hash stores one entry per distinct row.
# - Memory usage grows with the number of unique rows.
#
# Security Notes:
# - No external input execution.
# - Input validation is performed before processing.
#
# Architecture:
# - validate_matrix! : validates arguments.
# - repeated_rows   : core business logic.
# - print_results   : presentation layer.
#
# Edge Cases:
# - Empty matrix.
# - Single-row matrix.
# - All rows unique.
# - All rows identical.
# - Rows repeated more than twice.
# - Mixed data types inside rows.

# Validates that the supplied value is a matrix-like structure.
def validate_matrix!(matrix)
  unless matrix.is_a?(Array)
    raise ArgumentError, "Matrix must be an Array."
  end

  unless matrix.all? { |row| row.is_a?(Array) }
    raise ArgumentError, "Every matrix row must be an Array."
  end
end

# Returns a Hash containing only duplicated rows.
#
# Example:
# {
#   [1, 2, 3] => 2,
#   [4, 5, 6] => 3
# }
def repeated_rows(matrix)
  validate_matrix!(matrix)

  frequencies = matrix.each_with_object(Hash.new(0)) do |row, counts|
    counts[row] += 1
  end

  frequencies.select { |_row, count| count > 1 }
end

# Prints matrix contents and duplicate information.
def print_results(matrix)
  puts "Matrix:"
  matrix.each { |row| p(row) }

  duplicates = repeated_rows(matrix)

  puts

  if duplicates.empty?
    puts "Repeated rows: none"
  else
    puts "Repeated rows:"

    duplicates.each do |row, count|
      puts "#{row.inspect} -> #{count} occurrences"
    end
  end

  puts "-" * 60
end

# ------------------------------------------------------------------
# Tests
# ------------------------------------------------------------------
#
# The examples below exercise common and edge-case scenarios.
#
# Expected behavior:
# - Duplicate rows are reported with occurrence counts.
# - Unique rows are ignored.
# - Empty matrices are handled gracefully.
#
# Note:
# In production code, a testing framework such as Minitest or RSpec
# would typically be used instead of manual examples.

def main
  test_cases = [
    {
      name: "Duplicate rows",
      matrix: [
        [1, 2, 3],
        [4, 5, 6],
        [1, 2, 3],
        [7, 8, 9],
        [4, 5, 6]
      ]
    },

    {
      name: "No duplicates",
      matrix: [
        [1, 2],
        [3, 4],
        [5, 6]
      ]
    },

    {
      name: "Empty matrix",
      matrix: []
    },

    {
      name: "All rows identical",
      matrix: [
        ["A", "B"],
        ["A", "B"],
        ["A", "B"],
        ["A", "B"]
      ]
    },

    {
      name: "Repeated more than twice",
      matrix: [
        [10],
        [20],
        [10],
        [20],
        [20],
        [10]
      ]
    },

    {
      name: "Mixed data types",
      matrix: [
        [1, "x", true],
        [2, "y", false],
        [1, "x", true]
      ]
    }
  ]

  test_cases.each do |test|
    puts
    puts "Test: #{test[:name]}"
    print_results(test[:matrix])
  end
rescue ArgumentError => e
  warn "Input Error: #{e.message}"
end

main if __FILE__ == $PROGRAM_NAME



#
# Run:
# 
# Test: Duplicate rows
# Matrix:
# [1, 2, 3]
# [4, 5, 6]
# [1, 2, 3]
# [7, 8, 9]
# [4, 5, 6]
# 
# Repeated rows:
# [1, 2, 3] -> 2 occurrences
# [4, 5, 6] -> 2 occurrences
# ------------------------------------------------------------
# 
# Test: No duplicates
# Matrix:
# [1, 2]
# [3, 4]
# [5, 6]
# 
# Repeated rows: none
# ------------------------------------------------------------
# 
# Test: Empty matrix
# Matrix:
# 
# Repeated rows: none
# ------------------------------------------------------------
# 
# Test: All rows identical
# Matrix:
# ["A", "B"]
# ["A", "B"]
# ["A", "B"]
# ["A", "B"]
# 
# Repeated rows:
# ["A", "B"] -> 4 occurrences
# ------------------------------------------------------------
# 
# Test: Repeated more than twice
# Matrix:
# [10]
# [20]
# [10]
# [20]
# [20]
# [10]
# 
# Repeated rows:
# [10] -> 3 occurrences
# [20] -> 3 occurrences
# ------------------------------------------------------------
# 
# Test: Mixed data types
# Matrix:
# [1, "x", true]
# [2, "y", false]
# [1, "x", true]
# 
# Repeated rows:
# [1, "x", true] -> 2 occurrences
# ------------------------------------------------------------
#

 



answered Sep 25 by avibootz
...