3
\$\begingroup\$

I implemented the Multiparental Sorting Crossover as described here in section 4.2. The (compiled) program can be run as follows:

$ java MPSX input.txt

where input.txt looks like this (the first line is the mask followed by three parents):

3 1 2 1 1 1 1 2 2

8 4 7 3 6 2 5 1 9

9 1 2 3 4 5 6 7 8

4 7 9 3 6 2 5 1 8

As for output, it merely prints the correct result as a string.

import edu.princeton.cs.algs4.In;
import java.io.InputStream;


public class MPSX {

    public static void main(String[] args) {

        String filename = args[0];
        In in = new In(filename);

        String[] Input = in.readAllLines();

        String result = solve(Input);

        System.out.println(result);

    }


    private static void swap(int[] parent_x, int[] parent_y, int index) {


        for (int i = 0; i < parent_y.length; i++) {

            if (parent_y[i] == parent_x[index]) {

                int tmp = parent_y[index];
                parent_y[index] = parent_y[i];
                parent_y[i] = tmp; 

            }

        }

    }


    private static String solve(String[] Input) {

        String result = "";

        String[] parent1str = Input[1].split(" ");
        String[] parent2str = Input[2].split(" ");
        String[] parent3str = Input[3].split(" ");

        int[] parent1 = new int[parent1str.length];
        int[] parent2 = new int[parent2str.length];
        int[] parent3 = new int[parent3str.length];

        for (int i = 0; i < parent1str.length; i++) {
            parent1[i] = Integer.parseInt(parent1str[i]);
            parent2[i] = Integer.parseInt(parent2str[i]);
            parent3[i] = Integer.parseInt(parent3str[i]);
        }

        String mask = Input[0].replaceAll("\\s","");


        for (int i = 0; i < mask.length(); i++) {

            int mask_element = Character.getNumericValue(mask.charAt(i));;

            if (mask_element == 1) {    
                result += parent1[i];
                swap(parent1, parent2,i);
                swap(parent1, parent3,i);
            }

            else if (mask_element == 2) {
                result += parent2[i];
                swap(parent2, parent1,i);
                swap(parent2, parent3,i);
            }

            else if (mask_element == 3) {
                result += parent3[i];
                swap(parent3, parent1,i);
                swap(parent3, parent2,i);
            }

        }

        return result;
    }

}

It is effectively the first program I wrote in Java so I know there is a lot of room for improvement and refactorization.

In particular, I am sure there is a better (more concise) way of processing the input text file. I thought of creating an array of arrays of Strings instead of 3 separate arrays but I wasn't sure how to do it.

\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

Parsing a line of space separated integers is repeated 4 times you can replace those with the method below:

private static int[] parseLineOfInts(String s) {
    String[] tokens = s.split(" ");
    int[] arr = new int[tokens.length];
    for (int j = 0; j < tokens.length; j++)
       arr[j] = Integer.parseInt(tokens[j]);
    return arr;
}

You can use arrays of arrays to hold 2D data. Parsing the parents becomes as below:

int nParents = 3;
int[][] parents = new int[nParents][];
for (int i = 0; i < nParents; i++) {
    parents[i] = parseLineOfInts(Input[i + 1]);
}

Note parent1 is now parent[0] and so on.

You can use parseLineOfInts method to calculate mask_elements as below:

int[] maskElements = parseLineOfInts(Input[0]);

parameters and local variables should be camelcase: first word starts with lowercase, subsequent words start with upper case:

  • Input should be input
  • parent_x should be parentX
  • parent_y should be parentY

Separate parsing and actual algorithm. Separation of concerns improves readability, testability, many other ...abilities. As a first step you can extract not string manipulation related code into a new function such that its signature becomes as below:

int[] solve(int[] mask, int[][] parents)
\$\endgroup\$
2
  • \$\begingroup\$ Thank you! One question - when you define the array of arrays like this int[][] parents = new int[nParents][]; how come you don't need to specify the size of the individual arrays? \$\endgroup\$
    – Jan Pisl
    Commented Mar 11, 2019 at 18:55
  • 1
    \$\begingroup\$ Individual elements are just null; you can assign them later any int[], no matter the length. You can leave them null, or assign some or all of them the same int[] for that matter. All of this is because Java arrays are reference types, the variables hold just the memory location of the actual value, you allocate the actual memory with new. You can think of new int[m][n] as a shorthand. \$\endgroup\$ Commented Mar 12, 2019 at 6:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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