Task: Next highest int from digits
C: #include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

void swap(char* str, int i, int j) {
    char c = str[i];
    str[i] = str[j];
    str[j] = c;
}

void reverse(char* str, int i, int j) {
    for (; i < j; ++i, --j)
        swap(str, i, j);
}

bool next_permutation(char* str) {
    int len = strlen(str);
    if (len < 2)
        return false;
    for (int i = len - 1; i > 0; ) {
        int j = i, k;
        if (str[--i] < str[j]) {
            k = len;
            while (str[i] >= str[--k]) {}
            swap(str, i, k);
            reverse(str, j, len - 1);
            return true;
        }
    }
    return false;
}

uint32_t next_highest_int(uint32_t n) {
    char str[16];
    snprintf(str, sizeof(str), "%u", n);
    if (!next_permutation(str))
        return 0;
    return strtoul(str, 0, 10);
}

int main() {
    uint32_t numbers[] = {0, 9, 12, 21, 12453, 738440, 45072010, 95322020};
    const int count = sizeof(numbers)/sizeof(int);
    for (int i = 0; i < count; ++i)
        printf("%d -> %d\n", numbers[i], next_highest_int(numbers[i]));
    
    const char big[] = "9589776899767587796600";
    char next[sizeof(big)];
    memcpy(next, big, sizeof(big));
    next_permutation(next);
    printf("%s -> %s\n", big, next);
    return 0;
}

Java: import java.math.BigInteger;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class NextHighestIntFromDigits {

    public static void main(String[] args) {
        for ( String s : new String[] {"0", "9", "12", "21", "12453", "738440", "45072010", "95322020", "9589776899767587796600", "3345333"} ) {
            System.out.printf("%s -> %s%n", format(s), format(next(s)));
        }
        testAll("12345");
        testAll("11122");
    }

    private static NumberFormat FORMAT = NumberFormat.getNumberInstance();
    
    private static String format(String s) {
        return FORMAT.format(new BigInteger(s));
    }

    private static void testAll(String s) {
        System.out.printf("Test all permutations of:  %s%n", s);
        String sOrig = s;
        String sPrev = s;
        int count = 1;
        
        
        boolean orderOk = true;
        Map <String,Integer> uniqueMap = new HashMap<>();
        uniqueMap.put(s, 1);
        while ( (s = next(s)).compareTo("0") != 0 ) {
            count++;
            if ( Long.parseLong(s) < Long.parseLong(sPrev) ) {
                orderOk = false;
            }
            uniqueMap.merge(s, 1, (v1, v2) -> v1 + v2);
            sPrev = s;
        }
        System.out.printf("    Order:  OK =  %b%n", orderOk);

        
        String reverse = new StringBuilder(sOrig).reverse().toString();
        System.out.printf("    Last permutation:  Actual = %s, Expected = %s, OK = %b%n", sPrev, reverse, sPrev.compareTo(reverse) == 0);

        
        boolean unique = true;
        for ( String key : uniqueMap.keySet() ) {
            if ( uniqueMap.get(key) > 1 ) {
                unique = false;
            }
        }
        System.out.printf("    Permutations unique:  OK =  %b%n", unique);
        
        
        Map<Character,Integer> charMap = new HashMap<>();
        for ( char c : sOrig.toCharArray() ) {
            charMap.merge(c, 1, (v1, v2) -> v1 + v2);
        }
        long permCount = factorial(sOrig.length());
        for ( char c : charMap.keySet() ) {
            permCount /= factorial(charMap.get(c));
        }
        System.out.printf("    Permutation count:  Actual = %d, Expected = %d, OK = %b%n", count, permCount, count == permCount);
        

    }
    
    private static long factorial(long n) {
        long fact = 1;
        for (long num = 2 ; num <= n ; num++ ) {
            fact *= num;
        }
        return fact;
    }
    
    private static String next(String s) {
        StringBuilder sb = new StringBuilder();
        int index = s.length()-1;
        
        while ( index > 0 && s.charAt(index-1) >= s.charAt(index)) {
            index--;
        }
        
        if ( index == 0 ) {
            return "0";
        }

        
        int index2 = index;
        for ( int i = index + 1 ; i < s.length() ; i++ ) {
            if ( s.charAt(i) < s.charAt(index2) && s.charAt(i) > s.charAt(index-1) ) {
                index2 = i;
            }
        }
        
        
        
        if ( index > 1 ) {
            sb.append(s.subSequence(0, index-1));
        }

        
        sb.append(s.charAt(index2));
        
        
        List<Character> chars = new ArrayList<>();
        chars.add(s.charAt(index-1));
        for ( int i = index ; i < s.length() ; i++ ) {
            if ( i != index2 ) {
                chars.add(s.charAt(i));
            }
        }
        
        
        Collections.sort(chars);
        for ( char c : chars ) {
            sb.append(c);
        }
        return sb.toString();
    }
}