According to the rubric, for this program we are to use "two stacks to evaluate an infix arithmetic expression from an InputStream. It should not create a full postfix expression along the way; it should convert and evaluate in a pipelined fashion, in a single pass."
package cs445.a2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class InfixExpressionEvaluator {
// Tokenizer to break up our input into tokens
StreamTokenizer tokenizer;
// Stacks for operators (for converting to postfix) and operands (for
// evaluating)
StackInterface<Character> operatorStack;
StackInterface<Double> operandStack;
/**
* Initializes the evaluator to read an infix expression from an input
* stream.
* #param input the input stream from which to read the expression
*/
public InfixExpressionEvaluator(InputStream input) {
// Initialize the tokenizer to read from the given InputStream
tokenizer = new StreamTokenizer(new BufferedReader(
new InputStreamReader(input)));
// StreamTokenizer likes to consider - and / to have special meaning.
// Tell it that these are regular characters, so that they can be parsed
// as operators
tokenizer.ordinaryChar('-');
tokenizer.ordinaryChar('/');
// Allow the tokenizer to recognize end-of-line, which marks the end of
// the expression
tokenizer.eolIsSignificant(true);
// Initialize the stacks
operatorStack = new ArrayStack<Character>();
operandStack = new ArrayStack<Double>();
}
/**
* Parses and evaluates the expression read from the provided input stream,
* then returns the resulting value
* #return the value of the infix expression that was parsed
*/
public Double evaluate() throws ExpressionError {
// Get the first token. If an IO exception occurs, replace it with a
// runtime exception, causing an immediate crash.
try {
tokenizer.nextToken();
} catch (IOException e) {
throw new RuntimeException(e);
}
// Continue processing tokens until we find end-of-line
while (tokenizer.ttype != StreamTokenizer.TT_EOL) {
// Consider possible token types
switch (tokenizer.ttype) {
case StreamTokenizer.TT_NUMBER:
// If the token is a number, process it as a double-valued
// operand
processOperand((double)tokenizer.nval);
break;
case '+':
case '-':
case '*':
case '/':
case '^':
// If the token is any of the above characters, process it
// is an operator
processOperator((char)tokenizer.ttype);
break;
case '(':
case '[':
// If the token is open bracket, process it as such. Forms
// of bracket are interchangeable but must nest properly.
processOpenBracket((char)tokenizer.ttype);
break;
case ')':
case ']':
// If the token is close bracket, process it as such. Forms
// of bracket are interchangeable but must nest properly.
processCloseBracket((char)tokenizer.ttype);
break;
case StreamTokenizer.TT_WORD:
// If the token is a "word", throw an expression error
throw new ExpressionError("Unrecognized token: " +
tokenizer.sval);
default:
// If the token is any other type or value, throw an
// expression error
throw new ExpressionError("Unrecognized token: " +
String.valueOf((char)tokenizer.ttype));
}
// Read the next token, again converting any potential IO exception
try {
tokenizer.nextToken();
} catch(IOException e) {
throw new RuntimeException(e);
}
}
// Almost done now, but we may have to process remaining operators in
// the operators stack
processRemainingOperators();
// Return the result of the evaluation
// TODO: Fix this return statement
return null;
}
/**
* This method is called when the evaluator encounters an operand. It
* manipulates operatorStack and/or operandStack to process the operand
* according to the Infix-to-Postfix and Postfix-evaluation algorithms.
* #param operand the operand token that was encountered
*/
void processOperand(double operand) {
// TODO: Complete this method
}
/**
* This method is called when the evaluator encounters an operator. It
* manipulates operatorStack and/or operandStack to process the operator
* according to the Infix-to-Postfix and Postfix-evaluation algorithms.
* #param operator the operator token that was encountered
*/
void processOperator(char operator) {
// TODO: Complete this method
}
/**
* This method is called when the evaluator encounters an open bracket. It
* manipulates operatorStack and/or operandStack to process the open bracket
* according to the Infix-to-Postfix and Postfix-evaluation algorithms.
* #param openBracket the open bracket token that was encountered
*/
void processOpenBracket(char openBracket) {
// TODO: Complete this method
}
/**
* This method is called when the evaluator encounters a close bracket. It
* manipulates operatorStack and/or operandStack to process the close
* bracket according to the Infix-to-Postfix and Postfix-evaluation
* algorithms.
* #param closeBracket the close bracket token that was encountered
*/
void processCloseBracket(char closeBracket) {
// TODO: Complete this method
}
/**
* This method is called when the evaluator encounters the end of an
* expression. It manipulates operatorStack and/or operandStack to process
* the operators that remain on the stack, according to the Infix-to-Postfix
* and Postfix-evaluation algorithms.
*/
void processRemainingOperators() {
// TODO: Complete this method
}
/**
* Creates an InfixExpressionEvaluator object to read from System.in, then
* evaluates its input and prints the result.
* #param args not used
*/
public static void main(String[] args) {
System.out.println("Infix expression:");
InfixExpressionEvaluator evaluator =
new InfixExpressionEvaluator(System.in);
Double value = null;
try {
value = evaluator.evaluate();
} catch (ExpressionError e) {
System.out.println("ExpressionError: " + e.getMessage());
}
if (value != null) {
System.out.println(value);
} else {
System.out.println("Evaluator returned null");
}
}
}
I'm at a lost on how to implement the "void processOperand(double operand)" method(only need to worry about this method for now). I do understand how to convert Infix-to-Postfix using numbers/variables but I don't understand how to do the coding part. Could anybody give me a hint on how to start this method? I have also included the StackInterface class which has all of the push,pop,peek,etc. methods.
package cs445.a2;
import java.util.EmptyStackException;
public interface StackInterface<E> {
/** Adds a new entry to the top of this stack.
* #param newEntry An object to be added to the stack */
public void push(E newEntry);
/** Removes and returns this stack's top entry.
* #return The object at the top of the stack.
* #throws EmptyStackException if the stack is empty. */
public E pop() throws EmptyStackException;
/** Retrieves this stack's top entry.
* #return The object at the top of the stack.
* #throws EmptyStackException if the stack is empty. */
public E peek() throws EmptyStackException;
/** Detects whether this stack is empty.
* #return True if the stack is empty. */
public boolean isEmpty();
/** Removes all entries from this stack. */
public void clear();
}
Related
I am using change stream to see the changes in mongodb. I retrieve the document in the below format, now how to parse in strings. I need the value of $oid and name
Full document is
{"_id": {"$oid": "5c60f87a9ea5deac53457e9c"}, "name": "freddy"}
I am using Java code
MongoCursor<ChangeStreamDocument<BasicDBObject>> cursor1 = collection.watch().iterator();
System.out.println("Connection Completely Established 4");
for(int i = 1; i <= 200; i++)
{
ChangeStreamDocument<BasicDBObject> next1 = cursor1.next();
System.out.println("Operation Type is " + next1.getOperationType());
System.out.println("Database Name is" + next1.getDatabaseName());
System.out.println("Full Document is " + next1.getFullDocument());
}
If you know the format of the document string then you can use a method to acquire the data needed. The getBetween() method below will retrieve the information you want from your provided document string, here is how it might be used to achieve this:
String docString = "Full Document is {\"_id\": {\"$oid\": \"5c60f87a9ea5deac53457e9c\"}, \"name\": \"freddy\"}";
String oid = getBetween(docString, "$oid\": \"", "\"}")[0];
String name = getBetween(docString, "name\": \"", "\"}")[0];
System.out.println(oid);
System.out.println(name);
The Console Window will display:
5c60f87a9ea5deac53457e9c
freddy
Here is the getBetween() method:
/**
* Retrieves any string data located between the supplied string leftString
* parameter and the supplied string rightString parameter.<br><br>
* <p>
* <p>
* This method will return all instances of a substring located between the
* supplied Left String and the supplied Right String which may be found
* within the supplied Input String.<br>
*
* #param inputString (String) The string to look for substring(s) in.
*
* #param leftString (String) What may be to the Left side of the substring
* we want within the main input string. Sometimes the
* substring you want may be contained at the very
* beginning of a string and therefore there is no
* Left-String available. In this case you would simply
* pass a Null String ("") to this parameter which
* basically informs the method of this fact. Null can
* not be supplied and will ultimately generate a
* NullPointerException.
*
* #param rightString (String) What may be to the Right side of the
* substring we want within the main input string.
* Sometimes the substring you want may be contained at
* the very end of a string and therefore there is no
* Right-String available. In this case you would simply
* pass a Null String ("") to this parameter which
* basically informs the method of this fact. Null can
* not be supplied and will ultimately generate a
* NullPointerException.
*
* #param options (Optional - Boolean - 2 Parameters):<pre>
*
* ignoreLetterCase - Default is false. This option works against the
* string supplied within the leftString parameter
* and the string supplied within the rightString
* parameter. If set to true then letter case is
* ignored when searching for strings supplied in
* these two parameters. If left at default false
* then letter case is not ignored.
*
* trimFound - Default is true. By default this method will trim
* off leading and trailing white-spaces from found
* sub-string items. General sentences which obviously
* contain spaces will almost always give you a white-
* space within an extracted sub-string. By setting
* this parameter to false, leading and trailing white-
* spaces are not trimmed off before they are placed
* into the returned Array.</pre>
*
* #return (1D String Array) Returns a Single Dimensional String Array
* containing all the sub-strings found within the supplied Input
* String which are between the supplied Left String and supplied
* Right String.
*/
public String[] getBetween(String inputString, String leftString, String rightString, boolean... options) {
// Return nothing if nothing was supplied.
if (inputString.equals("") || (leftString.equals("") && rightString.equals(""))) {
return null;
}
// Prepare optional parameters if any supplied.
// If none supplied then use Defaults...
boolean ignoreCase = false; // Default.
boolean trimFound = true; // Default.
if (options.length > 0) {
if (options.length >= 1) {
ignoreCase = options[0];
}
if (options.length >= 2) {
trimFound = options[1];
}
}
// Remove any ASCII control characters from the
// supplied string (if they exist).
String modString = inputString.replaceAll("\\p{Cntrl}", "");
// Establish a List String Array Object to hold
// our found substrings between the supplied Left
// String and supplied Right String.
List<String> list = new ArrayList<>();
// Use Pattern Matching to locate our possible
// substrings within the supplied Input String.
String regEx = Pattern.quote(leftString)
+ (!rightString.equals("") ? "(.*?)" : "(.*)?")
+ Pattern.quote(rightString);
if (ignoreCase) {
regEx = "(?i)" + regEx;
}
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(modString);
while (matcher.find()) {
// Add the found substrings into the List.
String found = matcher.group(1);
if (trimFound) {
found = found.trim();
}
list.add(found);
}
return list.toArray(new String[0]);
}
I am getting the error when I launch my UI that causes this code to spit the error at me in the title. It works for all of my other operator symbols so I am really not sure what's going on here. I didn't want to post all the code so you can find the rest if this isn't enough on my gitHub: https://github.com/jparr721/Calculator-App/tree/master/src/calculator
public class Calculation_Controls {
public double A, B;
private String[] operators = new String[] {"-","+","/","*","x","^","X"};
/**
* Check for the symbol being used within the TextArea to then
* apply the correct caculation method.
* FIXME - Allow for multiple symbols to be used and have them return
* FIXME - a result in accordance with PEMDAS
*
*#param nums
*
* #return operator, or error
*/
public String findSymbol(String nums) {
for (String operator : operators) {
if (nums.contains(operator)) {
return operator;
}
}
return "invalid input";
}
/**
* Input method to take the user input from the text area
* and apply the correct calculation to it
*
* #param nums - Stores the input as a String which I then convert to an int
* then back to a string to be printed to the TextArea
*
* #return - The result of the calculation as a string
*/
public String input(String nums){
String operator = findSymbol(nums);
if (operator == null){
System.out.println("Invalid input");
}
String[] split = nums.split(operator);
int left = Integer.parseInt(split[0]);
int right = Integer.parseInt((split[1]));
String result = "";
switch (operator){
case "+":
result = Double.toString(add(left, right));
break;
case "-":
result = Double.toString(subtract(left, right));
break;
case "*":
case "x":
case "X":
result = Double.toString(multiply(left, right));
break;
case "/":
result = Double.toString(divide(left, right));
break;
case "^":
result = Double.toString(pwr(left, right));
break;
default:
System.out.println("Invalid Operator");
}
return result;
}
There are reserved character in Regex and you should scape these character to achieve what you want. For example, you can't use String.split("+"), you have to use String.split("\\+").
The correct operators would be:
String[] operators = new String[] {"-","\\+","/","\\*","x","\\^","X"};
in your case + * and ^ are treated with a special meaning, most often called as Metacharacters. String.split() method takes a regex expression as its argument and return a String array. To avoid treating above as a Metacharacters you need to use these escape sequences in your code "\\+" "\\*" "\\^"
modify your operator array like this
private String[] operators = new String[] {"-","\\+","/","\\*","x","\\^","X"};
for more detalis refere these links regex.Pattern and String.split()
you can use
case String.valueOf('+');
Change: String[] split = nums.split(operator);
To this: String[] split = nums.split("\\" + operator);
edit: This will only work for standard operators, not the x or X. You'll have to change your String[] operators declaration actually, like the other answer mentioned. Personally though, I'd do some kind of input validation and do a replace() on x or X to be * instead
the split() method uses regex. the '+' symbol is a special character in regex, so you need to escape it with the backslash symbol ('\'). But you also need to escape the backslash symbol in java, so you need two backslashes, e.g. "\\+"
On the Internet, I found very useful class, using which I can restrict TextField. I encountered a problem, where my TextField can contain only one '.' character. I suspect that I can handle this by writing an appripriate regex and set it as a restriction on the instance of that class. I use the following regex: "[0-9.-]", but it allows as many dots as the user types. May I ask you to help me to configure my TextField so that no more than one '.' is allowed.
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;
/**
* Created by Anton on 7/14/2015.
*/
public class RestrictiveTextField extends TextField {
private IntegerProperty maxLength = new SimpleIntegerProperty(this, "maxLength", -1);
private StringProperty restrict = new SimpleStringProperty(this, "restrict");
public RestrictiveTextField() {
super("0");
textProperty().addListener(new ChangeListener<String>() {
private boolean ignore;
#Override
public void changed(ObservableValue<? extends String> observableValue, String s, String s1) {
if (ignore || s1 == null)
return;
if (maxLength.get() > -1 && s1.length() > maxLength.get()) {
ignore = true;
setText(s1.substring(0, maxLength.get()));
ignore = false;
}
if (restrict.get() != null && !restrict.get().equals("") && !s1.matches(restrict.get() + "*")) {
ignore = true;
setText(s);
ignore = false;
}
}
});
}
/**
* The max length property.
*
* #return The max length property.
*/
public IntegerProperty maxLengthProperty() {
return maxLength;
}
/**
* Gets the max length of the text field.
*
* #return The max length.
*/
public int getMaxLength() {
return maxLength.get();
}
/**
* Sets the max length of the text field.
*
* #param maxLength The max length.
*/
public void setMaxLength(int maxLength) {
this.maxLength.set(maxLength);
}
/**
* The restrict property.
*
* #return The restrict property.
*/
public StringProperty restrictProperty() {
return restrict;
}
/**
* Gets a regular expression character class which restricts the user input.
*
* #return The regular expression.
* #see #getRestrict()
*/
public String getRestrict() {
return restrict.get();
}
/**
* Sets a regular expression character class which restricts the user input.
* E.g. [0-9] only allows numeric values.
*
* #param restrict The regular expression.
*/
public void setRestrict(String restrict) {
this.restrict.set(restrict);
}
}
There are various versions of the regex, depending on exactly what you want to support. Note that you don't only want to match valid numbers, but also partial entries, because the user has to be able to edit this. So, for example, an empty string is not a valid number, but you certainly want the user to be able to delete everything that's there while they are editing; similarly you want to allow "0.", etc.
So you probably want something like
Optional minus sign, followed by either any number of digits, or at least one digit, a period (.), and any number of digits.
The regex for this could be -?((\\d*)|(\\d+\.\\d*)). There are probably other ways to do this, some of them perhaps more efficient. And if you want to support exponential forms ("1.3e12") it gets more complex.
To use this with a TextField, the recommended way is to use a TextFormatter. The TextFormatter consists of two things: a converter to convert between the text and the value it represents (a Double in your case: you can just use the built-in DoubleStringConverter), and vice versa, and then a filter. The filter is implemented as a function that takes a TextFormatter.Change object and returns an object of the same type. Typically you either leave the Change object as it is and return it (to accept the Change "as is"), or modify it somehow. It is also legal to return null to represent "no change". So in your simple case here, just examine the new proposed text, see if it matches the regular expression, return the change "as is" if it matches and return null otherwise.
Example:
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.converter.DoubleStringConverter;
public class NumericTextFieldExample extends Application {
#Override
public void start(Stage primaryStage) {
TextField textField = new TextField();
Pattern validDoubleText = Pattern.compile("-?((\\d*)|(\\d+\\.\\d*))");
TextFormatter<Double> textFormatter = new TextFormatter<Double>(new DoubleStringConverter(), 0.0,
change -> {
String newText = change.getControlNewText() ;
if (validDoubleText.matcher(newText).matches()) {
return change ;
} else return null ;
});
textField.setTextFormatter(textFormatter);
textFormatter.valueProperty().addListener((obs, oldValue, newValue) -> {
System.out.println("New double value "+newValue);
});
StackPane root = new StackPane(textField);
root.setPadding(new Insets(24));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You can use the following regex,
"[^\\.]*\\.{0,1}[^\\.]"
Or as VGR has pointed out, "A period has no special meaning inside character class brackets and 0 or 1 time can be represented with a '?' (question mark).", so you can also use,
"[^.]*\\.?[^.]"
I don't know why but your class seems to append a * to the regex, so the above regex will effectively become,
"[^\\.]*\\.{0,1}[^\\.]*"
Which means,
It will allow any character except a . 0 or more times (greedy).
It will allow a . 0 or 1 times.
It will allow any character except a . 0 or more times (greedy).
This is what you seem to be needing. DEMO
{[0-9]+\\.[0-9]+}
to match any number if this is in fact what you are wanting to do
I need an equivalent behaviour in java for this command in Unix cli:
ls /data/archive/users/*/*.xml
Which outputs me:
/data/archive/users/2012/user1.xml
/data/archive/users/2013/user2.xml
Is there a simple equivalent implementation for Java 6?
Get user input using java.util.Scanner and use java.io.File.listFiles(FilenameFilter) method to get the list of files in the folder with specific filter.
Yes, there is, and it's called the list method of the File class. See it's Javadoc for details.
I forget where this came from but this should be a good start. There are many more available via Google.
public class RegexFilenameFilter implements FilenameFilter {
/**
* Only file name that match this regex are accepted by this filter
*/
String regex = null; // setting the filter regex to null causes any name to be accepted (same as ".*")
public RegexFilenameFilter() {
}
public RegexFilenameFilter(String filter) {
setWildcard(filter);
}
/**
* Set the filter from a wildcard expression as known from the windows command line
* ("?" = "any character", "*" = zero or more occurances of any character")
*
* #param sWild the wildcard pattern
*
* #return this
*/
public RegexFilenameFilter setWildcard(String sWild) {
regex = wildcardToRegex(sWild);
// throw PatternSyntaxException if the pattern is not valid
// this should never happen if wildcardToRegex works as intended,
// so thiw method does not declare PatternSyntaxException to be thrown
Pattern.compile(regex);
return this;
}
/**
* Set the regular expression of the filter
*
* #param regex the regular expression of the filter
*
* #return this
*/
public RegexFilenameFilter setRegex(String regex) throws java.util.regex.PatternSyntaxException {
this.regex = regex;
// throw PatternSyntaxException if the pattern is not valid
Pattern.compile(regex);
return this;
}
/**
* Tests if a specified file should be included in a file list.
*
* #param dir the directory in which the file was found.
*
* #param name the name of the file.
*
* #return true if and only if the name should be included in the file list; false otherwise.
*/
public boolean accept(File dir, String name) {
boolean bAccept = false;
if (regex == null) {
bAccept = true;
} else {
bAccept = name.toLowerCase().matches(regex);
}
return bAccept;
}
/**
* Converts a windows wildcard pattern to a regex pattern
*
* #param wild - Wildcard patter containing * and ?
*
* #return - a regex pattern that is equivalent to the windows wildcard pattern
*/
private static String wildcardToRegex(String wild) {
if (wild == null) {
return null;
}
StringBuilder buffer = new StringBuilder();
char[] chars = wild.toLowerCase().toCharArray();
for (int i = 0; i < chars.length; ++i) {
if (chars[i] == '*') {
buffer.append(".*");
} else if (chars[i] == '?') {
buffer.append('.');
} else if (chars[i] == ';') {
buffer.append('|');
} else if ("+()^$.{}[]|\\".indexOf(chars[i]) != -1) {
buffer.append('\\').append(chars[i]); // prefix all metacharacters with backslash
} else {
buffer.append(chars[i]);
}
}
return buffer.toString();
}
}
Here is the code I used, it works with relative and absolute paths:
DirectoryScanner scanner = new DirectoryScanner();
if (!inputPath.startsWith("/") || inputPath.startsWith(".")) {
scanner.setBasedir(".");
}
scanner.setIncludes(new String[]{inputPath});
scanner.setCaseSensitive(false);
scanner.scan();
String[] foundFiles = scanner.getIncludedFiles();
(DirectoryScanner from org.apache.tools.ant)
I am working on a project since we are starting to studying recursion. I am very new on this so I am not sure how to tackle this puzzle. This is the problem in the book and I would appreciate any STEPS(step1, step2, ...) that may help me to come up with ideas to solve this problem ALSO, I really appreciate if any one can share with me a way to understand recursion, still it does not make a lot of sense to me so I would appreciate any advice on how to understand better this topic. Ok, so these are the instructions. Thank you.
An AdditionPuzzle has a form such as 2BCD+BCDE=DA01. We want to find all solutions, where A, B, C, D are distinct digits, different from any digits in the puzzle. Here, a solution is 2345+3456=5801. In general, a puzzle can have any combination of up to ten digits and numbers. Write a recursive method for computing a solution to a puzzle using these two classes:
Class #1
public class ThisPuzzle
{
/**
Returns a solution to a puzzle.
#param p a puzzle
#return a solution or null if none exists
*/
public static Puzzle solvePuzzle(Puzzle p)
{
// ...
return null;
}
public static void main(String[] args)
{
Puzzle p = new Puzzle("3A6", "36B", "71C");
System.out.println(solvePuzzle(p));
}
}
Class #2
public class Puzzle
{
private String add1;
private String add2;
private String result;
/**
Constructs a puzzle.
#param add1 a string containing digits 0 - 9 and letters
#param add2 a string containing digits 0 - 9 and letters
#param result a string containing digits 0 - 9 and letters
*/
public Puzzle(String add1, String add2, String result)
{
this.add1 = add1;
this.add2 = add2;
this.result = result;
}
/**
Makes a new puzzle by replacing a letter with a digit.
#param letter the letter to be replaced
#param digit the digit to replace it with
#return the new puzzle
*/
public Puzzle replace(String letter, int digit)
{
// ...
}
/**
Returns true if the puzzle is solved.
#return true if the puzzle has no letters and the
first two numbers add up to the third
*/
public boolean isSolved()
{
// ...
}
/**
Gets the first letter in this puzzle.
#return the first letter, or "" if there are no letters.
*/
public String firstLetter()
{
// ...
}
/**
Checks whether this puzzle contains a given digit.
#param digit a digit
#return true if this puzzle returns digit
*/
public boolean contains(int digit)
{
// ...
}
public String toString()
{
return add1 + "+" + add2 + "=" + result;
}
}
Recursion is when you call a method inside it's own definition.
A very simple infinite recursion is:
public static void recurse(){
recurse();
}
Calling this method will cause a stack overflow exception. It might be easier to imagine why there would be an error if you print a message inside recurse.
public static void recurse(){
recurse();
System.out.println("finished recursing")
}
An error will be thrown before you hit the print because the machine has to maintain a stack of all the method calls in the vain hope that the inner recursion will finish and it can print you a message.
For your problem you will need to call solvePuzzle within solvePuzzle. The idea is that you should attempt to solve easier Puzzle inside each level of recursion. Think trial and error.