What is wrong with my Stack/isPalindrome() class/method? - java

For this method I needed to implement a custom made Stack class to see if the given string is a palindrome.
This is the custom Stack class:
public class Stack<T> {
private ArrayList<T> arrayList = new ArrayList<>();
private T head;
public Stack() {
arrayList.add(head);
}
#Override
public String toString() {
return arrayList.toString();
}
public boolean empty() {
return arrayList.size() == 1 ? true : false;
}
public T push(T element) {
arrayList.add(element);
head = element;
return element;
}
public T pop() {
T returnVal = arrayList.get(arrayList.size()-1);
if (!empty()) {
arrayList.remove(returnVal);
head = arrayList.get(arrayList.size()-1);
}
return returnVal;
}
public T peek() {
return head;
}
}
And this is the palindrome method:
public static boolean isPalindrome(String string) {
var stack = new Stack<Character>();
var flag = true;
for (int i=0; i<string.length(); i++)
stack.push(string.charAt(i));
if (string.charAt(0) == stack.peek()) {
for (int j=0; j<string.length(); j++) {
System.out.println(string.charAt(j) + " " + stack.peek());
if (string.charAt(j) != stack.pop()) {
flag = false;
break;
}
}
}
else
return false;
return flag;
}
When I run the method, it runs the loop only 2 times. The Stack object doesn't seem to pop. But when I tested the pop() method in the main method with just a set of different characters, it seemed to work. But in this isPalindrome() method, it doesn't seem to me that it works. Can someone please help out?

In your Stack.pop() method, the line arrayList.remove(returnVal); is not what you want.
It will remove the first occurrence of returnVal from the stack, but in pop() you need to remove the last occurrence of returnVal.
In Stack.pop() you need to remove the last element - which means you need to write
arrayList.remove(arrayList.size()-1);
Your complete Stack.pop() method would then be:
public T pop() {
T returnVal = arrayList.get(arrayList.size()-1);
if (!empty()) {
arrayList.remove(arrayList.size()-1);
head = arrayList.get(arrayList.size()-1);
}
return returnVal;
}

Related

Validating expression using 2 Generic Stacks

