Click here to Skip to main content
15,881,089 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
The late coding challenge for today is straightforward.

Given a set of integers, arrange the integers so that the final integer thus formed is the largest number possible.

For example.

{ 1,5,67,9 } would be arranged to form 96751

The list may contain up to 50 numbers, and each number will be less than 256 and positive.

What I have tried:

To keep the problems suitably ambiguous.

Last week's winner was Graeme_Grant, mainly because he taught us all words we never knew. Send Sean your details and something (possibly) appropriate will wing it's way home.
Posted
Updated 23-Jan-17 20:37pm
v2
Comments
PIEBALDconsult 20-Jan-17 18:48pm    
"To keep the problems suitably ambiguous."


1 == 1
5 == 101
9 == 1001
67 == 1000011

110110011000011
Graeme_Grant 20-Jan-17 19:43pm    
Linq makes it simple...

var sorted = (new [] { 1, 5, 67, 9 }).Select(i => i.ToString()).OrderByDescending(i => i).Select(i => Convert.ToInt32(i)).ToArray();

but where is the fun in that... ;)
Graeme_Grant 20-Jan-17 21:54pm    
It's a little bit tricker than this, so I've created a one-liner Linq solution[^] below.
Patrice T 21-Jan-17 1:31am    
Idea: keeping spaces in answer help reading the order of numbers.
Graeme_Grant 21-Jan-17 1:48am    
My output was as per Chris' request. Not hard to add spaces if needed. ;)

C#
System.Console.WriteLine ( BiggestIntegerInator
(
  System.Environment.CommandLine.Rive 
  ( Option.RemoveEmptyEntries 
  | Option.RemoveQuotes 
  | Option.HonorEscapes 
  | Option.HonorQuotes 
  )
) ) ;


(Rive is in one of my Articles, it's a more flexible version of Split.)

1 05 6.7E+1 "9" yields 96751


C#
private static string
BiggestIntegerInator
(
  System.Collections.Generic.IList<string> Values
)
{
  System.Text.StringBuilder result = new System.Text.StringBuilder() ;

  System.Collections.Generic.SortedList<string,int> l =
    new System.Collections.Generic.SortedList<string,int>
    (
      Values.Count
    ,
      new DescendingComparer<string>()
    ) ;

  for ( int i = 0 ; i < Values.Count ; i++ )
  {
    string v = Values [ i ] ;

    double j ;

    if ( System.Double.TryParse ( v , out j ) && ( ( v = j.ToString() ).IndexOf ( '.' ) == -1 ) )
    {
      if ( l.ContainsKey ( v ) )
      {
        l [ v ]++ ;
      }
      else
      {
        l [ v ] = 1 ;
      }
    }
  }

  for ( int i = 0 ; i < l.Count ; i++ )
  {
    string v = l.Keys [ i ] ;

    for ( int j = 0 ; j < l [ v ] ; j++ )
    {
      result.Append ( v ) ;
    }
  }

  return  ( result.ToString() );
}

private class DescendingComparer<T> : System.Collections.Generic.IComparer<T>
where T : System.IComparable<T>
{
  public int
  Compare
  (
    T Op0
  ,
    T Op1
  )
  {
    return ( Op1.CompareTo ( Op0 ) ) ;
  }
}


OK, so that comparer above doesn't quite do the trick, here's another:

C#
private class DescendingNumericStringComparer : System.Collections.Generic.IComparer<string>
{
  public int
  Compare
  (
    string Op0
  ,
    string Op1
  )
  {
    int result = 0 ;

    int i0 = -1 ;
    int i1 = -1 ;

    while ( ( result == 0 ) && ( ( i0 < Op0.Length - 1 ) || ( i1 < Op1.Length - 1 ) ) )
    {
      if ( i0 < Op0.Length - 1 ) i0++ ;
      if ( i1 < Op1.Length - 1 ) i1++ ;

      result = Op1 [ i1 ].CompareTo ( Op0 [ i0 ] ) ;
    }

    if ( result == 0 )
    {
      result = Op0.Length.CompareTo ( Op1.Length ) ;
    }

    return ( result ) ;
  }
}


43 432 435 433 yields 435 43 433 432


So that one has a flaw as well. Here's a dirty little fix (not recommended, due to string manipulation) while I work on a better implementation:

C#
private class DescendingStringComparer : System.Collections.Generic.IComparer<string>
{
  public int
  Compare
  (
    string Op0
  ,
    string Op1
  )
  {
    int result = (Op1 + Op0).CompareTo ( Op0 + Op1 ) ;

    if ( result == 0 )
    {
      result = Op0.Length.CompareTo ( Op1.Length ) ;
    }

    return ( result ) ;
  }
}


24 242 243 yields 243 24 242

Fourth comparer, no string concatenation.
Get the longer of the two lengths and iterate.
When we run out of characters in one of the values, start using the characters at the start of the other value instead.

C#
private class DescendingStringComparer : System.Collections.Generic.IComparer<string>
{
  public unsafe int
  Compare 
  (
    string Op0
  ,
    string Op1
  )
  {
    int result = 0 ;

    int len = Op0.Length > Op1.Length ? Op0.Length : Op1.Length ;

    for ( int i = 0 ; ( result == 0 ) && ( i < len ) ; i++ )
    {
      char c0 = i < Op0.Length ? Op0 [ i ] : Op1 [ i - Op0.Length ] ;
      char c1 = i < Op1.Length ? Op1 [ i ] : Op0 [ i - Op1.Length ] ;
              
      result = c1.CompareTo ( c0 ) ;
    }

    if ( result == 0 )
    {
      result = Op0.Length.CompareTo ( Op1.Length ) ;
    }

    return ( result ) ;
  }
}
 
Share this answer
 
v4
Comments
Patrice T 22-Jan-17 0:43am    
Hu,
I don't see how you are padding small numbers.
How do you handle 4 45 46 43 and 43 432 435 433 ?
PIEBALDconsult 22-Jan-17 1:17am    
I don't; why would I?
Hmmm... I think I see the problem...
Graeme_Grant 22-Jan-17 1:42am    
I like the idea of a SortedList using a custom comparer - I did not think of that! :)

But ppolymorphe is right, try this set: {1, 5, 67, 94, 96, 91, 9}. Your output is: 96-94-91-9-67-5-1 but should yield: 9-96-94-91-67-5-1 - the latter is a larger number - 996...51 is a larger number than 969...51
Graeme_Grant 22-Jan-17 1:50am    
I plugged this in and it corrected the output:
private class InvertedCodeProjectComparer<T> : IComparer<T> where T : IComparable<T>
{
    int IComparer<T>.Compare(T x, T y)
        => Convert.ToInt32(string.Join("", new[] { y, x })) -
           Convert.ToInt32(string.Join("", new[] { x, y }));
}
PIEBALDconsult 22-Jan-17 2:03am    
I'm on it, just testing now...
My Clipper (xBase family like FoxPro) language once again.
Procedure:
1) Convert to strings
2) Sort the numbers in reverse order after some padding to same size.

C++
*   CCCP Code Challenge Code Project
*    Build largest integer
clear
largest({1, 5, 67, 9})
largest({100, 11, 10, 110, 112,1,114})
largest({4, 45, 46, 43})
largest({43, 432, 435, 433})
largest({2, 243, 242, 245, 241, 24, 221})
largest({20, 221, 226, 202, 2, 201})

procedure largest(lst)
	*	convert 2 string
	for scan=1 to len(lst)
		lst[scan]= str(lst[scan],,,.T.)
	next
	?
	? lst[1]
	for scan=2 to len(lst)
		?? " "
		?? lst[scan]
	next
		
	*	tri par insertion
	for scan=2 to len(lst)
		for ptr= scan to 2 step -1
			*	pad until same lentgh 
			mx= max(len(lst[ptr]), len(lst[ptr-1]))+1
			tmp1= lst[ptr]
			while len(tmp1) < mx
				tmp1 += lst[ptr]
			enddo
			tmp1= left(tmp1,mx)
			
			tmp2= lst[ptr-1]
			while len(tmp2) < mx
				tmp2 += lst[ptr-1]
			enddo
			tmp2= left(tmp2,mx)
			
			if tmp1 > tmp2
				tmp= lst[ptr]
				lst[ptr]= lst[ptr-1]
				lst[ptr-1]= tmp
			endif
		next
	next
	
	*	result
	? lst[1]
	for scan=2 to len(lst)
		?? " "
		?? lst[scan]
	next
	
	return

Variant without padding the strings:
C++
for scan=2 to len(lst)
    for ptr= scan to 2 step -1
        if len(lst[ptr])= len(lst[ptr-1])
            tmp1= lst[ptr]
            tmp2= lst[ptr-1]
        else
            mx= len(lst[ptr])+ len(lst[ptr-1])- 1
            for scanl= 0 to mx
                tmp1= lst[ptr, scanl%len(lst[ptr])+1]
                tmp2= lst[ptr-1, scanl%len(lst[ptr-1])+1]
                if tmp1 != tmp2
                    exit
                endif
            next
        endif
        if tmp1 > tmp2
            tmp= lst[ptr]
            lst[ptr]= lst[ptr-1]
            lst[ptr-1]= tmp
        endif
    next
next

Test sets
VB
1 5 67 9
9 67 5 1

100 11 10 110 112 1 114
114 112 11 1 110 10 100

4 45 46 43
46 45 4 43

43 432 435 433
435 43 433 432

2 243 242 245 241 24 221
245 243 24 242 241 2 221

20 221 226 202 2 201
226 2 221 202 20 201

Note: Spaces in answers just help reading out how numbers are ordered.

[Update] Refined the sort part
The padding part is really tricky, my best guess so far:
The padding is to be made until maximum length + 1
The padding is to be made by repeating the value.

Take 20 and 202. What is the order ?
padding: 20 -> 2020, 202 -> 2022
The order is same as for 2020 and 2022, so 202, 20.

Take 24 and 242. What is the order ?
padding: 24 -> 2424, 242 -> 2422
The order is same as for 2424 and 2422, so 24, 242.
 
Share this answer
 
v20
A LINQ one-liner! (Well, to be honest, about eight lines brutally mashed into one...)
C#
public static BigInteger DoChallenge(this IEnumerable<byte> question)
{
    return (from x in question
            orderby (x < 10) ? x * 1110 :
                    (x < 100) ? x * 100 + Math.Min(x, (x % 10) * 10 + x / 10) :
                    x * 10 descending
            select new BigInteger(x))
        .Aggregate((x, y) =>
            (y < 10) ? x * 10 + y :
            (y < 100) ? x * 100 + y :
            x * 1000 + y);
}
The math idea is to convert each 1- 2- and 3-digit number to a 4-digit number for the purposes of sorting:
  • 123 goes to 1230
  • 12 goes to 1212, slotting it between 122 (1220) and 121 (1210)
  • 21 goes to 2112, slotting it between 212 (2120) and 211 (2110)
  • 2 goes to 2220, slotting it between 223 (2230) and 221 (2210), and between 23 (2323) and 21 (2112)
It seems to work for a bunch of assorted test cases, though it's not thoroughly tested or proven yet.
 
Share this answer
 
