views:

782

answers:

9

You are given an integer 51234 (say) we need to sort the digits of a number the output will be 12345.

How to do it without using array ?

+2  A: 

Divide by 10 given integer in loop. Print the reminder in each iteration.

Or "sort" means what here? For real sorting you will need two loops. One of them will be from 0 to 9. Another one will be that was described early.

int main()
{
    int x = 0;
    cin >> x;

    for ( int l = 0; l < 10; ++l )
    {
        int rem = x % 10;
        int tx = x / 10;
        while ( rem || tx )
        {
            if ( rem == l ) cout << rem;
            rem = tx % 10;
            tx = tx / 10;
        }
    }
    cout << endl;
}
Kirill V. Lyadvinsky
+21  A: 

You can use a loop and % 10 to extract each digit. An outer loop from 0 to 9 could be used to test if the digit exists. If it exists, print it.

In pseudo code:

n = integer // 51234
FOR digit = 0 TO 9
  temp = n
  REPEAT
    IF temp % 10 = digit THEN PRINT digit
    temp /= 10
  UNTIL temp = 0

Edit: This test in gcc shows that it handles zeros and repeated digits:

$ cat sortdigits.c
#include <stdio.h>
main () {
 int n,digit,temp;
 n = 43042025;
 for (digit=0;digit<9;digit++)
   for (temp=n;temp>0;temp/=10)
     if (temp%10==digit) printf("%d",digit);
 printf("\n");
}
$ ./sortdigits
00223445
Carlos Gutiérrez
+1 I will accept this :) Pseudo code won't necessary though :)
nthrgeek
Beautiful... Hmm... in a way.
Pascal Cuoq
@Pascal: I guess. If you want to iterate over a number 10 times instead of one. It saves on memory, though :-).
Alok
well done. lateral thinking :)
Learning
I think this will not work with numbers having some digits more then once. For example for 3221 it will print 123 while it should 1223.
Adam Badura
@ Adam Badura: Why not ? This will too give correct output.
nthrgeek
Yes. Indeed. My bad.
Adam Badura
@Adam Funnily, that was my first reaction too. What made me fall in love with this program really is the aha moment when I realized it worked...
Pascal Cuoq
+4  A: 

General overview:

  • loop for i = 0 to 9
  • in each loop iteration, walk through the digits in the number (using another loop that does a "mod 10" operation to peel off the digits until the number reduces to zero) - if it matches the digit you're currently working on, print it

The only potentially tricky bit might be properly handling zeros - you don't want too many, and you'll want to handle the edge case where the input is zero properly.

Actual implementation is left as an exercise...

Michael Burr
+4  A: 

Easy:

#include <stdio.h>
#include <stdlib.h>

static void pput(int n, int c)
{
    int i;
    for (i=0; i < n; ++i) putchar(c);
}

int main(int argc, char *argv[])
{
    int zeros = 0;
    int ones = 0;
    int twos = 0;
    int threes = 0;
    int fours = 0;
    int fives = 0;
    int sixes = 0;
    int sevens = 0;
    int eights = 0;
    int nines = 0;
    long num = 0;

    if (argc > 1) {
        char *eptr;
        num = strtol(argv[1], &eptr, 0);
        if (*eptr) {
            fprintf(stderr, "Invalid number: '%s', using 0.\n", argv[1]);
            num = 0;
        }
    }
    do {
        switch (num % 10) {
            case 0: ++zeros;
                    break;
            case 1: ++ones;
                    break;
            case 2: ++twos;
                    break;
            case 3: ++threes;
                    break;
            case 4: ++fours;
                    break;
            case 5: ++fives;
                    break;
            case 6: ++sixes;
                    break;
            case 7: ++sevens;
                    break;
            case 8: ++eights;
                    break;
            case 9: ++nines;
                    break;
            default:
                    break;
        }
    } while ((num /= 10));
    pput(zeros, '0');
    pput(ones, '1');
    pput(twos, '2');
    pput(threes, '3');
    pput(fours, '4');
    pput(fives, '5');
    pput(sixes, '6');
    pput(sevens, '7');
    pput(eights, '8');
    pput(nines, '9');
    putchar('\n');
    return 0;
}

Compiling and running:

$ gcc -Wextra -Wall -ansi -pedantic -Wfloat-equal -Wundef -Wshadow \
  -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes \
  -Wswitch-default -Wswitch-enum -Wstrict-overflow=5 \
  -Wdeclaration-after-statement -Wwrite-strings -Wconversion \
  -Waggregate-return -Wunreachable-code a.c
$ ./a.out
0
$ ./a.out 54321
12345
$ ./a.out 9834346
3344689
$ ./a.out hello
Invalid number: 'hello', using 0.
0

:-)

