14,118,915 members
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
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

Graeme_Grant 21-Jan-17 1:48am

My output was as per Chris' request. Not hard to add spaces if needed. ;)
Patrice T 21-Jan-17 1:54am

was just an idea, not a complaint.
Yes but easier with spaces already there.
Graeme_Grant 21-Jan-17 2:21am

I work with raw data and specifications all day ... just a habit of conformity. Yes, you are right, spaces does make it easier to read - so data labelling the datasets. :)
Patrice T 21-Jan-17 2:58am

I think we can take some freedom on the statement.
remember that solutions giving a wrong circle have been accepted.
By the wan did you found why your translation didn't work?
Graeme_Grant 21-Jan-17 6:33am

Sorry, forgot about it. I will have a look at it again tonight.
Graeme_Grant 21-Jan-17 6:33am

I just posted Solution 5 - visualize the 3 different sorting algorithms in action. Manually coded sorting algorithms rather than letting Linq do all the heavy lifting. I left this one with the spaces rather than a joined string. ;)
PIEBALDconsult 21-Jan-17 13:47pm

Just told mine to accept "6.7E+1" as an integer... :D

## Solution 7

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

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:

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:

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.

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 ) ;
}
}
v4
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...
Graeme_Grant 22-Jan-17 2:06am

Sorry, but you have another problem (using your comparer - any actually):

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} || elements: 50

Output: 99 98 91 90 9 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 || elements:51

Spaced to make it easier to spot wally ;)
PIEBALDconsult 22-Jan-17 2:12am

New comparer produces:
9 99 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
Graeme_Grant 22-Jan-17 2:28am

Glad to see it working. :)
PIEBALDconsult 22-Jan-17 2:27am

And how do you figure 51 elements?
Graeme_Grant 22-Jan-17 2:34am

one random test had an extra 9 in it ...

{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}

resulted in: 99999891908481706761535251434241403124824624524234233229228223220215203200193191186180179169156151150145142139135123122120115109106

On review, I can see in the above when I changed the source code to count, I didn't tell split to ignore empty results - sorry.

But there is something odd going on with that test...

PIEBALDconsult 22-Jan-17 2:41am

Ah, OK.

## Solution 1

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.

*   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
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

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
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:

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.
v20

## Solution 2

A LINQ one-liner! (Well, to be honest, about eight lines brutally mashed into one...)
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.
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...
PIEBALDconsult 21-Jan-17 0:30am

Strings are easier...
Graeme_Grant 21-Jan-17 0:36am

I try to code to the challenge like it is a specification. Chris asked for Int[]/List<int> for input and a single number as a string for output. What we do in the middle is up to us. ;)
PIEBALDconsult 21-Jan-17 1:05am

"To keep the problems suitably ambiguous."

I would not be so restrictive; he did _not_ ask for Int[]/List<int> .
Graeme_Grant 21-Jan-17 1:10am

Looking forward to seeing what you come up with... :)
PIEBALDconsult 21-Jan-17 1:42am

Did you see my comment on the challenge?
Graeme_Grant 21-Jan-17 1:47am

Did you see that I too posted just below yours? ;)
Chris Maunder 21-Jan-17 4:13am

I said "a set of integers", not "a set of values of type int". I mean integers in the mathematical sense.
Graeme_Grant 21-Jan-17 6:10am

Bad habit of working with RFCs, specification documents, etc all day... Glad to know that your definitions are loose... :)
PIEBALDconsult 21-Jan-17 14:24pm

Oh shoot, a Set doesn't allow duplicates, my solution (so far) allows duplicates, but I can easily change that or make it configurable...
Chris Maunder 21-Jan-17 17:00pm

Since when does a set not allow duplicates? A set of marbles can contain two marbles that are the same.
PIEBALDconsult 21-Jan-17 17:44pm

A Set in the mathematical sense.

And no two marbles are actually the same.
H2O-au 21-Jan-17 17:14pm

Actually, my main reason for using byte is more devious. I know my algorithm fails for numbers above 999. I couldn't be bothered going through and checking that all numbers are less than 999, so by using byte, I cover the required range but make the data integrity the caller's responsibility! ;D

I'm sure I could justify it by mumbling something about 'type safety', but I'm probably just being lazy...