Comments
Graeme_Grant 20-Jan-17 20:30pm    
I get a wrong result for this set: { 1, 5, 67, 94, 96, 91, 9 } - 910668943 instead of 99694916751
H2O-au 20-Jan-17 20:42pm    
Yeah I get 910668943 when I use an int instead of a System.Numerics.BigInteger. The aggregation epic-fails. Seems that lowly ints can't handle 150-digit numbers! :D Though with BigInteger I get 99694916751.
Graeme_Grant 20-Jan-17 20:57pm    
ah ... int vs BigInt ... gotcha! Will check that later... :)
Patrice T 20-Jan-17 20:46pm    
I get: 9 96 94 91 67 5 1
Graeme_Grant 20-Jan-17 21:58pm    
"Given a set of integers..." > The input should be of type int and not byte...
Here is another Linq one-liner. I've wrapped it up as an extension method. The comparer can be used for both ascending & descending calculation although for this challenge only descending positive numbers ranging from 1 to 256 is required.

The core logic is a simple one-liner that can be used with any sorting algorithm - join (not add) the numbers alternatively and subtract the first value from the second. A negative result means left is smaller (we need to swap), zero is equal (nothing to do), and positive is left is larger (nothing to do). eg: {94, 9} = 949 - 994 = -45, so we need to swap the numbers and the new sequence should be {9, 94}. However, {1, 112} = 1112 - 1121 = -9, so the correct order is {112, 1}.

Here is the comparer method that does all the work:
C#
class CodeProjectComparer : IComparer<int>
    {
        int IComparer<int>.Compare(int x, int y)
            => Convert.ToInt32(string.Join("", new[] { x, y })) -
               Convert.ToInt32(string.Join("", new[] { y, x }));
    }

This class can be used with any sorting algorithm. I have added Solution 5 that visually demonstrates the effectiveness of the comparer method above with up to 9 different sorting algorithms.

If you do not want a seperate class but rather as an expression-body member[^]:
C#
Comparer<int> Compare()
        => Comparer<int>.Create((x, y)
            => Convert.ToInt32(string.Join("", new[] { x, y })) -
               Convert.ToInt32(string.Join("", new[] { y, x })));

Here is a Linq one-liner (used in this solution) that includes the comparer in-line:
C#
public static string ArrangedFormNumbersDescending(this int[] nums)
    => string.Join("", 
                   nums.OrderByDescending(
                       i => i, 
                       Comparer<int>.Create((x, y)
                           => Convert.ToInt32(string.Join("", new[] { x, y })) - 
                              Convert.ToInt32(string.Join("", new[] { y, x })))));

Side note: If you are interested in seeing how Microsoft implements sorting for their Linq OrderBy and OrderByDescending, you can view their source code[^].

Below is a sample app using the Linq one-liner and the output it generates.

Here is my attempt, of a fully working version, to make the solution "suitably ambiguous" to meet one of the challenge's requirement:
C#
using System                                                                                      ;
using System.Collections.Generic                                                                  ;
using System.Linq                                                                                 ;

namespace ArrangedFormNumbers                                                                     {
    static class Program                                                                          {
        static void Main(string[] args)                                                           {
            var max = 50                                                                          ;
            var r = new Random()                                                                  ;
            var randomSet = new int[max]                                                          ;

            for (int i = 0; i < max; i++)                                                         {
                for (;;)                                                                          {
                    var n = r.Next(1, 255)                                                        ;
                    if (!randomSet.Contains(n))                                                   {
                        randomSet[i] = n                                                          ;
                        break                                                                     ;
                                                                                                  }
                                                                                                  }
                                                                                                  }
            var tests = new List<int[]>()                                                         {
                new[] { 1, 5, 67, 9 },
                new[] { 1, 5, 67, 94, 96, 91, 9 },
                new[] { 11, 112, 1, 114 },
                randomSet                                                                         }
                                                                                                  ;
            foreach (var test in tests)                                                           {
                Console.WriteLine($"Input:  {{{string.Join(", ", test)}}}")                       ;
                Console.WriteLine($"Output: {test.ArrangedFormNumbersDescending()}\r\n")          ;
                                                                                                  }
            Console.WriteLine("-- Press any key to exit --")                                      ;
            Console.ReadKey()                                                                     ;
                                                                                                  }
                                                                                                  }
    public static class ArrangeFormNumbersExtension                                               {
        public static string ArrangedFormNumbersAscending(this int[] nums)
            => string.Join("", nums.OrderBy(
                i => i,
                Comparer<int>.Create((x, y) =>
                    Convert.ToInt32(string.Join("", new[] { x, y })) - 
                    Convert.ToInt32(string.Join("", new[] { y, x })))))                           ;

        public static string ArrangedFormNumbersDescending(this int[] nums)
            => string.Join("", nums.OrderByDescending(
                i => i, 
                Comparer<int>.Create((x, y) => 
                    Convert.ToInt32(string.Join("", new[] { x, y })) - 
                    Convert.ToInt32(string.Join("", new[] { y, x })))))                           ;
                                                                                                  }
                                                                                                  }

This is a properly formatted version:
C#
using System;
using System.Collections.Generic;
using System.Linq;

namespace ArrangedFormNumbers
{
    static class Program
    {
        static void Main(string[] args)
        {
            var max = 50;
            var r = new Random();
            var randomSet = new int[max];

            for (int i = 0; i < max; i++)
            { 
                for (;;)
                {
                    var n = r.Next(1, 255);
                    if (!randomSet.Contains(n))
                    {
                        randomSet[i] = n;
                        break;
                    }
                }
            }

            var tests = new List<int[]>()
            {
                new[] { 1, 5, 67, 9 },
                new[] { 1, 5, 67, 94, 96, 91, 9 },
                new[] { 11, 112, 1, 114 },
                randomSet
            };


            foreach (var test in tests)
                Console.WriteLine($"Input:  {{{string.Join(", ", test)}}}\r\nOutput: {test.ArrangedFormNumbersDescending()}\r\n");

            Console.WriteLine("-- Press any key to exit --");
            Console.ReadKey();
        }
    }

    public static class ArrangeFormNumbersExtension
    {
        public static string ArrangedFormNumbersAscending(this int[] nums)
            => string.Join("", nums.OrderBy(
                i => i,
                Comparer<int>.Create((x, y) =>
                    Convert.ToInt32(string.Join("", new[] { x, y })) - Convert.ToInt32(string.Join("", new[] { y, x })))));

        public static string ArrangedFormNumbersDescending(this int[] nums)
            => string.Join("", nums.OrderByDescending(
                i => i, 
                Comparer<int>.Create((x, y) => 
                    Convert.ToInt32(string.Join("", new[] { x, y })) - Convert.ToInt32(string.Join("", new[] { y, x })))));
    }
}

Update: Added a random generator to test range & max requirement.

Output:
Input:  {1, 5, 67, 9}
Output: 96751

Input:  {1, 5, 67, 94, 96, 91, 9}
Output: 99694916751

Input:  {11, 112, 1, 114}
Output: 114112111

Input:  {239, 196, 48, 208, 206, 94, 238, 246, 20, 81, 47, 115, 254, 144, 226, 45, 8, 249, 140, 53, 245, 190, 252, 135, 96, 63, 28, 110, 243, 143, 247, 146, 88, 13, 77, 18, 204, 142, 193, 34, 30, 148, 251, 228, 15, 170, 67, 149, 184, 202}
Output: 9694888817767635348474534302825425225124924724624524323923822822620820620420220196193190184181701514914814614414314214013513115110

-- Press any key to exit --

If you wanted to clean up the extensions and remove duplication, then you could use:
C#
public static class ArrangeFormNumbersExtension
{
    private static Comparer<int> Compare()
        => Comparer<int>.Create((x, y)
            => Convert.ToInt32(string.Join("", new[] { x, y })) - Convert.ToInt32(string.Join("", new[] { y, x })));

    public static string ArrangedFormNumbersAscending(this int[] nums)
        => string.Join("", nums.OrderBy(i => i, Compare()));

    public static string ArrangedFormNumbersDescending(this int[] nums)
        => string.Join("", nums.OrderByDescending(i => i, Compare()));
}

... but then it's no longer a one liner. Where is the fun in that.

Update: PIEBALDConsult doesn't like the idea of using strings in the Comparer, so here is a pure Integer calculated version just for him ;)

1. Comparer class version:
C#
class CodeProjectComparer : IComparer<int>
    {
        int IComparer<int>.Compare(int x, int y) => (int)(x.Concat(y) - y.Concat(x));
    }

