Implement T9 Dictionary using Trie? - java

I have to implement the T9 Dictionary .
Essentially, when I am pressing any of the 9 keys, it should show me
the top 5 words that can be started with that combination of keys.
If I type '46', it can give 'hotel' or 'good' depending on whether I
intended 'g' or 'h' when I pressed 4.
The priority is based on which words are relatively popular - you can
use, say, the first 5000 words from the top 100 000 words.
The code I am doing is:
Import
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
T9Dict class
public class T9Dict {
private static final Runtime s_runtime = Runtime.getRuntime();
public static void main(String[] args) throws Exception {
runGC();
long heap1 = usedMemory();
long start = new Date().getTime();
Trie trie = Trie.getInstance();
System.out.println("Creating Dictionary");
File f = new File("C:\\Users\\hp1\\Desktop\\100kfound.txt");
BufferedReader br = new BufferedReader(new FileReader(f));
String s = br.readLine();
int i = 0;
do {
i++;
trie.add(s);
s = br.readLine();
} while (s != null);
br.close();
long end = new Date().getTime();
long time = (end - start);
System.out.println("Loaded Dictionary with " + i + " words in " + time
+ " msec");
// runGC();
long heap2 = usedMemory(); // take an "after" heap snapshot:
System.out.println("Memory used = " + (heap2 - heap1));
String pattern = "4663";
start = new Date().getTime();
String word = trie.getWord(pattern);
end = new Date().getTime();
time = (end - start);
System.out.println("Found word : " + word + " in " + time + " msec");
}
private static void runGC() throws Exception {
// for whatever reason it helps to call Runtime.gc()
// using several method calls:
for (int r = 0; r < 4; ++r) {
_runGC();
}
}
private static void _runGC() throws Exception {
long usedMem1 = usedMemory();
long usedMem2 = Long.MAX_VALUE;
for (int i = 0; (usedMem1 < usedMem2) && (i < 1000); ++i) {
s_runtime.runFinalization();
s_runtime.gc();
Thread.currentThread().yield();
usedMem2 = usedMem1;
usedMem1 = usedMemory();
}
}
private static long usedMemory() {
return s_runtime.totalMemory() - s_runtime.freeMemory();
}
}
Trie class
class Trie {
private static final String regex = "[a-zA-Z]*";
private static Trie instance = null;
Node root = null;
Map<Character, Integer> map = new HashMap<Character, Integer>();
private Trie() {
map.put('a', 2);
map.put('b', 2);
map.put('c', 2);
map.put('d', 3);
map.put('e', 3);
map.put('f', 3);
map.put('g', 4);
map.put('h', 4);
map.put('i', 4);
map.put('j', 5);
map.put('k', 5);
map.put('l', 5);
map.put('m', 6);
map.put('n', 6);
map.put('o', 6);
map.put('p', 7);
map.put('q', 7);
map.put('r', 7);
map.put('s', 7);
map.put('t', 8);
map.put('u', 8);
map.put('v', 8);
map.put('w', 9);
map.put('x', 9);
map.put('y', 9);
map.put('z', 9);
}
private int getVal(char c) {
return map.get(c);
}
public static Trie getInstance() {
if (instance == null) {
synchronized (Trie.class) {
instance = new Trie();
}
}
return instance;
}
public String getWord(String pattern) {
String s = null;
Node node = root;
int i = 0;
int num = 0;
while (i < pattern.length()) {
num = pattern.charAt(i) - '0';
if (num == node.val) {
i++;
if (i == pattern.length()) {
s = node.list.get(0);
}
node = node.middle;
} else if (num < node.val) {
if (i == pattern.length()) {
s = node.list.get(0);
}
node = node.left;
} else {
if (i == pattern.length()) {
s = node.list.get(0);
}
node = node.right;
}
}
return s;
}
public void add(String s) {
if (s.length() > 0) {
s = s.toLowerCase();
System.out.println("Adding : " + s);
if (root == null) {
root = new Node(this.getVal(s.charAt(0)));
Node node = root;
Node temp = null;
for (int i = 1; i < s.length(); i++) {
temp = new Node(getVal(s.charAt(i)));
node.middle = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
}
}
} else {
Node node = root;
int i = 0;
Node temp = null;
int val = 0;
while (i < s.length()) {
val = getVal(s.charAt(i));
if (node.val == val) {
if (i == s.length() - 1) {
node.set(s);
i++;
} else {
i++;
if (node.middle == null) {
while (i < s.length()) {
val = getVal(s.charAt(i));
temp = new Node(val);
node.middle = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
}
i++;
}
} else {
node = node.middle;
}
}
} else if (val < node.val) {
if (node.left == null) {
temp = new Node(val);
node.left = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
} else {
i++;
while (i < s.length()) {
val = getVal(s.charAt(i));
temp = new Node(val);
node.middle = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
}
i++;
}
}
} else {
node = node.left;
}
} else {
if (node.right == null) {
temp = new Node(val);
node.right = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
} else {
i++;
while (i < s.length()) {
val = getVal(s.charAt(i));
temp = new Node(val);
node.middle = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
}
i++;
}
}
} else {
node = node.right;
}
}
}
}
}
}
}
Node class
class Node {
int val;
Node left;
Node middle;
Node right;
List<String> list = new LinkedList<String>();
public Node(int val) {
this.val = val;
}
public void set(String s) {
list.add(s);
}
public String toString() {
return String.valueOf(val);
}
}
This code is giving nullpointerexception when adding to Trie
I cannot find the solution please help

1 - You File doesn't contains characters. It is binary so you should use FileInputStream object to read it.
2 - In reading file and adding string in your Trie you should verify that this string is not null, otherwise it can throws a NullPointerException. You can run your file like this:

When I run this I find that the exception occurs on this line:
root = new Node(this.getVal(s.charAt(0)));
Let's unroll this, you're passing the first character of the "word" (ie the String, s) to the getVal(), and this in turn will return an int if, and only if, that character is a lowercase letter, a-z.
When I run the file the "word" is 6724 yahoo - this is the first line of the dictionary text file you linked to. There is nothing in your code to clean up this line to get to the actual word itself, instead you are facing a series of spaces and then a number.
So the reason it fails is because you're effectively going this.getVal(" "). If you call map.get() and the key doesn't exist it'll return null (as described in the Map documentation).
One simple way of getting to the word itself and not the whitespace or frequency number is to first process the string:
s = s.trim(); // removes all leading and trailing whitespace
String word = s.substring(s.indexOf(" ")+1); // extract just the word after the space
And then you can pass the first character of word:
root = new Node(this.getVal(word.charAt(0)));

Related

Java to C # code translation error in huffman encryption

Well you will see the problem is that I am translating a C # java code that encrypts a text file by the huffman method, in java where the original program runs perfect but the question here is that I need it in C #.
I'm trying to translate it to C # but it generates 4 errors inside the setPrefixCodes and buildTree methods which I don't understand anything and I don't know what I'm translating wrong, or I need to implement something else.
I really need to know how to translate it correctly
Help!!!!!!
namespace Huffman_v2
{
public partial class Form1: Form
{
public Form1()
{
InitializeComponent();
}
String documento;
private static IDictionary<char, string> charPrefixHashMap = new Dictionary<char, string> ();
internal static HuffmanNode root;
private void btnCifrar_Click(object sender, EventArgs e)
{
string txtText = documento;
IDictionary<char, int> freq = new Dictionary<char, int> ();
for (int i = 0; i < txtText.Length; i++)
{
if (!freq.ContainsKey(txtText[i]))
{
freq[txtText[i]] = 0;
}
freq[txtText[i]] = freq[txtText[i]] + 1;
}
txtFrecuencia.Text = freq.ToString();
root = buildTree(freq);
setPrefixCodes(root, new StringBuilder());
StringBuilder s = new StringBuilder();
for (int i = 0; i < txtText.Length; i++)
{
char c = txtText[i];
s.Append(charPrefixHashMap[c]);
}
string xs = decode(s.ToString());
txtPrefijos.Text = charPrefixHashMap.ToString();
txtCifrado.Text = xs.ToString();
}
private static void setPrefixCodes(HuffmanNode node, StringBuilder prefix)
{
if (node != null)
{
if (node.left == null && node.right == null)
{
charPrefixHashMap[node.data] = prefix.ToString();
}
else
{
prefix.Append('0');
setPrefixCodes(node.left, prefix);
prefix.deleteCharAt(prefix.Length - 1); //error en .deleteChatAt
prefix.Append('1');
setPrefixCodes(node.right, prefix);
prefix.deleteCharAt(prefix.Length - 1); //error en .deleteChatAt
}
}
}
private static string decode(string s)
{
StringBuilder stringBuilder = new StringBuilder();
HuffmanNode temp = root;
for (int i = 0; i < s.Length; i++)
{
int j = int.Parse(s[i].ToString());
if (j == 0)
{
temp = temp.left;
if (temp.left == null && temp.right == null)
{
stringBuilder.Append(temp.data);
temp = root;
}
}
if (j == 1)
{
temp = temp.right;
if (temp.left == null && temp.right == null)
{
stringBuilder.Append(temp.data);
temp = root;
}
}
}
return stringBuilder.ToString();
}
private static HuffmanNode buildTree(IDictionary < char, int > freq)
{
PriorityQueue<HuffmanNode> priorityQueue = new PriorityQueue<HuffmanNode>(); // esta linea tiene el error en PriorityQueue<HuffmanNode>
ISet<char> keySet = (ISet<char>) freq.Keys;
foreach(char ? c in keySet) {
HuffmanNode huffmanNode = new HuffmanNode();
huffmanNode.data = (char) c;
huffmanNode.frequency = freq.get(c); //aqui en .get
huffmanNode.left = null;
huffmanNode.right = null;
priorityQueue.offer(huffmanNode);
}
Debug.Assert(priorityQueue.size() > 0);
while (priorityQueue.size() > 1)
{
HuffmanNode x = priorityQueue.peek();
priorityQueue.poll();
HuffmanNode y = priorityQueue.peek();
priorityQueue.poll();
HuffmanNode sum = new HuffmanNode();
sum.frequency = x.frequency + y.frequency;
sum.data = '-';
sum.left = x;
sum.right = y;
root = sum;
priorityQueue.offer(sum);
}
return priorityQueue.poll();
}
}
}

