patternjavaMinor
Two sets came to an intersection
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:
Sample Input:
9,10,11;33,34,35
3,7,8,22;11,22
11,12,13,14;14,15,16
20,2
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
There are a couple of points to improve though.
You have a bug
Do you notice something fishy here?
The condition in the
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.