2. expression-body member[^]:
C#
Comparer<int> Compare()
        => Comparer<int>.Create((x, y) => (int)(x.Concat(y) - y.Concat(x));

3. A Linq one-liner (used in this solution) that includes the comparer in-line:
C#
public static string ArrangedFormNumbersDescending(this int[] nums)
    => string.Join("", nums.OrderByDescending(
           i => i, Comparer<int>.Create((x, y) => (int)(x.Concat(y) - y.Concat(x)))));

All three (3) versions will however require the following supporting extension:
C#
public static class SystemExtension
{
    public static Int64 Concat(this Int32 x, Int32 y)
    {
        Int64 pow = 1;
        while (pow <= y) pow = ((pow << 2) + pow) << 1;
        return x * pow + y;
    }
}

Here is the complete Integer only version:
C#
using System;
using System.Collections.Generic;
using System.Linq;

namespace ArrangedFormNumbers
{
    public static class AppExtensions
    {
        public static string ArrangedFormNumbersDescending(this int[] nums)
            => string.Join(" ", nums.OrderByDescending( i => i, Comparer<int>.Create((x, y) => (int)(x.Concat(y) - y.Concat(x)))));

        public static Int64 Concat(this Int32 x, Int32 y)
        {
            Int64 pow = 1;
            while (pow <= y) pow = ((pow << 2) + pow) << 1;
            return x * pow + y;
        }
    }

    public static class Program
    {
        static void Main(string[] args)
        {
            var tests = InitTests();
            foreach (var test in tests)
                Console.WriteLine($"----\r\nInput:  {{{string.Join(", ", test)}}}\r\n\r\nOutput: {test.ArrangedFormNumbersDescending()}\r\n");

            Console.WriteLine("----\r\n\r\n-- Press any key to exit --");
            Console.ReadKey();
        }

        static List<int[]> InitTests(int max = 50)
        {
            var r = new Random();
            var randomSet = new int[max];

            for (int i = 0; i < max; i++)
                for (;;)
                {
                    var n = r.Next(1, 255);
                    if (!randomSet.Contains(n))
                    {
                        randomSet[i] = n;
                        break;
                    }
                }

            return new List<int[]>()
            {
                new[] { 1, 5, 67, 9 },
                new[] { 1, 5, 67, 94, 96, 91, 9 },
                new[] { 11, 112, 1, 114 },
                new[] {4, 45, 46, 43},
                new[] {23, 232, 235, 233},
                new[] { 102, 1, 36, 12, 21, 79, 170, 9 },
                new[] { 3, 12, 306, 12, 21, 190, 170, 90 },
                new[] { 122, 151, 169, 139, 99, 245, 31, 67, 42, 61, 180, 52, 248, 200, 90, 223, 109, 51, 91, 98, 186, 191, 215, 70, 193, 179, 43, 84, 203, 228, 106, 246, 142, 150, 81, 145, 123, 229, 135, 120, 41, 40, 9, 234, 53, 156, 115, 24, 220, 233 },
                randomSet
            };
        }
    }
}

And the output (results spaced as suggested by ppolymorphe) using the new (pure Integer) comparer:
----
Input:  {1, 5, 67, 9}

Output: 9 67 5 1

----
Input:  {1, 5, 67, 94, 96, 91, 9}

Output: 9 96 94 91 67 5 1

----
Input:  {11, 112, 1, 114}

Output: 114 112 11 1

----
Input:  {4, 45, 46, 43}

Output: 46 45 4 43

----
Input:  {23, 232, 235, 233}

Output: 235 233 23 232

----
Input:  {102, 1, 36, 12, 21, 79, 170, 9}

Output: 9 79 36 21 170 12 1 102

----
Input:  {3, 12, 306, 12, 21, 190, 170, 90}

Output: 90 3 306 21 190 170 12 12

----
Input:  {122, 151, 169, 139, 99, 245, 31, 67, 42, 61, 180, 52, 248, 200, 90, 223, 109, 51, 91, 98, 186, 191, 215, 70, 193, 179, 43, 84, 203, 228, 106, 246, 142, 150, 81, 145, 123, 229, 135, 120, 41, 40, 9, 234, 53, 156, 115, 24, 220, 233}

Output: 99 9 98 91 90 84 81 70 67 61 53 52 51 43 42 41 40 31 248 246 245 24 234 233 229 228 223 220 215 203 200 193 191 186 180 179 169 156 151 150 145 142 139 135 123 122 120 115 109 106

----
Input:  {241, 17, 122, 59, 108, 206, 69, 107, 64, 140, 38, 84, 3, 249, 10, 133, 240, 253, 54, 248, 182, 51, 247, 11, 132, 172, 61, 171, 175, 219, 13, 66, 35, 123, 252, 99, 195, 147, 119, 250, 204, 161, 232, 77, 106, 162, 146, 93, 168, 131}

Output: 99 93 84 77 69 66 64 61 59 54 51 38 35 3 253 252 250 249 248 247 241 240 232 219 206 204 195 182 175 172 17 171 168 162 161 147 146 140 133 132 13 131 123 122 119 11 108 107 106 10

----

-- Press any key to exit --

Enjoy!
 
Share this answer
 
v17
Comments
PIEBALDconsult 22-Jan-17 12:26pm    
"but then it's no longer a one liner. Where is the fun in that"
You can have either one-line or performance; you can't have both.
Graeme_Grant 22-Jan-17 12:45pm    
Clean or duplicated code... yes...
Updated on 1/21. Obviously the previous solution has a flaw in it. Thanks to Graeme_Grant for pointing it out. I modified the solution to add some redundant step into it such as grouping by the first digit and then sort it by group. After that concatenate the group into a string. Anyway, I think the key here is the Comparer<int>. I think the solution from Graeme_Grant is outstanding.

------
i think this should do it. First, divide the integer by base 10 to the power of length of the integer (weight), then sort it by the weight and concatenate the output into string using string.join method.

logic
C#
var testData = new List<int[]>()
            {
                new[] { 1, 5, 67, 6, 9, 91 },
                new[] { 81, 8, 8111, 811 },
                new[] { 1,102,0,10,1, 60, 61 },
                new[] { 2,0,11,10,69,79,4 },
                new[] { 102,01,36,12,21,79,970,9 },
                new[] { 3,012,306,12,21,790,970,90 },
                new[] { 10, 5, 67, 97, 8 },
                new[] { 70, 71, 102, 1, 10,8,80, 9,91, 90, 900, 9000, 2, 4, 1112, 1100,11,99}
            };

            foreach (var d in testData)
            {
                var result = string.Join("", d.GroupBy(x => x.ToString().Substring(0, 1), (number, subList) => new
                {
                    Number = number,
                    SubList = subList.OrderByDescending(x => x, 
                    Comparer<int>.Create((a, b) => int.Parse(string.Format("{0}{1}", a, b)) - int.Parse(string.Format("{0}{1}", b, a))))

                }).OrderByDescending(x => x.Number).SelectMany(s => s.SubList));

                Console.WriteLine("input: {0} ", string.Join(",", d));
                Console.WriteLine("output: {0} ", result);
                Console.WriteLine();
            }

            Console.WriteLine();
            Console.ReadLine();


Output
input: 1,5,67,6,9,91
output: 9-91-67-6-5-1

input: 81,8,8111,811
output: 8-81-811-8111

input: 1,102,0,10,1,60,61
output: 61-60-1-1-102-10-0

input: 2,0,11,10,69,79,4
output: 79-69-4-2-11-10-0

input: 102,1,36,12,21,79,970,9
output: 9-970-79-36-21-12-1-102

input: 3,12,306,12,21,790,970,90
output: 970-90-790-3-306-21-12-12

input: 10,5,67,97,8
output: 97-8-67-5-10

input: 70,71,102,1,10,8,80,9,91,90,900,9000,2,4,1112,1100,11,99
output: 9-99-91-90-900-9000-8-80-71-70-4-2-1112-1-11-1100-102-10
 
Share this answer
 
v2
Comments
Graeme_Grant 20-Jan-17 23:33pm    
try this set: { 1, 5, 67, 94, 96, 91, 9 }
Bryian Tan 21-Jan-17 0:12am    
haha, yeah, too good to be true, doesn't work well with 81,8,91,9
Graeme_Grant 21-Jan-17 0:24am    
yes ... I too made the mistake with my initial comment at the top... [edit] I gather that is why Chris posted it as a challenge. ;)
Graeme_Grant 22-Jan-17 0:32am    
Hey Bryian, Thanks for the comments in your solution. I am humbly honored. :)
Patrice T 21-Jan-17 1:29am    
I get
102 1 36 12 21 79 970 9
9 970 79 36 21 12 1 102

3 12 306 12 21 790 970 90
970 90 790 3 306 21 12 12
[Updated] Using the IComparer<T> method from Solution 3, here is a visualization of the sorting with up to nine (9) sorting algorithms: Bubble sort[^], Comb Sort[^], Cycle Sort[^], Gnome Sort[^], Insertion Sort[^], Odd-even sort[^], Quick Sort[^], Selection Sort[^], Shell sort[^].

I have made them asynchronous so several can run simultaneously and see how they function. I've colour-coded the actions: blue = evaluating, green = swapping, gray = inactive. Lastly, there is a sleep delay value that can be set before running the app so that you can adjust it to suit you.