DFS puzzle game solver (java)

I'm working with DFS solver on 8 puzzle game. This code print all children from the tree until the correct state, but I want to print only the correct solution.
My output:
120
345
678
125
340
678
102
345
678
125
348
670
125
304
678
142
305
678
012
345
678
Expected output:
120
345
678
102
345
678
012
345
678
Code:
public class puzzle {
public static LinkedHashSet<String> OPEN = new LinkedHashSet<String>();
public static HashSet<String> CLOSED = new HashSet<String>();
public static boolean STATE = false;
public static void main(String args[]) {
int statesVisited = 0;
String start = "120345678";
String goal = "012345678";
String X = "";
String temp = "";
OPEN.add(start);
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
print(X);
int pos = X.indexOf('0'); // get position of ZERO or EMPTY SPACE
if (X.equals(goal)) {
System.out.println("SUCCESS");
STATE = true;
} else {
// generate children
CLOSED.add(X);
temp = up(X, pos);
if (!(temp.equals("-1")))
OPEN.add(temp);
temp = down(X, pos);
if (!(temp.equals("-1")))
OPEN.add(temp);
temp = left(X, pos);
if (!(temp.equals("-1")))
OPEN.add(temp);
temp = right(X, pos);
if (!(temp.equals("-1")))
OPEN.add(temp);
}
}
}
/*
* MOVEMENT UP
*/
public static String up(String s, int p) {
String str = s;
if (!(p < 3)) {
char a = str.charAt(p - 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p - 3)) + '0' + newS.substring(p - 2);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT DOWN
*/
public static String down(String s, int p) {
String str = s;
if (!(p > 5)) {
char a = str.charAt(p + 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p + 3)) + '0' + newS.substring(p + 4);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT LEFT
*/
public static String left(String s, int p) {
String str = s;
if (p != 0 && p != 3 && p != 7) {
char a = str.charAt(p - 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p - 1)) + '0' + newS.substring(p);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT RIGHT
*/
public static String right(String s, int p) {
String str = s;
if (p != 2 && p != 5 && p != 8) {
char a = str.charAt(p + 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p + 1)) + '0' + newS.substring(p + 2);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
public static void print(String s) {
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3, 6));
System.out.println(s.substring(6, 9));
System.out.println();
}
}
DFS returns the first path it finds. To get the shortest path use BFS.
You can use a map
private static Map<String, List<String>> paths = new HashMap<>();
to map each node (state) to the path that led to it:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
public class puzzle {
private static LinkedHashSet<String> OPEN = new LinkedHashSet<>();
private static HashSet<String> CLOSED = new HashSet<>();
private static Map<String, List<String>> paths = new HashMap<>();
public static boolean STATE = false;
public static void main(String args[]) {
String start = "120345678";
String goal = "012345678";
String X = "";
String temp = "";
OPEN.add(start);
paths.put(start, Arrays.asList(start));
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
print(X);
int pos = X.indexOf('0'); // get position of ZERO or EMPTY SPACE
if (X.equals(goal)) {
System.out.println("SUCCESS" +"\n" + paths.get(X));
STATE = true;
} else {
// generate children
CLOSED.add(X);
temp = up(X, pos);
if (!temp.equals("-1")) {
OPEN.add(temp);
updatePaths(temp, paths.get(X));
}
temp = down(X, pos);
if (!temp.equals("-1")) {
OPEN.add(temp);
updatePaths(temp, paths.get(X));
}
temp = left(X, pos);
if (!temp.equals("-1")) {
OPEN.add(temp);
updatePaths(temp, paths.get(X));
}
temp = right(X, pos);
if (!temp.equals("-1")) {
OPEN.add(temp);
updatePaths(temp, paths.get(X));
}
}
}
}
static void updatePaths(String s, List<String> path){
if(paths.containsKey(s)) return;
List<String> newPath = new ArrayList<>(path);
newPath.add(s);
paths.put(s, newPath);
}
/*
* MOVEMENT UP
*/
public static String up(String s, int p) {
String str = s;
if (!(p < 3)) {
char a = str.charAt(p - 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, p - 3) + '0' + newS.substring(p - 2);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT DOWN
*/
public static String down(String s, int p) {
String str = s;
if (!(p > 5)) {
char a = str.charAt(p + 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, p + 3) + '0' + newS.substring(p + 4);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT LEFT
*/
public static String left(String s, int p) {
String str = s;
if (p != 0 && p != 3 && p != 7) {
char a = str.charAt(p - 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, p - 1) + '0' + newS.substring(p);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT RIGHT
*/
public static String right(String s, int p) {
String str = s;
if (p != 2 && p != 5 && p != 8) {
char a = str.charAt(p + 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, p + 1) + '0' + newS.substring(p + 2);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
public static void print(String s) {
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3, 6));
System.out.println(s.substring(6, 9));
System.out.println();
}
}
Online code can be reviewed and executed here and a refactored version here
We need somehow save relation between steps to find only steps from successful path.
Here is my solution:
public class Puzzle {
public static LinkedHashSet<Step> open = new LinkedHashSet<>();
public static HashSet<Step> closed = new HashSet<>();
public static boolean problemSolved = false;
private static class Step {
final String data;
Step previous = null;
Step(String data) {
this.data = data;
}
Step(Step previous, String data) {
this.previous = previous;
this.data = data;
}
public String getData() {
return data;
}
public Step getPrevious() {
return previous;
}
#Override
public String toString() {
return new StringBuilder()
.append(data.substring(0, 3))
.append("\r\n")
.append(data.substring(3, 6))
.append("\r\n")
.append(data.substring(6, 9))
.toString();
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Step)) {
return false;
}
if (obj == this) {
return true;
}
return this.getData().equals(((Step) obj).getData());
}
#Override
public int hashCode() {
return this.getData().hashCode();
}
}
public static void main(String args[]) {
int statesVisited = 0;
Step startStep = new Step("120345678");
Step goalStep = new Step("012345678");
Step currentStep;
open.add(startStep);
while (!open.isEmpty() && !problemSolved) {
currentStep = open.iterator().next();
open.remove(currentStep);
// print(currentStep);
if (currentStep.equals(goalStep)) {
System.out.println("SUCCESS PATH: \r\n");
printSuccessPath(
getSuccessPathFromFinishStep(currentStep) // here currentStep is finish step
);
problemSolved = true;
} else {
// generate children
closed.add(currentStep);
Step nextStep = up(currentStep);
if (nextStep != null) {
open.add(nextStep);
}
nextStep = down(currentStep);
if (nextStep != null) {
open.add(nextStep);
}
nextStep = left(currentStep);
if (nextStep != null) {
open.add(nextStep);
}
nextStep = right(currentStep);
if (nextStep != null) {
open.add(nextStep);
}
}
}
}
/*
* MOVEMENT UP
*/
public static Step up(Step step) {
int p = step.getData().indexOf('0');
String str = step.getData();
if (!(p < 3)) {
char a = str.charAt(p - 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p - 3)) + '0' + newS.substring(p - 2);
}
Step nexStep = new Step(step, str); // Creates new step with step as previous one
// Eliminates child of X if its on open or closed
if (!open.contains(nexStep) && !closed.contains(nexStep))
return nexStep;
else
return null;
}
/*
* MOVEMENT DOWN
*/
public static Step down(Step step) {
int p = step.getData().indexOf('0');
String str = step.getData();
if (!(p > 5)) {
char a = str.charAt(p + 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p + 3)) + '0' + newS.substring(p + 4);
}
Step nexStep = new Step(step, str); // Creates new step with step as previous one
// Eliminates child of X if its on open or closed
if (!open.contains(nexStep) && !closed.contains(nexStep))
return nexStep;
else
return null;
}
/*
* MOVEMENT LEFT
*/
public static Step left(Step step) {
int p = step.getData().indexOf('0');
String str = step.getData();
if (p != 0 && p != 3 && p != 7) {
char a = str.charAt(p - 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p - 1)) + '0' + newS.substring(p);
}
Step nexStep = new Step(step, str); // Creates new step with step as previous one
// Eliminates child of X if its on open or closed
if (!open.contains(nexStep) && !closed.contains(nexStep))
return nexStep;
else
return null;
}
/*
* MOVEMENT RIGHT
*/
public static Step right(Step step) {
int p = step.getData().indexOf('0');
String str = step.getData();
if (p != 2 && p != 5 && p != 8) {
char a = str.charAt(p + 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p + 1)) + '0' + newS.substring(p + 2);
}
Step nexStep = new Step(step, str); // Creates new step with step as previous one
// Eliminates child of X if its on open or closed
if (!open.contains(nexStep) && !closed.contains(nexStep))
return nexStep;
else
return null;
}
private static void print(Step s) {
System.out.println(s);
System.out.println();
}
private static void printSuccessPath(List<Step> successPath) {
for (Step step : successPath) {
print(step);
}
}
private static List<Step> getSuccessPathFromFinishStep(Step finishStep) {
LinkedList<Step> successPath = new LinkedList<>();
Step step = finishStep;
while (step != null) {
successPath.addFirst(step);
step = step.getPrevious();
}
return successPath;
}
}
I've refactored your code a bit. And introduced new class Step which allows us to save relation between current step and previous one.
Logic is a bit complicated, but feel free to ask additional question if something if not clear for you)
And, by the way, here is the result:
SUCCESS PATH:
120
345
678
102
345
678
012
345
678
So, a clean(er) solution that does what you've asked for looks like this:
package basic;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
public class Puzzle {
private static class Node {
private final Node previous;
private final String data;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.hashCode());
return result;
}
public Node getPrevious() {
return previous;
}
public String getData() {
return data;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
return true;
}
public Node(String data) {
this.data = data;
this.previous = null;
}
public Node(String data, Node previous) {
this.data = data;
this.previous = previous;
}
}
public static void main(String args[]) {
Queue<Node> open = new LinkedList<>();
Set<Node> closed = new HashSet<>();
Node start = new Node("120345678");
Node goal = new Node("012345678");
open.add(start);
boolean solving = true;
while (!open.isEmpty() && solving) {
Node current = open.poll();
int pos = current.getData().indexOf('0');
if (!closed.contains(current)) {
if (current.equals(goal)) {
printPath(current);
System.out.println("SUCCESS");
solving = false;
} else {
// generate children
up(current, pos, open, closed);
down(current, pos, open, closed);
left(current, pos, open, closed);
right(current, pos, open, closed);
closed.add(current);
}
}
}
}
/*
* MOVEMENT UP
*/
private static void up(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
if (zeroPosition >= 3) {
char substitutedChar = current.getData().charAt(zeroPosition - 3);
open.add(new Node(current.getData().substring(0, zeroPosition - 3) + '0'
+ current.getData().substring(zeroPosition - 2, zeroPosition) + substitutedChar
+ current.getData().substring(zeroPosition + 1), current));
}
}
/*
* MOVEMENT DOWN
*/
private static void down(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
if (zeroPosition <= 5) {
char substitutedChar = current.getData().charAt(zeroPosition + 3);
open.add(new Node(current.getData().substring(0, zeroPosition) + substitutedChar
+ current.getData().substring(zeroPosition + 1, zeroPosition + 3) + '0'
+ current.getData().substring(zeroPosition + 4), current));
}
}
/*
* MOVEMENT LEFT
*/
private static void left(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
if (zeroPosition % 3 != 0) {
char substitutedChar = current.getData().charAt(zeroPosition - 1);
open.add(new Node(current.getData().substring(0, zeroPosition - 1) + '0' + substitutedChar
+ current.getData().substring(zeroPosition + 1), current));
}
}
/*
* MOVEMENT RIGHT
*/
private static void right(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
if (zeroPosition % 3 != 2) {
char substitutedChar = current.getData().charAt(zeroPosition - 1);
open.add(new Node(current.getData().substring(0, zeroPosition) + substitutedChar + '0'
+ current.getData().substring(zeroPosition + 2), current));
}
}
private static void printPath(Node current) {
Stack<String> stack = new Stack<>();
for (; current != null; current = current.getPrevious()) {
stack.push(current.getData());
}
while (!stack.isEmpty()) {
print(stack.pop());
}
}
private static void print(String s) {
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3, 6));
System.out.println(s.substring(6, 9));
System.out.println();
}
}
Do note that I haven't changed the basic board representation (you chose to use String, while I recommend using a 2d array, where swaps are much less costly and the code becomes easier to understand)
A few notes:
To print the entire "path" you must maintain connections between the "steps" of your solution
Avoid using globals where possible
Prefer using Interfaces (Set, Queue) as the types of your collections (and choose them based on how you would use them)
Java 8 doesn't require you to specify the concrete types used in a generic collection during construction (So use Set<String> set = new HashSet<>(); instead of using Set<String> set = new HashSet<String>();
Where possible, avoid using superfluous (and less readable) conditions / code structure (prefer if (booleanVariable) over if (booleanVariable == true)
(There are probably a few more things to take away from this, but this is a useful list to start with)
EDIT:
a version where data is a 2d array is added below
package basic;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
public class Puzzle {
private static class Node {
private final Node previous;
private final char[][] data;
public Node getPrevious() {
return previous;
}
public char[][] getData() {
return data;
}
public int getZeroX() {
return zeroX;
}
public int getZeroY() {
return zeroY;
}
private final int zeroX;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.deepHashCode(data);
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (!Arrays.deepEquals(data, other.data))
return false;
return true;
}
private final int zeroY;
public Node(Node previous, char[][] data, int zeroX, int zeroY) {
super();
this.previous = previous;
this.data = data;
this.zeroX = zeroX;
this.zeroY = zeroY;
}
}
public static void main(String args[]) {
Queue<Node> open = new LinkedList<>(); //Stack<Node> open = new Stack<>();
Set<Node> closed = new HashSet<>();
Node start = new Node(null, new char[][] { { '1', '2', '0' }, { '3', '4', '5' }, { '6', '7', '8' } }, 2, 0);
Node goal = new Node(null, new char[][] { { '0', '1', '2' }, { '3', '4', '5' }, { '6', '7', '8' } }, 0, 0);
open.add(start); //open.push(start);
boolean solving = true;
while (!open.isEmpty() && solving) {
Node current = open.poll(); //open.pop();
if (!closed.contains(current)) {
if (current.equals(goal)) {
printPath(current);
System.out.println("SUCCESS");
solving = false;
} else {
// generate children
up(current, open, closed);
down(current, open, closed);
left(current, open, closed);
right(current, open, closed);
closed.add(current);
}
}
}
}
/*
* MOVEMENT UP
*/
private static void up(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
if (current.getZeroY() > 0) {
char[][] chars = copy(current.getData());
chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY() - 1][current.getZeroX()];
chars[current.getZeroY() - 1][current.getZeroX()] = '0';
open.add/*push*/(new Node(current, chars, current.getZeroX(), current.getZeroY() - 1));
}
}
/*
* MOVEMENT DOWN
*/
private static void down(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
if (current.getZeroY() < 2) {
char[][] chars = copy(current.getData());
chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY() + 1][current.getZeroX()];
chars[current.getZeroY() + 1][current.getZeroX()] = '0';
open.add/*push*/(new Node(current, chars, current.getZeroX(), current.getZeroY() + 1));
}
}
/*
* MOVEMENT LEFT
*/
private static void left(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
if (current.getZeroX() > 0) {
char[][] chars = copy(current.getData());
chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY()][current.getZeroX() - 1];
chars[current.getZeroY()][current.getZeroX() - 1] = '0';
open.add/*push*/(new Node(current, chars, current.getZeroX() - 1, current.getZeroY()));
}
}
/*
* MOVEMENT RIGHT
*/
private static void right(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
if (current.getZeroX() < 2) {
char[][] chars = copy(current.getData());
chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY()][current.getZeroX() + 1];
chars[current.getZeroY()][current.getZeroX() + 1] = '0';
open.add/*push*/(new Node(current, chars, current.getZeroX() + 1, current.getZeroY()));
}
}
private static char[][] copy(char[][] data) {
char[][] newData = new char[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
newData[i][j] = data[i][j];
}
}
return newData;
}
private static void printPath(Node current) {
Stack<char[][]> stack = new Stack<>();
for (; current != null; current = current.getPrevious()) {
stack.push(current.getData());
}
while (!stack.isEmpty()) {
print(stack.pop());
}
}
private static void print(char[][] chars) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(chars[i][j]);
}
System.out.println();
}
System.out.println();
}
}
EDIT2: added comments of changes that turn this into DFS
Good luck!

