首页 > 解决方案 > 最大系列产品

问题描述

给定一串数字,计算长度为 n 的连续数字子串的最大乘积。例如,对于输入'1027839564',3位系列的最大乘积为270(9 * 5 * 6),5位系列的最大乘积为7560(7 * 8 * 3 * 9 * 5)。注意,这些系列只需要在输入中占据相邻位置即可;数字不必在数字上是连续的。对于输入 '73167176531330624919225119674426574742355349194934',一系列 6 位数字的最大乘积是 23520。>

我正在尝试完成来自exercism.io的代码挑战, 这是给出的描述。我正在进行第二次重构,但在两个测试用例上仍然失败。

using System;
using System.Collections.Generic;
using System.Linq;

public static class LargestSeriesProduct
{
    /* Function to get product of digits */
    static int getProduct(int n)
    {
        int product = 1;

        while (n != 0)
        {
            product = product * (n % 10);
            n = n / 10;
        }

        return product;
    }

    static long getAnswer(string d, int s)
    {
        List<string> listString = new List<string>();

        for (int i = 0; i < d.Length - s + 1; ++i)
            listString.Add(d.Substring(i, s));

        List<int> listInt = listString.ConvertAll(int.Parse);

        return getProduct(listInt.Max());
    }

    public static long GetLargestProduct(string digits, int span)
    {
        if (span > digits.Length)
        {
            throw new ArgumentException("Rejects_span_longer_than_string_length");
        }

        else if (span == 0 || digits.Length == 0)
        {
            return 1;
        }

        else if (span == 1 && digits.Length == 0)
        {
            throw new ArgumentException("Rejects_empty_string_and_nonzero_span");
        }

        else if (span < 0)
        {
            throw new ArgumentException("Rejects_negative_span");
        }

        else if (!digits.All(char.IsDigit))
        {
            throw new ArgumentException("Rejects_invalid_character_in_digits");
        }

        else if (digits.All(c => c == '0'))
        {
            return 0;
        }

        else
        {
            return getAnswer(digits, span);
        }
    }
}






/*
public static class LargestSeriesProduct
{
    public static long GetLargestProduct(string digits, int span)
    {
        try
        {
            return Enumerable.Range(0, digits.Length - span + 1).
            Select(i => digits.Substring(i, span)).
            Select(x => x.Aggregate(1, (a, b) => a * Convert.ToInt32(b.ToString()))).
            Max();
        }
        catch
        {
            throw new ArgumentException();
        }
    }
}
*/

被注释掉的代码是最受欢迎的答案。但是,这不是我的答案,我正试图自己解决这个问题。我一次通过代码进行一项测试。我被困在两个测试用例上。以下两种情况在测试中启用了跳过

// This file was auto-generated based on version 1.2.0 of the canonical data.

using System;
using Xunit;

public class LargestSeriesProductTest
{
    [Fact]
    public void Finds_the_largest_product_if_span_equals_length() => Assert.Equal(18, LargestSeriesProduct.GetLargestProduct("29", 2));

    [Fact]
    public void Can_find_the_largest_product_of_2_with_numbers_in_order() => Assert.Equal(72, LargestSeriesProduct.GetLargestProduct("0123456789", 2));

    [Fact(Skip = "specific reason")]
    public void Can_find_the_largest_product_of_2() => Assert.Equal(48, LargestSeriesProduct.GetLargestProduct("576802143", 2));

    [Fact]
    public void Can_find_the_largest_product_of_3_with_numbers_in_order() => Assert.Equal(504, LargestSeriesProduct.GetLargestProduct("0123456789", 3));

    [Fact]
    public void Can_find_the_largest_product_of_3() => Assert.Equal(270, LargestSeriesProduct.GetLargestProduct("1027839564", 3));

    [Fact]
    public void Can_find_the_largest_product_of_5_with_numbers_in_order() => Assert.Equal(15120, LargestSeriesProduct.GetLargestProduct("0123456789", 5));

    [Fact(Skip = "specific reason")]
    public void Can_get_the_largest_product_of_a_big_number() => Assert.Equal(23520, LargestSeriesProduct.GetLargestProduct("73167176531330624919225119674426574742355349194934", 6));

    [Fact]
    public void Reports_zero_if_the_only_digits_are_zero() => Assert.Equal(0, LargestSeriesProduct.GetLargestProduct("0000", 2));

    [Fact]
    public void Reports_zero_if_all_spans_include_zero() => Assert.Equal(0, LargestSeriesProduct.GetLargestProduct("99099", 3));

    [Fact]
    public void Rejects_span_longer_than_string_length() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("123", 4));

    [Fact]
    public void Reports_1_for_empty_string_and_empty_product_0_span_() => Assert.Equal(1, LargestSeriesProduct.GetLargestProduct("", 0));

    [Fact]
    public void Reports_1_for_nonempty_string_and_empty_product_0_span_() => Assert.Equal(1, LargestSeriesProduct.GetLargestProduct("123", 0));

    [Fact]
    public void Rejects_empty_string_and_nonzero_span() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("", 1));

    [Fact]
    public void Rejects_invalid_character_in_digits() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("1234a5", 2));

    [Fact]
    public void Rejects_negative_span() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("12345", -1));
}

我已经尝试使用正则表达式来删除 0,但这会导致其他通过测试失败。我尝试将 0 更改为 1,但这会产生不同的产品。我能给出的通过所有这些测试的最佳线索是在我自己下面的注释掉的代码中。我正在尝试使用我得到的东西,完成它,然后用我对 C# 的知识将它重构为不那么冗长的东西。我是 C# 新手。

非常感谢通过这两个测试而不使我通过的其他测试失败的任何帮助。

标签: c#

解决方案


我明白迈克尔兰德尔现在在说什么了。这是该链接中建议的代码。它通过了所有测试。我将接受这一点,并忽略我的代码是不可接受的重构。这也更简洁易读。

using System;
using System.Linq;
using System.Numerics;

public static class LargestSeriesProduct
{
    static BigInteger getAnswer(string d, int s) => Enumerable.Range(0, d.Length - s + 1)
        .Select(i => d.Substring(i, s))
        .Select(n => n.Aggregate(new BigInteger(1), (current, t) => current * (t - '0')))
        .OrderByDescending(x => x)
        .First();

    public static long GetLargestProduct(string digits, int span)
    {
        if (span > digits.Length)
        {
            throw new ArgumentException("Rejects_span_longer_than_string_length");
        }

        else if (span == 0 || digits.Length == 0)
        {
            return 1;
        }

        else if (span == 1 && digits.Length == 0)
        {
            throw new ArgumentException("Rejects_empty_string_and_nonzero_span");
        }

        else if (span < 0)
        {
            throw new ArgumentException("Rejects_negative_span");
        }

        else if (!digits.All(char.IsDigit))
        {
            throw new ArgumentException("Rejects_invalid_character_in_digits");
        }

        else if (digits.All(c => c == '0'))
        {
            return 0;
        }

        else
        {
            return (int)getAnswer(digits, span);
        }
    }
}

推荐阅读