1
\$\begingroup\$

I'm a student in my first semester and in my free time and holidays, I do some java training to keep my mind from rusting...so I downloaded this amazing Digital Algorithms practice app and came across the Plus One problem and that inspired me to code the Plus-Target problem:

Question

Given an Integer Array (non-empty Array) you have to add specific number = target to this array then return an Array to main.

my humble solution: let's assume the following:

int [] x={9,9,9,9}

so, what first came to my mind is that the Elements

  • x[0] represent Mathematically 9000.
  • x[1 ] represent Mathematically 900.
  • x[2] represent Mathematically 90.
  • x[3] represent Mathematically 9.

then turning the array to int by summing 9000+900+90+9.

so now after converting the arrays to number, we can add the target to it. (target can be<0).

After adding the target I had to look upon to scenarios:

  1. If the result is not zero then I convert the int value of temp to string and assign the chars as numbers to a newly made array according to the length of the string minus one.

  2. If the temp is zero which would mean that the target=-9999 in our particular case. so I had to assign each and every element of the forwarded array to zero and then return it.

so now enough talking and here is my code:

private static int [] plusTarget(int[]x,int target){
    int size=x.length;//get the ze of the array
    int toPower=1;//to help set the power of 10..
    int temp=0;//this will have the array value
    char offSet='0';
    String convert=null;
    int []arr=null;
    /*
     * 9000=9*10^4-1
     * where 4 is the size of the forwarded array.
     * and so on...
     */
    for (int i = 0; i < x.length; i++) {
        temp +=x[i]*( Math.pow(10,(size-toPower) ) );
        toPower++;
    }
    System.out.println("the value of the array after turning it to number "+temp);
    temp+=target;
    System.out.println("value after adding target!. "+ temp);

    if(temp!=0){
        convert = Integer.toString(temp);//converting the number to string..
        if (temp>0) {
            arr= new int [convert.length()];
        } else if (temp<0){
            arr= new int [convert.length()-1];//minus one because the string size is more by one because of the minus sign..    
        }

        for (int i = 0; i < arr.length; i++) {
            if (convert.charAt(i)- offSet >0) {
                arr[i]=convert.charAt(i)- offSet;
            }
        }
        if (arr[0]==0) {//if the first emelent is zero then the number is minus..

            for (int i = 0; i < arr.length; i++) {
                if (i+1 != arr.length) {
                    //shifting the elements backwards one step 
                    arr[i]=arr[i+1];
                }
            }
            arr[0]*=-1;//multiplying the first element by -1
        }
        return arr;

    }else{//if (temp+(-target)==0)..then we have to assign zeros to each element of the fowarded array
        for (int i = 0; i < x.length; i++) {
            x[i]=0;
        }
    return x;
    }   
}

tests done:

target=-9999;
output=[0, 0, 0, 0]

target=-19998;
output=[-9, 9, 9, 9]

target=1;
output=[1, 0, 0, 0, 0]

target=-1
output=[9, 9, 9, 8]

I couldn't find any bugs. I might have made some mistakes unintentionally and that's why I'm posting the code here to get some suggestions from you guys.

my solution for the one plus problem:

private static int [] plusOne(int[]x){
    int size=x.length;
    int power=1;
    int temp=0;
    for (int i = 0; i < x.length; i++) {
        temp +=x[i]*( Math.pow(10,(size-power) ) );
        power++;
    }
    System.out.println("the value of the array after turning it to number "+temp);
    temp++;
    System.out.println("temp after adding one!. "+ temp);
    String convert = Integer.toString(temp);//converting the number to string..
    int [] arr= new int [convert.length()];
    for (int i = 0; i < convert.length(); i++) {
        arr[i]=(int)(convert.charAt(i)-'0'); 
    }
    return arr;
}

the app solution for the plus One case:

private static int [] app (int[]x){
  int n=x.length;

  for(int i=n-1;i>=0;i--){

      if (x[i]<9) {
          x[i]++;
          return x;
      }
      x[i]=0;
  }

  int [] newNumber= new int[n+1];

  newNumber[0]=1;

  return newNumber;

}

Please evalute my solution for the plus one problem vs the app solution as well. there is no solution for the plus-Target problem thus it came across my mind after finishing the plus-one exercise.

\$\endgroup\$
  • 6
    \$\begingroup\$ Presumably, the motivation for using an array of digits to represent the addend is because it may be arbitrarily large, possibly larger than what an int can represent. If the first thing you do is to convert that representation to an int, I'd consider the solution as a failure (if I were evaluating your code as an interviewer). And if you converted it into a BigInteger instead, I would say that the solution works, but is still "cheating" by violating the spirit of the exercise. \$\endgroup\$ – 200_success Aug 10 at 16:27
  • \$\begingroup\$ Something that's not immediately clear from the problem description you gave: it's actually a number, separated per character, that's passed as an array. 9009 => [9, 0, 0, 9]. Add a number to the original number and return it as array. Right? \$\endgroup\$ – Mast Aug 14 at 12:26
  • \$\begingroup\$ So why don't you simply merge the array, add 1 and split it back up again? \$\endgroup\$ – Mast Aug 14 at 12:26
  • \$\begingroup\$ @Mast It's exactly what the sample code does, albeit by using addition instead of string concatenation, and as 200_success explained, such a solution is not in the spirit of the exercise. The point of the exercise is to pass the carry along the array elements. \$\endgroup\$ – TorbenPutkonen Aug 15 at 12:12
1
\$\begingroup\$

I'm going to leave aside @200_success's very reasonable observation and assume the general approach you're taking is valid. That being said, I suspect your conversion approach is slower than operating directly on the array, and it's almost certainly more complex.

Variables which should not change after initial assignment should also be made final. In addition to documenting design intent, they make it easier to read the code because you know they won't change.

In idiomatic java, whitespace is put on both sides of operators such as =. Whitespace is put before {. Whitespace is not put between multiple ). There should be no whitespace between int and [], and there should be whitespace between [] and the variable name. There should be whitespace after ,.

Your comments are almost entirely noise. Comments are for explaining why design decisions were made in non-obvious cases, not what the decisions were. The reason is that it's very easy for comments and code to get out of synch, at which point somebody reading the code will not get an accurate picture of what's going on.

You declare size and then use it inconsistently. Referencing x.length directly is clear, succinct, and efficient. There's no reason for a variable.

Your conversion operation is overly verbose. Every time you get a new digit, multiply the old value by ten and add the new digit. You don't need to mess with powers at all. It might even be nice to break it out into its own method, since you're using it in both plusOne and plusTarget.

Likewise, your deconversion can be pulled out into its own method. Using String is readable, but not efficient. You can play with math to make the more efficient approach work for all numbers. Is the efficiency gain worth the tradeoff? Maybe not. Readability is probably more important unless you have a known bottleneck.

In plusTarget, your deconversion is overly complex. You can use a guard clause for the zero case which simply returns new int[] { 0 }; It would also be easier if you tracked negativity as a boolean and treated all numbers as positive, then did the *= -1 at the end.

If you were to make all these modifications, your code might look more like:

private static int[] plusOne(final int[] x) {
    int value = toInt(x);

    System.out.println("the value of the array after turning it to number: " + value);
    value++;
    System.out.println("value after adding one: " + value);

    return toIntArrayUsingMath(value);
}

private static int[] plusTarget(final int[] x, final int target) {
    int value = toInt(x);

    System.out.println("the value of the array after turning it to number: " + value);
    value += target;
    System.out.println("value after adding target: " + value);

    return toIntArrayUsingString(value);

}

private static int toInt(final int[] value) {
    int result = value[0];
    for (int i = 1; i < value.length; i++) {
        result = (10 * result) + value[i];
    }
    return result;
}

private static int[] toIntArrayUsingMath(final int value) {
    if (value == 0) {
        return new int[] { 0 };
    }

    int absoluteValue = Math.abs(value);
    final int length = (int) Math.log10(absoluteValue) + 1;
    final int[] array = new int[length];

    for (int i = array.length - 1; i >= 0; i--) {
        array[i] = absoluteValue % 10;
        absoluteValue = absoluteValue / 10;
    }

    if (value < 0) {
        array[0] *= -1;
    }

    return array;
}

private static int[] toIntArrayUsingString(final int value) {
    if (value == 0) {
        return new int[] { 0 };
    }

    final boolean negativeValue = value < 0;
    final String convert = Integer.toString(Math.abs(value));
    final int[] array = new int[convert.length()];

    for (int i = 0; i < array.length; i++) {
        array[i] = Character.digit(convert.charAt(i), 10);
    }

    if (negativeValue) {
        array[0] *= -1;
    }

    return array;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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