Int not able to accomodate the result and hence program fails

This is a leetcode problem number 2. I guess I am really dumb not able to solve this. I encountered a particular issue where I am not able to solve it for the test case
[9]
[9,9,9,9,9,9,9,9,9,1]
The issue is that my program is returning 1410065399 instead of 9999999991 when I try to make a digit out of the link list. I have mentioned the actual problem statement and my solution alongside. Please provide some light so that I can understand what went wrong.
PROBLEM
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
Actual Code which I wrote
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
class Solution {
ListNode first;
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int finalResult = returnNumber(l1)+returnNumber(l2);
System.out.println(returnNumber(l1));
System.out.println(returnNumber(l2));
int length=0;
if(finalResult!=0){
length = (int)(Math.log10(finalResult)+1);
}else{
length =1;
}
for(int i=length-1;i>=0;i--){
generateList(finalResult,i);
}
return first;
}
public void generateList(int finalResult,int number){
ListNode oldNode = first;
first = new ListNode((finalResult / (int)Math.pow(10,number)) % 10);
System.out.println((finalResult / (int)Math.pow(10,number)) % 10);
first.next = oldNode;
}
public int returnNumber(ListNode list){
int i=0;
int base = 10;
int total = 0;
while(list!=null){
total=total+(list.val*(int)Math.pow(10,i));
i++;
list = list.next;
}
return total;
}
}
public class MainClass {
public static int[] stringToIntegerArray(String input) {
input = input.trim();
input = input.substring(1, input.length() - 1);
if (input.length() == 0) {
return new int[0];
}
String[] parts = input.split(",");
int[] output = new int[parts.length];
for(int index = 0; index < parts.length; index++) {
String part = parts[index].trim();
output[index] = Integer.parseInt(part);
}
return output;
}
public static ListNode stringToListNode(String input) {
// Generate array from the input
int[] nodeValues = stringToIntegerArray(input);
// Now convert that list into linked list
ListNode dummyRoot = new ListNode(0);
ListNode ptr = dummyRoot;
for(int item : nodeValues) {
ptr.next = new ListNode(item);
ptr = ptr.next;
}
return dummyRoot.next;
}
public static String listNodeToString(ListNode node) {
if (node == null) {
return "[]";
}
String result = "";
while (node != null) {
result += Integer.toString(node.val) + ", ";
node = node.next;
}
return "[" + result.substring(0, result.length() - 2) + "]";
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = in.readLine()) != null) {
ListNode l1 = stringToListNode(line);
line = in.readLine();
ListNode l2 = stringToListNode(line);
ListNode ret = new Solution().addTwoNumbers(l1, l2);
String out = listNodeToString(ret);
System.out.print(out);
}
}
}
As the inputs are list instead of an Integer so there isn't a restriction on length of it. So I would suggest looping through the input and collecting the sum of elements as you go through it and creating the result list. (don't forget the carry which can be of multiple digits)
Below you can find my code for reference.
(Any suggestions will always be welcomed)
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = null, node = null;
int carry = 0, sum = 0;
while (!(l1 == null && l2 == null)) {
// both not null
if (l1 != null && l2 != null) {
sum = (l1.val + l2.val + carry) % 10;
carry = (l1.val + l2.val + carry) / 10;
l1 = l1.next;
l2 = l2.next;
}
// l1==null
else if (l1 == null && l2 != null) {
sum = (l2.val + carry) % 10;
carry = (l2.val + carry) / 10;
l2 = l2.next;
}
// l2==null
else if (l1 != null && l2 == null) {
sum = (l1.val + carry) % 10;
carry = (l1.val + carry) / 10;
l1 = l1.next;
}
// both null
else {
// break out of the loop
}
if (head == null) {
head = new ListNode(sum);
node = head;
} else {
node.next = new ListNode(sum);
node = node.next;
}
}
if (carry > 0) {
while (carry > 0) {
int curr = carry % 10;
node.next = new ListNode(curr);
node = node.next;
carry = carry / 10;
}
}
return head;
}

insert method of the Trie data structure

I am trying ti implement the insert method of the Patricia Trie data structure but I have the feeling I wrote to many code lines. Please can someone tell me where can I call the method insert(TrieNode nodeRoot, String s) rekursiv?
Code:
private void insert(TrieNode nodeRoot, String s) {
int len1 = nodeRoot.value.length();
int len2 = s.length();
int len = Math.min(len1, len2);
for (int index = 0; index < len; index++) {
if (s.charAt(index) != nodeRoot.value.charAt(index)) {
// In case the both words have common substrings and after the
// common substrings the words are split.
String samesubString = s.substring(0, index);
String substringSplit1 = nodeRoot.value.substring(index);
String substringSplit2 = s.substring(index);
if (!samesubString.isEmpty()) {
nodeRoot.value = samesubString;
}
TrieNode nodeLeft = new TrieNode(substringSplit1);
nodeLeft.isWord = true;
TrieNode nodeRight = new TrieNode(substringSplit2);
nodeRight.isWord = true;
if (nodeRoot.getNext() != null && !nodeRoot.getNext().isEmpty()) {
checkTheValieAvialable(nodeRoot, s, nodeRight);
} else {
nodeRoot.next.add(nodeLeft);
nodeRoot.next.add(nodeRight);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
break;
} else if (index == (s.length() - 1)
|| index == (nodeRoot.value.length() - 1)) {
// In case the node just needs one path since one word is
// substring of the other.
// For example (aba and abac)
if (len1 > len2) {
// root value is longer
System.out.println("root value is longer");
String samesubString = nodeRoot.value.substring(0,
index + 1);
String different = nodeRoot.value.substring(index + 1);
if (nodeRoot.getNext() != null
&& !nodeRoot.getNext().isEmpty()) {
for (TrieNode subword : nodeRoot.getNext()) {
String subword2 = subword.getValue();
boolean contains = different.contains(subword2);
if (contains) {
String[] split = different.split(subword2);
TrieNode leaf1 = new TrieNode(split[1]);
leaf1.isWord = true;
subword.next.add(leaf1);
System.out.println("Test.");
}
}
} else {
String substringSplit1 = nodeRoot.value.substring(index + 1);
nodeRoot.value = samesubString;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
String substringSplit1 = nodeRoot.value
.substring(index + 1);
nodeRoot.value = samesubString;
nodeRoot.isWord = true;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
} else {
// new inserted string value is longer. For example (abac and aba).
System.out.println("instered is longer");
String samesubString = s.substring(0, index + 1);
String different = s.substring(index + 1);
if (nodeRoot.getNext() != null
&& !nodeRoot.getNext().isEmpty()) {
for (TrieNode subword : nodeRoot.getNext()) {
String subword2 = subword.getValue();
boolean contains = different.contains(subword2);
if (contains) {
String[] split = different.split(subword2);
TrieNode leaf1 = new TrieNode(split[1]);
leaf1.isWord = true;
subword.next.add(leaf1);
System.out.println("Test.");
}
}
} else {
String substringSplit1 = s.substring(index + 1);
s = samesubString;
TrieNode parentLeaf = new TrieNode(s);
parentLeaf.isWord = true;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
}
} else {
System.out.println("They are the same - " + index);
}
}
}
TrieNode class:
package patriciaTrie;
import java.util.ArrayList;
public class TrieNode {
ArrayList<TrieNode> next = new ArrayList<TrieNode>();
String value;
boolean isWord;
TrieNode(String value){
this.value = value;
}
public ArrayList<TrieNode> getNext() {
return next;
}
public void setNext(ArrayList<TrieNode> next) {
this.next = next;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
While using recursion please consider the steps:
Base condition
Logic (if any)
Recursive call.
Ex. for factorial of number:
int fact(int n)
{
if(n==0 || n==1)
return 1; // Base condition
return n * fact(n-1); // Recursive call
}
Applying the same concept in Trie:
base condition is: while traversing through a path, if we have reached leaf, current string is not in trie, then create a new edge or node and add remaining character to it.
Recursively call the insert if we have found a matching node. And if a matching node doen't exist create a new path with common parent.
You can take help from link : http://www.geeksforgeeks.org/trie-insert-and-search/
The best way to approach to problem recursively is to identify base condition in a problem.

Count continuous repeated occurrence of characters from String

This is my code.
public static void countContinuosOccurence() {
String first = "ABBCDDDEFGGH";
StringBuffer result = new StringBuffer();
int count = 1;
for (int i = 1; i < first.length(); i++) {
if (first.charAt(i) == (first.charAt(i - 1))) {
count++;
} else {
if (count > 1) {
result.append(String.valueOf(count) + first.charAt(i - 1));
} else {
result.append(first.charAt(i - 1));
}
count = 1;
}
}
System.out.println("First String is:"+ first);
System.out.println("Result is:" + result);
}
The result is:
First String is:ABBCDDDEFGGH
Result is:A2BC3DEF2G
It is missing the last character? May someone help me to solve this?
Not top-performing, but simplest code:
final String in = "ABBCDDDEFGGH" + '\u0000';
final StringBuilder b = new StringBuilder();
char prev = in.charAt(0);
int rpt = 0;
for (int i = 1; i < in.length(); i++) {
final char curr = in.charAt(i);
if (curr == prev) rpt++;
else {
b.append(rpt == 0? prev : "" + (rpt + 1) + prev);
rpt = 0; prev = curr;
}
}
System.out.println(b);
After the for loop ends, you'll need to append the count and the character of the last run of character(s) to the result:
public static void countContinuosOccurence() {
String first = "ABBCDDDEFGGH";
StringBuffer result = new StringBuffer();
int count = 1;
int i;
for (i = 1; i < first.length(); i++) {
if (first.charAt(i) == (first.charAt(i - 1))) {
count++;
} else {
if (count > 1) {
result.append(String.valueOf(count) + first.charAt(i - 1));
} else {
result.append(first.charAt(i - 1));
}
count = 1;
}
}
// ADD THIS - to take care of the last run.
if (count > 1) {
result.append(String.valueOf(count) + first.charAt(i - 1));
} else {
result.append(first.charAt(i - 1));
}
System.out.println("First String is:"+ first);
System.out.println("Result is:" + result);
}
public static void countContinuosOccurence() {
String[] input = "ABBCDDDEFGGH".split("");
String out = "";
for (int i = 0; i < input.length; i++) {
int repeatedCharCount = 1;
String currentChr = input[i];
if (!(i == input.length - 1)) {
while (input[i].equals(input[i + 1])) {
repeatedCharCount++;
i++;
}
}
out = out + repeatedCharCount + currentChr;
}
System.out.println(out);
}
There is also a hidden problem, that is that if you are terminating with a sequence with more than one occurrence, you will not write anything.
The simplest way to solve this problem and the problem you detected is to add a final check after the for block
[...]
}
int l = first.length();
if (count > 1) {
result.append(String.valueOf(count) + first.charAt(l - 1));
} else {
result.append(first.charAt(l - 1));
}
}
System.out.println("First String is:"+ first);
System.out.println("Result is:" + result);
}
import java.util.*;
public class HelloWorld{
public static void main(String []args){
System.out.println("Hello World");
String first = "ABBCDDDEFGGHhhhhh456456456{{{67}}}";
StringBuffer result = new StringBuffer();
result.append(first);
System.out.println(result);
Map<Character,Integer> map = new HashMap<Character,Integer>();
for(int i = 0; i < first.length(); i++) {
char c = first.charAt(i);
if (map.containsKey(c)) {
int cnt = map.get(c);
map.put(c, ++cnt);
} else {
map.put(c, 1);
}
}
Set set = map.entrySet();
// Get an iterator
Iterator itr = set.iterator();
// Display elements
while(itr.hasNext()) {
Map.Entry me = (Map.Entry)itr.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
System.out.println("Hello World1");
}
}

Categories

Resources