Largest Minus Smallest Digit Rearrangement
National Olympiad — Regional round (2009 season)
Submission name: sub.cpp
Problem summary
Rearrange all digits of a positive integer into the largest and smallest numeric values, subtract them, and print no leading zeros. In this version zeros may lead the minimum arrangement.
Source clarification. The official sample requires leading zeros to be allowed in the minimum arrangement:765211110−011112567=754098543. This is different from a problem requiring both rearrangements to retain the original digit count.
Input
One positive integer A.
Output
The exact difference.
Constraints
A has1…80 decimal digits.
Worked example
Input and output for the worked example discussed below.
Input
210151617
Output
754098543
Solution analysis
- Sort the digits descending for the largest arrangement and ascending for the smallest. Unlike an n-digit-minimum variant, this source allows leading zeros in the minimum, as its sample demonstrates.
- Keep both arrangements as equal-length decimal strings. Subtract right to left with a borrow; when a digit difference is negative, add10 and borrow1 from the next higher position.
- For210151617, the largest arrangement is765211110 and the smallest padded arrangement011112567. Their difference is754098543. Strip leading zeros only from the final answer, and print0 if all result digits are zero.
Why it works
An inversion swap proves descending digits maximize the value and ascending digits minimize it when leading zeros are permitted. Standard decimal subtraction computes their difference exactly. Removing output-leading zeros changes only representation, not value.
Watch out. Do not force a nonzero leading digit in the minimum: that contradicts this sample. Use strings rather than fixed-width integers and propagate borrows through zeros.
Commented C++17 solution
An independently written complete program with standard headers.
#include<algorithm>
#include<iostream>
#include<string>
using namespace std;
int main(){
string lowest;
cin>>lowest;
sort(lowest.begin(),lowest.end());
string highest=lowest;
reverse(highest.begin(),highest.end());
string difference(highest.size(),'0');
int borrow=0;
for(int i=int(highest.size())-1;i>=0;i--){
int digit=highest[i]-lowest[i]-borrow;
borrow=digit<0;
if(borrow!=0){
digit+=10;
}
difference[i]=char('0'+digit);
}
// Only the printed result loses its leading zero padding.
size_t first=difference.find_first_not_of('0');
cout<<(first==string::npos?"0":difference.substr(first))<<'\n';
}