Skip to content

Instantly share code, notes, and snippets.

@ajesler
Last active June 16, 2022 03:40
Show Gist options
  • Save ajesler/0ca52605806eee213f14d97267070218 to your computer and use it in GitHub Desktop.
Save ajesler/0ca52605806eee213f14d97267070218 to your computer and use it in GitHub Desktop.
A template for containing puzzle problems in a single file, including input data, and tests.
# frozen_string_literal: true
# The Sock Merchant
# from https://www.hackerrank.com/challenges/sock-merchant/problem
#
# Run the solver with the input after __END__
# $ ruby sock_merchant.rb
#
# Run the solver using a file as input
# $ ruby sock_merchant.rb test_input.txt
#
# Run solver specs with
# $ ruby sock_merchant.rb --specs
require "bundler/inline"
# Uncomment this block to install byebug
# gemfile true do
# source "https://rubygems.org"
# gem "test-unit"
# # Useful for debugging
# gem "byebug", platforms: [:mri, :mingw, :x64_mingw]
# gem "pry-byebug"
# end
require 'test/unit'
Test::Unit::AutoRunner.need_auto_run = false
class SockCounter
def initialize(socks)
@socks = socks
end
def pair_count
# group by type
# binding.pry
count_per_type = @socks.group_by(&:itself)
pairs_per_type = count_per_type.transform_values { |v| v.size.div 2 }
total_pairs = pairs_per_type.values.sum
total_pairs
end
end
class SockCounterSpec < Test::Unit::TestCase
def expect_pair_count(expected_pair_count, socks:)
pair_count = SockCounter.new(socks).pair_count
assert_equal expected_pair_count, pair_count
end
def test_none
expect_pair_count(0, socks: [])
end
def test_no_pairs
expect_pair_count(0, socks: [1, 2, 3, 4])
end
def test_some_pairs
expect_pair_count(2, socks: [1, 2, 3, 4, 1, 2])
end
end
if $PROGRAM_NAME == __FILE__
first_argument = ARGV.shift
if first_argument == '--specs'
# Run the specs
Test::Unit::AutoRunner.need_auto_run = true
else
data_source = first_argument.nil? ? DATA.read : File.read(first_argument)
# Run the solver
raw_number_of_socks, raw_socks = data_source.split(/\r?\n/, 2)
number_of_socks = raw_number_of_socks.to_i
socks = raw_socks.split(' ').map(&:to_i)
if number_of_socks != socks.size
raise("Sock mismatch! Expected #{number_of_socks}, got #{socks.size}")
end
pairs = SockCounter.new(socks).pair_count
puts pairs
end
end
__END__
9
10 20 20 10 10 30 50 10 20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment