I was designing a simple parser(it works on a simple version of Shunting Yard Algorithm). Here's my code(I haven't dealt with associativity).
public class Parser {
String stack[] = new String[50];
String res = "";
int top = 0;
Operator o1 = new Operator("", 0, 0);
public String parse(String x) {
push("(");
x = x + ")";
for (int i = 0; i < x.length(); i++) {
if (o1.isNumber(x.charAt(i) + "")) {
res = res + x.charAt(i);
} else if (x.charAt(i) == '(') {
push("(");
} else if (o1.isOperator("" + x.charAt(i))) {
if (top != -1) {
while ((top != -1) && (o1.isOperator(stack[top]))) {
int m = o1.getOperatorIndex(stack[top]);
int mp = o1.op[m].prec;
int xp = o1.op[o1.getOperatorIndex("" + x.charAt(i))].prec;
if (m >= xp) {
res = res + stack[top];
}
top--;
}
}
push("" + x.charAt(i));
} else {
if (top != -1) {
while ((top != -1) && (stack[top] != ")")) {
if (o1.isOperator(stack[top])) {
res = res + stack[top];
}
top--;
}
}
}
}
return res;
}
public void push(String m) {
if (top != 49) {
stack[top] = m;
top++;
} else {
System.out.println("Overflow");
}
}
}
I guess you won't need the Operator class's code. When I try executing parse("1+2"), it just returns 12 and not the + sign. What is wrong? and yes, o[0] is +,o[1] is -,o[2] is*, o[3] is /
Related
So here is my dart version of java's huffman algorithm. I have a problem with getCodeForChar function, it says what return type of String can't be null, and even if for every return i added +'h'. How to deal with null-safety at that case?
Originally the function is:
public String getCodeForCharacter(Character ch, String parentPath) {
if (content == ch) {
return parentPath;
} else {
if (left != null) {
String path = left.getCodeForCharacter(ch, parentPath + 0);
if (path != null) {
return path;
}
}
if (right != null) {
String path = right.getCodeForCharacter(ch, parentPath + 1);
if (path != null) {
return path;
}
}
}
return null;
}
And my full code:
import 'dart:collection';
void main() {
String text = 'where there,s a will there,s a way';
SplayTreeMap? frequencies = countFrequency(text);
frequencies.forEach((key, value) {
print('$key \t $value');
});
var sk = frequencies.values.toList();
print(sk);
List<CodeTreeNode> codeTreeNode = [];
for (String? c in frequencies.keys) {
codeTreeNode.add(new CodeTreeNode.simple(c, frequencies[c]));
}
CodeTreeNode tree = huffman(codeTreeNode);
SplayTreeMap<String, String> codes = SplayTreeMap();
for (String c in frequencies.keys) {
//codes.addAll(c, (value) => tree.getCodeForChar(c, ""));
codes.addAll({c: tree.getCodeForChar(c, "")});
}
codes.forEach((key, value) {
print('$key \t $value');
});
}
SplayTreeMap countFrequency(String text) {
SplayTreeMap? myMap = SplayTreeMap<String, int>();
int tempCount = 0;
// for (int i = 0; i < text.length; i++) {
// String c = text[i];
// int count = myMap[];
// //myMap[int count]
// myMap[c] = count != -1 ? count + 1 : 1;
// }
for (int i = 0; i < text.length; i++) {
String c = text[i];
if (myMap.containsKey(c)) {
//tempCount++;
//myMap[text[i]] = tempCount;
tempCount = myMap[c] + 1;
myMap.update(c, (value) => tempCount);
} else {
myMap[c] = 1;
}
//счетчик = мапа[i] +1;
//заменить эту валью на счетчик
}
return myMap;
}
CodeTreeNode huffman(List<CodeTreeNode> codeTreeNodes) {
while (codeTreeNodes.length > 1) {
codeTreeNodes.sort();
CodeTreeNode left = codeTreeNodes.removeAt(codeTreeNodes.length - 1);
CodeTreeNode right = codeTreeNodes.removeAt(codeTreeNodes.length - 1);
CodeTreeNode parent =
CodeTreeNode.hard(null, right.weight + left.weight, left, right);
codeTreeNodes.add(parent);
}
return codeTreeNodes[0];
}
class CodeTreeNode implements Comparable<CodeTreeNode> {
String? content;
//List<Node> children = [];
int weight;
CodeTreeNode? left;
CodeTreeNode? right;
CodeTreeNode.simple(this.content, this.weight);
CodeTreeNode.hard(this.content, this.weight, this.left, this.right);
// Node(String content, int weight){(this.content, this.weight)
// }
#override
int compareTo(CodeTreeNode other) {
// TODO: implement compareTo
//throw UnimplementedError();
return other.weight - weight;
}
String getCodeForChar(String ch, String parentPath) {
if (content == ch) {
return 'h'+ parentPath;
} else {
if (left != null) {
String path = left.getCodeForChar(ch, parentPath + '0');
if (path != null) {
return 'h'+path;
}
}
if (right != null) {
String path = right.getCodeForChar(ch, parentPath + '1');
if (path != null) {
return 'h'+ path;
}
}
}
return 'hui';
}
}
Inserting you code int DartPad shows two errors.
The method 'getCodeForChar' can't be unconditionally invoked because the receiver can be 'null'.
Fixing this is easy: Insert the bang operator ('!'):
String path = left!.getCodeForChar(ch, parentPath + '0');
See also Working with nullable fields
i'm using TextFomater to make my TextField as a dynamic monetary textfield, using the following code:
public class MoneyTextFieldOperator implements UnaryOperator<TextFormatter.Change>
{
final char seperatorChar = '.';
final Pattern p;
int length;
public MoneyTextFieldOperator(int length) {
this.length=length;
this.p = Pattern.compile("[0-9. ]*");
}
#Override
public TextFormatter.Change apply(final TextFormatter.Change c) {
if (c.isContentChange() && c.getControlNewText().length() > length) {
return null;
}
else {
if (!c.isContentChange()) {
return c;
}
final String newText = c.getControlNewText();
if (newText.isEmpty()) {
return c;
}
if (!this.p.matcher(newText).matches()) {
return null;
}
final int suffixCount = c.getControlText().length() - c.getRangeEnd();
int digits = suffixCount - suffixCount / 4;
final StringBuilder sb = new StringBuilder();
if (digits % 3 == 0 && digits > 0 && suffixCount % 4 != 0) {
sb.append('.');
}
for (int i = c.getRangeStart() + c.getText().length() - 1; i >= 0; --i) {
final char letter = newText.charAt(i);
if (Character.isDigit(letter)) {
sb.append(letter);
if (++digits % 3 == 0) {
System.out.println("digits : "+digits);
sb.append('.');
}
}
}
if (digits % 3 == 0) {
sb.deleteCharAt(sb.length() - 1);
}
sb.reverse();
final int length = sb.length();
c.setRange(0, c.getRangeEnd());
c.setText(sb.toString());
c.setCaretPosition(length);
c.setAnchor(length);
return c;
}}
And calling it as follow :
montantTextField.setTextFormatter(new TextFormatter(new MoneyTextFieldOperator(10)));
the issue is that it's valable just for integer numbers, and i want make it now valable for decimal numbers, so when the user type 254648,32
it converts it to 254.648,32
here is a proposed solution using numberformat :
public class MoneyTextFieldOperator implements UnaryOperator<TextFormatter.Change> {
Pattern p;
int length;
public MoneyTextFieldOperator(int length) {
this.length = length;
this.p = Pattern.compile("[0-9. ,]*");
}
#Override
public TextFormatter.Change apply(TextFormatter.Change c) {
Pattern acceptedKeywords = Pattern.compile("[0-9 . ,]*");
int wholeNumberLength = 9;
int decimalPartLength = 2;
String newText = c.getControlNewText();
String wholeNumber;
String decimalPart;
if (newText.contains(",")) {
wholeNumber = newText.substring(0, newText.indexOf(","));
decimalPart = newText.substring(newText.indexOf(",") + 1, newText.length());
} else {
wholeNumber = newText;
decimalPart = "";
}
Matcher matcher = acceptedKeywords.matcher(newText);
boolean isMatchingWithAcceptedKeywords = matcher.matches();
String letter = c.getText();
if (newText.isEmpty()) {
return c;
} else if (!c.isContentChange()) {
return c;
} else if (countChar(c.getControlNewText(), ',') > 1) {
return null;
} else if (!isMatchingWithAcceptedKeywords) {
return null;
} else if (wholeNumber.replace(".", "").length() > wholeNumberLength || decimalPart.length() > decimalPartLength) {
return null;
} else if (c.getControlNewText().charAt(0)==',') {
return null;
}
else {
c.setRange(0, c.getControlText().length());
if (newText.contains(",")) {
c.setText(NumbersTools.getMonetaryFormat(Integer.parseInt(wholeNumber.replace(".", ""))) + "," + decimalPart);
} else {
c.setText(NumbersTools.getMonetaryFormat(Integer.parseInt(wholeNumber.replace(".", ""))));
}
c.setCaretPosition(c.getText().length());
c.setAnchor(c.getText().length());
return c;
}
}
public int countChar(String string, char charactere) {
int x = 0;
for (int i = 0; i <= string.length() - 1; ++i) {
if (string.charAt(i) == charactere) {
++x;
}
}
return x;
}
and you use it as follow :
textField.setTextFormatter(new TextFormatter<Object>(new MoneyTextFieldOperator(10)));
I almost have a working Huffman algorithm but I'm having trouble figuring out how to implement it / or make it work together with the Code class. It is my method generateHuffmanCode that needs to be working with the Code class.
I don't know if I'm missing something or if I'm just using the wrong approach.
My Huffman class
package code;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import code.Code;
import application.TCode;
class Node{
Character ch;
Integer freq;
Node left = null, right = null;
Node(Character ch, Integer freq){
this.ch = ch;
this.freq = freq;
}
public Node (Character ch, Integer freq, Node left, Node right) {
this.ch = ch;
this.freq = freq;
this.left = left;
this.right = right;
}
}
public class Huffman {
public static void encode(Node root, String str, Map<Character, String> huffmanCode) {
if (root == null) {
return;
}
if(isLeaf(root)) {
huffmanCode.put(root.ch, str.length() > 0 ? str : "1");
}
encode(root.left, str + '0', huffmanCode);
encode(root.right, str + '1', huffmanCode);
}
public static int decode(Node root, int index, StringBuilder sb) {
if(root == null) {
return index;
}
index++;
if(isLeaf(root)) {
System.out.println(root.ch);
}
index++;
root = (sb.charAt(index) == '0') ? root.left : root.right;
index = decode(root, index, sb);
return index;
}
public static boolean isLeaf(Node root) {
return root.left == null && root.right == null;
}
public static void generateHuffmanCode(Code c) {
// if(c == null || c.length() == 0) {
// return;
// }
Map<Character, double> freq = new HashMap<>(); // why can't I use a double in Map<Character, double>??
for(char s : probability.toCharArry()){
freq.put(s, freq.getOrDefault(s, 0) + 1);
}
PriorityQueue<Node> pq;
pq = new PriorityQueue<>(Comparator.comparingInt(l -> l.freq));
for(var entry: freq.entrySet()) {
pq.add(new Node(entry.getKey(), entry.getValue()));
}
while (pq.size() != 1) {
Node left = pq.poll();
Node right = pq.poll();
int sum = left.freq + right.freq;
pq.add(new Node(null, sum, left, right));
}
Node root = pq.peek();
Map<Character, String> huffmanCode = new HashMap<>();
encode(root, "", huffmanCode);
System.out.println("Huffman Codes are: " + huffmanCode);
System.out.println(probability);
StringBuilder sb = new StringBuilder();
for(char s : probability.toCharArray()) {
sb.append(huffmanCode.get(s));
}
System.out.println("The endcoded String is: " + sb);
System.out.println("The decoded String is: " );
if (isLeaf(root)) {
while (root.freq-- > 0) {
System.out.println(root.ch);
}
} else {
int index = -1;
while(index < sb.length() - 1) {
index = decode(root, index, sb);
}
}
}
public static void main(String[] args) {
generateHuffmanCode(Code probability);
// Code.CodeItem[] ci = {
// new Code.CodeItem("A", 0.12),
// new Code.CodeItem("B", 0.19),
// new Code.CodeItem("C", 0.40),
// new Code.CodeItem("D", 0.13),
// new Code.CodeItem("E", 0.16)
// };
// Code c = new Code(ci);
}
}
And my Code class
package code;
public final class Code {
private CodeItem[] item = null;
public final static class CodeItem {
private String symbol;
private double probability; // the sum of all probabilities must be approx. 1
private String encoding; // a string containing only '0' and '1'
public CodeItem(String symbol, double probability, String encoding) {
this.symbol = symbol.trim();
this.probability = probability;
this.encoding = encoding;
if (!is01() || this.symbol == null || this.symbol.length() == 0 || this.probability < 0.0)
throw new IllegalArgumentException();
}
public CodeItem(String symbol, double probability) {
this(symbol, probability, null);
}
public String getSymbol() {
return symbol;
}
public double getProbability() {
return probability;
}
public String getEncoding() {
return encoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
public boolean is01() {
if (encoding == null || encoding.length() == 0)
return true;
for (int i = 0; i < encoding.length(); ++i)
if ("01".indexOf(encoding.charAt(i)) < 0)
return false;
return true;
}
}
public Code(CodeItem[] codeItem) {
if (codeItem == null || codeItem.length == 0)
throw new IllegalArgumentException();
double sum = 0.0;
for (int i = 0; i < codeItem.length; ++i) {
sum += codeItem[i].probability;
if (codeItem[i].probability == 0.0)
throw new IllegalArgumentException();
}
if (Math.abs(sum - 1.0) > 1e-10)
throw new IllegalArgumentException();
item = new CodeItem[codeItem.length];
for (int i = 0; i < codeItem.length; ++i)
item[i] = codeItem[i];
}
public boolean is01() {
for (int i = 0; i < item.length; ++i)
if (!item[i].is01())
return false;
return true;
}
public double entropy() {
double result = 0.0;
for(int i = 0; i < item.length; ++i)
result += item[i].probability * (-Math.log(item[i].probability) / Math.log(2.0));
return result;
}
public double averageWordLength() {
double result = 0.0;
for(int i = 0; i < item.length; ++i)
result += item[i].encoding.length() * item[i].probability;
return result;
}
public boolean isPrefixCode() {
for(int i = 1; i < item.length; ++i)
for(int j = 0; j < i; ++j)
if (item[i].encoding.startsWith(item[j].encoding) || item[j].encoding.startsWith(item[i].encoding))
return false;
return true;
}
public int size() {
return item.length;
}
public CodeItem getAt(int index) {
return item[index];
}
public CodeItem getBySymbol(String symbol) {
for (int i = 0; i < item.length; ++i) {
if (item[i].symbol.equals(symbol))
return item[i];
}
return null;
}
public String toString() {
String result = "";
for(int i = 0; i < item.length; ++i) {
result += item[i].symbol + " (" + item[i].probability + ") ---> " + item[i].encoding + "\n";
}
return result.substring(0, result.length()-1);
}
}
This is my assignment on number 6:
And this is what I have so far. It's not working properly and I am not sure why. Any help would be greatly appreciated. I showed what error I get at the bottom of the code. I'm not sure how to fix it and where to go from here.
import java.util.Arrays;
public class st {
public static void main(String[] args) {
String aa = "8 + (2+2)";
Init init = new Init(aa);
}
}
public final class Init {
public int top = 1;
Integer[] stack = new Integer[10];
String[] queue = new String[10];
int number, x, y, z, op, front, rear;
int finalValue;
int CurrValue;
String queueOperand;
Character s;
public Init(String s) {
ValidateEquation(s);
int finalVal = postFix(s);
System.out.printf("The answer is " + finalVal + "\n");
}
void ValidateEquation(String s) {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') {
push(c);
} else if (c == ')') {
if (isStackEmpty()) {
System.out.printf("Error: Too many ')'");
System.exit(0);
} else {
int closeParen = pop();
}
}
}
}
public int postFix(String s) {
int CurrentCalculation;
int i = 0;
while (i < s.length()) {
char c = s.charAt(i);
if ((int) c > 47 && (int) c < 58) {
int numVal = Character.getNumericValue(c);
push(numVal);
} else if ((int) c > 41 && (int) c < 48) {
String StrVal = Character.toString(c);
pushQ(StrVal);
}
if (c == '(' || c == ')' || i == s.length()-1) {
String newString = "";
for (Integer stack1 : stack) {
/* iterate through the stack */
if (stack1 != null) {
newString = newString + stack1 + " ";
}
}
for (String queue1 : queue) {
/* iterate through the queue */
if (queue1 != null) {
newString = newString + queue1 + " ";
queueOperand = queue1;
}
}
if (newString.length() > 2) {
int CurrValue = calculateEquation(newString);
if ("+".equals(queueOperand)) {
finalValue = finalValue + CurrValue;
} else if ("-".equals(queueOperand)) {
finalValue = finalValue - CurrValue;
} else if ("*".equals(queueOperand)) {
finalValue = finalValue * CurrValue;
} else if ("/".equals(queueOperand)) {
finalValue = finalValue / CurrValue;
}
popAll();
}
}
i++;
}
return finalValue;
}
int calculateEquation(String s) {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if ((int) c > 47 && (int) c < 58) {
int numVal = Character.getNumericValue(c);
push(numVal);
}
if ((int)c > 41 && (int)c < 48) {
if (s.length() <= 4) {
x = pop();
if (c == '*' || c == '/') {
y = 1;
} else {
y = 0;
}
} else {
x = pop();
y = pop();
}
System.out.println("\n" + x + " " + y + " " + c);
if (c == '+') {
z = x + y;
} else if (c == '-') {
z = x - y;
} else if (c == '*') {
z = x * y;
} else if (c == '/') {
z = x / y;
}
}
}
return z;
}
void push(int x) {
top = top + 1;
/* Increment stack pointer. */
stack[top] = x;
/* Place x on top of stack. */
}
void pushQ(String x) {
rear = rear + 1;
/* Increment stack pointer. */
queue[rear] = x;
/* Place x on top of stack. */
}
int pop() {
int x;
x = stack[top];
/* Retrieve item from top of stack. */
top = top - 1;
/* Decrement stack. */
return x;
}
void popAll() {
Arrays.fill(stack, null);
Arrays.fill(queue, null);
}
boolean isStackEmpty() {
boolean empty;
empty = false;
if (top == -1) {
/* If top = -1, that indicates an empty stack. */
empty = true;
}
return empty;
}
}
This is the error I get:
"/st.java:12: error: class Init is public, should be declared in a file named Init.java
public final class Init {"
You should put each public class in separate file and file name must be class name.
I have a JTextField.I want after each character the user types,a method call and change the order of character in same JTextField,but in my code displayArrestNo2() method call and print in consol right answer but dont update content of JTextField.How can do it?
public static void main(String args[]) {
final JTextField textField = new JTextField();
textField.setSize(100, 100);
textField.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
}
public void removeUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent e) {
try{
Stringx=displayArrestNo2(e.getDocument().getText(0,e.getDocument().getLength()));
System.out.println(x);
}catch(Exception ex){
ex.printStackTrace();
}
}
public void warn() {
}
public String displayArrestNo2(String aValue){
System.out.println("oroginal value: " + aValue);
aValue = " "+aValue+" ";
System.out.println("space added value: "+aValue);
final String validStr = " ابپتثجچحخدرزژسشصضطظعغفقکگلمنوهیي";
int lPos, fPos, i, j, k;
boolean flgEnterIntSection, lastWasChar;
String result = "";
flgEnterIntSection= false;
lastWasChar = false;
lPos = 0;
i = aValue.length()-1;
while( i >= 0) {
char[] aValueArr = aValue.toCharArray();
/* char[] tmpArr = aValue.toCharArray();
char[] aValueArr = new char[tmpArr.length];
for(int x=0; x<tmpArr.length; x++)
aValueArr[x]= tmpArr[tmpArr.length-x-1]; */
if (aValueArr[i] == 'ß')
aValueArr[i] = '˜';
if (convert(aValueArr[i]) == -1)
{
if(validStr.indexOf(aValueArr[i]) > 0)
{
j = 0;
while ( ( (i - j) > 0) && (validStr.indexOf(aValueArr[i-j]) > 0 ))
j = j + 1;
if (j >1)//j>1
{
k = j;
while (j > 0)
{
result = result + aValueArr[i - j+1];//i-j+1
j--;
}
i = i - k+1;//i-k+1
}
else
result = result + aValueArr[i];
}
else
result = result + aValueArr[i];
i--;
flgEnterIntSection = false;
}
else
{
fPos = i;
j = i;
while ((j >= 0) && ((!flgEnterIntSection) || (convert(aValueArr[j]))!=-1))// (StrToIntDef(AValue[j], -1) <> -1)
{
flgEnterIntSection = true;
while ((j >= 0) && (convert(aValueArr[j]))!=-1) // StrToIntDef(AValue[j], -1) <> -1)
j--;
if ((j > 0) && ((aValueArr[j] == '.') || (aValueArr[j] == '/')) )
if (((j-1) >= 0) && (convert(aValueArr[j-1]))!=-1) //StrToIntDef(AValue[j - 1], -1) <> -1)
j--;
}
lPos = j + 1;
for (j = lPos; j <= fPos; j++)
{
result = result + aValueArr[j];
}
i = lPos-1;
}
}
// return result;
// System.out.println("before reverse "+result);
return reverseOrder(result);
}
String reverseOrder(String input){
String [] inArr = input.split(" ");
String reversed = "";
for(int i = inArr.length-1; i>=0; i--){
reversed += inArr[i] + " ";
}
return reversed;
}
public int convert(char ch) {
try {
int m = Integer.parseInt(String.valueOf(ch));
return m;
} catch (Exception e) {
return -1;
}
}
TestJTextField x=new TestJTextField();
x.add(textField);
x.setVisible(true);
}
in insertUpdate() method ,displayArrestNo2() is called per character but dont change content of JTextField.