Avatar of patrickdavey

patrickdavey's solution

to Largest Series Product in the Ruby Track

Published at Apr 25 2019 · 0 comments
Instructions
Test suite
Solution

Given a string of digits, calculate the largest product for a contiguous substring of digits of length n.

For example, for the input '1027839564', the largest product for a series of 3 digits is 270 (9 * 5 * 6), and the largest product for a series of 5 digits is 7560 (7 * 8 * 3 * 9 * 5).

Note that these series are only required to occupy adjacent positions in the input; the digits need not be numerically consecutive.

For the input '73167176531330624919225119674426574742355349194934', the largest product for a series of 6 digits is 23520.


For installation and learning resources, refer to the Ruby resources page.

For running the tests provided, you will need the Minitest gem. Open a terminal window and run the following command to install minitest:

gem install minitest

If you would like color output, you can require 'minitest/pride' in the test file, or note the alternative instruction, below, for running the test file.

Run the tests from the exercise directory using the following command:

ruby largest_series_product_test.rb

To include color from the command line:

ruby -r minitest/pride largest_series_product_test.rb

Source

A variation on Problem 8 at Project Euler http://projecteuler.net/problem=8

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

largest_series_product_test.rb

require 'minitest/autorun'
require_relative 'largest_series_product'

# Common test data version: 1.2.0 85da7a5
class LargestSeriesProductTest < Minitest::Test
  def test_finds_the_largest_product_if_span_equals_length
    # skip
    assert_equal 18, Series.new('29').largest_product(2)
  end

  def test_can_find_the_largest_product_of_2_with_numbers_in_order
    skip
    assert_equal 72, Series.new('0123456789').largest_product(2)
  end

  def test_can_find_the_largest_product_of_2
    skip
    assert_equal 48, Series.new('576802143').largest_product(2)
  end

  def test_can_find_the_largest_product_of_3_with_numbers_in_order
    skip
    assert_equal 504, Series.new('0123456789').largest_product(3)
  end

  def test_can_find_the_largest_product_of_3
    skip
    assert_equal 270, Series.new('1027839564').largest_product(3)
  end

  def test_can_find_the_largest_product_of_5_with_numbers_in_order
    skip
    assert_equal 15120, Series.new('0123456789').largest_product(5)
  end

  def test_can_get_the_largest_product_of_a_big_number
    skip
    assert_equal 23520, Series.new('73167176531330624919225119674426574742355349194934').largest_product(6)
  end

  def test_reports_zero_if_the_only_digits_are_zero
    skip
    assert_equal 0, Series.new('0000').largest_product(2)
  end

  def test_reports_zero_if_all_spans_include_zero
    skip
    assert_equal 0, Series.new('99099').largest_product(3)
  end

  def test_rejects_span_longer_than_string_length
    skip
    assert_raises(ArgumentError) do
      Series.new('123').largest_product(4)
    end
  end

  def test_reports_1_for_empty_string_and_empty_product_0_span
    skip
    assert_equal 1, Series.new('').largest_product(0)
  end

  def test_reports_1_for_nonempty_string_and_empty_product_0_span
    skip
    assert_equal 1, Series.new('123').largest_product(0)
  end

  def test_rejects_empty_string_and_nonzero_span
    skip
    assert_raises(ArgumentError) do
      Series.new('').largest_product(1)
    end
  end

  def test_rejects_invalid_character_in_digits
    skip
    assert_raises(ArgumentError) do
      Series.new('1234a5').largest_product(2)
    end
  end

  def test_rejects_negative_span
    skip
    assert_raises(ArgumentError) do
      Series.new('12345').largest_product(-1)
    end
  end
end
class Series
  def initialize(numbers)
    raise ArgumentError if numbers =~ /\D/
    @numbers = numbers.chars.map(&:to_i)
  end

  def largest_product(size)
    raise ArgumentError if size > numbers.size
    return 1 if size.zero?

    numbers
      .each_cons(size)
      .map { |seq| seq.reduce(&:*) }
      .max
  end


  private

  attr_reader :numbers
end

Community comments

Find this solution interesting? Ask the author a question to learn more.

patrickdavey's Reflection

The error checking seems a bit ugly, I'm off to look and see how others did it.