Positions Average in Java

The challenge

Suppose you have 4 numbers: '0', '9', '6', '4' and 3 strings composed with them:

s1 = "6900690040" s2 = "4690606946" s3 = "9990494604"
Code language: JavaScript (javascript)

Compare s1 and s2 to see how many positions they have in common: 0 at index 3, 6 at index 4, 4 at index 8 ie 3 common positions out of ten.

Compare s1 and s3 to see how many positions they have in common: 9 at index 1, 0 at index 3, 9 at index 5 ie 3 common positions out of ten.

Compare s2 and s3. We find 2 common positions out of ten.

So for the 3 strings we have 8 common positions out of 30 ie 0.2666… or 26.666…%

Given n substrings (n >= 2) in a string s our function pos_average will calculate the average percentage of positions that are the same between the (n * (n-1)) / 2 sets of substrings taken amongst the given n substrings. It can happen that some substrings are duplicate but since their ranks are not the same in s they are considered as different substrings.

The function returns the percentage formatted as a float with 10 decimals but the result is tested at 1e.-9 (see function assertFuzzy in the tests).

Example:

Given string s = “444996, 699990, 666690, 096904, 600644, 640646, 606469, 409694, 666094, 606490” composing a set of n = 10 substrings (hence 45 combinations), pos_average returns 29.2592592593.

In a set the n substrings will have the same length ( > 0 ).

The solution in Java code

Option 1:

public class PositionAverage { public static double posAverage(String s) { String[] strings = s.split(","); int matchs = 0; double of = 0; for (int i = 0; i < strings.length; i++) strings[i] = strings[i].trim(); for (int i = 0; i < strings.length; i++) { for (int j = i + 1; j < strings.length; j++) for (int k = 0; k < strings[i].length(); k++) { matchs += (strings[i].charAt(k) == strings[j].charAt(k)) ? 1 : 0; of++; } } return matchs * 100 / of; } }
Code language: Java (java)

Option 2:

class PositionAverage { private static double pairPercentage(String s1, String s2) { int lg = s1.length(); int count = 0; for (int pos = 0; pos < lg; pos++) { if (s1.charAt(pos) == s2.charAt(pos)) count += 1; } return (double)count / lg; } public static double posAverage(String s) { String[] strings = s.split(", "); double result = 0.0; int cnt = 0; int lg = strings.length; for (int k = 0; k < lg; k++) { for (int i = k + 1; i < lg; i++) { result += pairPercentage(strings[k], strings[i]); cnt += 1; } } result = 100.0 * result / cnt; return Math.floor(result * Math.pow(10.0, 10)) / Math.pow(10.0, 10); } }
Code language: Java (java)

Option 3:

public class PositionAverage { public static double posAverage(String s) { long posCount = 0; long matchCount = 0; String[] parts = s.split(", "); for(int i=0; i<parts.length-1; i++){ for(int k=i+1; k<parts.length; k++){ for(int z=0; z<parts[k].length(); z++){ posCount++; if(parts[i].charAt(z)==parts[k].charAt(z)) matchCount++; } } } return (double)matchCount / (double) posCount * 100.0; } }
Code language: Java (java)

Test cases to validate our solution

import org.junit.Test; import org.junit.runners.JUnit4; import static org.junit.Assert.*; import org.junit.Test; public class PositionAverageTest { private static void assertFuzzy(String s, double exp){ System.out.println("Testing " + s); boolean inrange; double merr = 1e-9; double actual = PositionAverage.posAverage(s); inrange = Math.abs(actual - exp) <= merr; if (inrange == false) { System.out.println("Expected mean must be near " + exp +", got " + actual); } assertEquals(true, inrange); } @Test public void test() { assertFuzzy("466960, 069060, 494940, 060069, 060090, 640009, 496464, 606900, 004000, 944096", 26.6666666667); assertFuzzy("444996, 699990, 666690, 096904, 600644, 640646, 606469, 409694, 666094, 606490", 29.2592592593); assertFuzzy("4444444, 4444444, 4444444, 4444444, 4444444, 4444444, 4444444, 4444444", 100); assertFuzzy("0, 0, 0, 0, 0, 0, 0, 0", 100); } }
Code language: Java (java)
Tags:
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments