Textfield JavaFX with dynamic mask for monetary values (Using TextFormatter) - java

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)));

Related

Implementing Huffman class into another class

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);
}
}

How to solve this java.lang.NumberFormatException: For input string: "" based on my code?

I write the code for the LeetCode problem Reverse Integer. I cannot find what's wrong with my solution, but when running it in the LeetCode official site, it propagates this runtime error.
class Solution {
public int reverse(int x)
{
String resultStr = "";
int result = 0;
boolean isNegative = false;
if(x < 0)
{
isNegative = true;
}
int integer = Math.abs(x);
int divid = integer;
while(divid!= 0)
{
divid = divid/10;
resultStr += integer%10;
integer = divid;
}
result = Integer.parseInt(resultStr);
if(isNegative)
{
result = 0-result;
}
return result;
}
}
The final solution for this problem:
class Solution {
public int reverse(int x)
{
String resultStr = "";
int result = 0;
boolean isNegative = false;
if(x < 0)
{
isNegative = true;
}
int integer = Math.abs(x);
int divid = integer;
while(divid!= 0)
{
divid = divid/10;
resultStr += integer%10;
integer = divid;
}
if(resultStr.equals(""))
{
return 0;
}
else
{
try
{
result = Integer.parseInt(resultStr);
if(isNegative)
{
result = 0-result;
}
return result;
}
catch(Exception e)
{
return 0;
}
}
}
}

I'm trying to perform integer division on numbers greater than size of any data type available

As far big numbers are concerned, i know there is a class available in java BigInteger, but i have a constraint that i can't use this and i have to perform division without using library.
This is what i have tried so far, but got memory leakage issues and not getting any answer
private Integer getDivisionResult(ArrayList<Integer> first, ArrayList<Integer> second) {
int firstLength = first.size();
int secondLength = second.size();
int counter = 0;
if (firstLength < secondLength) {
return counter;
}
do {
int carry = 0, cursor1 = firstLength - 1, cursor2 = secondLength - 1;
for (int i = firstLength - 1; i >= 0; i--, cursor1--, secondLength--) {
int value = 0, from = 0;
from = first.get(cursor1) - carry;
if (from < (cursor2 < 0 ? 0 : second.get(cursor2))) {
if (cursor1 > 0) {
from = 10 + from;
}
carry = 1;
} else {
carry = 0;
}
value = from - (cursor2 < 0 ? 0 : second.get(cursor2));
first.set(i, value);
}
counter++;
}while (isLesserThan(second,first));
return counter;
}
private boolean isLesserThan(ArrayList<Integer> list, ArrayList<Integer> firstList) {
boolean result = true;
if (list.size() < firstList.size()) {
return true;
}
for (int i = 0; i < list.size(); i++) {
if (firstList.get(i) > list.get(i)) {
result = true;
break;
} else if (firstList.get(i) == list.get(i)) {
continue;
} else {
result = false;
break;
}
}
return result;
}
I'm calling getDivisionResult inside this method, after passing certain error cases:
/**
* #param numOne
* #param numTwo
* #return sign : true (negative) , false (positive)
*/
public Result getResult(String numOne, String numTwo) {
Result result = new Result();
int res = 0;
boolean sign = false;
ArrayList<Integer> firstNum;
ArrayList<Integer> secondNum;
if (isNegative(numOne)) {
firstNum = getArray(numOne.substring(1));
if (isNegative(numTwo)) {
sign = false;
secondNum = getArray(numTwo.substring(1));
} else {
secondNum = getArray(numTwo);
sign = true;
}
} else {
firstNum = getArray(numOne);
if (isNegative(numTwo)) {
sign = true;
secondNum = getArray(numTwo.substring(1));
} else {
secondNum = getArray(numTwo);
}
}
if (isNull(secondNum)) {
result.setSign("Division by 0 is not permissable");
result.setValue(res);
return result;
} else {
if (isNull(firstNum)) {
result.setSign("");
result.setValue(res);
return result;
}
firstNum = getNumberWithoutZeroes(firstNum);
secondNum = getNumberWithoutZeroes(secondNum);
res = getDivisionResult(firstNum, secondNum);
if (sign) {
result.setSign("-");
} else {
result.setSign("");
}
result.setValue(res);
}
return result;
}
private ArrayList<Integer> getNumberWithoutZeroes(ArrayList<Integer> num) {
ArrayList<Integer> list = new ArrayList<>();
for (Integer x : num) {
if (x == 0) {
continue;
} else {
list.add(x);
}
}
return list;
}
private boolean isNegative(String num) {
boolean result = false;
if (num.startsWith("-")) {
result = true;
}
return result;
}
private boolean isNull(ArrayList<Integer> num) {
boolean result = true;
for (Integer x : num) {
if (x > 0) {
result = false;
}
}
return result;
}
private ArrayList<Integer> getArray(String num) {
ArrayList<Integer> list = new ArrayList<>();
char[] arr = num.toCharArray();
for (int i = 0; i < num.length(); i++) {
list.add(Integer.valueOf(arr[i]));
}
return list;
}
if someone can help me to give a better solution to my problem, I would be grateful
I've made the solution to my own problem, but the problem now is its processing speed.

how update Jtextfield text simultaneously when typing on it?

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.

My parser function is not working

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 /

Categories