Another solution, not using arrays, and pretty short on line-count:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    long num = 0;
    int i;
    size_t *freq;

    if (argc > 1) {
        char *eptr;
        num = strtol(argv[1], &eptr, 0);
        if (*eptr || errno == ERANGE) {
            fprintf(stderr, "Invalid number: '%s', using 0.\n", argv[1]);
            num = 0;
        }
    }

    if ((freq = calloc(10, sizeof *freq)) == NULL) {
        perror("malloc failure");
        return EXIT_FAILURE;
    }

    do
        ++freq[num % 10];
    while ((num /= 10));

    for (i=0; i < 10; ++i) {
        size_t j;
        for (j=0; j < freq[i]; ++j)
            putchar(i + '0');
    }
    putchar('\n');
    free(freq);

    return EXIT_SUCCESS;
}

Yes, I am aware of the "correct" solution. But why would one not use arrays for this problem? As one of the commentators said, I wouldn't want to work for a company that wouldn't let me use arrays in C.

Alok
Howz that easy ??!! All those lines really necessary ? :O
nthrgeek
@nthgreek: my point is that the question is really bad. Why wouldn't one want to use an array here?
Alok
Using an array will make it that easy,that even a kid can to it ! :P
nthrgeek
@nthgreek: I know the requirement is meant to make it not-easy. But there are plenty of non-easy *good* questions for interviewers to ask.
Alok
Yes may be ... easy and no-easy is rather a subjective term.
nthrgeek
@Alok: +1 because I also see this question as plain bad. The way it is asked it looks totally useless hair splitting (even if with some bits of context it could reveal otherwise).
kriss
@kriss: thanks. I don't understand the point of the question. It's not as if by not using arrays you're showing some real skill.
Alok
"Trick" interview questions might not be a great tool, but they're commonly used and arguably have some value. But, they need to be small problems that can be specified in a few sentences and have solutions that can reasonably be demonstrated in under an hour on a whiteboard. They're often also intended to draw out a thought process from an interviewee. Given all these constraints, they'll usually have bizarre restrictions that you might not see in the real world. If you have to try to figure out in a short time how much someone knows or how they reason, there are worse techniques.
Michael Burr
Ugly replacement of array with "ones", "twos", etc. :p
e.tadeu
+1 for sarcasm.
Steve Jessop
@Michael: I agree with you in general, however I don't know if the intended solution tests enough "skills" to warrant the question in the first place. @e.tadeu, @Steve: thanks! :-)
Alok
@Alok: I'd agree that this would probably be a pretty weak interview quiz. Maybe it's intended to screen applicants at the level of "fizz-buzz", but in that case you wouldn't want or need to disallow arrays, so I'll go with you on this.
Michael Burr
@Michael: I think Dan's answer is pretty strong (best use of a bubble sort I've ever seen), in the sense that he offers reasonable code that adapts a naturally array-based sort to the "no arrays" constraint. Likewise the adapted bucket sort given by you and Carlos. Maybe the question is designed to test whether you have the kind of candidate who rolls their eyes at bad questions, or the kind who rolls their sleeves up and gets on with it. Companies need both behaviours in the developer team - one to fix bad specs, and one to implement the bad specs that can't be fixed ;-)
Steve Jessop
@Steve: The problem I see here is that while "rolling up your sleeves and getting on with it" is excellent, if your arrays are broken this is the wrong place to deal with it. I want the candidate who would say (as I might) "Give me the source code to your C compiler, and I will fix its (apparently) broken array implementation". I don't want the coworker who sees a bug at some level, and doesn't even think to fix it, but instead work around it at every other level of the system -- like writing a bubble-sort on digits of an int. I've had to maintain code written by these people. It's not fun.
Ken
BTW, that's not taking a swipe at Dan's function, which is kind of clever, and solves the problem as asked. I guess in most interviews that would be a fine answer. But if *I* asked this question in an interview (for some strange reason), the only *good* answer would be "no arrays? WTF? I'll write my own compiler if I have to...".
Ken
I don't agree - the point of an interview question is not necessarily to set a practical problem that might arise in a professional situation, and see how you'd handle it. I don't think anyone would ask this question because they need programmers who can program in a subset of C with no arrays. For much the same reason, the "correct" answer to 90% of interview questions is "I'd look up on the internet how to do it", but even though that's the *correct* answer, it's not a *good* answer. Finally, I'd like to see you write a compiler in a version of C lacking arrays ;-)
Steve Jessop
I guess what I'm trying to convey is that interview questions need to pose a surprising problem, but one which doesn't take significant time to investigate or understand. I'm not saying this is the best question ever, but personally I'd have no interest in someone who interviewed by in effect saying "I reject the premise of all your questions, none of them has ever occurred in my working life and I have no interest in possible answers to them". The question isn't, "can you program in C without arrays?", it's "can you use an unfamiliar tool, but not one so unfamiliar it takes time to learn?"
Steve Jessop
Steve: Then I guess we disagree. :-) I also disagree that 90% of interview questions would actually be answered with google -- the internet is great for things like "I forget what the StringSplit function is called in language X", but I wouldn't look there for how to implement, say, a binary tree. If you can answer that in an interview, you can certainly write it yourself in the luxury of an editor.
Ken
I guess it would be hard to find anyone who didn't agree with what both of you are saying in general. It's more about *where* the line of "stupid" versus "clever" is in such questions. I personally believe that this question is more of a "stupid" kind, and if I were asked the question in an interview, I would provide the `malloc()` version as an answer, followed by my first version, followed by what the most obvious solution would be (iterate over the number once for each digit, starting at 0).
Alok
@Ken: I would totally hit Google for how to implement a binary tree, (or more realistically, for some other data structure I didn't know already). The Wikipedia article (http://en.wikipedia.org/wiki/Binary_tree) tells me to refer to pp.318-248 of Knuth, but IIRC the Wiki articles on AVL trees and red-black trees are both pretty comprehensive for when I can't remember all the details of rebalancing off the top of my head (i.e. always). Maybe 90%, maybe not, but in addition SO is increasing the proportion all the time ;-)
Steve Jessop
@Steve Jessop - Thanks for the pointer to *bucket sort*. I found that this solution and both I posted are implementations of *Counting Sort* created in 1954, which is a special case of bucket sort where buckets are size 1. I learned something today :-)
Carlos Gutiérrez
+5  A: 
// Bubblesort
long sortNum(long n) {
  while (true) {
    long a = n % 10, p = 9;
    bool s = false;
    for (long r = n / 10; r; r/= 10) {
      long b = r % 10;
      if (a < b) {
        n -= p * (b - a);
        s = true;
      } else a = b;
      p *= 10;
    }
    if (!s) return n;
  }
}

