# 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
# ------------------------------------------------------------
#