8
\$\begingroup\$

input 3,5 output should be 3,4,5

input 5,3 output should be 5,4,3

And the code

public static void test(int a, int b) {
        if(a>b) {
            for (int i = a; i >= b; i--) {
                System.out.print(i + "\t");
            }
        }else if(a<b) {
            for (int i = a; i <= b; i++) {
                System.out.print(i + "\t");
            }
        }
    }

It works but looks a little messy. Is it possible to do without if else thing? Only one loop.

\$\endgroup\$
12
\$\begingroup\$

The function name is weird. What is it testing? A more appropriate name might be printInclusiveRange(…, …).

Since the bounds are inclusive, I would expect that for input 3,3, the output should be 3. Yet you output nothing.

I would also expect the output not to end with a Tab character.

Here's one solution that corrects those two problems, and also combines the loops:

public static void printInclusiveRange(int a, int b) {
    System.out.print(a);
    if (a != b) {
        int i = a;
        int step = (a < b) ? +1 : -1;
        do {
            i += step;
            System.out.print("\t" + i);
        } while (i != b);
    }
    System.out.println();  // Perhaps you want a newline here?
}
\$\endgroup\$
  • \$\begingroup\$ The way I wrote this loop is pretty lame. @rolfl's is much better. \$\endgroup\$ – 200_success May 12 '15 at 18:21
11
\$\begingroup\$

Conventional way

public static void testA(int a, int b) {
    if (a == b) {
        return;
    }
    StringBuilder result = new StringBuilder();
    for (int i = a; ; i += a < b ? 1 : -1) {
        result.append(i).append("\t");
        if (i == b) {
            break;
        }
    }
    System.out.println(result.deleteCharAt(result.length() - 1).toString());
}

The for-loop is slightly unconventional in the sense that it terminates when i == b during the loop. A terminal condition doesn't work as cleanly here, as far as I know, since i will either keep getting smaller or larger than b. That is why the 'middle' part reads ; ;.

We then either increment or decrement i based on the condition a < b. Finally, we remove the last tab character with a deleteCharAt() call.

Java 8 features ahead...

Going above and beyond the question, if you can also consider using Java 8's IntStream and a Comparator.reverseOrder()...

public static void test(int a, int b) {
    if (a == b) {
        return;
    }
    String result = IntStream.rangeClosed(Math.min(a, b), Math.max(a, b))
                    .boxed()
                    .sorted(a > b ? Comparator.reverseOrder() : Comparator.naturalOrder())
                    .map(Object::toString)
                    .collect(Collectors.joining("\t"));
    System.out.println(result);
}

You can optionally pass in "\t" as a method argument...

You need a better name than test() BTW. :)

\$\endgroup\$
6
\$\begingroup\$

I am going with the theory that your implementation is buggy when it comes to the a == b condition. Other answers have replicated this bug, and, frankly, I think the intent of the specification is clear enough that the a == b condition is a bug, not a feature to be reproduced. Additionally there are three comments I would like to add:

  1. if performance is a problem, then the multiple print operations would be a real problem. But, having them all on one line is also a problem, so if there's a lot of output, well, you're in trouble anyway.
  2. Other answers have attempted math on the a and b values which will fail if the differences between them are large. This is sort of OK, because if the differences ever were that large, you would run out of memory first... But, for example, an a of -2 and a b of Integer.MAX_VALUE, will produce different results for different solutions. Again, though, will it get that far?
  3. I agree with many other comments about method names, etc. This question has me wondering whether it should be closed.... either as unclear, or broken.

Still, taking the assumption that when a == b, I would like to present two solutions, one is a traditional loop, and it is simple, and clear, and is what I imagine you were "supposed" to do:

int step = a < b ? 1 : -1;
for (int i = a; i != b; i += step) {
    System.out.print(i + '\t');
}
System.out.print(b);

The other solution is a Stream solution which is just "nice". Note that it accumulates the values in to a single print, which may have memory effects for you. By converting the values to long, you can avoid issues around large differences....

private static final LongUnaryOperator INC = v -> v + 1;
private static final LongUnaryOperator DEC = v -> v - 1;

and then the code:

final long limit = Math.abs((long)a - (long)b) + 1;
System.out.println(LongStream.iterate(a, a < b ? INC : DEC)
        .limit(limit)
        .mapToObj(Long::toString)
        .collect(Collectors.joining("\t")));
\$\endgroup\$
3
\$\begingroup\$

I'd like to supplement the answer given by 200_success in saying that I think the printing should be done outside of the function, and that the function should return a value like an array or ArrayList. I suppose this really depends on your usage, but I prefer to keep functions that modify values apart from I/O. This makes it easier to test and also manipulate the format of your output with less risk of breaking your code.

Complete usage might be like this:

import java.util.ArrayList;

public class Consecutives {

    public static void main(String[] args) {
        int start = Integer.parseInt(args[0]);
        int end = Integer.parseInt(args[1]);
        ArrayList<Integer> range = inclusiveRange(start, end);
        System.out.println(joinList(range, "\t"));
    }

    public static ArrayList<Integer> inclusiveRange(int a, int b) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        result.add(a);
        if (a != b) {
            int i = a;
            int step = (a < b) ? +1 : -1;
            do {
                i += step;
                result.add(i);
            } while (i != b);
        }
        return result;
    }

    public static String joinList(ArrayList<Integer> list, String separator){
        StringBuilder sb = new StringBuilder();
        for (Integer i : list) {
            sb.append(i);
            sb.append(separator);
        }
        return sb.toString();
    }
}
\$\endgroup\$
2
\$\begingroup\$

Do you want to use math functions like min or abs? You can do it like that:

    public static void test(int a, int b) {
        for(int i=0;i !=Math.abs(b-a)+1;i++){
           System.out.println((b>=a)?a+i:a-i);                
        }        
 }

You can also remove the second if - do it with just if -else

\$\endgroup\$
  • 1
    \$\begingroup\$ Not that this is likely the case, but note that b-a could produce odd results if the difference is > Integer.MAX_VALUE. This is almost certainly not the case, but one day this may bite. \$\endgroup\$ – rolfl May 12 '15 at 10:58

protected by rolfl May 12 '15 at 10:56

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.