#include <iostream>

int main(int argc, char **argv) {
  if (argc > 1) {
    long n = strtol(argv[1], 0, 0);
    std::cout << "Unsorted: " << n << std::endl;
    n = sortNum(n);
    std::cout << "Sorted:   " << n << std::endl;
  }
  return 0;
}

$ g++ -Wall -Wextra bubble-int.cpp && ./a.exe 183974425
Unsorted: 183974425
Sorted:   123445789
Dan
Clever - I didn't even look closely at this until I saw Steve Jessop's comment in another answer. It does need a bit added to handle zeros. Still very clever.
Michael Burr
Thanks. Kind of a "trick answer" to a trick question. If someone actually gave me this answer in an interview, I'd have to ask, "why so complicated? why not use std::map?" It's good to have people that **can** do this sort of thing, but also who know when it's better not to.
Dan
A: 

One could try something like an insertion sort. Essentially create a new number from taking one digit of the old one at a time and putting it in the correct place.something like this.

while(num!=0){

dig = num%10; // get the last digit 
if(newNum=0 ) newNum+=dig;
else{
    newNumTemp = 0; flag =1;i =1;
    while (newNum != 0){
    Newdig = newNum%10;
   if(flag){
      if (Newdig >= dig )
         {NewNumTemp = Newdig*(10^i)+ NewNumTemp; }
      else { flag=0; NewNumTemp = dig*(10^i) +NewNumTemp; i++;NewNumTemp = Newdig*   (10^i)+    NewNumTemp;}

     } // end of outer if 
     i++;
     newNum/=10;

   } // end of while
   newNum= newNumTemp;
}// end of else 

num/=10;

}// end of outer while
Aman Neelappa
sorry bout the format. How does one insert a code snippet ?
Aman Neelappa
Any line that starts with four spaces is left untouched. Click on the "?" on the top right of the edit box for help.
Alok
@Alok : Thanks for the tip
Aman Neelappa
+4  A: 

You don't need to write a program at all, just do it with shell commands:

echo "51234" | sed 's+\(.\)+\1\n+g' | sort | tr -d '\n'
50 years ago this would be considered high-level programming. :-)
Ken
A: 

Create a container interface over the int (something like vector), where operator references the i'th decimal digit. You would have to define iterators and other things too. Then call std::sort on it. ;)

e.tadeu
+1  A: 

Sure arrays are out, but we've got a better container anyway:

void foo(unsigned i) {
  std::set<char> digits;
  do {
    digits.insert(`0` + i % 10);
    i /= 10;
  while(i!=0);
}

Use multiset if your input includes numbers like 887 that should be printed as 788

MSalters
I think that if arrays are not allowed then in fact any containers are not allowed.
Adam Badura