Here is my attempt, a fully working version, to make the solution "suitably ambiguous" to meet one of the challenge's requirement:
C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace VisualSort {

public class CodeProjectComparer : IComparer<int> { int IComparer<int>.Compare(int a, int b) => Convert.ToInt32(string.Join("", new[] { a, b })) - Convert.ToInt32(string.Join("", new[] { b, a })); }

public enum SortType { Bubble, Comb, Cycle, Gnome, Insertion, OddEven, Quick, Selection, Shell }

static class Program { static object P = new object(); static int Q { get; set; } static int R { get; set; } static Dictionary<SortType, SortTracker> S = new Dictionary<SortType, SortTracker>(); static List<List<Position>> U = new List<List<Position>>();
static void Main(string[] a) { ucolr = Console.ForegroundColor; ecolr = ConsoleColor.Blue; scolr = ConsoleColor.Green; R = 50; Q = 100; Intro(); PromptUser("-- Press any key to begin --", true); MainAsync().GetAwaiter().GetResult(); PromptUser("-- Press any key to exit --"); }
static async Task MainAsync() { InitPos(); Add(SortType.Bubble, "Bubble Sort Descending"); Add(SortType.Insertion, "Insertion Sort"); Add(SortType.Quick, "Quick Sort"); Add(SortType.Shell, "Shell Sort Descending"); InitArea(); var a = InitTests(); for (int b = 0; b < a.Count; b++) { await ExecuteTestAsync(a[b], string.Format("Running Test: {0} of {1}...", b + 1, a.Count)); if (b < a.Count - 1) PromptUser("-- Press any key to run the next test --"); } }
static async Task ExecuteTestAsync(int[] a, string b) { ClearArea(S.Count); SetAreas(a); await Task.Delay(1000); WriteAt(new Position(5, upos), ucolr, b); await Task.WhenAll(S.Execute(a)); }
static void Add(SortType a, string b) { S.Add(a, new SortTracker(b, ucolr, ecolr, scolr, U[S.Count], new Position(23, 9 + S.Count * 10), Q, WriteAt)); }
static List<int[]> InitTests(int a = 50) { R = a; var b = new Random(); var c = new int[R]; for (int d = 0; d < R; d++) for (;;) { int e = b.Next(1, 255); if (!c.Contains(e)) { c[d] = e; break; } } return new List<int[]>(){new[]{1,5,67,9},new[]{1,5,67,94,96,91,9},new[]{11,112,1,114},new[]{4,45,46,43},new[]{23,232,235,233},new[]{102,1,36,12,21,79,170,9},new[]{3,12,306,12,21,190,170,90},c}; }
static int upos; static ConsoleColor ucolr { get; set; } static ConsoleColor ecolr { get; set; } static ConsoleColor scolr { get; set; }
static void SetAreas(int[] a) { foreach (var tracker in S) for (int b = 0; b < a.Length; b++) WriteAt(tracker.Value.Z[b], tracker.Value.W, a[b].ToString().PadLeft(5)); }
static void ClearArea(int a) { int b = 9; foreach (var tracker in S) { for (int c = 0; c < R; c++) WriteAt(tracker.Value.Z[c], tracker.Value.W, "     "); WriteAt(new Position(23, b), tracker.Value.W, "0".PadRight(5)); b += 10; } WriteAt(new Position(5, upos), Console.ForegroundColor, "".PadLeft(40)); }
static void Intro() { Console.WriteLine("CodeProject's Coding challenge: arrange numbers to form the largest possible integer"); Console.WriteLine(""); Console.WriteLine("This is a Visualualisaton of different sorting algorithms on number datasets\r\nthat meet the following requirements:"); Console.WriteLine(""); Console.WriteLine("1. Given a set of integers, arrange the integers so that the final integer\r\n   thus formed is the largest number possible."); Console.WriteLine("2. The list may contain up to 50 numbers, and each number will be less than\r\n   256 and positive."); Console.WriteLine(""); Console.WriteLine("There are a number of different sorting algorithms that can be toggled on/off\r\nin the MainAsync method before running."); Console.WriteLine(""); Console.WriteLine("NOTE: It is advisable to adjust the size of the console window to see all\r\nsorts in action at the same time."); Console.WriteLine(""); Console.WriteLine("Enjoy! :)"); Console.WriteLine(""); Console.WriteLine(""); }
static void InitPos() { int a = R < 11 ? R : 10; int b = R < 11 ? 1 : R / 10; for (int c = 0; c < 9; c++) U.Add(new List<Position>()); for (int d = 0; d < b; d++) for (int e = 0; e < a; e++) { int f = 3; foreach (var postion in U) { postion.Add(new Position((e * 5) + 5, d + f)); f += 10; } } }
static void InitArea() { upos = 2 + S.Count * 10; Console.CursorVisible = false; Console.Clear(); var a = Console.ForegroundColor; var b = Console.BackgroundColor; int c = 1, d = 9; foreach (var tracker in S) { Console.BackgroundColor = ConsoleColor.Blue; WriteAt(new Position(5, c), ConsoleColor.White, string.Format("  {0}", tracker.Value.P).PadRight(50)); Console.BackgroundColor = b; WriteAt(new Position(15, d), ConsoleColor.White, "Steps:"); c += 10; d += 10; } ConsoleBox(new Position(60, 3), 17, 8, ConsoleColor.White); Console.BackgroundColor = ConsoleColor.Blue; WriteAt(new Position(61, 4), ConsoleColor.White, " COLOUR LEGEND "); Console.BackgroundColor = b; WriteAt(new Position(64, 6), ucolr, "idle"); WriteAt(new Position(64, 7), ecolr, "Evaluating"); WriteAt(new Position(64, 8), scolr, "Changing"); Console.ForegroundColor = a; }
static void WriteAt(Position a, ConsoleColor b, string c) { lock (P) { Console.ForegroundColor = b; if (a != null) Console.SetCursorPosition(a.C, a.R); Console.Write(c); } }
static void PromptUser(string a, bool b = false) { WriteAt(b ? null : new Position(5, upos), Console.ForegroundColor, a); Console.ReadKey(); }
static void ConsoleBox(Position a, int b, int c, ConsoleColor d) { var e = Console.ForegroundColor; Console.OutputEncoding = Encoding.GetEncoding(866); Console.ForegroundColor = d; int f = b - 2; var g = string.Join("", Enumerable.Range(1, f).Select(h => "─")); var i = new StringBuilder().Append("┌").Append(g).Append("┐\n").ToString(); var j = new StringBuilder().Append("│").Append("".PadLeft(f)).Append("│\n").ToString(); var k = new StringBuilder().Append("└").Append(g).Append("┘").ToString(); Console.SetCursorPosition(a.C, a.R); Console.Write(i); for (int l = 1; l < c; l++) { Console.SetCursorPosition(a.C, a.R + l); Console.Write(j); } Console.SetCursorPosition(a.C, a.R + c - 1); Console.Write(k); Console.ForegroundColor = e; } }

public enum FeedbackType { Eval, Swap, Done }

public class Position { public Position(int c, int r) { C = c; R = r; } public int C { get; set; } public int R { get; set; } }

public class SortTracker { public SortTracker() { }
public SortTracker(string a, ConsoleColor b, ConsoleColor c, ConsoleColor d, List<Position> e, Position f, int g, Action<Position, ConsoleColor, string> h) { P = a; W = b; X = c; Y = d; Z = e; V = g; U = f; Writer = h; S = new[] { -1, -1 }; }
public string P { get; set; } public int Q { get; set; } public int[] R { get; set; } int[] S { get; } Position U; public int V { get; set; } public ConsoleColor W { get; set; } public ConsoleColor X { get; set; } public ConsoleColor Y { get; set; } public List<Position> Z { get; set; } public Action<Position, ConsoleColor, string> Writer { get; set; }
public void a0(int[] a) { R = a; Q = 0; S[0] = -1; S[1] = -1; }
public Task a1(int a, int b, FeedbackType c, bool d) { switch (c) { case FeedbackType.Done: case FeedbackType.Eval: if (S[0] != -1) { Writer(Z[S[0]], W, R[S[0]].ToString().PadLeft(5)); Writer(Z[S[1]], W, R[S[1]].ToString().PadLeft(5)); } if (a != -1) { S[0] = a; S[1] = b; Writer(Z[a], X, R[a].ToString().PadLeft(5)); Writer(Z[b], X, R[b].ToString().PadLeft(5)); } break; case FeedbackType.Swap: if (d) { Writer(Z[S[0]], W, R[S[0]].ToString().PadLeft(5)); Writer(Z[S[1]], W, R[S[1]].ToString().PadLeft(5)); S[0] = a; S[1] = b; } Writer(Z[a], Y, R[a].ToString().PadLeft(5)); Writer(Z[b], Y, R[b].ToString().PadLeft(5)); break; } Writer(U, W, (++Q).ToString("N0")); return Task.Delay(V); } }

public static class SortHelpers { public static Task[] Execute(this Dictionary<SortType, SortTracker> a, int[] b) { var c = new Task[a.Count]; for (int d = 0; d < a.Count; d++) { var e = a.ElementAt(d); e.Value.a0(b.Select(f => f).ToArray()); switch (e.Key) { case SortType.Bubble: c[d] = e.Value.R.Bubble(new CodeProjectComparer(), e.Value.a1); break; case SortType.Comb: c[d] = e.Value.R.Comb(new CodeProjectComparer(), e.Value.a1); break; case SortType.Cycle: c[d] = e.Value.R.Cycle(new CodeProjectComparer(), e.Value.a1); break; case SortType.Gnome: c[d] = e.Value.R.Gnome(new CodeProjectComparer(), e.Value.a1); break; case SortType.Insertion: c[d] = e.Value.R.Insertion(new CodeProjectComparer(), e.Value.a1); break; case SortType.OddEven: c[d] = e.Value.R.OddEven(new CodeProjectComparer(), e.Value.a1); break; case SortType.Quick: c[d] = e.Value.R.Quick(new CodeProjectComparer(), e.Value.a1); break; case SortType.Selection: c[d] = e.Value.R.Selection(new CodeProjectComparer(), e.Value.a1); break; case SortType.Shell: c[d] = e.Value.R.Shell(new CodeProjectComparer(), e.Value.a1); break; } } return c; }
public static Task Bubble<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { for (int d = 0; d < a.Count - 1; d++) for (int e = 1; e < a.Count - d; e++) { if (c != null) await c.Invoke(e, e - 1, FeedbackType.Eval, false); if (b.Compare(a[e], a[e - 1]) > 0) { a.P(e - 1, e); if (c != null) await c.Invoke(e - 1, e, FeedbackType.Swap, false); } } if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); });
public static Task Comb<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { double d = a.Count; var e = true; while (d > 1 || e) { d /= 1.247330950103979; if (d < 1) d = 1; int f = 0; e = false; while (f + d < a.Count) { int g = f + (int)d; if (c != null) await c.Invoke(f, g, FeedbackType.Eval, false); if (b.Compare(a[f], a[g]) < 0) { a.P(f, g); e = true; if (c != null) await c.Invoke(f, g, FeedbackType.Swap, false); } f++; } } if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); });
public static Task Cycle<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { for (int d = 0; d < a.Count; d++) { T e = a[d]; int f = d; do { int g = 0; for (int h = 0; h < a.Count; h++) { if (c != null) await c.Invoke(f, h, FeedbackType.Eval, false); if (h != d && b.Compare(a[h], e) > 0) g++; } if (f != g) { while (f != g && b.Compare(e, a[g]) == 0) { if (c != null) await c.Invoke(f, g, FeedbackType.Eval, false); g++; } T i = a[g]; a[g] = e; e = i; if (c != null) await c.Invoke(f, g, FeedbackType.Swap, true); f = g; } } while (f != d); } if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); });
public static Task Gnome<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { int d = 1; while (d < a.Count) { if (c != null) await c.Invoke(d, d - 1, FeedbackType.Eval, false); if (b.Compare(a[d], a[d - 1]) <= 0) d++; else { a.P(d, d - 1); if (c != null) await c.Invoke(d, d - 1, FeedbackType.Swap, false); if (d > 1) d--; } } if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); });
public static Task Insertion<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { int d; for (int e = 1; e < a.Count; e++) { T f = a[e]; d = e - 1; if (c != null) await c.Invoke(e, d, FeedbackType.Eval, false); while ((d >= 0) && (b.Compare(a[d], f) < 0)) { a[d + 1] = a[d]; if (c != null) await c.Invoke(d + 1, e, FeedbackType.Swap, true); d--; } a[d + 1] = f; if (c != null) await c.Invoke(d + 1, e, FeedbackType.Swap, true); } if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); });
public static Task OddEven<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { var d = false; while (!d) { d = true; for (int e = 1; e < a.Count - 1; e += 2) { if (c != null) await c.Invoke(e, e + 1, FeedbackType.Eval, false); if (b.Compare(a[e], a[e + 1]) < 0) { a.P(e, e + 1); d = false; if (c != null) await c.Invoke(e, e + 1, FeedbackType.Swap, false); } } for (int e = 0; e < a.Count - 1; e += 2) { if (c != null) await c.Invoke(e, e + 1, FeedbackType.Eval, false); if (b.Compare(a[e], a[e + 1]) < 0) { a.P(e, e + 1); d = false; if (c != null) await c.Invoke(e, e + 1, FeedbackType.Swap, false); } } } if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); });
public static Task Quick<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { await a.X(0, a.Count - 1, b, c); if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); });
static async Task X<T>(this IList<T> a, int b, int c, IComparer<T> d, Func<int, int, FeedbackType, bool, Task> e = null) { if (b < c) { int f = await a.Y(b, c, d, e); await a.X(b, f - 1, d, e); await a.X(f + 1, c, d, e); } }
static async Task<int> Y<T>(this IList<T> a, int b, int c, IComparer<T> d, Func<int, int, FeedbackType, bool, Task> e = null) { int f, g; g = c; T h = a[g]; f = b; for (int i = b; i <= (c - 1); i++) { if (e != null) await e.Invoke(i, g, FeedbackType.Eval, false); if (d.Compare(a[i], h) >= 0) { a.P(i, f); if (e != null) await e.Invoke(i, f, FeedbackType.Swap, true); f++; } } a.P(f, g); if (e != null) await e.Invoke(f, g, FeedbackType.Swap, true); return f; }
public static Task Selection<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { for (int d = a.Count - 1; d > 0; d--) { int e = d; for (int f = 0; f <= d; f++) { if (c != null) await c.Invoke(f, e, FeedbackType.Eval, false); if (b.Compare(a[f], a[e]) < 0) e = f; } a.P(d, e); if (c != null) await c.Invoke(d, e, FeedbackType.Swap, false); } if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); });
public static Task Shell<T>(this IList<T> a, IComparer<T> b, Func<int, int, FeedbackType, bool, Task> c = null) => Task.Run(async () => { var d = true; int e = a.Count; while (d || (e > 1)) { d = false; e = (e + 1) / 2; for (int f = 0; f < (a.Count - e); f++) { if (c != null) await c.Invoke(f + e, f, FeedbackType.Eval, false); if (b.Compare(a[f + e], a[f]) > 0) { a.P(f + e, f); d = true; if (c != null) await c.Invoke(f + e, f, FeedbackType.Swap, false); } } } if (c != null) await c.Invoke(-1, -1, FeedbackType.Done, false); }); }

public static class CollectionExtensions { public static void P<T>(this IList<T> a, int b, int c) { if (a.Count < 2 || b == c) return; T d = a[b]; a[b] = a[c]; a[c] = d; } } }

This is a readable version for those who want to be able to read and understand it:
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisualSort
{
    public class CodeProjectComparer : IComparer<int>
    {
        int IComparer<int>.Compare(int x, int y)
            => Convert.ToInt32(string.Join("", new[] { x, y })) - Convert.ToInt32(string.Join("", new[] { y, x }));
    }

    public enum SortType
    {
        Bubble,
        Comb,
        Cycle,
        Gnome,
        Insertion,
        OddEven,
        Quick,
        Selection,
        Shell
    }

    static class Program
    {
        static object lockObj = new object();
        static int SleepMS { get; set; }
        static int MaxEntries { get; set; } = 50;

        static Dictionary<SortType, SortTracker> Trackers = new Dictionary<SortType, SortTracker>();
        static List<List<Position>> Positions = new List<List<Position>>();

        static void Main(string[] args)
        {
            SleepMS = 100;
            IntroMessage();
            PromptUser("-- Press any key to begin --", true);
            MainAsync().GetAwaiter().GetResult();
            PromptUser("-- Press any key to exit --");
        }

        static async Task MainAsync()
        {
            InitPositions();

            //NOTE: Uncomment up to 4 different sorts at a time...
            //      or all 9 if you have the screen resolution
            //      (or set a very small console font size)
            //
            AddTracker(SortType.Bubble, "Bubble Sort Descending");
            //AddTracker(SortType.Comb, "Comb Sort Descending");
            //AddTracker(SortType.Cycle, "Cycle Sort Descending");
            //AddTracker(SortType.Gnome, "Gnome Sort Descending");
            AddTracker(SortType.Insertion, "Insertion Sort");
            //AddTracker(SortType.OddEven, "Odd-Even Sort Descending");
            AddTracker(SortType.Quick, "Quick Sort");
            //AddTracker(SortType.Selection, "Selection Sort Descending");
            AddTracker(SortType.Shell, "Shell Sort Descending");

            InitWorkArea();
            var tests = InitTests();

            for (int i = 0; i < tests.Count; i++)
            {
                await ExecuteTestAsync(tests[i], $"Running Test: {i + 1} of {tests.Count}...");
                if (i < tests.Count - 1)
                    PromptUser("-- Press any key to run the next test --");
            }
        }

        static async Task ExecuteTestAsync(int[] test, string msg)
        {
            ClearAreas(Trackers.Count);
            SetAreas(test);
            await Task.Delay(1000);
            WriteAt(new Position(5, promptPosition), unsetColor, msg);
            await Task.WhenAll(Trackers.Execute(test));
        }

        static void AddTracker(SortType type, string Title)
        {
            Trackers.Add(type, new SortTracker(Title, unsetColor, evalColor, swapColor, 
                Positions[Trackers.Count], new Position(23, 9 + Trackers.Count * 10), SleepMS, WriteAt));
        }

        static List<int[]> InitTests(int max = 50)
        {
            MaxEntries = max;
            var r = new Random();
            var randomSet = new int[MaxEntries];

            for (int i = 0; i < MaxEntries; i++)
            {
                for (;;)
                {
                    var n = r.Next(1, 255);
                    if (!randomSet.Contains(n))
                    {
                        randomSet[i] = n;
                        break;
                    }
                }
            }

            return new List<int[]>()
            {
                new[] { 1, 5, 67, 9 },
                new[] { 1, 5, 67, 94, 96, 91, 9 },
                new[] { 11, 112, 1, 114 },
                new[] {4, 45, 46, 43},
                new[] {23, 232, 235, 233},
                new[] { 102, 1, 36, 12, 21, 79, 170, 9 },
                new[] { 3, 12, 306, 12, 21, 190, 170, 90 },
                randomSet
            };
        }

        #region Console

        static int promptPosition;

        static ConsoleColor unsetColor { get; } = Console.ForegroundColor;
        static ConsoleColor evalColor { get; } = ConsoleColor.Blue;
        static ConsoleColor swapColor { get; } = ConsoleColor.Green;

        const int Unset = -1;

        static void SetAreas(int[] test)
        {
            foreach (var tracker in Trackers)
                for (int i = 0; i < test.Length; i++)
                    WriteAt(tracker.Value.Positions[i], tracker.Value.UnsetColor, test[i].ToString().PadLeft(5));
        }

        static void ClearAreas(int count)
        {
            int yPos = 9;
            foreach (var tracker in Trackers)
            {
                for (int i = 0; i < MaxEntries; i++)
                    WriteAt(tracker.Value.Positions[i], tracker.Value.UnsetColor, "     ");
                WriteAt(new Position(23, yPos), tracker.Value.UnsetColor, "0".PadRight(5));
                yPos += 10;
            }
            WriteAt(new Position(5, promptPosition), Console.ForegroundColor, "".PadLeft(40));
        }

        static void IntroMessage()
        {
            Console.WriteLine("CodeProject's Coding challenge: arrange numbers to form the largest possible integer");
            Console.WriteLine("");
            Console.WriteLine("This is a Visualualisaton of different sorting algorithms on number datasets\r\nthat meet the following requirements:");
            Console.WriteLine("");
            Console.WriteLine("1. Given a set of integers, arrange the integers so that the final integer\r\n   thus formed is the largest number possible.");
            Console.WriteLine("2. The list may contain up to 50 numbers, and each number will be less than\r\n   256 and positive.");
            Console.WriteLine("");
            Console.WriteLine("There are a number of different sorting algorithms that can be toggled on/off\r\nin the MainAsync method before running.");
            Console.WriteLine("");
            Console.WriteLine("NOTE: It is advisable to adjust the size of the console window to see all\r\nsorts in action at the same time.");
            Console.WriteLine("");
            Console.WriteLine("Enjoy! :)");
            Console.WriteLine("");
            Console.WriteLine("");
        }

        static void InitPositions()
        {
            var cols = MaxEntries < 11 ? MaxEntries : 10;
            var rows = MaxEntries < 11 ? 1 : MaxEntries / 10;

            for (int i = 0; i < 9; i++)
                Positions.Add(new List<Position>());

            for (int y = 0; y < rows; y++)
            {
                for (int x = 0; x < cols; x++)
                {
                    var yOffset = 3;
                    foreach (var postion in Positions)
                    {
                        postion.Add(new Position((x * 5) + 5, y + yOffset));
                        yOffset += 10;
                    }
                }
            }
        }

        static void InitWorkArea()
        {
            promptPosition = 2 + Trackers.Count * 10;

            Console.CursorVisible = false;
            Console.Clear();

            var oldColor = Console.ForegroundColor;
            var oldBack = Console.BackgroundColor;

            int tPos = 1, sPos = 9;
            foreach (var tracker in Trackers)
            {
                Console.BackgroundColor = ConsoleColor.Blue;
                WriteAt(new Position(5, tPos), ConsoleColor.White, $"  {tracker.Value.Title}".PadRight(50));
                Console.BackgroundColor = oldBack;
                WriteAt(new Position(15, sPos), ConsoleColor.White, "Steps:");
                tPos += 10; sPos += 10;
            }

            ConsoleBox(new Position(60, 3), 17, 8, ConsoleColor.White);
            Console.BackgroundColor = ConsoleColor.Blue;
            WriteAt(new Position(61, 4), ConsoleColor.White, " COLOUR LEGEND ");
            Console.BackgroundColor = oldBack;
            WriteAt(new Position(64, 6), unsetColor, "idle");
            WriteAt(new Position(64, 7), evalColor, "Evaluating");
            WriteAt(new Position(64, 8), swapColor, "Changing");

            Console.ForegroundColor = oldColor;
        }

        static void WriteAt(Position pos, ConsoleColor color, string msg)
        {
            lock (lockObj)
            {
                Console.ForegroundColor = color;
                if (pos != null) Console.SetCursorPosition(pos.X, pos.Y);
                Console.Write(msg);
            }
        }

        static void PromptUser(string msg, bool isFlow = false)
        {
            WriteAt(isFlow ? null : new Position(5, promptPosition), Console.ForegroundColor, msg);
            Console.ReadKey();
        }
        static void ConsoleBox(Position pos, int width, int height, ConsoleColor foreColor)
        {
            var oldColor = Console.ForegroundColor;
            Console.OutputEncoding = Encoding.GetEncoding(866);
            Console.ForegroundColor = foreColor;

            var w = width - 2;
            var bar = string.Join("", Enumerable.Range(1, w).Select(_ => "─"));
            var top = new StringBuilder().Append("┌").Append(bar).Append("┐\n").ToString();
            var row = new StringBuilder().Append($"│{"".PadLeft(w)}│\n").ToString();
            var bot = new StringBuilder().Append("└").Append(bar).Append("┘").ToString();

            Console.SetCursorPosition(pos.X, pos.Y);
            Console.Write(top);
            for (int i = 1; i < height; i++)
            {
                Console.SetCursorPosition(pos.X, pos.Y + i);
                Console.Write(row);
            }
            Console.SetCursorPosition(pos.X, pos.Y + height - 1);
            Console.Write(bot);

            Console.ForegroundColor = oldColor;
        }

        #endregion
    }

    public enum FeedbackType
    {
        Evaluate,
        Swap,
        Done
    }

    public class Position
    {
        public Position(int x, int y)
        {
            X = x;
            Y = y;
        }
        public int X { get; set; }
        public int Y { get; set; }
    }

    public class SortTracker
    {
        public SortTracker() { }
        public SortTracker(string title,
                           ConsoleColor unsetColor, ConsoleColor evalColor, ConsoleColor swapColor,
                           List<Position> positions, Position stepPos, int sleepMS,
                           Action<Position, ConsoleColor, string> writer)
        {
            Title = title;
            UnsetColor = unsetColor;
            EvalColor = evalColor;
            SwapColor = swapColor;
            Positions = positions;
            SleepMS = sleepMS;
            stepPoint = stepPos;
            Writer = writer;
        }

        const int Unset = -1;

        public string Title { get; set; }
        public int StepCount { get; set; }
        public int[] Data { get; set; }

        private int[] pointers { get; } = new[] { Unset, Unset };
        private Position stepPoint;

        public int SleepMS { get; set; }
        public ConsoleColor UnsetColor { get; set; }
        public ConsoleColor EvalColor { get; set; }
        public ConsoleColor SwapColor { get; set; }
        public List<Position> Positions { get; set; }
        public Action<Position, ConsoleColor, string> Writer { get; set; }

        public void SetData(int[] data)
        {
            Data = data;
            StepCount = 0;
            pointers[0] = Unset;
            pointers[1] = Unset;
        }

        public Task ReportAsync(int ndx1, int ndx2, FeedbackType feedback, bool alternate)
        {
            switch (feedback)
            {
                case FeedbackType.Done:
                case FeedbackType.Evaluate:
                    if (pointers[0] != Unset)
                    {
                        Writer(Positions[pointers[0]], UnsetColor, Data[pointers[0]].ToString().PadLeft(5));
                        Writer(Positions[pointers[1]], UnsetColor, Data[pointers[1]].ToString().PadLeft(5));
                    }
                    if (ndx1 != -1)
                    {
                        pointers[0] = ndx1;
                        pointers[1] = ndx2;
                        Writer(Positions[ndx1], EvalColor, Data[ndx1].ToString().PadLeft(5));
                        Writer(Positions[ndx2], EvalColor, Data[ndx2].ToString().PadLeft(5));
                    }
                    break;

                case FeedbackType.Swap:
                    if (alternate) // some sort algorithms don't toggle eval/swap states
                    {
                        Writer(Positions[pointers[0]], UnsetColor, Data[pointers[0]].ToString().PadLeft(5));
                        Writer(Positions[pointers[1]], UnsetColor, Data[pointers[1]].ToString().PadLeft(5));
                        pointers[0] = ndx1;
                        pointers[1] = ndx2;
                    }
                    Writer(Positions[ndx1], SwapColor, Data[ndx1].ToString().PadLeft(5));
                    Writer(Positions[ndx2], SwapColor, Data[ndx2].ToString().PadLeft(5));
                    break;
            }
            Writer(stepPoint, UnsetColor, (++StepCount).ToString("N0"));
            return Task.Delay(SleepMS);
        }
    }

    public static class SortingHelperExtensions
    {
        public static Task BubbleSortDescendingAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                for (int i = 0; i < collection.Count - 1; i++)
                {
                    for (int index = 1; index < collection.Count - i; index++)
                    {
                        await feedbackAsync?.Invoke(index, index - 1, FeedbackType.Evaluate, false);
                        if (comparer.Compare(collection[index], collection[index - 1]) > 0)
                        {
                            collection.Swap(index - 1, index);
                            await feedbackAsync?.Invoke(index - 1, index, FeedbackType.Swap, false);
                        }
                    }
                }
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        public static Task CombSortDescendingAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                double gap = collection.Count;
                bool swaps = true;

                while (gap > 1 || swaps)
                {
                    gap /= 1.247330950103979;
                    if (gap < 1) gap = 1;
                    int i = 0;
                    swaps = false;

                    while (i + gap < collection.Count)
                    {
                        int igap = i + (int)gap;
                        await feedbackAsync?.Invoke(i, igap, FeedbackType.Evaluate, false);
                        if (comparer.Compare(collection[i], collection[igap]) < 0)
                        {
                            collection.Swap(i, igap);
                            swaps = true;
                            await feedbackAsync?.Invoke(i, igap, FeedbackType.Swap, false);
                        }
                        i++;
                    }
                }
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        public static Task CycleSortDescendingAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                for (int cycleStart = 0; cycleStart < collection.Count; cycleStart++)
                {
                    T item = collection[cycleStart];
                    int position = cycleStart;

                    do
                    {
                        int to = 0;
                        for (int i = 0; i < collection.Count; i++)
                        {
                            await feedbackAsync?.Invoke(position, i, FeedbackType.Evaluate, false);
                            if (i != cycleStart && comparer.Compare(collection[i], item) > 0)
                                to++;
                        }

                        if (position != to)
                        {
                            while (position != to && comparer.Compare(item, collection[to]) == 0)
                            {
                                await feedbackAsync?.Invoke(position, to, FeedbackType.Evaluate, false);
                                to++;
                            }
                            T temp = collection[to];
                            collection[to] = item;
                            item = temp;
                            await feedbackAsync?.Invoke(position, to, FeedbackType.Swap, true);
                            position = to;
                        }
                    } while (position != cycleStart);
                }
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        public static Task GnomeSortDescendingAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                int pos = 1;
                while (pos < collection.Count)
                {
                    await feedbackAsync?.Invoke(pos, pos - 1, FeedbackType.Evaluate, false);
                    if (comparer.Compare(collection[pos], collection[pos - 1]) <= 0)
                        pos++;
                    else
                    {
                        collection.Swap(pos, pos - 1);
                        await feedbackAsync?.Invoke(pos, pos - 1, FeedbackType.Swap, false);
                        if (pos > 1) pos--;
                    }
                }
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        public static Task InsertionSortAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                int j;
                for (int i = 1; i < collection.Count; i++)
                {
                    T value = collection[i];
                    j = i - 1;
                    await feedbackAsync?.Invoke(i, j, FeedbackType.Evaluate, false);
                    while ((j >= 0) && (comparer.Compare(collection[j], value) < 0))
                    {
                        collection[j + 1] = collection[j];
                        await feedbackAsync?.Invoke(j + 1, i, FeedbackType.Swap, true);
                        j--;
                    }
                    collection[j + 1] = value;
                    await feedbackAsync?.Invoke(j + 1, i, FeedbackType.Swap, true);
                }
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        public static Task OddEvenSortDescendingAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                bool sorted = false;

                while (!sorted)
                {
                    sorted = true;
                    for (var i = 1; i < collection.Count - 1; i += 2)
                    {
                        await feedbackAsync?.Invoke(i, i + 1, FeedbackType.Evaluate, false);
                        if (comparer.Compare(collection[i], collection[i + 1]) < 0)
                        {
                            collection.Swap(i, i + 1);
                            sorted = false;
                            await feedbackAsync?.Invoke(i, i + 1, FeedbackType.Swap, false);
                        }
                    }

                    for (var i = 0; i < collection.Count - 1; i += 2)
                    {
                        await feedbackAsync?.Invoke(i, i + 1, FeedbackType.Evaluate, false);
                        if (comparer.Compare(collection[i], collection[i + 1]) < 0)
                        {
                            collection.Swap(i, i + 1);
                            sorted = false;
                            await feedbackAsync?.Invoke(i, i + 1, FeedbackType.Swap, false);
                        }
                    }
                }
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        public static Task QuickSortAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                await collection.InternalQuickSortAsync(0, collection.Count - 1, comparer, feedbackAsync);
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        private static async Task InternalQuickSortAsync<T>(this IList<T> collection, int leftmostIndex, int rightmostIndex, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
        {
            if (leftmostIndex < rightmostIndex)
            {
                int wallIndex = await collection.InternalPartitionAsync(leftmostIndex, rightmostIndex, comparer, feedbackAsync);
                await collection.InternalQuickSortAsync(leftmostIndex, wallIndex - 1, comparer, feedbackAsync);
                await collection.InternalQuickSortAsync(wallIndex + 1, rightmostIndex, comparer, feedbackAsync);
            }
        }

        private static async Task<int> InternalPartitionAsync<T>(this IList<T> collection, int leftmostIndex, int rightmostIndex, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
        {
            int wallIndex, pivotIndex;
            pivotIndex = rightmostIndex;
            T pivotValue = collection[pivotIndex];
            wallIndex = leftmostIndex;

            for (int i = leftmostIndex; i <= (rightmostIndex - 1); i++)
            {
                await feedbackAsync?.Invoke(i, pivotIndex, FeedbackType.Evaluate, false);
                if (comparer.Compare(collection[i], pivotValue) >= 0)
                {
                    collection.Swap(i, wallIndex);
                    await feedbackAsync?.Invoke(i, wallIndex, FeedbackType.Swap, true);
                    wallIndex++;
                }
            }
            collection.Swap(wallIndex, pivotIndex);
            await feedbackAsync?.Invoke(wallIndex, pivotIndex, FeedbackType.Swap, true);
            return wallIndex;
        }

        public static Task SelectionSortDescendingAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                for (int i = collection.Count - 1; i > 0; i--)
                {
                    int max = i;
                    for (int j = 0; j <= i; j++)
                    {
                        await feedbackAsync?.Invoke(j, max, FeedbackType.Evaluate, false);
                        if (comparer.Compare(collection[j], collection[max]) < 0)
                            max = j;
                    }
                    collection.Swap(i, max);
                    await feedbackAsync?.Invoke(i, max, FeedbackType.Swap, false);
                }
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        public static Task ShellSortDescendingAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
            => Task.Run(async () =>
            {
                bool flag = true;
                int d = collection.Count;

                while (flag || (d > 1))
                {
                    flag = false;
                    d = (d + 1) / 2;
                    for (int i = 0; i < (collection.Count - d); i++)
                    {
                        await feedbackAsync?.Invoke(i + d, i, FeedbackType.Evaluate, false);
                        if (comparer.Compare(collection[i + d], collection[i]) > 0)
                        {
                            collection.Swap(i + d, i);
                            flag = true;
                            await feedbackAsync?.Invoke(i + d, i, FeedbackType.Swap, false);
                        }
                    }
                }
                await feedbackAsync?.Invoke(-1, -1, FeedbackType.Done, false);
            });

        public static Task[] Execute(this Dictionary<SortType, SortTracker> trackers, int[] data)
        {
            var tasks = new Task[trackers.Count];
            for (int i = 0; i < trackers.Count; i++)
            {
                var tracker = trackers.ElementAt(i);
                tracker.Value.SetData(data.Select(x => x).ToArray());

                switch (tracker.Key)
                {
                    case SortType.Bubble:
                        tasks[i] = tracker.Value.Data.BubbleSortDescendingAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                    case SortType.Comb:
                        tasks[i] = tracker.Value.Data.CombSortDescendingAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                    case SortType.Cycle:
                        tasks[i] = tracker.Value.Data.CycleSortDescendingAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                    case SortType.Gnome:
                        tasks[i] = tracker.Value.Data.GnomeSortDescendingAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                    case SortType.Insertion:
                        tasks[i] = tracker.Value.Data.InsertionSortAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                    case SortType.OddEven:
                        tasks[i] = tracker.Value.Data.OddEvenSortDescendingAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                    case SortType.Quick:
                        tasks[i] = tracker.Value.Data.QuickSortAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                    case SortType.Selection:
                        tasks[i] = tracker.Value.Data.SelectionSortDescendingAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                    case SortType.Shell:
                        tasks[i] = tracker.Value.Data.ShellSortDescendingAsync(new CodeProjectComparer(), tracker.Value.ReportAsync);
                        break;
                }
            }
            return tasks;
        }
    }

    public static class CollectionExtensions
    {
        public static void Swap<T>(this IList<T> list, int firstIndex, int secondIndex)
        {
            if (list.Count < 2 || firstIndex == secondIndex) return;
            var temp = list[firstIndex];
            list[firstIndex] = list[secondIndex];
            list[secondIndex] = temp;
        }
    }
}

Static output does not convey how it perfoms but here is sample Output:
.
       Bubble Sort Descending

         9   95   94   93   89    8   84   63   55   52     ┌───────────────┐
        51   44   30  254  252  244   24  237  236  234     │ COLOUR LEGEND │
       229  227  222  216  214   21  205  201  196  189     │               │
       180  178  174  172   17  171  170  156  153  146     │   idle        │
        14  137  136  132  127  126  124  121  112  100     │   Evaluating  │
                                                            │   Changing    │
               Steps:  1,760                                │               │
                                                            └───────────────┘
       Comb Sort Descending

         9   95   94   93   89    8   84   63   55   52
        51   44   30  254  252  244   24  237  236  234
       229  227  222  216  214   21  205  201  196  189
       180  178  174  172   17  171  170  156  153  146
        14  137  136  132  127  126  124  121  112  100

               Steps:  797

       Cycle Sort Descending

         9   95   94   93   89    8   84   63   55   52
        51   44   30  254  252  244   24  237  236  234
       229  227  222  216  214   21  205  201  196  189
       180  178  174  172   17  171  170  156  153  146
        14  137  136  132  127  126  124  121  112  100

               Steps:  4,547

       Gnome Sort Descending

         9   95   94   93   89    8   84   63   55   52
        51   44   30  254  252  244   24  237  236  234
       229  227  222  216  214   21  205  201  196  189
       180  178  174  172   17  171  170  156  153  146
        14  137  136  132  127  126  124  121  112  100

               Steps:  1,649

       Insertion Sort

         9   95   94   93   89    8   84   63   55   52
        51   44   30  254  252  244   24  237  236  234
       229  227  222  216  214   21  205  201  196  189
       180  178  174  172   17  171  170  156  153  146
        14  137  136  132  127  126  124  121  112  100

               Steps:  633

       Odd-Even Sort Descending

         9   95   94   93   89    8   84   63   55   52
        51   44   30  254  252  244   24  237  236  234
       229  227  222  216  214   21  205  201  196  189
       180  178  174  172   17  171  170  156  153  146
        14  137  136  132  127  126  124  121  112  100

               Steps:  1,711

       Quick Sort

         9   95   94   93   89    8   84   63   55   52
        51   44   30  254  252  244   24  237  236  234
       229  227  222  216  214   21  205  201  196  189
       180  178  174  172   17  171  170  156  153  146
        14  137  136  132  127  126  124  121  112  100

               Steps:  424

       Selection Sort Descending

         9   95   94   93   89    8   84   63   55   52
        51   44   30  254  252  244   24  237  236  234
       229  227  222  216  214   21  205  201  196  189
       180  178  174  172   17  171  170  156  153  146
        14  137  136  132  127  126  124  121  112  100

               Steps:  1,324

       Shell Sort Descending

         9   95   94   93   89    8   84   63   55   52
        51   44   30  254  252  244   24  237  236  234
       229  227  222  216  214   21  205  201  196  189
       180  178  174  172   17  171  170  156  153  146
        14  137  136  132  127  126  124  121  112  100

               Steps:  722


     -- Press any key to exit --

To watch multiple sorts at the same time, I recommend selecting 3 or 4 differnt types of sorts plus resizing the console window before the they run. If you have the screen resolution (or set a very small font size), you could run all 9 at the same time like above!

Enjoy!
 
Share this answer
 
v5
Decided to use this as an exercise to get intimate with my new found love with Python. The solution is simple, I mean it. Just pad up a list of integers with zeros up to the max digits available in the list, sort them in descending order, then concatenate the original list of integers according to this order. It turned out I have fun flirting with the list and dictionary in Python, the result is shown:
"""
largest_possible_integer.py
by Peter Leow

Coding challenge: arrange numbers to form the largest possible integer

"""

import random

# Create a list of x number of random integers from 0 to 255
x = 50
list_int = random.sample(range(0,256), x)
print("List of {} positive integers (0 to 255): {}".format(x, list_int))

# Find the max integer in the list
max_int = max(list_int)
print("Max integer = {}".format(max_int))

# Find number of digits for this max integer
max_digit_count = len(str(max_int))
print("Most number of digits = {}".format(max_digit_count))

# Create a dictionary with list elements as keys and 
# their zero-padded values up to max_digit_count as values
dict_int = {}
for int in (list_int):
    dict_int[int] =  int * 10**(max_digit_count - len(str(int)))
print("Dictionary = {}".format(dict_int))

# Sort the original integer list based on the descending order
# of their padded values in the dictionary 
sorted_list_int = sorted(list_int, key=dict_int.__getitem__, reverse=True)

print("Sorted integer list to form the largest integer = {}".format(sorted_list_int))

largest_integer = ''.join(str(int) for int in sorted_list_int)

print("The largest integer is {}".format(largest_integer))
Try it out at this playground[^]. Change the x value and have fun! Disclaimer: Overflow at your own risk!
Two example outputs:
List of 10 positive integers (0 to 255): [93, 185, 191, 48, 209, 26, 36, 42, 25, 107]
Max integer = 209
Most number of digits = 3
Dictionary = {48: 480, 209: 209, 42: 420, 36: 360, 25: 250, 185: 185, 26: 260, 107: 107, 93: 930, 191: 191}
Sorted integer list to form the largest integer = [93, 48, 42, 36, 26, 25, 209, 191, 185, 107]
The largest integer is 934842362625209191185107
and
List of 50 positive integers (0 to 255): [26, 2, 246, 241, 107, 92, 215, 173, 119, 176, 156, 235, 125, 165, 129, 13, 19, 74, 227, 81, 248, 159, 102, 180, 90, 63, 123, 232, 217, 133, 224, 219, 98, 57, 95, 179, 245, 140, 151, 68, 254, 250, 117, 203, 9, 52, 222, 34, 41, 11]
Max integer = 254
Most number of digits = 3
Dictionary = {129: 129, 2: 200, 107: 107, 133: 133, 9: 900, 11: 110, 140: 140, 13: 130, 19: 190, 151: 151, 26: 260, 156: 156, 159: 159, 34: 340, 165: 165, 41: 410, 173: 173, 176: 176, 179: 179, 180: 180, 57: 570, 117: 117, 52: 520, 68: 680, 74: 740, 203: 203, 81: 810, 215: 215, 217: 217, 90: 900, 219: 219, 92: 920, 222: 222, 95: 950, 224: 224, 98: 980, 227: 227, 102: 102, 232: 232, 63: 630, 235: 235, 241: 241, 245: 245, 246: 246, 119: 119, 248: 248, 250: 250, 123: 123, 125: 125, 254: 254}
Sorted integer list to form the largest integer = [98, 95, 92, 90, 9, 81, 74, 68, 63, 57, 52, 41, 34, 26, 254, 250, 248, 246, 245, 241, 235, 232, 227, 224, 222, 219, 217, 215, 203, 2, 19, 180, 179, 176, 173, 165, 159, 156, 151, 140, 133, 13, 129, 125, 123, 119, 117, 11, 107, 102]
The largest integer is 9895929098174686357524134262542502482462452412352322272242222192172152032191801791761731651591561511401331312912512311911711107102
+++++[Round 2]+++++

ALerted by ppolymorphe. Found the mischief which is caused by single digits. See the corrected code:
"""
largest_possible_integer.py
by Peter Leow

Coding challenge: arrange numbers to form the largest possible integer

"""

import random

# Create a list of x number of random integers from 0 to 255
x = 50
# list_int = random.sample(range(0,256), x)

list_int = [26, 2, 246, 241, 107, 92, 215, 173, 119, 176, 156, 235, 125, 165, 129, 13, 19, 74, 227, 81, 248, 159, 102, 180, 90, 63, 123, 232, 217, 133, 224, 219, 98, 57, 95, 179, 245, 140, 151, 68, 254, 250, 117, 203, 9, 52, 222, 34, 41, 11]

print("List of {} positive integers (0 to 255): {}".format(x, list_int))

# Find the max integer in the list
max_int = max(list_int)
print("Max integer = {}".format(max_int))

# Find number of digits for this max integer
max_digit_count = len(str(max_int))
print("Most number of digits = {}".format(max_digit_count))

# Create a dictionary with list elements as keys and 
# their zero-padded values up to max_digit_count as values
dict_int = {}
for int in (list_int):
    length = len(str(int))
    
    if length == 1: # if single digit
        # make it the max in its range e.g. 2 to 299
        dict_int[int] =  (int + 1) * 10**(max_digit_count - length) - 1 
    else:
        dict_int[int] =  int * 10**(max_digit_count - length)
        
print("Dictionary = {}".format(dict_int))

# Sort the original integer list based on the descending order
# of their padded values in the dictionary 
sorted_list_int = sorted(list_int, key=dict_int.__getitem__, reverse=True)

print("Sorted integer list to form the largest integer = {}".format(sorted_list_int))

largest_integer = ''.join(str(int) for int in sorted_list_int)

print("The largest integer is {}".format(largest_integer))
Check it out: Python Playround[^] and the output:
List of 50 positive integers (0 to 255): [26, 2, 246, 241, 107, 92, 215, 173, 119, 176, 156, 235, 125, 165, 129, 13, 19, 74, 227, 81, 248, 159, 102, 180, 90, 63, 123, 232, 217, 133, 224, 219, 98, 57, 95, 179, 245, 140, 151, 68, 254, 250, 117, 203, 9, 52, 222, 34, 41, 11]
Max integer = 254
Most number of digits = 3
Dictionary = {129: 129, 2: 299, 107: 107, 133: 133, 9: 999, 11: 110, 140: 140, 13: 130, 19: 190, 151: 151, 26: 260, 156: 156, 159: 159, 34: 340, 165: 165, 41: 410, 173: 173, 176: 176, 179: 179, 180: 180, 57: 570, 117: 117, 52: 520, 68: 680, 74: 740, 203: 203, 81: 810, 215: 215, 217: 217, 90: 900, 219: 219, 92: 920, 222: 222, 95: 950, 224: 224, 98: 980, 227: 227, 102: 102, 232: 232, 63: 630, 235: 235, 241: 241, 245: 245, 246: 246, 119: 119, 248: 248, 250: 250, 123: 123, 125: 125, 254: 254}
Sorted integer list to form the largest integer = [9, 98, 95, 92, 90, 81, 74, 68, 63, 57, 52, 41, 34, 2, 26, 254, 250, 248, 246, 245, 241, 235, 232, 227, 224, 222, 219, 217, 215, 203, 19, 180, 179, 176, 173, 165, 159, 156, 151, 140, 133, 13, 129, 125, 123, 119, 117, 11, 107, 102]
The largest integer is 9989592908174686357524134226254250248246245241235232227224222219217215203191801791761731651591561511401331312912512311911711107102

+++++[round 3]+++++
I am back. It about my bed time after a busy day preparing for the coming Chinese New Year. Realizing the discussions that streaming in and the interests that generated, can't just walk away from it. Spare some time to ponder over it on how to fix this single digit mischief. I think I got it this time. See this:
"""
largest_possible_integer.py
by Peter Leow

Coding challenge: arrange numbers to form the largest possible integer

"""

import random

# Create a list of x number of random integers from 0 to 255
x = 50
# list_int = random.sample(range(0,256), x)


list_int = [26, 2, 246, 241, 107, 92, 215, 173, 119, 176, 156, 235, 125, 165, 129, 13, 19, 74, 227, 81, 248, 159, 102, 180, 90, 63, 123, 232, 217, 133, 224, 219, 98, 57, 95, 179, 245, 140, 151, 68, 254, 250, 117, 203, 9, 52, 222, 34, 41, 11]

print("List of {} positive integers (0 to 255): {}".format(x, list_int))

# Find the max integer in the list
max_int = max(list_int)
print("Max integer = {}".format(max_int))

# Find number of digits for this max integer
max_digit_count = len(str(max_int))
print("Most number of digits = {}".format(max_digit_count))

# Create a dictionary with list elements as keys and 
# their zero-padded values up to max_digit_count as values
dict_int = {}
for int in (list_int):
    length = len(str(int))
    
    if length == 1:
        
        temp = int
        
        for i in range(1, max_digit_count):
            temp += int * 10**i
        
        dict_int[int] = temp
    else:
        dict_int[int] =  int * 10**(max_digit_count - length)
        
print("Dictionary = {}".format(dict_int))

# Sort the original integer list based on the descending order
# of their padded values in the dictionary 
sorted_list_int = sorted(list_int, key=dict_int.__getitem__, reverse=True)

print("Sorted integer list to form the largest integer = {}".format(sorted_list_int))

largest_integer = ''.join(str(int) for int in sorted_list_int)

print("The largest integer is {}".format(largest_integer))
The output is:
List of 50 positive integers (0 to 255): [26, 2, 246, 241, 107, 92, 215, 173, 119, 176, 156, 235, 125, 165, 129, 13, 19, 74, 227, 81, 248, 159, 102, 180, 90, 63, 123, 232, 217, 133, 224, 219, 98, 57, 95, 179, 245, 140, 151, 68, 254, 250, 117, 203, 9, 52, 222, 34, 41, 11]
Max integer = 254
Most number of digits = 3
Dictionary = {129: 129, 2: 222, 107: 107, 133: 133, 9: 999, 11: 110, 140: 140, 13: 130, 19: 190, 151: 151, 26: 260, 156: 156, 159: 159, 34: 340, 165: 165, 41: 410, 173: 173, 176: 176, 179: 179, 180: 180, 57: 570, 117: 117, 52: 520, 68: 680, 74: 740, 203: 203, 81: 810, 215: 215, 217: 217, 90: 900, 219: 219, 92: 920, 222: 222, 95: 950, 224: 224, 98: 980, 227: 227, 102: 102, 232: 232, 63: 630, 235: 235, 241: 241, 245: 245, 246: 246, 119: 119, 248: 248, 250: 250, 123: 123, 125: 125, 254: 254}
Sorted integer list to form the largest integer = [9, 98, 95, 92, 90, 81, 74, 68, 63, 57, 52, 41, 34, 26, 254, 250, 248, 246, 245, 241, 235, 232, 227, 224, 2, 222, 219, 217, 215, 203, 19, 180, 179, 176, 173, 165, 159, 156, 151, 140, 133, 13, 129, 125, 123, 119, 117, 11, 107, 102]
The largest integer is 9989592908174686357524134262542502482462452412352322272242222219217215203191801791761731651591561511401331312912512311911711107102
Check it out online[^]Thank you for all the attention, I hope I did not disappoint you. Happy Chinese New Year!
 
Share this answer
 
v14
Comments
Patrice T 21-Jan-17 18:05pm    
Last set
I think 2 is misplaced, it should be placed around 222.
Peter Leow 21-Jan-17 22:00pm    
Why?
Patrice T 21-Jan-17 23:04pm    
Because
224, 222, 219, 217, 215, 203, 2 -> 2242222192172152032
and
224, 222, 2, 219, 217, 215, 203 -> 2242222219217215203
Peter Leow 21-Jan-17 23:31pm    
Got it, thanks.
Peter Leow 22-Jan-17 0:15am    
Thank you for the feedback. Taken a second look. Found the culprit which are all the single digits. Put them to the max in their respective ranges, e.g. 2 => 299. Solved it.
Here is a quick WPF MVVM version that I put together over lunch using the Integer Comparer from my other solution (Solution 3).

I have used a custom SortableObservableCollection from an extended ObservableCollection passing a Comparer and will refresh the view via the binding system when the order of the elements change.

Here is the ViewModel & supporting classes:
C#
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

namespace WpfCodeChallenge
{
    public class CodeProjectComparer : IComparer<int>
    {
        int IComparer<int>.Compare(int x, int y) => (int)(Concat(x, y) - Concat(y, x));

        private Int64 Concat(Int32 x, Int32 y)
        {
            Int64 pow = 1;
            while (pow <= y) pow = ((pow << 2) + pow) << 1;
            return x * pow + y;
        }
    }

    public class SortableObservableCollection<T> : ObservableCollection<T>
    {
        public void SortDescending<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer)
        {
            ApplySort(Items.OrderByDescending(keySelector, comparer));
        }

        private void ApplySort(IEnumerable<T> sortedItems)
        {
            var sortedItemsList = sortedItems.ToList();
            foreach (var item in sortedItemsList)
                Move(IndexOf(item), sortedItemsList.IndexOf(item));
        }
    }

    public class MainViewModel : INotifyPropertyChanged
    {
        public MainViewModel()
        {
            Parse("94,9,99,98,111,11,112,1");
        }

        private IComparer<int> comparer = new CodeProjectComparer();
        public event PropertyChangedEventHandler PropertyChanged;

        public SortableObservableCollection<int> DataSet { get; set; }
            = new SortableObservableCollection<int>();

        private string csvValues;
        public string CsvValues { get { return csvValues; } set { Parse(value); } }

        private void Parse(string value)
        {
            csvValues = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CsvValues"));

            try
            {
                var values = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                          .Select(x => Convert.ToInt32(x));
                if (values.Any())
                {
                    DataSet.Clear();
                    foreach (var val in values)
                        DataSet.Add(val);
                    DataSet.SortDescending(x => x, comparer);
                }
            }
            catch { }
        }
    }
}

Here is the view (no code-behind used):
XML
<Window x:Class="WpfCodeChallenge.MainWindow" Height="350" Width="525"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:vm="clr-namespace:WpfCodeChallenge"
		Title="Weekly Coding Challenge Code Project: Arrange Numbers">
	<Window.DataContext>
		<vm:MainViewModel/>
	</Window.DataContext>
	<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="50">
		<Grid.RowDefinitions>
			<RowDefinition Height="Auto"/>
			<RowDefinition MinHeight="100"/>
		</Grid.RowDefinitions>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="Auto"/>
			<ColumnDefinition MinWidth="200"/>
		</Grid.ColumnDefinitions>
		<TextBlock Text="Input csv numeric values:" Margin="4 10" 
                   VerticalAlignment="Top"/>
		<TextBox Text="{Binding CsvValues, UpdateSourceTrigger=PropertyChanged, Delay=200}" 
				 TextWrapping="Wrap" MaxLines="1" Grid.Column="1" Margin="0 10" 
                 VerticalAlignment="Top"/>
		<TextBlock Text="Output(sorted)" Grid.Row="1" Margin="4 10" MinHeight="100"/>
		<ListBox ItemsSource="{Binding DataSet}" Grid.Row="1" Grid.Column="1" Margin="0 10"
				 ScrollViewer.HorizontalScrollBarVisibility="Disabled"
				 ScrollViewer.VerticalScrollBarVisibility="Auto">
			<ListBox.ItemsPanel>
				<ItemsPanelTemplate>
                    <WrapPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
			</ListBox.ItemsPanel>
		</ListBox>
	</Grid>
</Window>

Update: I have discovered an issue with the custom SortableObservableCollection - it does not correctly handle duplicates. So to keep code simple, I have changed to a CollectionViewSorce in Xaml. To apply the custom sorting using CodeProjectComparer, I have added manual wiring of the Comparer to the CollectionViewSorce.CustomSort property. This can not be wired up in Xaml. Also, as the CollectionViewSorce is in the Xaml, we need to wait until it is loaded. So we do this in the Listbox.Loaded event.

Here is the revised CodeProjectComparer and MainViewModel classes:
C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

namespace WpfCodeChallenge
{
    public class CodeProjectComparer : IComparer
    {
        public int Compare(object x, object y) 
            => (int)(Concat((int)y, (int)x) - Concat((int)x, (int)y));

        private Int64 Concat(Int32 x, Int32 y)
        {
            Int64 pow = 1;
            while (pow <= y) pow = ((pow << 2) + pow) << 1;
            return x * pow + y;
        }
    }

    public class MainViewModel : INotifyPropertyChanged
    {
        public MainViewModel()
        {
            Parse("94,9,99,98,111,11,112,1");
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public ObservableCollection<int> DataSet { get; set; }
            = new ObservableCollection<int>();

        private string csvValues;
        public string CsvValues { get { return csvValues; } set { Parse(value); } }

        private void Parse(string value)
        {
            csvValues = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CsvValues"));

            try
            {
                var values = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                  .Select(x => Convert.ToInt32(x));
                if (values.Any())
                {
                    DataSet.Clear();
                    foreach (var val in values) DataSet.Add(val);
                }
            }
            catch { }
        }
    }
}

Here is the view:
XML
<Window x:Class="WpfCodeChallenge.MainWindow" Height="350" Width="525"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:vm="clr-namespace:WpfCodeChallenge"
		Title="Weekly Coding Challenge Code Project: Arrange Numbers">
	<Window.DataContext>
		<vm:MainViewModel/>
	</Window.DataContext>
	<Window.Resources>
		<CollectionViewSource x:Key="CsvData" Source="{Binding DataSet}" 
                                      IsLiveSortingRequested="True"/>
	</Window.Resources>
	<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="50">
		<Grid.RowDefinitions>
			<RowDefinition Height="Auto"/>
			<RowDefinition MinHeight="100"/>
		</Grid.RowDefinitions>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="Auto"/>
			<ColumnDefinition MinWidth="200"/>
		</Grid.ColumnDefinitions>
		<TextBlock Text="Input csv numeric values:" Margin="4 10" 
				   VerticalAlignment="Top"/>
		<TextBox Text="{Binding CsvValues, UpdateSourceTrigger=PropertyChanged, Delay=200}" 
				 TextWrapping="Wrap" MaxLines="1" Grid.Column="1" Margin="0 10" 
				 VerticalAlignment="Top"/>
		<TextBlock Text="Output(sorted)" Grid.Row="1" Margin="4 10" MinHeight="100"/>
		<ListBox ItemsSource="{Binding Source={StaticResource CsvData}}" 
				 Grid.Row="1" Grid.Column="1" Margin="0 10" Loaded="OnLoaded"
				 ScrollViewer.HorizontalScrollBarVisibility="Disabled"
				 ScrollViewer.VerticalScrollBarVisibility="Auto">
			<ListBox.ItemsPanel>
				<ItemsPanelTemplate>
					<WrapPanel Orientation="Horizontal"/>
				</ItemsPanelTemplate>
			</ListBox.ItemsPanel>
		</ListBox>
	</Grid>
</Window>

And lastly, here is the view code-behind:
C#
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace WpfCodeChallenge
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            ((ListCollectionView)((ListBox)sender).ItemsSource).CustomSort
                = new CodeProjectComparer();
        }
    }
}