## Solution 3

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:
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[^]:
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:
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:
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 --")                                      ;
}
}
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:
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 --");
}
}

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:
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:
class CodeProjectComparer : IComparer<int>
{
int IComparer<int>.Compare(int x, int y) => (int)(x.Concat(y) - y.Concat(x));
}

2. expression-body member[^]:
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:
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:
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:
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 --");
}

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!
v17
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...

## Solution 4

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
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();

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
v2
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...  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

## Solution 5

[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:
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:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

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 --");
}

{
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)
//

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);
WriteAt(new Position(5, promptPosition), unsetColor, msg);
}

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++)
}

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, "     ");
yPos += 10;
}
}

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++)

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);
}
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 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)
{
}
if (ndx1 != -1)
{
pointers[0] = ndx1;
pointers[1] = ndx2;
}
break;

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

public static class SortingHelperExtensions
{
public static Task BubbleSortDescendingAsync<T>(this IList<T> collection, IComparer<T> comparer, Func<int, int, FeedbackType, bool, Task> feedbackAsync = null)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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:
break;
case SortType.Comb:
break;
case SortType.Cycle:
break;
case SortType.Gnome:
break;
case SortType.Insertion:
break;
case SortType.OddEven:
break;
case SortType.Quick:
break;
case SortType.Selection:
break;
case SortType.Shell:
break;
}
}
}
}

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!
v5

## Solution 6

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!
v14
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.
Patrice T 22-Jan-17 0:29am

"e.g. 2 => 299. Solved it."
I fear padding is even more tricky.
Look at position of 2 in previous comment
Peter Leow 22-Jan-17 0:34am

You are right again. I rest the case. Got to get on with other business.
PIEBALDconsult 22-Jan-17 2:38am

Peter Leow 22-Jan-17 6:33am

Noted. Thanks.
Patrice T 22-Jan-17 8:34am

Depend on the method used.
How do you sort 242 and 24 without padding ?
PIEBALDconsult 22-Jan-17 10:45am

As per my second comparer. No padding or other string manipulation required. Just character compares and integer compares to break ties.
Patrice T 22-Jan-17 10:52am

Note that round 2 is still wrong.
2 go near 222
PIEBALDconsult 22-Jan-17 11:00am

Examples?
2 precedes 222
Patrice T 22-Jan-17 11:14am

"2, 26, 254, 250, 248, 246, 245, 241, 235, 232, 227, 224, 222"
"26, 254, 250, 248, 246, 245, 241, 235, 232, 227, 224, 222, 2"
"26, 254, 250, 248, 246, 245, 241, 235, 232, 227, 224, 2, 222"
PIEBALDconsult 22-Jan-17 11:25am

Mine produces:
26 254 250 248 246 245 241 235 232 227 224 2 222
Patrice T 22-Jan-17 11:35am

Ok output corrected.
Patrice T 22-Jan-17 12:04pm

If I understand your padding method, it fail on tricky values like {242, 24]
PIEBALDconsult 22-Jan-17 12:13pm

Mine produces:
242 24 ==> 24 242
Patrice T 22-Jan-17 12:24pm

In round 3, your code seems to pad 24 to 240 which should lead to 242 24, thus my doubt.
PIEBALDconsult 22-Jan-17 12:31pm

Mine does not pad at all, I think you replied to the wrong poster.
_If_ padding is done (and that will kill performance), then when comparing 24 with 242, the 24 should pad to 244 -- the last digit of the shorter value should be repeated enough times to make the strings equal in length.
Patrice T 22-Jan-17 12:41pm

"the last digit of the shorter value should be repeated enough times to make the strings equal in length."
In fact, wrong assumption, if you try 24, 242, 243, it should sort to 243 24 242
PIEBALDconsult 22-Jan-17 12:49pm

Aha... hmm...
Sooo... use the leading characters from the longer value to "pad" the shorter value maybe...
Patrice T 22-Jan-17 13:04pm

Since padding is interesting only when both values have same beginning, I pad a value by repeating itself. And I pad to maximum length+1.
24, 242, 243 get padded to 2424, 2422, 2432, then sort is obvious.
PIEBALDconsult 22-Jan-17 13:12pm

Just posted another comparer that shows another technique -- though I am still seeking a non-string-manipulating technique.
PIEBALDconsult 22-Jan-17 20:00pm

Well, you need only "pad" once you determine that the two values are identical up to the length of the shorter -- no need to "pad" prior to that.
Patrice T 22-Jan-17 20:12pm

