Implement illustration for the folding technique
This commit is contained in:
parent
2449c8117a
commit
97c1f79f32
@ -0,0 +1,77 @@
|
|||||||
|
package com.baeldung.folding;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a hash value for the strings using the folding technique.
|
||||||
|
*
|
||||||
|
* The implementation serves only to the illustration purposes and is far
|
||||||
|
* from being the most efficient.
|
||||||
|
*
|
||||||
|
* @author veontomo
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FoldingHash {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the hash value of a given string
|
||||||
|
* @param str
|
||||||
|
* @param groupSize
|
||||||
|
* @param maxValue
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int hash(String str, int groupSize, int maxValue) {
|
||||||
|
final int[] codes = this.toAsciiCodes(str);
|
||||||
|
return IntStream.range(0, str.length())
|
||||||
|
.filter(i -> i % groupSize == 0)
|
||||||
|
.mapToObj(i -> extract(codes, i, groupSize))
|
||||||
|
.map(block -> concatenate(block))
|
||||||
|
.reduce(0, (a, b) -> (a + b) % maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new array of given length whose elements are take from
|
||||||
|
* the original one starting from the offset.
|
||||||
|
*
|
||||||
|
* If the original array has not enough elements, the returning array will contain
|
||||||
|
* element from the offset till the end of the original array.
|
||||||
|
*
|
||||||
|
* @param numbers
|
||||||
|
* @param offset
|
||||||
|
* @param length
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int[] extract(int[] numbers, int offset, int length) {
|
||||||
|
final int defect = numbers.length - (offset + length);
|
||||||
|
final int s = defect < 0 ? length + defect : length;
|
||||||
|
int[] result = new int[s];
|
||||||
|
for (int index = 0; index < s; index++) {
|
||||||
|
result[index] = numbers[index + offset];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenate the numbers into a single number.
|
||||||
|
* Assume that the procedure does not suffer from the overflow.
|
||||||
|
* @param numbers
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int concatenate(int[] numbers) {
|
||||||
|
final String merged = IntStream.of(numbers)
|
||||||
|
.mapToObj(number -> "" + number)
|
||||||
|
.collect(Collectors.joining());
|
||||||
|
return Integer.parseInt(merged, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the string into its characters' ascii codes.
|
||||||
|
* @param str
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int[] toAsciiCodes(String str) {
|
||||||
|
return str.chars()
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.baeldung.folding;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class FoldingHashUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringJavaLanguage_whenSize2Capacity100000_then48933() throws Exception {
|
||||||
|
final FoldingHash hasher = new FoldingHash();
|
||||||
|
final int value = hasher.hash("Java language", 2, 100_000);
|
||||||
|
assertEquals(value, 48933);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringVaJaLanguage_whenSize2Capacity100000_thenSameAsJavaLanguage() throws Exception {
|
||||||
|
final FoldingHash hasher = new FoldingHash();
|
||||||
|
final int java = hasher.hash("Java language", 2, 100_000);
|
||||||
|
final int vaja = hasher.hash("vaJa language", 2, 100_000);
|
||||||
|
assertTrue(java == vaja);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSingleElementArray_whenOffset0Size2_thenSingleElement() throws Exception {
|
||||||
|
final FoldingHash hasher = new FoldingHash();
|
||||||
|
final int[] value = hasher.extract(new int[] {5}, 0, 2);
|
||||||
|
assertArrayEquals(new int[] {5}, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenFiveElementArray_whenOffset0Size3_thenFirstThreeElements() throws Exception {
|
||||||
|
final FoldingHash hasher = new FoldingHash();
|
||||||
|
final int[] value = hasher.extract(new int[] {1, 2, 3, 4, 5}, 0, 3);
|
||||||
|
assertArrayEquals(new int[] {1, 2, 3}, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenFiveElementArray_whenOffset1Size2_thenTwoElements() throws Exception {
|
||||||
|
final FoldingHash hasher = new FoldingHash();
|
||||||
|
final int[] value = hasher.extract(new int[] {1, 2, 3, 4, 5}, 1, 2);
|
||||||
|
assertArrayEquals(new int[] {2, 3}, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenFiveElementArray_whenOffset2SizeTooBig_thenElementsToTheEnd() throws Exception {
|
||||||
|
final FoldingHash hasher = new FoldingHash();
|
||||||
|
final int[] value = hasher.extract(new int[] {1, 2, 3, 4, 5}, 2, 2000);
|
||||||
|
assertArrayEquals(new int[] {3, 4, 5}, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user