I am trying to fill in the code for the updateLetterCount() method, which should be quite similar to the updateDigramCount() method. However, I am stuck. Any suggestions would be helpful! I am having trouble with defining the letter variable, because I know it has to be defined for the Map. Any idea about how to go about doing so?
// imports of classes used for creating GUI
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
// imports related to reading/writing files
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
// imports of general-purpose data-structures
import java.util.TreeMap;
import java.util.Map;
import java.util.Set;
/**
* WordCount
*
* WordCount is an application for analyzing the occurrence of words, letters,
* and letter-combinations that are found in a text block.
*
* The text block can be either pasted into a window, or it can be loaded from a
* text-file.
*
*/
public class WordCount extends JFrame {
//-------------------------------------------------------------------------------------------------------
public static final String startString =
"Infrequently Asked Questions\n"
+ "\n"
+ " 1. Why does my country have the right to be occupying Iraq?\n"
+ " 2. Why should my country not support an international court of justice?\n"
+ " 3. Is my country not strong enough to achieve its aims fairly?\n"
+ " 4. When the leaders of a country cause it to do terrible things, what is the best way to restore the honor of that country?\n"
+ " 5. Is it possible for potential new leaders to raise questions about their country's possible guilt, without committing political suicide?\n"
+ " 6. Do I deserve retribution from aggrieved people whose lives have been ruined by actions that my leaders have taken without my consent?\n"
+ " 7. How can I best help set in motion a process by which reparations are made to people who have been harmed by unjust deeds of my country?\n"
+ " 8. If day after day goes by with nobody discussing uncomfortable questions like these, won't the good people of my country be guilty of making things worse?\n"
+ "\n"
+ "Alas, I cannot think of a satisfactory answer to any of these questions. I believe the answer to number 6 is still no; yet I fear that a yes answer is continually becoming more and more appropriate, as month upon month goes by without any significant change to the status quo.\n"
+ "\n"
+ "Perhaps the best clues to the outlines of successful answers can be found in a wonderful speech that Richard von Weizsäcker gave in 1985:\n"
+ "\n"
+ " > The time in which I write ... has a horribly swollen belly, it carries in its womb a national catastrophe ... Even an ignominious issue remains something other and more normal than the judgment that now hangs over us, such as once fell on Sodom and Gomorrah ... That it approaches, that it long since became inevitable: of that I cannot believe anybody still cherishes the smallest doubt. ... That it remains shrouded in silence is uncanny enough. It is already uncanny when among a great host of the blind some few who have the use of their eyes must live with sealed lips. But it becomes sheer horror, so it seems to me, when everybody knows and everybody is bound to silence, while we read the truth from each other in eyes that stare or else shun a meeting. \n"
+ " >\n"
+ " > Germany ... today, clung round by demons, a hand over one eye, with the other staring into horrors, down she flings from despair to despair. When will she reach the bottom of the abyss? When, out of uttermost hopelessness --- a miracle beyond the power of belief --- will the light of hope dawn? A lonely man folds his hands and speaks: ``God be merciful to thy poor soul, my friend, my Fatherland!'' \n"
+ " >\n"
+ " > -- Thomas Mann, Dr. Faustus (1947, written in 1945)\n"
+ " > [excerpts from chapter 33 and the epilogue] \n"
+ "\n"
+ "[ Author: Donald Knuth ; Source: http://www-cs-faculty.stanford.edu/~uno/iaq.html ]\n";
//-------------------------------------------------------------------------------------------------------
/**
* getDigramCount
*
* Get a count of how many times each digram occurs in an input String.
* A digram, in case you don't know, is just a pair of letters.
*
* #param text a string containing the text you wish to analyze
* #return a map containing entries whose keys are digrams, and
* whose values correspond to the number of times that digram occurs
* in the input String text.
*/
public Map<String,Integer> getDigramCount(String text)
{
Map<String,Integer> digramMap = new TreeMap<String,Integer>();
text = text.toLowerCase();
text = text.replaceAll("\\W|[0-9]|_","");
for(int i=0;i<text.length()-1;i++)
{
String digram = text.substring(i,i+2);
if(!digramMap.containsKey(digram))
{
digramMap.put(digram,1);
} else {
int freq = digramMap.get(digram);
freq++;
digramMap.put(digram,freq);
}
}
return digramMap;
}
/**
* updateDigramCount
*
* Use the getDigramCount method to get the digram counts from the
* input text area, and then update the appropriate output area with
* the information.
*/
public void updateDigramCount()
{
Map<String,Integer> wordCountList = getDigramCount(words);
StringBuffer sb = new StringBuffer();
Set<Map.Entry<String,Integer>> values = wordCountList.entrySet();
for(Map.Entry<String,Integer> me : values)
{
// We will only print the digrams that occur at least 5 times.
if(me.getValue() >= 5)
{
sb.append(me.getKey()+" "+me.getValue()+"\n");
}
}
digramCountText.setText(sb.toString());
}
/**
* getLetterCount
*
* Get a count of how many times each letter occurs in an input String.
*
* #param text a string containing the text you wish to analyze
* #return a map containing entries whose keys are alphabetic letters, and
* whose values correspond to the number of times that letter occurs
* in the input String text.
*/
public Map<Character,Integer> getLetterCount(String text)
{
Map<Character,Integer> letterMap = new TreeMap<Character,Integer>();
text = text.toLowerCase();
// Now get rid of anything that is not an alphabetic character.
text = text.replaceAll("\\W|[0-9]|_","");
for(int i=0;i<text.length()-1;i++)
{
Character letter = text.charAt(i);
if(!letterMap.containsKey(letter))
{
letterMap.put(letter,1);
} else {
int freq = letterMap.get(letter);
freq++;
letterMap.put(letter,freq);
}
}
return new TreeMap<Character,Integer>();
}
/**
* updateLetterCount
*
* Use the getLetterCount method to get the letter counts from the
* input text area, and then update the appropriate output area with
* the information.
*/
public void updateLetterCount()
{
String words = theText.getText();
Map<Character,Integer> letterCountList = getLetterCount(letter);
StringBuffer sb = new StringBuffer();
Set<Map.Entry<Character,Integer>> values = letterCountList.entrySet();
for(Map.Entry<Character,Integer> me : values)
{
if(me.getValue() >= 5)
{
sb.append(me.getKey()+" "+me.getValue()+"\n");
}
}
letterCountText.setText(sb.toString());
}
This is a screenshot of the error
public Map<Character,Integer> getLetterCount(String text)
{
...
return new TreeMap<Character,Integer>();
}
returns an empty map. You want to return letterMap here,
Related
I am creating a JavaFX Seating Arrangement APP
#FXML
void addStudentClicked(ActionEvent event) {
String str = studentname.getText();
Random random = new Random();
int randomInt = random.nextInt(9);
if(randomInt == 0){
if(str.isEmpty()){
errorLabel.setText("ERROR");
}
else{
studentname1.setText(studentname.getText());
student1.setFill(studentcolour.getValue());
}
}
else if(randomInt == 1){
if(str.isEmpty()){
errorLabel.setText("ERROR");
}
This is my code that so far will take the user input and apply it to a random seat, it continues with else if's for each seat is there a cleaner way for me to do this then with all the else if's and how can I check to see if the seat is already filled so I am not filling the same seat twice?
Also is there a way to check if the colour has already been taken?
An interesting alternative to using the random function is to put all your choices in a List and then apply the Collection method shuffle(). Then, you can iterate through the list. This ensures that each option is chosen once and only once.
I haven't looked closely enough at the code to tell if a switch/case construct would be a better choice, but that is always something to consider.
Here is a similar (deliberately not the same) example just using the console.
I leave it to you to create a GUI.
Hints
Writing GUIs is not the same as writing console apps because GUIs are event-driven, so you need to get rid of some loops and act on events.
You can use ObservableLists to have list changes reflected in the UI.
When you remove something from an ObservableList, it will no longer be in the list, so if it is bound to something in the UI, it will no longer be there
e.g. if it is a color selection list and a color is removed from it, the color will no longer be available for selection.
Shuffle a list, then pick from the shuffled list
This is the same idea as physically shuffling a deck of cards, then grabbing the cards in order from top to bottom.
The basic idea is that one way to solve this problem is to apply:
Random shuffling of an array
You could also study:
Unique (non-repeating) random numbers in O(1)?
https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
But you don't need to write the shuffle algorithm yourself, you can just use the one already implemented in the java collection library.
Collections.shuffle(seatNumbers);
Example app
Console app-based example.
I'm sure the example uses some concepts you aren't familiar with, and if you use them, you should understand them or do them a different way. In particular:
Colors could be selected from a pre-defined array (like the names are) rather than using an interpolated generator.
An array of seat numbers could be generated using a loop adding to a list rather than a stream adding to a collection in a lambda.
Try running the sample application and look at the output to see what it did, then try to think about how you might apply similar concepts to your program.
import javafx.scene.paint.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class MusicalDragons {
public static final int NUM_ROUNDS = 3;
public static void main(String[] args) {
MusicalDragons game = new MusicalDragons();
for (int i = 0; i < NUM_ROUNDS; i++) {
System.out.println("Round " + (i+1));
System.out.println("=========");
game.play();
System.out.println();
}
}
private final List<String> dragons;
private final List<Color> palette;
private final List<Integer> seatNumbers;
private final int numSeats;
public MusicalDragons() {
// generate a list of names.
dragons = Arrays.asList(
"Oyositatu (Old + Dragon)",
"Tamasipionosi (Soul + Master)",
"Timatamï (Crossroad + Snake)",
"Tômiarôzi (Wealth + Master)",
"Ararepemi (Hail + Snake)",
"Umasumera (Horse + Emperor)",
"Umitatu (Sea + Dragon)",
"Akitatu (Autumn + Dragon)",
"Tawayatatu (Weak + Dragon)",
"Amoritatu (Descend From Heaven + Dragon)"
);
numSeats = dragons.size() - 1;
// generate a list of colors.
palette = new ArrayList<>();
for (int i = 0; i < numSeats; i++) {
palette.add(
Color.RED.interpolate(
Color.VIOLET,
i * (1.0 / (numSeats - 1))
)
);
}
// generate a list of seat numbers.
seatNumbers =
IntStream.range(0, numSeats)
.boxed()
.collect(
Collectors.toCollection(
ArrayList::new
)
);
}
private void play() {
// randomize the order of everything.
Collections.shuffle(palette);
Collections.shuffle(seatNumbers);
Collections.shuffle(dragons);
// display the seat assignments.
for (int i = 0; i < numSeats; i++) {
System.out.println(
dragons.get(i) + "\n" +
" gets seat #" + seatNumbers.get(i) + "\n" +
" colored " + palette.get(i)
);
}
// hmm, one dragon missed out . . .
System.out.println();
System.out.println(
dragons.get(numSeats) +
" does not get a seat and is very angry."
);
}
}
Output
Round 1
=========
Tawayatatu (Weak + Dragon)
gets seat #1
colored 0xf64884ff
Tamasipionosi (Soul + Master)
gets seat #4
colored 0xff0000ff
Oyositatu (Old + Dragon)
gets seat #7
colored 0xfd0e1aff
Ararepemi (Hail + Snake)
gets seat #0
colored 0xf074d4ff
Umasumera (Horse + Emperor)
gets seat #8
colored 0xfb1d35ff
Amoritatu (Descend From Heaven + Dragon)
gets seat #3
colored 0xf73a6aff
Timatamï (Crossroad + Snake)
gets seat #2
colored 0xf4579fff
Umitatu (Sea + Dragon)
gets seat #5
colored 0xf265b9ff
Tômiarôzi (Wealth + Master)
gets seat #6
colored 0xf92b4fff
Akitatu (Autumn + Dragon) does not get a seat and is very angry.
I'm in the process of making a program using input from a text file, it only has 2 lines of text in it which is
120 (this is the time)
2 (this is changes)
My code is meant to read the user's input which converts hours to minutes, and then asks for a number of changes. If the hours entered are 02:00 which is 120 minutes and the changes entered are 2 or less then it will come back saying 'acceptable', and if not it will read 'unacceptable' however I am having a bit of trouble formulating this. If anybody could provide assistance I would appreciate it greatly!
Code to follow:
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class InputOutput {
public static void main(String[] args) throws IOException{
final Scanner S = new Scanner(System.in);
final Scanner inFile = new Scanner(new FileReader("task.txt"));
// open file and associate objects
int IOminutes = Integer.parseInt(inFile.next());
int changes = Integer.parseInt(inFile.next());
// close the input file
inFile.close();
System.out.print("Specify Time (HH:MM): ");
String givenTime = S.next();
System.out.print("Specify Changes: ");
String givenChanges = S.next();
// save the index of the colon
int colon = givenTime.indexOf(':');
// strip the hours preceding the colon then convert to int
int givenHours = Integer.parseInt(givenTime.substring(0, colon));
// strip the mins following the colon then convert to int
int givenMins = Integer.parseInt(givenTime.substring(colon + 1, givenTime.length()));
// calculate the time's total mins
int mins = (givenHours * 60) + givenMins;
// using given time
System.out.println(givenTime + " = " + mins + " minutes");
if (!givenTime.equals(IOminutes) && changes >= 3) {
System.out.println("Time: " + givenTime + ", Changes: " + givenChanges + " = unacceptable!");
} else if (givenTime.equals(IOminutes) && changes <= 2) {
System.out.println("Time: " + givenTime + ", Changes: " + givenChanges + " = acceptable!");
}
S.close();
}
}
Your inputs (file-based and user-based) look reasonable.
By the time you reach your if-elseif logic on line 40, you have the following values (all values based on the problem description in the question):
loaded from "task.txt"...
IOminutes: 120
changes: 2
user input:
givenTime="02:00"
givenChanges=2
givenHours=2
givenMins=0
mins=2*60+0 = 120
Your conversion from strings to integers looks like no problem.
Your desired outcome of "acceptable" / "unacceptable" is hard for me to understand; not what it is doing, but Why it is doing that.
I'm having trouble understanding why you have two "changes".
This would make more sense to me if you just had:
task.txt: IOminutes=120, changes=2
given: time="hh:mm"
Now compute difference (in minutes) between task.txt's IOminutes and user's given time. Let's call that difference givendiff. Then you have something like:
if givendiff > changes then unacceptable.
Examples (user input values more or less made up):
task.txt: IOminutes=120, changes=2
test 1: given time="02:00" (computed givendiff=0, so acceptable)
test 2: given time="01:50" (computed givendiff=-10, so unacceptable)
test 3: given time="02:05" (computed givendiff=5, so unacceptable)
test 3: given time="02:02" (computed givendiff=2, so acceptable)
test 3: given time="01:58" (computed givendiff=-2, so acceptable)
I would encourage you to review the original requirements and verify whether your user is supposed to be give you an extra "changes" in addition to task.txt's changes. Or if you're supposed to compute a the difference between task.txt's IOminutes and the user-entered value, and complain if that difference exceeds task.txt's changes value.
I would go further but this seems like a homework or code-challenge problem; if so, hopefully this is enough to help nudge your perspective to re-thing what "changes" means in the original requirements. Good luck.
I have a txt file of a WhatsApp chat and I want to parse it using Java.
But all emojis used is displayed as "😂" in the txt file. I wanted to try and findout how to learn which emoji is actually used and tried this:
System.out.print( "\\u" + Integer.toHexString(line.charAt(i) | 0x10000).substring(1) );
But it displays a wrong unicode such as \ud83d etc.
I also got this list but I don't know exactly how to use it:
http://grumdrig.com/emoji-list/#
The \uD83D is part of a surrogate paring with \uDE04 which is actually encoded together to produce\u0001F604.
U+1F604 (U+D83D U+DE04) produces the SMILING FACE WITH OPEN MOUTH AND SMILING EYES emoji -> 😄
This Gist (mranney/emoji_sad.txt) might be a starting point for figuring out how to parse your files.
Example
You could possibly port some of this JavaScript to Java.
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
long codepoint = 0x1f600;
int[] pair = findSurrogatePair(codepoint);
System.out.printf("%s -> %s%n", toHex(codepoint),
IntStream.of(pair).mapToObj(v -> toHex(v))
.collect(Collectors.joining(" + ")));
}
/**
* Assumes point > 0xFFFF
* <p>
*
* #param point Unicode codepoint to convert to surrogate pairs.
* #return Returns the surrogate pairing for the input code-point.
*/
public static int[] findSurrogatePair(final long point) {
long offset = point - 0x10000;
int lead = (int) (0xD800 + (offset >> 10));
int trail = (int) (0xDC00 + (offset & 0x3FF));
return new int[] { lead, trail };
}
public static String toHex(Number value) {
return String.format("\\u%X", value);
}
}
Output
\u1F600 -> \uD83D + \uDE00
This is my first post so apologies if I haven't quite got the framing of the question quite right yet. I'll put my hands up straight away and say this is part of my 'homework', I've got about 99% of it done but I've got this niggling bug that has been driving me crazy all week and I simply can't see the wood through the trees here.
The basic concept is that we have a text file, a poem of sorts, that our program has to look at and then place into a binary tree. We should record each word, the occurrence of each word and which line it appears in. I have managed to do that, save for that for in the example "And I went to StackOverFlow and I asked the question, and the answer was..." my program should return that the word "And" appears in line 1 (which it currently does), but it is currently recording every occurrence of that word and it should only record that the word "and" occurs in line 1 and not every instance of it.
So in the above example "And I went to StackOverFlow and I asked the question, and the answer was.."
So just picking out the word "And" here since it occurs multiple times, my program is currently returning:
"And [1, 1, 1]"
But it should be returning:
"And [1]"
I have supplied the code for the entire program, but the method I think to focus on is the recordWord method, at the final else if, something isn't quite right there clearly! Apologies if this explanation is hugely convoluted but I couldn't think of another way to explain it! Any help would be hugely appreciated
import java.util.*;
/**
* A class representing a binary tree containing words.
*
*/
public class WordTree {
public String word;
public ArrayList<Integer> lineNumbers;
public WordTree left, right;
/**
* Constructs a tree consisting of a single node, with the given word and
* line number.
*
* #param w
* the word
* #param lineNo
* the line number
* #pre true
* #post word tree containing word w on line lineNo has been constructed
*/
public WordTree(String w, int lineNo) {
word = w;
lineNumbers = new ArrayList<Integer>();
lineNumbers.add(lineNo);
left = null;
right = null;
}
/**
* Records a new occurrence of the given word, in the tree.
*
* #param w
* the word
* #param lineNo
* the line number
* #pre this is a well formed binary search tree
* #post if word was not in this tree, then the word and its line number
* line have been inserted into ordered word tree, else line has been
* appended to line-number list for word (if we haven't already
* recorded that line number for this word)
*/
public void recordWord(String word2, int lineNo) {
if (word.compareToIgnoreCase(word2) < 0) {
if (right != null) {
right.recordWord(word2, lineNo);
} else {
right = new WordTree(word2, lineNo);
}
} else if (word.compareToIgnoreCase(word2) > 0) {
if (left != null) {
left.recordWord(word2, lineNo);
} else {
left = new WordTree(word2, lineNo);
}
} else if (word.compareToIgnoreCase(word2) == 0) {
lineNumbers.add(lineNo);
}
}
// System.out.println("method recordWord not implemented yet");
/**
* Displays all the words in this tree.
*
* #pre this is a well formed binary search tree
* #post words have been written out in alphabetical order, each followed by
* ascending list of line numbers on which the word occurs
*/
public void display() {
if (left != null) {
left.display();
}
System.out.println(word + lineNumbers);
if (right != null) {
right.display();
}
}
/**
* Counts how many different words there are in this tree.
*
* #pre this is a well formed binary search tree
* #return the number of different words in tree
*/
public int numberOfEntries() {
int count = 1;
if (left != null) {
count += left.numberOfEntries();
}
if (right != null) {
count += right.numberOfEntries();
}
}
}
Since List accepts duplication, it may accepts elements with the same value. Instead, you could use Set interface which eliminates duplication for you automatically. In your example, you can declare lineNumbers as a TreeSet to print the output in ascending line number.
Declare lineNumbers as a Set
public Set<Integer> lineNumbers;
Then initialize it in the constructor using TreeSet
lineNumbers = new TreeSet<Integer>();
It's all that you need to change. Hope it's clear enough.
I am attempting to implement the following Basic Sliding Window algorithm in Java. I get the basic idea of it, but I am a bit confused by some the wording, specifically the sentence in bold:
A sliding window of fixed width w is moved across the file,
and at every position k in the file, the fingerprint of
its content is computed. Let k be a chunk boundary
(i.e., Fk mod n = 0). Instead of taking the hash of the
entire chunk, we choose the numerically smallest fingerprint
of a sliding window within this chunk. Then we compute a hash
of this randomly chosen window within the chunk. Intuitively,
this approach would permit small edits within the chunks to
have less impact on the similarity computation. This method
produces a variable length document signature, where the
number of fingerprints in the signature is proportional to
the document length.
Please see my code/results below. Am I understanding the basic idea of the algorithm? As per the text in bold, what does it mean to "choose the numerically smallest fingerprint of a sliding window within its chunk"? I am currently just hashing the entire chunk.
code:
public class BSW {
/**
* #param args
*/
public static void main(String[] args) {
int w = 15; // fixed width of sliding window
char[] chars = "Once upon a time there lived in a certain village a little
country girl, the prettiest creature who was ever seen. Her mother was
excessively fond of her; and her grandmother doted on her still more. This
good woman had a little red riding hood made for her. It suited the girl so
extremely well that everybody called her Little Red Riding Hood."
.toCharArray();
List<String> fingerprints = new ArrayList<String>();
for (int i = 0; i < chars.length; i = i + w) {
StringBuffer sb = new StringBuffer();
if (i + w < chars.length) {
sb.append(chars, i, w);
System.out.println(i + ". " + sb.toString());
} else {
sb.append(chars, i, chars.length - i);
System.out.println(i + ". " + sb.toString());
}
fingerprints.add(hash(sb));
}
}
private static String hash(StringBuffer sb) {
// Implement hash (MD5)
return sb.toString();
}
}
results:
0. Once upon a tim
15. e there lived i
30. n a certain vil
45. lage a little c
60. ountry girl, th
75. e prettiest cre
90. ature who was e
105. ver seen. Her m
120. other was exces
135. sively fond of
150. her; and her gr
165. andmother doted
180. on her still m
195. ore. This good
210. woman had a lit
225. tle red riding
240. hood made for h
255. er. It suited t
270. he girl so extr
285. emely well that
300. everybody call
315. ed her Little R
330. ed Riding Hood.
That is not a sliding window. All you have done is break up the input into disjoint chunks. An example of a sliding window would be
Once upon a time
upon a time there
a time there lived
etc.
The simple answer is NO per my understanding (I once studied sliding window algorithm years ago, so I just remember the principles, while cannot remember some details. Correct me if you have more insightful understanding).
As the name of the algorithm 'Sliding Window', your window should be sliding not jumping as it says
at every position k in the file, the fingerprint of its content is computed
in your quotes. That is to say the window slides one character each time.
Per my knowledge, the concept of chunks and windows should be distinguished. So should be fingerprint and hash, although they could be the same. Given it too expense to compute hash as fingerprint, I think Rabin fingerprint is a more proper choice. The chunk is a large block of text in the document and a window highlight a small portion in a chunk.
IIRC, the sliding windows algorithm works like this:
The text file is chunked at first;
For each chunk, you slide the window (a 15-char block in your running case) and compute their fingerprint for each window of text;
You now have the fingerprint of the chunk, whose length is proportional to the length of chunk.
The next is how you use the fingerprint to compute the similarity between different documents, which is out of my knowledge. Could you please give us the pointer to the article you referred in the OP. As an exchange, I recommend you this paper, which introduce a variance of sliding window algorithm to compute document similarity.
Winnowing: local algorithms for document fingerprinting
Another application you can refer to is rsync, which is a data synchronisation tool with block-level (corresponding to your chunk) deduplication. See this short article for how it works.
package com.perturbation;
import java.util.ArrayList;
import java.util.List;
public class BSW {
/**
* #param args
*/
public static void main(String[] args) {
int w = 2; // fixed width of sliding window
char[] chars = "umang shukla"
.toCharArray();
List<String> fingerprints = new ArrayList<String>();
for (int i = 0; i < chars.length+w; i++) {
StringBuffer sb = new StringBuffer();
if (i + w < chars.length) {
sb.append(chars, i, w);
System.out.println(i + ". " + sb.toString());
} else {
sb.append(chars, i, chars.length - i);
System.out.println(i + ". " + sb.toString());
}
fingerprints.add(hash(sb));
}
}
private static String hash(StringBuffer sb) {
// Implement hash (MD5)
return sb.toString();
}
}
this program may help you. and please try to make more efficent