Yes, it is useful only when you can't tell apart based on shorter length.
Always padding or not is matter of design decision.
Graeme_Grant 22-Jan-17 11:24am

I have explained it above in Solution 3.

{94, 9} = 949 - 994 = -45, change to {9, 94}. However, {1, 112} = 1112 - 1121 = -9, the correct order is {112, 1}.
PIEBALDconsult 22-Jan-17 11:27am

Yes, and mine does
94 9 1 112 ==> 9 94 112 1
Graeme_Grant 22-Jan-17 11:29am

I posted to you but was really for Peter (and others who might submit). :)
PIEBALDconsult 22-Jan-17 11:31am

Ah, OK.
Peter Leow 22-Jan-17 11:38am

Hi, guys. Sorry for keeping you waiting. I just noticed the discussion generated here and can't just go to bed. A quick think through and got a third version. Check it out and give me your view. But I have to go to bed lest late for work tomorrow.
Graeme_Grant 22-Jan-17 11:46am

Looks good Peter ... 2 & 222 are equals, so the order is not important. The outcome will be dependent on the algorithm used.

2:45am here, so understand how you feel. :)
PIEBALDconsult 22-Jan-17 11:49am

2 and 222 are equal, but 20 and 200 are not, which is why I give the shorter value precedence whenever my first compare says they're equal.
Graeme_Grant 22-Jan-17 11:51am

yes, "20"+"200" != "200"+"20" but "2"+"222" = "222"+"2". :)
PIEBALDconsult 22-Jan-17 12:58pm

Ah, now that would simplify things (for they who want to do use string manipulation); rather than "padding" the shorter value, simply compare the two candidate concatenations. :D That's much more straight-forward.

I just posted a new comparer that does that. It seems to work, but I want to avoid string manipulation. I have something whacky in mind...
Graeme_Grant 22-Jan-17 20:06pm

Okay okay, you don't want to use strings... After a little thought, I have updated Solution 3 (see bottom section) with a calculated version just for you. The same design principle still applies... ;)
PIEBALDconsult 22-Jan-17 20:10pm

No, I do want to use strings, you _have_ to use strings, but string _manipulation_ should be avoided.
Graeme_Grant 22-Jan-17 20:13pm

Look again, a "dedicated to PIEBALDConsult" no strings used new Comparer in Solution 3 (look down at the bottom of the solution, last Update).
Graeme_Grant 23-Jan-17 1:02am

I just had another look at your code and noticed that it is "all string" but above you mentioned "I want to avoid string manipulation"... I still like Linq over your SortedList implementation. Both use Microsoft's Quicksort algorithm under the covers. At least with Linq you only need to iterate over the list once - much cleaner and more efficient. ;)
PIEBALDconsult 23-Jan-17 9:03am

Right, no string _manipulation_ -- such as concatention and substring, I don't even want to use string compares. I have the one IndexOf per value to determines integerness, and I'd like to eliminate that.
You can _have_ strings, but not manipulate them.
Graeme_Grant 23-Jan-17 9:23am

Yes... That is why I dedicated an Integer only solution to you. The Concat in the new Comparer (solution 3) is not a string concatenation, it is an Integer Extension Method that is a binary merge of the two numbers joining or "Concatenates" the two numbers into one Int64 just like the string concatenation would. ;)
Graeme_Grant 22-Jan-17 20:10pm

I just posted a calculated version of my comparer. I think that this is a cleaner way of doing what you were trying to do.
Patrice T 22-Jan-17 12:54pm

Hi Peter,
As far as I understand you padding in round 3, it is wrong.
if you try 24, 242, 243, it should sort to 243 24 242, but I think you get 243 242 24.
Peter Leow 22-Jan-17 23:03pm

I will go with PIEBALDconsult.

## Solution 8

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:
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.SortDescending(x => x, comparer);
}
}
catch { }
}
}
}

Here is the view (no code-behind used):
<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"/>

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:
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:
<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"/>

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}}"

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:
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:
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:
<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! :)
v7

Top Experts
Last 24hrsThis month
 OriginalGriff 185 Richard Deeming 130 Patrice T 130 phil.o 125 MadMyche 100
 OriginalGriff 4,056 Richard MacCutchan 1,700 Patrice T 1,267 Gerry Schmitz 924 phil.o 913