Interface implementation in static class - java

I'm trying to understand one java code, here is the code
package RestClient;
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.PrintStream;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) {
InputStream inputStream = System.in;
System.out.println("Its done");
OutputStream outputStream = System.out;
InputReader in = new InputReader(inputStream);
OutputWriter out = new OutputWriter(outputStream);
TaskE solver = new TaskE();
solver.solve(1, in, out);
out.close();
}
static class TaskE {
static long[] dp;
static long[] sum;
static int n;
static SegmentTreeRMQ tree;
public void solve(int testNumber, InputReader in, OutputWriter out) {
System.out.println("2");
n = in.nextInt();
System.out.println("It always come Here");
int c = in.nextInt();
if (c == 1) {
out.println(0);
return;
}
int[] a = in.nextIntArray(n);
dp = new long[n];
sum = new long[n + 1];
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1] + a[i - 1];
}
tree = new SegmentTreeRMQ();
tree.constructST(a, n);
out.println(comp(a, 0, n - 1, c));
}
private long comp(int[] a, int l, int r, int c) {
//System.out.println(l+" "+r);
if (r < l) return 0;
if (r == l && c == 1) return 0;
else if (r == l) return a[l];
if (dp[l] != 0) return dp[l];
int min = a[l];
long val = sum[r + 1] - sum[l];
val = Math.min(val, (a[l] + comp(a, l + 1, r, c)));
if (l + c <= n)
val = Math.min(val, sum[l + c] - sum[l] - tree.RMQ(n, l, l + c - 1) + comp(a, l + c, r, c));
//System.out.println("val:"+l+" "+val);
dp[l] = val;
return val;
}
}
static class InputReader {
private InputStream stream;
private byte[] buf = new byte[1024];
private int curChar;
private int numChars;
private InputReader.SpaceCharFilter filter;
public InputReader(InputStream stream) {
System.out.println("1");
this.stream = stream;
}
public int read() {
System.out.println("Its4");
System.out.println("numChars Near 4: " +numChars);
System.out.println("curChar Near 4: " +curChar);
if (numChars == -1) {
throw new InputMismatchException();
}
if (curChar >= numChars) {
curChar = 0;
try {
System.out.println("5");
numChars = stream.read(buf);
System.out.println("numChars: "+numChars);
System.out.println("Print: "+new String(new byte[]{ (buf[curChar]) }, "US-ASCII"));
} catch (IOException e) {
throw new InputMismatchException();
}
if (numChars <= 0) {
return -1;
}
}
System.out.println("curChar++: "+curChar);
return buf[curChar++];
}
public int nextInt() {
System.out.println("3");
int c = read();
System.out.println("c: "+c);
while (isSpaceChar(c)) {
System.out.println("6");
c = read();
}
int sgn = 1;
System.out.println("7");
if (c == '-') {
System.out.println("8");
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9') {
throw new InputMismatchException();
}
System.out.println("9");
res = res*10;
res = res+c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
public boolean isSpaceChar(int c) {
if (filter != null) {
System.out.println("here");
return filter.isSpaceChar(c);
}
return isWhitespace(c);
}
public static boolean isWhitespace(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
public int[] nextIntArray(int n) {
int[] array = new int[n];
for (int i = 0; i < n; ++i) array[i] = nextInt();
return array;
}
public interface SpaceCharFilter {
public boolean isSpaceChar(int ch);
}
}
static class SegmentTreeRMQ {
int[] st;
int minVal(int x, int y) {
return (x < y) ? x : y;
}
int getMid(int s, int e) {
return s + (e - s) / 2;
}
int RMQUtil(int ss, int se, int qs, int qe, int index) {
// If segment of this node is a part of given range, then
// return the min of the segment
if (qs <= ss && qe >= se)
return st[index];
// If segment of this node is outside the given range
if (se < qs || ss > qe)
return Integer.MAX_VALUE;
// If a part of this segment overlaps with the given range
int mid = getMid(ss, se);
return minVal(RMQUtil(ss, mid, qs, qe, 2 * index + 1),
RMQUtil(mid + 1, se, qs, qe, 2 * index + 2));
}
int RMQ(int n, int qs, int qe) {
// Check for erroneous input values
if (qs < 0 || qe > n - 1 || qs > qe) {
System.out.println("Invalid Input");
return -1;
}
return RMQUtil(0, n - 1, qs, qe, 0);
}
int constructSTUtil(int arr[], int ss, int se, int si) {
// If there is one element in array, store it in current
// node of segment tree and return
if (ss == se) {
st[si] = arr[ss];
return arr[ss];
}
// If there are more than one elements, then recur for left and
// right subtrees and store the minimum of two values in this node
int mid = getMid(ss, se);
st[si] = minVal(constructSTUtil(arr, ss, mid, si * 2 + 1),
constructSTUtil(arr, mid + 1, se, si * 2 + 2));
return st[si];
}
void constructST(int arr[], int n) {
// Allocate memory for segment tree
//Height of segment tree
int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
//Maximum size of segment tree
int max_size = 2 * (int) Math.pow(2, x) - 1;
st = new int[max_size]; // allocate memory
// Fill the allocated memory st
constructSTUtil(arr, 0, n - 1, 0);
}
}
static class OutputWriter {
private final PrintWriter writer;
public OutputWriter(OutputStream outputStream) {
writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
}
public OutputWriter(Writer writer) {
this.writer = new PrintWriter(writer);
}
public void close() {
writer.close();
}
public void println(long i) {
writer.println(i);
}
public void println(int i) {
writer.println(i);
}
}
}
Doubts:
1) InputReader is inner class of Test class, where SpaceCharFilter interface is created with one method declared. I have seen only where interface can be used by using implementation on class eg class implements Interface { implements methods}, but in this case it is setup with class's variable filter. May I know please how this functionality works in Java ?
2) In isSpaceChar(int c) method what is the significance of filter variable ? What type of values can come in filter variable ?
3) I'm running code with this input "10 2" then enter. Ideally it should go to filter!=null condition in isSpaceChar method while reading second character from input "0" from "10 2", but its not going, may I know please why ?
Can anyone help me to clear these doubts ?

this is what polymorhism is about: we define an interface and call the method(s) defined in it not caring about what the actual implementation is (but expecting the implementation matching the interfaces contract which is defined by the name of the interface, the names of the methods defined in it and any comments it may have).
it can hold an object that implements SpaceCharFilter.
This is because the variable filter never gets an object assigned.
Thus both, the interface and the variable are useless in this code.

Related

more efficiently read int values from console

How can I read int values from console more efficiently (from memory) than this:
BufferedReader in ...
number = Integer.parseInt(in.readLine());
When I use readLine() and parse it to int, java create many String objects and сonsumes memory. I try to use Scanner and method nextInt() but this approach is also not that efficiently.
P.S I need read > 1000_000 values and I have memory limit.
EDIT Full code of task
import java.io.*;
public class Duplicate {
public static void main(String[] args) throws IOException {
int last = 0;
boolean b = false;
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
for (int i = 0; i < n; i++) {
int number =Integer.parseInt(reader.readLine());
if (number == 0 && !b) {
System.out.println(0);
b = true;
}
if (number == last) continue;
last = number;
System.out.print(last);
}
}
}
And Rewrite variant:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
public class Duplicate {
public static void main(String[] args) throws IOException {
int last = 0;
boolean b = false;
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int nextInt = getNextInt(reader);
for (int i = 0; i < nextInt; i++) {
int number = getNextInt(reader);
if (number == 0 && !b) {
System.out.println(0);
b = true;
}
if (number == last) continue;
b = true;
last = number;
System.out.println(last);
}
}
static int getNextInt(Reader in) throws IOException {
int c;
boolean negative = false;
do {
c = in.read();
if (!Character.isDigit(c)) {
negative = c == '-';
}
} while (c != -1 && !Character.isDigit(c));
if (c == -1) return Integer.MIN_VALUE;
int num = Character.getNumericValue(c);
while ((c = in.read()) != -1 && Character.isDigit(c)) {
num = 10 * num + Character.getNumericValue(c);
}
return negative ? -num : num;
}
}
Both options do not pass from memory (((
EDIT2 I try profiling
int number = getRandom(); and start with 1000000
once again launched the same
and splash GC
You can read from in one char at a time, checking if it's a digit, and then accumulating it into a number. Something like:
int getNextInt(Reader in) throws IOException {
int c;
boolean negative = false;
do {
c = in.read();
if (!Character.isDigit(c)) { negative = c == '-' };
} while (c != -1 && !Character.isDigit(c));
if (c == -1) return Integer.MIN_VALUE; // Some sentinel to indicate nothing found.
int num = Character.getNumericValue(c);
while ((c = in.read()) != -1 && Character.isDigit(c)) {
num = 10 * num + Character.getNumericValue(c);
}
return negative ? -num : num;
}
Ideone demo
Of course, this is incredibly primitive parsing. But you could perhaps take this code as a basis and adapt it as required.
You can use this FastScanner class
static class FastScanner {
private BufferedReader reader = null;
private StringTokenizer tokenizer = null;
public FastScanner(InputStream in) {
reader = new BufferedReader(new InputStreamReader(in));
tokenizer = null;
}
public String next() {
if (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
if (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
return reader.readLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken("\n");
}
public long nextLong() {
return Long.parseLong(next());
}
public int nextInt() {
return Integer.parseInt(next());
}
}
It is very commonly used on codeforces to read large input where Scanner class leads to TLE
This is originally authored by https://codeforces.com/profile/Petr
I use this InputReader on codeforces. Works pretty well for me on large input cases. You can extend this up to your use case. I came across this after getting TLE using Scanner and add functionalities if needed.
static class InputReader {
private final InputStream stream;
private final byte[] buf = new byte[1024];
private int curChar;
private int numChars;
public InputReader(InputStream stream) {
this.stream = stream;
}
private int read() {
try {
if (curChar >= numChars) {
curChar = 0;
numChars = stream.read(buf);
if (numChars <= 0)
return -1;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return buf[curChar++];
}
public int readInt() {
return (int) readLong();
}
public long readLong() {
int c = read();
while (isSpaceChar(c)) {
c = read();
if (c == -1) throw new RuntimeException();
}
boolean negative = false;
if (c == '-') {
negative = true;
c = read();
}
long res = 0;
do {
if (c < '0' || c > '9') throw new InputMismatchException();
res *= 10;
res += (c - '0');
c = read();
} while (!isSpaceChar(c));
return negative ? (-res) : (res);
}
public int[] readIntArray(int size) {
int[] arr = new int[size];
for (int i = 0; i < size; i++) arr[i] = readInt();
return arr;
}
private boolean isSpaceChar(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
}

Breadth-First Search implementation not Working

I have a problem with the implementation of the breadth-first search algorithm, I have a method that gives me an array of integers from 0-8, in random order. I also have an integer m that tells me which number is blank. Here are the rules:
I get a block of numbers, like:
456
782
301
And lets say that 8 is the blank value, I can swap it with 5, 7, 2, and 0. since they are directly next to it. I have to use breadth-first search to solve this puzzle. Here is the code I have written so far:
package application;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Vector;
public class Solution {
/******************************************
* Implementation Here
***************************************/
/*
* Implementation here: you need to implement the Breadth First Search
* Method
*/
/* Please refer the instruction document for this function in details */
public static LinkedHashSet<int[]> OPEN = new LinkedHashSet<int[]>();
public static HashSet<int[]> CLOSED = new HashSet<int[]>();
public static boolean STATE = false;
public static int empty;
public static void breadthFirstSearch(int[] num, int m, Vector solution1) {
int statesVisited = 0;
for(int i : num) {
if(num[i] == m) {
empty = i;
}
}
int[] start = num;
int[] goal = {0,1,2,3,4,5,6,7,8};
int[] X;
int[] temp = {};
OPEN.add(start);
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
int pos = empty; // get position of ZERO or EMPTY SPACE
if (compareArray(X,goal)) {
System.out.println("SUCCESS");
STATE = true;
} else {
// generate child nodes
CLOSED.add(X);
temp = up(X, pos);
if (temp != null)
OPEN.add(temp);
temp = left(X, pos);
if (temp != null)
OPEN.add(temp);
temp = down(X, pos);
if (temp != null)
OPEN.add(temp);
temp = right(X, pos);
if (temp != null)
OPEN.add(temp);
if(OPEN.isEmpty())
System.out.println("Ending loop");
}
}
}
public static boolean compareArray(int[] a, int[] b) {
for(int i: a)
if(a[i] != b[i])
return false;
return true;
}
public static int[] up(int[] s, int p) {
int[] str = s;
if (p > 3) {
int temp = str[p-3];
str[p-3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] down(int[] s, int p) {
int[] str = s;
if (p < 6) {
int temp = str[p+3];
str[p+3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] left(int[] s, int p) {
int[] str = s;
if (p != 0 && p != 3 && p != 6) {
int temp = str[p-1];
str[p-1] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
public static int[] right(int[] s, int p) {
int[] str = s;
if (p != 2 && p != 5 && p != 8) {
int temp = str[p+1];
str[p+1] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return null;
}
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();
}
}
This code just immediately ends, and never finds an answer. Perhaps I have done something wrong? Please help.
Please Note: This is my first question on StackOverFlow, so if anyone has any criticisms please tell me and I will fix them right away.
First of all, you have a parameter which isn't doing anything, Vector solution in:
public static void breadthFirstSearch(int[] num, int m, Vector solution1)
Also you are passing in the position of the zero element which you are representing as m, then assigning a local variable to that position, seems a little pointless to me there's no need to pass in the zero position if you're going to search for it anyway.
Updated breadth first search method:
public static void breadthFirstSearch(int[] num) {
for (int i : num) {
if (num[i] == 0) {
empty = i;
}
}
int[] start = num;
int[] goal = {1, 2, 3, 4, 5, 6, 7, 8, 0};
int[] X;
int[] temp = {};
OPEN.add(start);
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
int pos = empty; // get position of ZERO or EMPTY SPACE
if (Arrays.equals(X, goal)) {
System.out.println("SUCCESS");
STATE = true;
} else {
// generate child nodes
CLOSED.add(X);
temp = up(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = left(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = down(X, pos);
if (temp != null) {
OPEN.add(temp);
}
temp = right(X, pos);
if (temp != null) {
OPEN.add(temp);
}
if (OPEN.isEmpty()) {
System.out.println("Ending loop");
}
}
}
}
The main issue with your program was that within your movement methods up(), down(), left(), right(). You weren't creating complete copies of the arrays, thus resulting in modifications happening to the original array.
Thus this assignment:
int[] str = s;
must be changed to:
int[] str = new int[s.length];
System.arraycopy(s, 0, str, 0, s.length);
Here's an example of a completed method:
public static int[] up(int[] s, int p) {
int[] str = new int[s.length];
System.arraycopy(s, 0, str, 0, s.length);
if (p > 3) {
int temp = str[p - 3];
str[p - 3] = str[p];
str[p] = temp;
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && !CLOSED.contains(str)) {
return str;
} else {
return null;
}
}
SIDE NOTE (Not essential):
There are certain permutations of the array which won't result in the goal state. This puzzle itself can have a total number of 9! configurations, but actually only 9!/2 of these are solvable.
I wrote an algorithm for checking the parity of the puzzle, which can be done as a kind of preprocessing, I used it in order to create random instances for testing the data.
public boolean isSolvable(int[] puzzle) {
boolean parity = true;
int gridWidth = (int) Math.sqrt(puzzle.length);
boolean blankRowEven = true; // the row with the blank tile
for (int i = 0; i < puzzle.length; i++) {
if (puzzle[i] == 0) { // the blank tile
blankRowEven = (i / gridWidth) % 2==0;
continue;
}
for (int j = i + 1; j < puzzle.length; j++) {
if (puzzle[i] > puzzle[j] && puzzle[j] != 0) {
parity = !parity;
}
}
}
// even grid with blank on even row; counting from top
if (gridWidth % 2 == 0 && blankRowEven) {
return !parity;
}
return parity;
}
For the vector
You want to be able to print out the path that has been taken to get to the goal state, I would recommend having a class for the State such:
private State previousState;
private int[] current;
public State(int[] current, State previousState) {
this.current = current;
this.previousState = previousState
}
public State getPreviouState(){
return previousState;
}
public int[] getCurrentState(){
return currentState;
}
Then when you have the goal State you can loop through all the previous States to see the path it took.
State current = GOAL;
while(current != null){
System.out.println(Arrays.toString(current));
current = current.getPreviousState();
}
The method up(...) has an error:
You have:
str[p] = str[p-3];
Which I'm guessing should be:
str[p] = temp;

Autocomplete byReverseWeightOrder comparator issue

I have been working on this problem for several hours now and I just cannot figure out what I am doing wrong here. Could anyone help point me in the right direction?
I was asked to write an Autocomplete program and I've completed everything except for this one method I cannot get working. Each term has: 1. String query and 2. long weight.
Here is the method:
public static Comparator<Term> byReverseWeightOrder() {
return new Comparator<Term>() { // LINE CAUSING PROBLEM
public int compare(Term t1, Term t2) {
if (t1.weight > t2.weight) { // LINE CAUSING PROBLEM
return -1;
} else if (t1.weight == t2.weight) {
return 0;
} else {
return 1;
}
}
};
}
My problem is that no matter how I mess with the method I always result in a NullPointerException(). Which, it points to this method (byReverseWeightOrder) as well as these two statements.
Arrays.sort(matches, Term.byReverseWeightOrder());
Term[] results = autocomplete.allMatches(prefix);
Here is the rest of the code if it can be found helpful:
Term
import java.util.Comparator;
public class Term implements Comparable<Term> {
public String query;
public long weight;
public Term(String query, long weight) {
if (query == null) {
throw new java.lang.NullPointerException("Query cannot be null");
}
if (weight < 0) {
throw new java.lang.IllegalArgumentException("Weight cannot be negative");
}
this.query = query;
this.weight = weight;
}
public static Comparator<Term> byReverseWeightOrder() {
return new Comparator<Term>() {
public int compare(Term t1, Term t2) {
if (t1.weight > t2.weight) {
return -1;
} else if (t1.weight == t2.weight) {
return 0;
} else {
return 1;
}
}
};
}
public static Comparator<Term> byPrefixOrder(int r) {
if (r < 0) {
throw new java.lang.IllegalArgumentException("Cannot order with negative number of characters");
}
final int ref = r;
return
new Comparator<Term>() {
public int compare(Term t1, Term t2) {
String q1 = t1.query;
String q2 = t2.query;
int min;
if (q1.length() < q2.length()) {
min = q1.length();
}
else {
min = q2.length();
}
if (min >= ref) {
return q1.substring(0, ref).compareTo(q2.substring(0, ref));
}
else if (q1.substring(0, min).compareTo(q2.substring(0, min)) == 0) {
if (q1.length() == min) {
return -1;
}
else {
return 1;
}
}
else {
return q1.substring(0, min).compareTo(q2.substring(0, min));
}
}
};
}
public int compareTo(Term that) {
String q1 = this.query;
String q2 = that.query;
return q1.compareTo(q2);
}
public long getWeight() {
return this.weight;
}
public String toString() {
return this.weight + "\t" + this.query;
}
}
BinarySearchDeluxe
import java.lang.*;
import java.util.*;
import java.util.Comparator;
public class BinarySearchDeluxe {
public static <Key> int firstIndexOf(Key[] a, Key key, Comparator<Key> comparator) {
if (a == null || key == null || comparator == null) {
throw new java.lang.NullPointerException();
}
if (a.length == 0) {
return -1;
}
int left = 0;
int right = a.length - 1;
while (left + 1 < right) {
int middle = left + (right - left)/2;
if (comparator.compare(key, a[middle]) <= 0) {
right = middle;
} else {
left = middle;
}
}
if (comparator.compare(key, a[left]) == 0) {
return left;
}
if (comparator.compare(key, a[right]) == 0) {
return right;
}
return -1;
}
public static <Key> int lastIndexOf(Key[] a, Key key, Comparator<Key> comparator) {
if (a == null || key == null || comparator == null) {
throw new java.lang.NullPointerException();
}
if (a == null || a.length == 0) {
return -1;
}
int left = 0;
int right = a.length - 1;
while (left + 1 < right) {
int middle = left + (right - left)/2;
if (comparator.compare(key, a[middle]) < 0) {
right = middle;
} else {
left = middle;
}
}
if (comparator.compare(key, a[right]) == 0) {
return right;
}
if (comparator.compare(key, a[left]) == 0) {
return left;
}
return -1;
}
}
AutoComplete
import java.util.Arrays;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.util.Comparator;
public class Autocomplete {
public Term[] terms;
public Autocomplete(Term[] terms) {
if (terms == null) {
throw new java.lang.NullPointerException();
}
this.terms = terms.clone();
Arrays.sort(this.terms);
}
public Term[] allMatches(String prefix) {
if (prefix == null) {
throw new java.lang.NullPointerException();
}
Term theTerm = new Term(prefix, 0);
int start = BinarySearchDeluxe.firstIndexOf(terms, theTerm, Term.byPrefixOrder(prefix.length()));
int end = BinarySearchDeluxe.lastIndexOf(terms, theTerm, Term.byPrefixOrder(prefix.length()));
int count = start;
System.out.println("Start: " + start + " End: " + end);
if (start == -1 || end == -1) {
// System.out.println("PREFIX: " + prefix);
throw new java.lang.NullPointerException();
} // Needed?
Term[] matches = new Term[end - start + 1];
//matches = Arrays.copyOfRange(terms, start, end);
for (int i = 0; i < end - start; i++) {
matches[i] = this.terms[count];
count++;
}
Arrays.sort(matches, Term.byReverseWeightOrder());
System.out.println("Finished allmatches");
return matches;
}
public int numberOfMatches(String prefix) {
if (prefix == null) {
throw new java.lang.NullPointerException();
}
Term theTerm = new Term(prefix, 0);
int start = BinarySearchDeluxe.firstIndexOf(terms, theTerm, Term.byPrefixOrder(prefix.length()));
int end = BinarySearchDeluxe.lastIndexOf(terms, theTerm, Term.byPrefixOrder(prefix.length()));
System.out.println("Finished numberMatches");
return end - start + 1; // +1 needed?
}
public static void main(String[] args) throws IOException {
// Read the terms from the file
Scanner in = new Scanner(new File("wiktionary.txt"));
int N = in.nextInt(); // Number of terms in file
Term[] terms = new Term[N];
for (int i = 0; i < N; i++) {
long weight = in.nextLong(); // read the next weight
String query = in.nextLine(); // read the next query
terms[i] = new Term(query.replaceFirst("\t",""), weight); // construct the term
}
Scanner ip = new Scanner(System.in);
// TO DO: Data Validation Here
int k;
do {
System.out.println("Enter how many matching terms do you want to see:");
k = ip.nextInt();
} while (k < 1 || k > N);
Autocomplete autocomplete = new Autocomplete(terms);
// TO DO: Keep asking the user to enter the prefix and show results till user quits
boolean cont = true;
do {
// Read in queries from standard input and print out the top k matching terms
System.out.println("Enter the term you are searching for. Enter * to exit");
String prefix = ip.next();
if (prefix.equals("*")) {
cont = false;
break;
}
Term[] results = autocomplete.allMatches(prefix);
System.out.println(results.length);
for(int i = 0; i < Math.min(k,results.length); i++)
System.out.println(results[i].toString());
} while(cont);
System.out.println("Done!");
}
}
I apologize for the sloppy code, I have been pulling my hair out for awhile now and keep forgetting to clean it up.
Two examples:
Example 1:
int k = 2;
String prefix = "auto";
Enter how many matching terms do you want to see:
2
Enter the term you are searching for. Enter * to exit
auto
619695 automobile
424997 automatic
Example 2:
int k = 5;
String prefix = "the";
Enter how many matching terms do you want to see:
5
Enter the term you are searching for. Enter * to exit
the
5627187200 the
334039800 they
282026500 their
250991700 them
196120000 there

Breadth first search cycling in rush hour solver when no solution is available

I'm trying to implement a rush hour solving algorithm using breadth first search to traverse a graph of the different paths, stopping when a solution has been found.
After numerous tests, I've come across a problem I have no idea how to solve. When there is a solution, the algorithm works very well, but when none can be found, it just endlessly cycles because it recreates "nodes" that contain the same information as older ones, instead of returning towards the older ones if the information is the same. How would I be able to make it stop when it figures out there are no more possibilities?
Here are the classes I am using for the solver:
This is the main class RushHour, the one I run.
package rush.hour;
import java.io.*;
import java.util.List;
import java.util.ArrayList;
public class RushHour
{
public static void main(String[] args)
{
String fileName = "Parking.txt";
String line;
int lineNumber = 0;
int numOfCars;
List<Car> carsList = new ArrayList<>();
try
{
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null)
{
lineNumber += 1;
// System.out.println(lineNumber);
System.out.println(line);
if (lineNumber == 15)
numOfCars = Integer.parseInt(
line.substring(line.length() - 1)) + 1;
if (lineNumber >= 17)
{
String[] splitLine = line.split(":");
char[] coordinates = splitLine[1].toCharArray();
int a = coordinates[3] - 48;
int b = coordinates[5] - 48;
int c = coordinates[10] - 48;
int d = coordinates[12] - 48;
Car car = new Car(lineNumber - 17, a, b, c, d);
carsList.add(car);
}
}
Parking parking = new Parking(carsList);
Graph graph = new Graph(parking);
List<Parking> sol = graph.bfs();
System.out.println("\n------------- Solution -------------");
for (Parking sols: sol)
{ // L = Left, D = Down, R = Right, U = Up
System.out.println(sols);
}
}
catch(FileNotFoundException ex)
{ex.printStackTrace();}
catch(IOException ex)
{ex.printStackTrace();}
}
}
And this is the "graph" that uses the adapted BFS
package rush.hour;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import java.util.Queue;
public class Graph
{
Parking posDepart;
public Graph(Parking parking)
{
posDepart = parking;
}
public List<Parking> bfs()
{
List<Parking> res = new ArrayList<>();
Queue<Parking> queue = new LinkedList<>();
queue.add(posDepart);
while (!queue.isEmpty())
{
Parking next = queue.remove();
if (next.isFinal())
{
res.add(next);
return next.getPath();
}
next.setChildren();
for (Parking child : next.children) {
queue.add(child);
}
}
return res;
}
}
This is the Graph's "node", it represents the disposition of the cars on the board
package rush.hour;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class Parking
{
Parking father = null;
List<Car> carsList = new ArrayList<>();
boolean visited = false;
List<Parking> children = new ArrayList<>();
List<Character> move = new ArrayList<>();
public Parking(List<Car> list)
{
for (Car car: list)
carsList.add(car.clone());
}
public Parking(Parking vader,List<Character> mov)
{
for (Car car: vader.carsList)
carsList.add(car.clone());
father = vader;
move = mov;
}
public void getNextParkings(List<List<Character>> moves)
{
children.clear();
for (int i = 0; i < moves.size(); ++i)
{
List<Character> info = moves.get(i);
Parking nextParking = new Parking(this, info);
nextParking.carsList.get(info.get(0) - 48).move(info.get(1));
children.add(nextParking);
}
}
#Override
public String toString()
{
String res = "";
if (!move.isEmpty())
{
res += "Move made to reach this parking:";
res += move;
res += "\n";
}
for (Car car : carsList)
res += car.toString();
return res;
}
public boolean isFinal()
{
return carsList.get(0).isFinal();
}
public void setChildren()
{
if (children.isEmpty())
{
List<List<Character>> moves = getPossibleMoves();
getNextParkings(moves);
}
}
public List<List<Character>> getPossibleMoves()
{
List<List<Character>> res = new ArrayList<>();
List<List<Character>> moves;
for (Car car : carsList)
{
moves = car.getPossibleMoves();
for (int i = 0; i < moves.size(); ++i)
{
List<Character> move = moves.get(i);
if (!hasNeighbour(move.get(0),
move.get(1) - 48, move.get(2) - 48))
{
List<Character> foo = new ArrayList<>(2);
foo.add(car.getNumber());
foo.add(move.get(0));
res.add(foo);
}
}
}
return res;
}
public boolean hasNeighbour(char direction, int x, int y)
{
for (Car car : carsList)
{
if (direction == 'U')
if ((car.getX1() == x - 1 && car.getY1() == y) ||
(car.getX2() == x - 1 && car.getY2() == y))
return true;
if (direction == 'D')
if ((car.getX1() == x + 1 && car.getY1() == y) ||
(car.getX2() == x + 1 && car.getY2() == y))
return true;
if (direction == 'L')
if ((car.getX1() == x && car.getY1() == y - 1) ||
(car.getX2() == x && car.getY2() == y - 1))
return true;
if (direction == 'R')
if ((car.getX1() == x && car.getY1() == y + 1) ||
(car.getX2() == x && car.getY2() == y + 1))
return true;
}
return false;
}
public List<Parking> getPath()
{
Parking temp_father;
List<Parking> path = new LinkedList<>();
path.add(this);
temp_father = this.father;
while (temp_father != null)
{
path.add(0, temp_father);
temp_father = temp_father.father;
}
return path;
}
}
And finally the Car class, which probably isn't very important to the problem but still
package rush.hour;
import java.util.List;
import java.util.ArrayList;
public class Car
{
char orientation;
int carNumber;
int x1;
int x2;
int y1;
int y2;
#Override
public String toString()
{
return "Car n° : " + (carNumber) + " : [(" + (x1) + ", " + y1 + ')' +
" (" + (x2) + ", " + y2 + ")]" + "\n";
}
public Car clone()
{
Car c = new Car(carNumber, x1, y1, x2, y2);
return c;
}
public Car(int n, int a, int b, int c, int d)
{
carNumber = n;
if (a <= c)
{
x1 = a;
x2 = c;
}
else
{
x1 = c;
x2 = a;
}
if (b <= d)
{
y1 = b;
y2 = d;
}
else
{
y1 = d;
y2 = b;
}
if (x1 == x2)
orientation = 'H';
else
orientation = 'V';
}
public char getNumber()
{
return Integer.toString(carNumber).charAt(0);
}
public int getX1()
{
return x1;
}
public int getX2()
{
return x2;
}
public int getY1()
{
return y1;
}
public int getY2()
{
return y2;
}
public void move(char direction)
{
if (direction == 'U')
{
--x1;
--x2;
}
if (direction == 'D')
{
++x1;
++x2;
}
if (direction == 'L')
{
--y1;
--y2;
}
if (direction == 'R')
{
++y1;
++y2;
}
}
public boolean isFinal()
{
return y2 == 4 && carNumber == 0;
}
public List<List<Character>> getPossibleMoves()
{
List<List<Character>> res = new ArrayList<>();
if (orientation == 'H')
{
if (y1 != 0)
{
List<Character> foo = new ArrayList<>(2);
foo.add('L');
foo.add(Integer.toString(x1).charAt(0));
foo.add(Integer.toString(y1).charAt(0));
res.add(foo);
}
if (y2 != 4)
{
List<Character> foo = new ArrayList<>(2);
foo.add('R');
foo.add(Integer.toString(x2).charAt(0));
foo.add(Integer.toString(y2).charAt(0));
res.add(foo);
}
}
else
{
if (x1 != 0)
{
List<Character> foo = new ArrayList<>(2);
foo.add('U');
foo.add(Integer.toString(x1).charAt(0));
foo.add(Integer.toString(y1).charAt(0));
res.add(foo);
}
if (x2 != 4)
{
List<Character> foo = new ArrayList<>(2);
foo.add('D');
foo.add(Integer.toString(x2).charAt(0));
foo.add(Integer.toString(y2).charAt(0));
res.add(foo);
}
}
return res;
}
}
Excuse me if I've made some blatant styling/coding mistakes, I am more used to coding in Python/C++. Would there be a way to make this work?
You need to use some type of data structure to keep track of paths already traversed. A hash table would be ideal and would provide a worst case of O(n) depending upon implementation. Not very familiar with Java but in C++ I would use std::unordered_map with the first field being a state of your board and the second being the number of moves at that point. I have implemented this algorithm before, and that's the approach I took. Incredibly fast.

Why is method A flawed compared to B for UVa online judge 100 (3n+1)?

Simply changing from Swap Method A to Swap Method B, the UVa judge goes from 'Wrong Answer' to 'Accepted'. Why is that? I thank you all in advance for your responses.
import java.io.IOException;
import java.util.StringTokenizer;
/**
* #author Coder47
* Another solution to 3n+1 (UVa ID: 100)
*/
class Main {
public static int[] cache = new int[1000000];
static String ReadLn (int maxLg) // utility function to read from stdin
{
byte lin[] = new byte [maxLg];
int lg = 0, car = -1;
try
{
while (lg < maxLg)
{
car = System.in.read();
if ((car < 0) || (car == '\n')) break;
lin [lg++] += car;
}
}
catch (IOException e)
{
return (null);
}
if ((car < 0) && (lg == 0)) return (null); // eof
return (new String (lin, 0, lg));
}
public static void main(String[] args) {
Main myWork = new Main(); // create a dynamic instance
myWork.Begin(); // the true entry point
}
void Begin() {
String input;
StringTokenizer idata;
// corresponds to swap method A
int a, b, temp, cycle, cycleMax;
// corresponds to swap method B
// int a, b, min, max, cycle, cycleMax;
while ((input = Main.ReadLn(255)) != null)
{
idata = new StringTokenizer(input);
a = Integer.parseInt(idata.nextToken());
b = Integer.parseInt(idata.nextToken());
// swap method A
if (b < a) {
temp = a;
a = b;
b = temp;
}
// swap method B
// min = Math.min(a, b);
// max = Math.max(a, b);
cycleMax = 0;
// corresponds to swap method A
for (int i = a; i <= b; i++)
// corresponds to swap method B
// for ( int i = min; i <= max; i++)
{
cycle = calculateCycle(i);
if (cycle > cycleMax) {
cycleMax = cycle;
}
}
System.out.println (a + " " + b + " " + cycleMax);
}
}
public int calculateCycle(int n) {
return calculateCycleHelper(n, 1);
}
public int calculateCycleHelper(int n, int cycleNum) {
if (n == 1) {
return cycleNum;
} else {
return calculateCycleHelper(next(n), cycleNum + 1);
}
}
public int next(int n) {
if (n % 2 == 0) {
n = n/2;
}
else {
n = 3*n+1;
}
return n;
}
}
Please overlook the efficiency and other related issues of the code, since that is not the issue here.
It's because if (a < b) says the opposite of what you want. You need to swap the elements if b < a, because in the for loop
for (int i = a; i <= b; i++)
you want a to be less than b.
EDIT
For your updated question, the answer is that it's because the judge is checking the output. If you swap a and b the output from the line
System.out.println (a + " " + b + " " + cycleMax);
changes, so the judge does not accept it.

Categories

Resources