Home > Enterprise >  Error when rearranging a three-digit number to find the maximum C#
Error when rearranging a three-digit number to find the maximum C#

Time:07-02

I need to find the maximum integer that can be obtained using numbers of arbitrary three-digit natural n permutation (100 <= n <= 999). Example:

n = 165   result =  651 

My decision

public static int Task2(int n)
{
    int firstValue = n / 100;
    int secondValue = n / 10 % 10;
    int thirdValue = n % 10;

    if (secondValue >= thirdValue)
    {
        int swap1 = secondValue * 100   firstValue * 10   thirdValue;
        return swap1; 
    }

    if (secondValue >= firstValue)
    {
        int swap2 = secondValue * 100   thirdValue * 10   firstValue;
    return swap2;
    }
    if (firstValue >= secondValue)
    {
        int swap3 = firstValue * 100   thirdValue * 10   secondValue;
        return swap3;
    }
    if (thirdValue >= secondValue)
    {
        int swap4 = thirdValue * 100   firstValue * 10   secondValue;
        return swap4;
    }
    if (thirdValue >= firstValue){
        int swap5 = thirdValue * 100   secondValue * 10   firstValue;
        return swap5;
    }
    if (thirdValue == firstValue && thirdValue == secondValue)
    {
        int swap0 = secondValue * 100   firstValue * 10   thirdValue;
        return swap0;
    }
    return 0;
}

And I pass all the tests except that:

[TestCase(174, 741)]

But these tests are going well

[TestCase(401, 410)]
[TestCase(999, 999)]
[TestCase(370,730)]
[TestCase(625,652)]      

From later comments:

The thing is that I need to make it as simple as possible and without using arrays, loops and third-party methods.

CodePudding user response:

With dumb constraints:

The idea is to manually sort the digits the more efficient way.
It can be done in three comparisons (witch is optimal because we have to test all digits, and there is three of them):

[TestCase(123, ExpectedResult = 321)]
[TestCase(132, ExpectedResult = 321)]
[TestCase(213, ExpectedResult = 321)]
[TestCase(231, ExpectedResult = 321)]
[TestCase(312, ExpectedResult = 321)]
[TestCase(321, ExpectedResult = 321)]
public int Test2(int input)
{
    var (u, t, h) = (input % 10, (input /= 10) % 10, (input /= 10) % 10);
    (h, t) = t > h ? (t, h) : (h, t);
    (t, u) = u > t ? (u, t) : (t, u);
    (h, t) = t > h ? (t, h) : (h, t);

    return h * 100   t * 10   u;
}

Original response:

You manually sort 3 values with a bunch of if.
There is many better way to do that.

[TestCase(12, ExpectedResult = 21)]
[TestCase(147, ExpectedResult = 741)]
public int Test(int input)
{
    return GetDigits(input)                  // get digits
          .OrderByDescending(v => v)         // order them from the biggest to the smallest
          .Aggregate((a, b) => 10 * a   b);  // rebuild a number from the sorted digits
}

/// <summary>
/// Return the digits of <param name="input" />, LSD first.
/// </summary>
/// <param name="input">The input value</param>
/// <param name="b">The base (10 by default)</param>
/// <returns>The digits of <param name="input" />, LSD first.</returns>
/// <exception cref="ArgumentException">
/// If <param name="input" /> is negative.
/// If <param name="b" /> is lower than 2.
/// </exception>
public static IEnumerable<int> GetDigits(int input, int b = 10)
{
    if (input < 0)
        throw new ArgumentException("input must not be a negative number", nameof(input));

    if (b < 2)
        throw new ArgumentException("base must not be lower than 2", nameof(input));

    // Handle the 0 case.
    if (input == 0)
    {
        yield return 0;
        yield break;
    }

    while (input > 0)
    {
        yield return input % b;
        input /= b;
    }
}

CodePudding user response:

The code below works, using an unrolled BubbleSort. But it uses some things that a teacher will know are too advanced for you at this moment, so don't use exactly this (teachers know about SO as well - at least, I hope they do). You can easily adjust it, once you understand what this does and how.

void Main()
{
    Verify(401, 410);
    Verify(999, 999);
    Verify(370, 730);
    Verify(625, 652);
    Verify(174, 741);
}

void Verify(int input, int expected)
{
    var sorted = BubbleSort(input);
    if (sorted == expected)
        Console.WriteLine($"{input} correctly sorted to {sorted}");
    else
        Console.WriteLine($"{input} should give {expected} but gave {sorted}");
}

int BubbleSort(int input)
{
    // get digits (assuming 'input' is between 0 and 999)
    int d1 = input / 100;
    int d2 = input / 10 % 10;
    int d3 = input % 10;
    
    if (d2 > d1)
    {
        // digits 1&2 in wrong order, so swap them
        (d1, d2) = (d2, d1);
    }
    
    if (d3 > d2)
    {
        // digits 2&3 in wrong order, so swap them
        (d2, d3) = (d3, d2);
    }

    if (d2 > d1)
    {
        // digits 1&2 in wrong order again, so swap them
        (d1, d2) = (d2, d1);
    }

    return d1*100   d2*10   d3;
}

After swapping two digits, it will continue checking the other digits.

  • Starting from a worst-case "123", it first swaps the first two digits, leading to 213.
  • Then it swaps the last two digits, leading to 231.
  • Then it swaps the first two again, giving the final 321

CodePudding user response:

You can achieve the same, by sorting each character taken from the input value.

    public static string FindLargest(int input)
    {
        var chars = input.ToString().ToArray<char>(); // split the number into characters.
        Array.Sort<char>(chars); // sort ascending.
        Array.Reverse(chars); // reverse the array.
        return string.Join(string.Empty, chars.ToArray()); // join them together.
    }
  •  Tags:  
  • c#
  • Related