Update #2: Today I was working on a TreeView where custom sorting at branch level was required and realized that the same method could be used here. So here is another version using a ValueConverter removing the need for wiring up an event in the View's code-behind and a ViewModel.

We now bind the ListBox directly to the user input. The single line value converter, using Linq, will filter out invalid characters from the input string, convert it to a list and apply the sort via the CollectionViewSource.

Here is the revised ValueConverter:
C#
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Data;

namespace WpfCodeChallenge
{
    public class CodeProjectSortConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
             => new ListCollectionView(
                string.Join("", ((string)value).Where(x => x == ',' || (x > 47 && x < 58)))
                    .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => System.Convert.ToInt32(x)).ToList())
            { CustomSort = Comparer<int>.Create((x, y) => (int)(Concat(y, x) - Concat(x, y))) };

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            => value;

        private Int64 Concat(Int32 x, Int32 y)
        {
            Int64 pow = 1;
            while (pow <= y) pow = ((pow << 2) + pow) << 1;
            return x * pow + y;
        }
    }
}

And the View using the revised ValueConverter:
XML
<Window x:Class="WpfCodeChallenge.MainWindow" Height="350" Width="525"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:c="clr-namespace:WpfCodeChallenge"
		Title="Weekly Coding Challenge Code Project: Arrange Numbers">
	<Window.Resources>
		<c:CodeProjectSortConverter x:Key="CodeProjectSortConverter"/>
	</Window.Resources>
	<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="50">
		<Grid.RowDefinitions>
			<RowDefinition Height="Auto"/>
			<RowDefinition MinHeight="100"/>
		</Grid.RowDefinitions>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="Auto"/>
			<ColumnDefinition MinWidth="200"/>
		</Grid.ColumnDefinitions>
		<TextBlock Text="Input csv numeric values:" Margin="4 10" 
				   VerticalAlignment="Top"/>
		<TextBox x:Name="DataSet" Text="94,9,99,98,111,11,112,1" 
				 TextWrapping="Wrap" MaxLines="1" Grid.Column="1" Margin="0 10" 
				 VerticalAlignment="Top"/>
		<TextBlock Text="Output(sorted)" Grid.Row="1" Margin="4 10" MinHeight="100"/>
		<ListBox ItemsSource="{Binding ElementName=DataSet, Path=Text, 
			Converter={StaticResource CodeProjectSortConverter}}" 
				 Grid.Row="1" Grid.Column="1" Margin="0 10"
				 ScrollViewer.HorizontalScrollBarVisibility="Disabled"
				 ScrollViewer.VerticalScrollBarVisibility="Auto">
			<ListBox.ItemsPanel>
				<ItemsPanelTemplate>
					<WrapPanel Orientation="Horizontal"/>
				</ItemsPanelTemplate>
			</ListBox.ItemsPanel>
		</ListBox>
	</Grid>
</Window>


WPF binding makes this cool ... you can edit the values in the IDE and the ListBox will update in real time! :)
 
Share this answer
 
v7

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900