Problem Statement :
Input Format : First line of the input contains an integer n. Second line of inputs contains the n array elements
Output format : The largest number that can be composed using all the array elements
Constraints : 1<=n<=100 and 1<=array elements<=1000
A simple sorting algorithm does not work for inputs like : 2,21 which gives the output as 212, but the largest number is 221
Hence I came up with the following algorithm :
- Sort all the numbers in descending order with respect to their msd (most significant digit)
- Find out ranges of elements having the same msd
- within each range containing elements of same msd, we sort each element according to a value returned by a upgrade function. Upgrade function does not alter values of elements.
The upgrade function returns a value on the following basis :
if element is equal to 1000 then -1 is returned, which causes it to be placed at the end of the array
if element is single digit and is equal to the msd of its range, we return msd100 + msd10 + msd
if element is double digit and is equal to msd10 + msd, we return msd100 + msd*10 + msd
if elemment is double digit we return element*10
in other cases we return the element
I came up with this algorithm considering the inputs 532, 5 , 55 ,56 the maximum number should be 56,555,532
My code :
#include<stdio.h>
#include<stdlib.h>
void sort_msd(int arr[],int n);
void range_provider_msd(int arr[], int n); // finds out the indexes within which elements of same msd are present
void swap(int a,int b, int arr[]); // swaps array elements with index a and b in array arr[]
int msd(int n); //finds msd of n
void sort_final(int range_left,int range_right,int arr[], int msd_); //gives the final sort on the basis of upgrade function
int upgrade(int n,int msd_); //upgrades element for better comparison
int main()
{
int n; //n is number of element in array
scanf("%d",&n);
int*arr=(int*)malloc(n*sizeof(int));
for(int i=0;i<n;++i){scanf("%d",&arr[i]);}
sort_msd(arr,n); //soritng according to msd
range_provider_msd(arr,n);
for(int i=0;i<n;++i){printf("%d",arr[i]);}
return 0;
}
void sort_msd(int arr[],int n)
{
for(int i=0;i<n;++i)
{
int max_index=i,max_msd=msd(arr[i]);
for(int j=i+1;j<n;j++)
{
int compare_msd=msd(arr[j]);
if(compare_msd>max_msd)
{
max_index=j;
max_msd=compare_msd;
}
}
swap(i,max_index,arr);
}
}
int msd(int n)
{
while(n>=10)
{
n=n/10;
}
return n;
}
void swap(int a,int b, int arr[])
{
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
void range_provider_msd(int arr[], int n)
{
//following code finds out the index ranges for elements with same msd and passes them onto the sort_final function
int left_range=0,right_range=0;
for(int i=1;i<(n+1);++i) //n+1 to check for the special case for last elements being equal
{
if(msd(arr[left_range])-msd(arr[i]) == 0 && left_range<n-1 && i<n)
++right_range;
else if(right_range== n-1 && i==n) //special code when last elements are equal
{
sort_final(left_range,right_range,arr,msd(arr[left_range]));
}
else
{
sort_final(left_range,right_range,arr,msd(arr[left_range]));
left_range=right_range+1;
++right_range;
}
}
}
void sort_final(int range_left,int range_right,int arr[],int msd_)
{
for(int i=range_left;i<=range_right;++i)
{
int max_index=i;
for(int j=i+1; j<=range_right;++j)
{
if(upgrade(arr[j],msd_)>upgrade(arr[max_index],msd_))
max_index=j;
}
swap(i,max_index,arr);
}
}
int upgrade(int n, int msd_)
{
if(n==1000)
return -1;
else if(n<10 && n==msd_)
return(100*msd_ + 10*msd_ + msd_);
else if(n>=10 && n<100 && n==(10*msd_+msd_))
return(100*msd_ + 10*msd_ + msd_);
else if(n>=10 && n<100)
return(n*10);
else
return(n);
}
I submitted this code on my grading system and got stuck on 9th test out of 11 tests, and test does not specify what inputs I am getting stuck on. How can I find a case in which the program fails to output the right answer?
Or is there any easier and obvious method to solve this problem? I have no knowledge of data structures or something like that.
p.s This is one of my assignments from the Coursera course "algorithmic toolbox" by University of California San Diego.
Try
Your code will give
but you could have formed
So your calculation of "weight" of the individual number is wrong.
Try this code:
Output:
Some hints for understanding the weight calculation.
Assume N1 is a 1 digit number, N2 is a 2 digit number and N3 is a 3 digit number.
Let's say you want to select between a N2 and a N3 number (i.e. which to use first). Depending on which you use first you get two different numbers that can be compared. Doing the math will give:
Let's do the same for N1 and N3:
Let's do the same for N1 and N2:
So we have 3 equations:
Notice that the scaling for N1 is always the same (i.e. 9 * 11 * 111), the scaling for N2 is always the same (i.e. 9 * 111) and the scaling for N3 is always the same (i.e. 9 * 11).
That's the basis for the weight calculation.
Oh yes... the extra
* 10and add of 1 or 2 in the function is for handle of ties. In that case we want the number with fewest digits first.So after assigning weight to all numbers, all you need is
qsort. You don't need any "pre-sorting" based on "most significant digit".Just calculate weight. Then sort the array. Done.
Edit
I just noticed this:
Well, if that means you want a solution without use of
structyou can move the weight calculation into theqsortcompare function. Then you won't need thestructbut the sorting will be slower as the weights will be calculated several times.Anyway it would be like: