简体   繁体   中英

Switch numbers in int array according to a pattern

I've been scanning the internet trying to come up with a solution for this simple program that will basically take user input in numbers (a telephone number) and change every number according to the following rules:

0 → (becomes) 5, 1 → 9, 2 → 8, 3 → 7, 4 → 6, 5 → 0, 6 → 4, 7 → 3, 8 → 2, 9 → 1.

So a number of 7784321600 becomes 3326789455.

I took user input as a String, converted it to an int array but when I try to swap, I don't get it to work as well as I hoped for.

I tried to swap the values with the in the following way:

for (int i = 0; i < input.length(); i++) {
    if (nrArray[i] == 0) {
        // 0 becomes 5
        int temp0[] = { 5 };
        nrArray[i] = nrArray[i] + temp0[i];
        temp0[i] = nrArray[i] - temp0[i];
        nrArray[i] = nrArray[i] - temp0[i];
    }
}

which works OK if it was only going to swap numbers 0-4, as soon as it reaches 5-9, the code will reverse it again like this:

for (int i = 0; i < input.length(); i++) {
    if (nrArray[i] == 5) {
        // 5 becomes 0
        int temp0[] = { 0 };
        nrArray[i] = nrArray[i] + temp0[i];
        temp0[i] = nrArray[i] - temp0[i];
        nrArray[i] = nrArray[i] - temp0[i];
    }
}

I also tried the replaceAll method for changing the string, but the same problem occurs.

Any suggestions?

All the answers so far have focused on giving you code that will work; none of them on telling you why your current code doesn't work.

The structure of what you've got is something like this:

if (a[i]==0) { a[i]=somefixedvalue }
if (a[i]==1) { a[i]=someothervalue }
if (a[i]==2) { a[i]=somethirdvalue }
//etc.

The problem here is that all your statements get executed, one by one. If the first one changes the value of a[i] to a 1, then the second one will also pass the guard and change it again.

What you really want is to say that the first statement whose guard matches should be executed, and after that it should stop. The right pattern for that would be

if (a[i]==0) { a[i]=somefixedvalue }
else if (a[i]==1) { a[i]=someothervalue }
else if (a[i]==2) { a[i]=somethirdvalue }
//etc.

There are neater approaches to a solution, including storing a fixed map, or using a switch statement, but hopefully this answers your question as to why your code doesn't work as it stands.

One simple solution would be having a fixed map :

{0: 5, 1: 9, 2: 8, 3: 7, 4: 6, 5: 0, 6: 4, 7: 3, 8: 2, 9: 1}

Then you simply iterate on the sequence, and for each character ch , you replace it with map[ch] .

The solution's complexity is O(n), the best you can have.


Pseudo code:

res = ""
for ch in seq:
    res += map[ch]

Use a hashmap to store source integer as key and target integer as value. Then iterate through the array, during each iteration get the current array value target from hashmap and replace it.

int a[] = {7,7,8,4,3,2,1,6,0,0};
Map<Integer, Integer> map = new HashMap<Integer, Integer>();

//0->5, 1->9, 2->8, 3->7, 4->6, 5->0, 6->4, 7->3, 8->2, 9->1
map.put(0, 5);
map.put(1, 9);
map.put(2, 8);
map.put(3, 7);
map.put(4, 6);
map.put(5, 0);
map.put(6, 4);
map.put(7, 3);
map.put(8, 2);
map.put(9, 1);

for (int i = 0; i < a.length; i++) {
    a[i] = map.get(a[i]);
}

Using an integer array, you can create a cheap and fast map, which you can use to map your input <-> your desire input. Also, using a stringbuilder you can create a string representation of the number, and then parse it to int

int [] switcher = {5,9,8,7,6,0,4,3,2,1};

    int [] input;
    StringBuilder wholeNumber = new StringBuilder();
    for(int i = 0; i < input.length; i++)
    {
        input[i] = switcher[input[i]];
        wholeNumber.append(String.valueOf(input[i]));
    }

    int wholeNumberInt = Integer.parseInt(wholeNumber.toString());

You can also use a Switch statement that replaces each array element to reach your goal. This example checks each element and replaces it with the correct digit then prints out the resulting array.

    int arr[] = {4,0,7,8,8,5,0,0,9,0};
    for(int i=0; i<arr.length;i++){
        switch(arr[i]){
            case 0:
                arr[i] = 5;
                break;
            case 1:
                arr[i] = 9;
                break;
            case 2:
                arr[i] = 8;
                break;
            case 3:
                arr[i] = 7;
                break;
            case 4:
                arr[i] = 6;
                break;
            case 5:
                arr[i] = 0;
                break;
            case 6:
                arr[i] = 4;
                break;
            case 7:
                arr[i] = 3;
                break;
            case 8:
                arr[i] = 2;
                break;
            case 9:
                arr[i] = 1;
                break;
            }
    }
    for(int i =0; i<arr.length;i++) {
        System.out.println(arr[i]);
    }
}

in your case you can use the following Condition

   if(nrArray[i]%5 == 0) {
     nrArray[i]= 5-nrArray[i];
    }
   else{
     nrArray[i]= 10-nrArray[i];
    }

Have only one for loop, containing all the number switches in if-else statements. The loop will only run once for each number in the array and therefore wont change the 5 to a 0 and back to a 5 again, like yours is doing.

for(int i=0; i<input.length(); i++){
    if(nrArray[i]==0){
        nrArray[i]=5;
    }else if(nrArray[i]==5){
        nrArray[i]=0;
    }//All the other else-if for the different number switches
}

Because you use an else if statement, only one block will run for each number in the array.

Since it's not a logical split (ie 0 <-> 9 ; 1 <-> 8 ; 2 <-> 7 ; 3 <-> 6 ; 4 <-> 5 ), I think a possible choice would be to use a map like this:

import java.util.HashMap;
import java.util.Map;

public class Main
{
    private static final Map<Character, Character> map = new HashMap<Character, Character>() {
        private static final long serialVersionUID = 1L;

        {
            put('0', '5');
            put('1', '9');
            put('2', '8');
            put('3', '7');
            put('4', '6');
            put('5', '0');
            put('6', '4');
            put('7', '3');
            put('8', '2');
            put('9', '1');
        }
    };

    public static void main(final String[] args) {

        final String aNumber = "7784321600";

        char[] list = aNumber.toCharArray();
        String result = "";
        for (final char ch : list) {
            result += map.get(ch);
        }

        System.out.println("Before: " + aNumber);
        System.out.println("After: " + result);
    }
}

Output:

Before: 7784321600
After: 3326789455

IF you want something nice and simple... You could store input in an int array and do this

int[] input = {1, 2, 3, 4, 5, 6, ,7 ,8, 9, 0};
int[] encoded = new int[input.length];

for(int i=0; i < encoded.length; i++)
{
    if (input[i] == 5)
    {
      encoded[i] = 0;
      continue;
    }

    if (input[i] == 0)
    {
      encoded[i] = 5;
      continue;
    }

    encoded[i] = 10 - input[i]; 
}

Your encoding seems to follow a pattern except 0 and 5. I see no need to map all the values. You just need to map the ones that don't fit the pattern.

One of the solutions with complexity O(n) is to simply store the new values in an array and replace it with your input tape while iterating it.

I took user input as a String, converted it to an int array

There is no explicit need of converting your input String to the int array.

Here is the code snippet:

public static void main (String[] args) throws Exception {
    int[] arr = {5,9,8,7,6,0,4,3,2,1};
    String input = "7784321600";
    for(char c : input.toCharArray()) {
        System.out.print(arr[Character.getNumericValue(c)]);
    }
    System.out.println();
}

Output:

3326789455

I believe that this is what you are aiming at.

Just use the value of the current number as the index of the key array. This will find its respective value to convert to.

public class NumberEncoder {
    private static final int[] KEY = { 5, 9, 8, 7, 6, 0, 4, 3, 2, 1 };

    public static void main(String[] args) {
        System.out.println(encode(125, KEY)); // 980
    }

    public static int encode(int n, int[] key) {
        String input = Integer.toString(n);
        StringBuffer result = new StringBuffer();

        for (int i = 0; i < input.length(); i++) {
            result.append(key[Character.getNumericValue(input.charAt(i))]);
        }

        return Integer.parseInt(result.toString());
    }
}

If you need to handle larger numbers which are greater than a long value, you can use BigInteger .

import java.math.BigInteger;

public class NumberEncoder {
    private static final int[] KEY = { 5, 9, 8, 7, 6, 0, 4, 3, 2, 1 };

    public static void main(String[] args) {
        System.out.println(encode(new BigInteger("123456789012345678901234567890"), KEY));
    }

    public static BigInteger encode(BigInteger value, int[] key) {
        String input = value.toString();
        StringBuffer result = new StringBuffer();

        for (int i = 0; i < input.length(); i++) {
            result.append(key[Character.getNumericValue(input.charAt(i))]);
        }

        return new BigInteger(result.toString()); // 987604321598760432159876043215
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM