HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Two sets came to an intersection

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
twocamesetsintersection

Problem

Challenge:


Print set intersections.

Specifications:


Your program should accept as its first argument a path to a filename.

Each line in the file is a test case.

Each test case contain two semicolon delimited sorted lists of numbers in ascending order, whose numbers are separated by a comma.


Print out the ascending order sorted intersection of the lists, one per line.

Print empty new line in case the lists have no intersection

Solution:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.LinkedHashSet;
import java.util.Scanner;
import java.util.Set;

public class SetIntersection {
    public static void main(String[] args) throws FileNotFoundException {
        Scanner input = new Scanner(new File(args[0]));
        String[] parts;

        while (input.hasNextLine()) {
            parts = input.nextLine().split(";");

            System.out.println(
                findIntersection(
                    toIntArray(parts[0].split(",")),
                    toIntArray(parts[1].split(","))
                )
            );
        }
    }

    private static String findIntersection(int[] foo, int[] bar) {
        Set intersection = new LinkedHashSet<>();

        for (int i = 0, j = 0; i  bar[j] && j < bar.length) {
                j++;
            }
            if (foo[i] < bar[j]) {
                continue;
            } else {
                intersection.add(bar[j++]);
            }
        }

        if (intersection.isEmpty()) {
            return ""; // none found
        }

        String result = intersection.toString();
        return result.substring(1, result.length() - 1);
    }

    private static int[] toIntArray(String[] array) {
        int[] nums = new int[array.length];

        for (int i = 0; i < array.length; i++) {
            nums[i] = Integer.parseInt(array[i]);
        }

        return nums;
    }
}


Sample Input:


9,10,11;33,34,35

3,7,8,22;11,22

11,12,13,14;14,15,16

20,2

Solution

This is a fine implementation.
It's well-formatted and nicely written.
I find the idea of using a LinkedHashSet quite clever and interesting.
There are a couple of points to improve though.

You have a bug

Do you notice something fishy here?

while (foo[i] > bar[j] && j < bar.length) {
    j++;
}
if (foo[i] < bar[j]) {


The condition in the while checks foo[i] > bar[j] before j

  • It should be faster to generate the output from a StringBuilder than from a LinkedHashSet



-
Disadvantage: in common cases it converts input values to numbers twice.
This is because in every step of the
while loop, when only one of the positions advance, then on the next step the other number will be converted to integer again.

There is possibly one more advantage:
it's not clear if in the output the values should be separated by single commas,
or by comma + space as in yours (and in the output of
Set.toString).
Since the values are separated by
, in the input,
I would assume the same rule for the output as well,
but I could be wrong.
But if I'm right,
then to get the right output you would have to strip the spaces from the result of the
Set.toString` call.

Code Snippets

while (foo[i] > bar[j] && j < bar.length) {
    j++;
}
if (foo[i] < bar[j]) {
@Test
public void test_9_10_11_x_33_34_35() {
    assertEquals("", findIntersection("9,10,11;33,34,35"));
}

@Test
public void test_3_7_8_22_x_11_22() {
    assertEquals("22", findIntersection("3,7,8,22;11,22"));
}

@Test
public void test_11_12_13_14_x_14_15_16() {
    assertEquals("14", findIntersection("11,12,13,14;14,15,16"));
}

@Test
public void test_20_21_22_x_45_46_47() {
    assertEquals("", findIntersection("20,21,22;45,46,47"));
}

@Test
public void test_77_78_79_x_78_79_80_81_82() {
    assertEquals("78,79", findIntersection("77,78,79;78,79,80,81,82"));
}

@Test
public void test_33_35_x_3_18_26_35() {
    assertEquals("35", findIntersection("33,35;3,18,26,35"));
}

@Test
public void test_33_x_3_4() {
    assertEquals("", findIntersection("33;3,4"));
}
private String findIntersection(String input) {
    String[] parts = input.split(";");
    String[] arr1 = parts[0].split(",");
    String[] arr2 = parts[1].split(",");
    return findIntersection(arr1, arr2);
}

private String findIntersection(String[] arr1, String[] arr2) {
    StringBuilder builder = new StringBuilder();
    for (int pos1 = 0, pos2 = 0; pos1 < arr1.length && pos2 < arr2.length; ) {
        int value1 = Integer.parseInt(arr1[pos1]);
        int value2 = Integer.parseInt(arr2[pos2]);

        if (value1 == value2) {
            builder.append(value1).append(",");
            ++pos1;
            ++pos2;
        } else if (value1 < value2) {
            ++pos1;
        } else {
            ++pos2;
        }
    }
    if (builder.length() == 0) {
        return "";
    }
    return builder.substring(0, builder.length() - 1);
}

Context

StackExchange Code Review Q#80613, answer score: 6

Revisions (0)

No revisions yet.