The task is to implement a generic stack (can not use the libraries from java), make the user input an expression using true and false for booleans b1 and b2, logical operators (and, or, not, iff, implies) recognize if its boolean or operator and send to 2 stacks, then poping the stacks to evaluate if its a valid expression, i.e: input:(b1 and b2) implies b3 is a valid expression but B3 and (b2 or) is not, I have issues with the stack part, since the peek is not returning any element, here is my code so far, note: the charat is because I would be checking that the brackets are balanced as well:
public class MyStack<T> {
class StackOverFlowException extends RuntimeException{}
class EmptyStackException extends RuntimeException{}
private T[] stack;
private int top;
public MyStack(int size) {
this.stack = (T[]) new Object[size];
this.top = 0;
}
public boolean isEmpty() {
return this.top == 0;
}
public boolean isFull() {
return this.top == stack.length;
}
public void push(T x) {
if(top == stack.length) {
throw new StackOverFlowException();
}
else {
this.stack[top] = x;
top++;
}
}
public T pop() {
if(isEmpty()) {
throw new EmptyStackException();
}
else {
T value = this.stack[--top];
return value;
}
}
public T peek() {
return this.stack[top];
}
public static void main(String[] args) {
MyStack<String> tf = new MyStack(100);
MyStack<String> operators = new MyStack(100);
System.out.println("Please input the expression to evaluate: ");
Scanner scn = new Scanner(System.in);
String expression = scn.nextLine();
String tokens[] = expression.split(" ");
int n = tokens.length;
boolean P1 = true;
boolean P2 = true;
boolean result = true;
for(int i = 0; i < n; i++ ) {
String separate = tokens[i];
char x = separate.charAt(i);
if(tokens[i].equalsIgnoreCase("true")||tokens[i].equalsIgnoreCase("false")) {
tf.push(separate);
tf.peek();
}
else if(tokens[i].equalsIgnoreCase("and")||tokens[i].equalsIgnoreCase("not")||tokens[i].equalsIgnoreCase("or")||tokens[i].equalsIgnoreCase("implies")||tokens[i].equalsIgnoreCase("iff")) {
operators.push(separate);
}
else {
System.out.println("Expression not Valid!");
}
}
}
The top variable is being misinterpreted in the peek() method (as well as the isEmpty() method).
As implemented, top is a misnomer since it is actually the size of the stack (which may also be considered the index for the next element to be pushed). So your peek() method should be looking at the element before top.
Alternatively, you may to define top as the element at the top of the stack, as this is generally how you are using it elsewhere. In this case, you will need to define a flag value to indicate the stack is empty.
In any case, you need handle the empty Stack case in the peek() method.
public class MyStack {
private static final int EMPTY = -1;
private int top = EMPTY;
... other stuff ...
public boolean isEmpty() {
return EMPTY == top;
}
public T peek() {
if (ifEmpty()) {
throw new EmptyStackException("Cannot peek into empty Stack");
}
return stack[top];
}
}

java - overriding iterator?

in all honesty, I've spent a few days looking at this and trying to figure it out, but have come up very short. The goal is to see if a trie node has a next, if so what it is.
Where it's called by:
public Iterator<String> iterator() {
return new TrieIterator();
}
calls this to implement my own iterator. I've tried using a position in the array + 1 for the hasNext(), also comparing things to size, and number or nodes, and children, and have come up short. My most recent try was something along the lines of (below) but doesn't work.
hasNext() {
return this.children.hasChildren(); /* doesn't work */
}
public class TrieIterator implements Iterator<String> {
public TrieIterator(){
}
public boolean hasNext() {
return false;
}
public String next() {
return null;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
here's the trieNode class as well:
public class TrieNode {
protected char letter = ' ';
protected TrieNode parentNode = null;
protected boolean fullWord = false;
protected TrieNode[] children = new TrieNode[26];
protected int prefixes = 0;
public TrieNode(char letter, TrieNode parentNode){
this.letter = letter;
this.parentNode = parentNode;
}
public boolean hasChildren(){
int index = 0;
while(index < children.length){
if(children[index] != null) {
return true;
}
index++;
}
return false;
}
public TrieNode nodeForLetter(char ch) {
return children[ch - 97];
}
public boolean isEndOfWord() {
return letter == '*';
}
}
and adding and deleting is as follows:
public void addWord(String s) {
if (hasWord(s)) return;
int index = 0;
TrieNode current = root;
char[] letters = s.toCharArray();
while(index < s.length()){
TrieNode child = current.children[letters[index] - 97];
if(child == null){
child = new TrieNode(letters[index], current);
child.prefixes++;
numOfNodes++;
}
current = child;
index++;
if(index == s.length()){
current.fullWord = true;
numOfWords++;
}
}
}
public void deleteWord(String s) {
if(s.length() == 0) return;
if(size() == 0) return;
if(!hasWord(s)) return;
TrieNode current = root;
for (char ch : s.toCharArray()) {
TrieNode child = current.children[s.charAt(ch) - 97];
if(child.prefixes == 1){
child = null;
return;
}
else{
child.prefixes--;
current = child;
}
}
current.fullWord = false;
}
public boolean hasWord(String s) {
if(size() == 0) return false;
char[] letters = s.toCharArray();
int l = letters.length;
TrieNode current = root;
int i;
for (i = 0; i < l; i++){
if (current == null) return false;
current = current.children[letters[i] - 97];
}
if (i == l && current == null) return false;
if (current != null && !current.fullWord) return false;
return true;
}
Please don't change current implementation of the trie :)
Your attempt at implementing hasNext() with this.children.hasChildren(); won't work because children is an array of TrieNode, so it doesn't have any hasChildren() method.
The hasChildren() method is a method of TrieNode, not its children array.
You need to keep track of the current node, the position in the current node, and all the characters seen so far. hasNext() should return true if there are any more words, which means if the node is a full word or if it has any children that haven't been visited yet that are full words. (But, I assume the leaf nodes are always full words, so the latter test can simply be if the node has any children that haven't been visited yet.)
You will need to decide if you will return shorter words before longer ones (do you return a word from next() as soon as you arrive at a full word node, or only after visiting its children?) You will also need to maintain a stack of nodes, so that after you have descended to a child node, you can return to your previous position in the parent node.
It isn't a trivial task. I would suggest starting with a Trie built from a very small set of words (like "a", "an", and "at"), and getting that fully debugged before you move on to three letter words or more.
(You should also consider what you intend to do if the Trie is modified while you're iterating through it. The standard java.util classes update a counter on every modification, and test that it hasn't changed in the iterator. If it has, they throw a ConcurrentModificationException. Iterators using this strategy are called fail-fast iterators.)

How does the contain method match?

Is the statement list.contains("are") (have commented it) being checked by matching character to character ?
import java.util.*;
class Tester {
public static void main(String args[]) {
String arr[] = {"how","are","you","veena"};
LinkedList<String> list = new LinkedList<String>();
for(String s : arr) {
list.add(s);
}
if(list.contains("are")) { // STATEMENT
System.out.println("Found !");
}
}
}
In this program if statement works. How does the contain method work ?
That method iterates over the linked list, and compare each element with the element passed by invoking equals() method. In this case, it will invoke String#equals(Object) method.
this is implementations of method contains and indexOf from LinkedList
public boolean contains(Object o) {
return indexOf(o) != -1;
}
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
so as you see it is iterating trough array till it finds first matching element

Error java.lang.ArrayIndexOutOfBoundsException: -1 on my code

This is my code. There is an error showing on the terminal window. It says java.lang.ArrayIndexOutOfBoundsException: -1 at top--; and while (!stack.isEmpty()). Please help me solve this issue. I looked it up online but it did not help much. That is why I am asking you for help.
import java.util.*;
public class ArrayStack<T> implements StackADT<T>
{
private final static int DEFAULT_CAPACITY = 100;
private int top;
private T[] stack;
public ArrayStack()
{
this(DEFAULT_CAPACITY);
}
public ArrayStack(int initialCapacity)
{
top = 0;
stack = (T[])(new Object[initialCapacity]);
}
public void push(T element)
{
if (size() == stack.length)
expandCapacity();
stack[top] = element;
top++;
}
private void expandCapacity()
{
stack = Arrays.copyOf(stack, stack.length * 2);
}
public T pop() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("stack");
top--;
T result = stack[top];
stack[top] = null;
return result;
}
public T peek() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("stack");
return stack[top-1];
}
public boolean isEmpty()
{
return stack.length == 0;
}
public int size()
{
return top;
}
public static void main(String[] args)
{
ArrayStack<Character> stack = new ArrayStack<Character>();
String sentence = " ", word;
Scanner in = new Scanner(System.in);
System.out.println("Enter a sentence:");
sentence= in.nextLine();
System.out.println("Reversing each word:");
Scanner sentenceScanner = new Scanner(sentence);
while(sentenceScanner.hasNext())
{
word = sentenceScanner.next();
for(int i= 0; i<word.length(); i++)
{
stack.push(word.charAt(i));
}
while (!stack.isEmpty())
{
System.out.print(stack.pop());
}
}
}
}
Your isEmpty() and pop() functions do not work together. Think about this: when you decrement top and set the index to null does the actual size of the list get adjusted? The fix will come by changing isEmpty() I am just using pop() as an example.
Your isEmpty() method is implemented incorrectly.
public boolean isEmpty()
{
return stack.length == 0;
}
It is currently comparing the size or capacity of of the stack array. This is a constant, it does not change. The value of
stack.length
is always equal to the value you used to initialize the array
new Object[length];
You should be comparing to the number of elements in your stack.
public boolean isEmpty()
{
return top == 0;
}

How do I print my linked list?

If you look at my toString() method below, you can see that I have not finished it. I don't know how? Can anyone explain how I might proceed? Confused :-| I'm new to linked lists and so I automatically went for the Arrays.toString() approach before I realized that there is, of course, no arrays anywhere.
import java.util.Arrays;
public class LinkedIntegerStack {
private Node top = null;
private int size = 0;
public int size(){
return size;
}
public boolean isEmpty() {
if(top == null){
return true;
}
else{
return false;
}
}
public void push(int value) {
Node n = new Node(value);
n.next = top;
top = n;
size++;
}
public int top(){ //just returns a value..doesn't change structure
return top.element;
}
public int pop(){
if (isEmpty()){
throw new StackEmptyException();
}
int toReturn = top.element;
top = top.next;
size--;
return toReturn;
}
public String toString() {
return "[ Top = " + size +"]" + "[Stack = " );
}
private class Node {
int element;
Node next;
public Node(int value){
element = value;
}
}
public static void main(String[] args) throws StackEmptyException{
LinkedIntegerStack stack = new LinkedIntegerStack();
stack.push(17);
System.out.println(stack);
stack.push(11);
System.out.println(stack);
try{
stack.pop();
System.out.println(stack);
}
catch(StackEmptyException ex){
System.out.print("Stack is Empty: Error");
}
System.out.println("Stack: " + stack);
}
}
The solution is pretty easy.
It should be enough to iterate through the stack.
public String toString() {
String result = "[ Top = " + size +"]" + "[Stack = [";
if (top == null) {
return result + "]]";
Node temp = top;
while (temp != null) {
result += temp + ', '
temp = temp.next;
}
return result += temp.element + "]]";
}
Of course you should add at least getter methods to Node class, i.e. getElement() and getNext();
PS: the code isn't tested, but it should be fine.
System.out.println(Arrays.toString(stack.toArray()));
From https://stackoverflow.com/a/395403/2736496
JavaDoc: Arrays.toString(o[]), Collection.toArray(cll)

Categories

Resources