I have 6 text fields (number1-6) in JavaFX and another textfield named "textfieldLF" that is the number that the user is searching for. I am trying to make a JavaFX program for searching between 6 different numbers using the binary search algorithm, but for some reason it's not working.
I used the algorithm from Wikipedia. I checked the indexes of arrays to make sure they are right, because the first if condition and statement works perfectly alone. It's only when it wants to determine what change it has to make to the midpoint that I think it has a problem in.
The code:
#FXML
private void handleButtonAction(ActionEvent event) {
// First and last indexes declaration
int imin = 1;
int imax = 6;
// Declare array for user inputs
String[] NumbersArray = {number1.getText(), number2.getText(), number3.getText(), number4.getText(), number5.getText(), number6.getText()};
// What to find? Get input from user
String ToFind = textfieldLF.getText();
// Match Index
String MatchID;
// Match Found? Boolean
boolean MatchFound = false;
// Find midpoint
int imid = (int) ceil((double)((imin + imax) / 2));
while (MatchFound = false)
{
// Try to find match in midpoint position
if (NumbersArray[imid].equals(ToFind))
{
System.out.println("Match #" + (imid + 1));
MatchFound = true;
} else if(Integer.parseInt(NumbersArray[imid]) < Integer.parseInt(ToFind)) {
imin = imid + 1;
MatchFound = false;
} else {
imax = imid - 1;
MatchFound = false;
}
}
}
I would appreciate any help
Thanks
It doesn't work, since you never change imid. It's also no binary search, since doesn't reduce the index range by half every step.
Move
int imid = (int) ceil((double)((imin + imax) / 2));
inside the loop(to the beginning of the loop body). You still have to add a way to exit the loop.
Also your start indices are wrong. The index range of your array is 0-5 and not 1-6.
Related
iv made a method to check if a given number is symmetric or not.
-the method is based on the idea that the given number is an array .
-i gave the methood 4 deifferent parameters- numberLength , middle , point1,point2(both pointing at a certain digit in the number(as an array))
-although wrote the code correctly , and it works when im initializing a specific array ,
i dont know how to use the method for a given number .
How can i set this Method - with parameter (int number) , so i can chek on the given number.
Thank you A lot
update** i added the code :
public boolean isSymmetric(int num){
int digits;
int[] number;
number = new int[num];
int length = number.length;
int mid;
if(length%2 == 0) //
{
mid = length/2;
}else {
mid = length/2+1;
}
int pointer1 =0;
int pointer2 = mid;
while(pointer1<mid && pointer2 < length)
{
if(number[pointer1] == number[pointer2])
{
pointer1=pointer1+1;
pointer2=pointer2+1;
}
else
System.out.println("number is not symmetric");
return false;
}
System.out.println("number is symmetric");
return true;
}
The easiest way to check if number symmetric or not is to map it to String::class, just like this:
// Your input number
Integer maybeSymmetricNumber = 12321;
String str = String.valueOf(maybeSymmetricNumber), reverseStr = "";
int strLength = str.length();
for (int i = (strLength - 1); i >=0; --i) {
reverseStr = reverseStr + str.charAt(i);
}
if (str.toLowerCase().equals(reverseStr.toLowerCase())) {
System.out.println(str + " is a symmetric number.");
}
else {
System.out.println(str + " is not a symmetric number.");
}
First, here is a method to convert your number to an array of ints.
it works by using the Math.log10 to compute the exponent of 10 for that number.
e.g. Math.log10(1234) = 3.xxx. So convert to an int and add 1 to get 4.
e.g. Math.log10(1000) = 3 so do the same thing.
then use that number to create an array of proper size.
and use the remainder(%) and division(/) operators to populate it.
then return the array.
public static int[] toArray(int number) {
number = Math.abs(number);
int[] arr = new int[(int) Math.log10(number)+1];
int i = 0;
while (number > 0) {
arr[i++] = number%10;
number/=10;
}
return arr;
}
Unfortunately, your method doesn't work properly as it always returns false. This is because of missing {} around the following.
else
System.out.println("number is not symmetric");
return false;
But it still doesn't process all values properly. Try 1234321 and 112211. They both return false but are symmetric. This is because pointer1 starts at 0 and pointer2 starts at mid and they are both incremented by 1.
I suggest you start pointer2 at length-1, going from outside in toward mid. This should then solve the issue (with a little debugging of course).
This is my current search method:
public static int search(int[] array, int numero) {
int start = 0;
int end = array.length - 1;
int center;
while (start <= end) {
center = (start + end) / 2;
if (array[center] == numero) {
return center;
} else if (array[center] < numero) {
start = center + 1;
} else {
end = center - 1;
}
}
return -1;
}
It searches from user input numero into a previously bubble sorted Array that's found in the Main method.
What I'm trying to figure out is how to print ALL of the coincidences found in the array, and not just the first one found.
I was thinking about adding results to a List and then returning that to Main, but as I tried that an endless loop happened at the first result found, causing it to add itself to the List repeatedly until the program crashes.
Assuming that you know the basic theory behind binary searches, separate it into 3 steps.
Search using binary search methods.
once a match is found, scan up from that point, until you find a non matching element.
Scan down, adding to a result list, until you find a non
matching element.
If you don't need to care about occurrence order, you could combine steps 2 and 3 and just scan up adding to the list, and scan down adding to the list, since due to the sorting, everything you hit is guaranteed to match until it doesn't.
If you do care about occurrence order, step 2 could be optimised by jumping ahead and checking, and writing a modified binary search that searches for a transition of matching/notmatching instead of a match.
This could be further optimised by keeping statistics or profiling, to find the perfect jump distance, or basing it off of the last up-most check.
actually it's easy because the list is already sorted, the numbers you expect to find are adjacent.
just like Ryan's answer, I'll put some code
public static List<Integer> searchAll (int[] array, int numero){
int firstMatchIndex = search( array, numero);
List<Integer> results = new ArrayList<Integer>():
results.add(firstMatchIndex);
boolean left = true;
while( left){
int i = firstMatchIndex - 1;
if(i<0 || array[i] != numero){
left = false;
}else{
results.add(i);
}
}
boolean right = true;
while( right){
int i = firstMatchIndex + 1;
if(i>array.length || array[i] != numero){
right = false;
}else{
results.add(i);
}
}
}
Sorry; I wasn't sure how to title this, so the question is a little shoddy.
I'm finishing up a small program for an extra credit assignment, and there are two very small details that are ruining it.
The purpose of the program is to read some data, divide it into a customer number and a flight number, then determine if the flight is suitable. I have an image screenshot of the file here, because it's a bit of a hassle to explain in short detail. Sorry for having to send a link.
Here is my code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class prog475a {
static Scanner inFile = null;
public static void main(String[] args) {
// make the flight plan array
boolean[][] flightPlan = new boolean[7][7];
// fill the true
flightPlan[1][2]=true;
flightPlan[1][3]=true;
flightPlan[1][6]=true;
flightPlan[2][1]=true;
flightPlan[2][3]=true;
flightPlan[2][6]=true;
flightPlan[3][4]=true;
flightPlan[4][2]=true;
flightPlan[4][5]=true;
flightPlan[4][6]=true;
flightPlan[5][2]=true;
flightPlan[5][4]=true;
flightPlan[6][2]=true;
flightPlan[6][5]=true;
// read for file
try {
// create scanner to read file
inFile = new Scanner(new File ("prog475a.dat"));
} catch (FileNotFoundException e) {
System.out.println("File not found!");
System.exit(0);
}
/*
* read customer number
* method to translate flight plan into coordinates
*
*/
int customer = 0;
int flight = 0;
while (inFile.hasNext()) {
customer = inFile.nextInt();
flight = inFile.nextInt();
translator(customer, flight, flightPlan);
}
}
public static void translator(int c, int f, boolean[][] fl) {
System.out.println("Customer Number " + c + "\tFlight Plan " + f);
// change int f into individual numbers?
int[] coo = new int[6];
int a = 10000;
// boolean ok = true;
for (int x = 0; x < coo.length - 1; x ++) {
coo[x] = (f / a) % 10;
a /= 10;
}
// test if your array has all the right numbers
// for (int x = 0; x < coo.length - 1; x++) {
//
// System.out.println(coo[x]);
//
// }
// instantiate variables to act as parameters to navigate boolean
int n = 0; // the actual coordinate
int p = 0; // placeholders
int q = 0;
while (q < coo.length) { // q has to end when it equals length of coo
p = coo[n];
q = coo[n + 1];
if (fl[p][q]) {
System.out.println(p + "\t" + q + "\t" + "Available");
n++;
} else {
System.out.println(p + "\t" + q + "\t" + "Unavailable\t Flight Plan invalid");
break; // if unavailable, break
}
}
System.out.println("");
}
}
Here is the data:
10123 13426
11305 62000
13427 42320
18211 34212
19006 65426
20831 52500
21475 32000
22138 13424
24105 65231
24216 34250
25009 43621
The issue I am having is very simple-- my program works perfectly fine, except I've tried various different ways to print "Flight Plan is Valid" at the end of the program to no avail. I've honestly done everything; I've added an extra if/else statement to account for when q = coo[coo.length - 1], tried to append it on the outside of the while-loop. I just can't get it to work.
Another issue I'm having is, for flight 34212, an extra line is arbitrarily printed out, indicating a flight from 2 to 0, which doesn't exist in the number at all. It's the only flight that's having this problem.
I'm really not sure what I'm doing wrong, and I hope that someone can give some advice on how to fix my code to make sure these errors are dealt with somewhat. Again, thank you for your time. I'm a bit of an arse, so I've spent a really long time trying to figure out what I was doing wrong, and I feel a bit frustrated.
Okay there are a lot of logical errors in the translator function, so I'll just list them and then provide some fixed code. However since this sounds like this is for a course, DO NOT JUST COPY AND PASTE. I think actually walking through some of the errors in your program would be highly beneficial.
The length of coo is 6. This may be intentional, but is unnecessary.
When you fill coo. You only fill 5 out of the 6 spots.
You never change the ok variable.
You never use the n variable.
I think in the first part of the while loop, comparing with q is a typo/logical mistake, I think you meant to compare with n.
Using both a check in the while loop for ok, and a break statement is redundant.
You didn't add in an if to do run code depending on the state of ok.
With all these errors, I think that you should definitely ask your teacher or whatever with help, because this is a lot to change in one post. Either way, I hope you don't misuse this code ;). Here's the new translate function:
public static void translator(int c, int f, boolean[][] fl) {
System.out.println("Customer Number " + c + " Flight Plan " + f);
int[] coo = new int[5];
int a = 10000;
for (int x = 0; x < coo.length; x++) {
coo[x] = (f / a) % 10;
a /= 10;
}
for (int x = 0; x < coo.length - 1; x++) {
int p = coo[x];
int q = coo[x + 1];
if (fl[p][q]) {
System.out.print(p + "\t" + q + "\tAvailable");
if (x == coo.length - 2) {
System.out.print("\tFlight Plan is Valid");
}
System.out.println();
}
else {
System.out.println(p + "\t" + q + "\tUnavailable\tFlight Plan is Invalid");
break;
}
}
}
Explanation: I used basically the same code until the last for loop except that I changed the length of coo to 5 and made the first for loop run 5 times. You will also notice that I removed ok because it was redundant. This is because once I have a bad flight, I just print the invalid flight message and then break. There's no need of a variable in there. For the last loop you can see, I use a for loop instead of a while loop. Why did I do this? Pretty much just cause of taste. I typically use a for loop when I know how many times I am going to loop, and a while when the number isn't clear cut. Also, in this case, since you were using a counting variable n anyways, that's just the kind of thing a for loop is good for (haha). The rest of the code is pretty self-explanatory. If the flight is valid, you do the print for that. And if it's the last loop, hence if (x == coo.length - 2) (this checks that its the last loop), then you print that the flight plan is valid. Otherwise you print it's not valid and you break. I have done a little testing with this code, and it works so far. I hope this helps you!
Im working on a project in which it reads book titles in from a .txt file and puts them into an arraylist, then the arraylist is converted to an array, The user enters a number which is the books reference number, then it does a linear search and a binary search to find that book. Im just having a trouble with the code for the binary search,as i have almost no idea how to do it, heres what I have:
private void FindItActionPerformed(java.awt.event.ActionEvent evt) {
String input;
input = Input.getText();
for(int i=0; i<bookList.length; i++){
if (bookList[i].referenceNumber.equals(input)){
Output1.setText("The Book is " + bookList[i].title);
}
}
Above is the code for the linear search, which works fine. Below is what i think i need for the binary search but again, i am not sure and cannot figure it out.
int right = 0, left = bookList.length;
while(right<= left){
int middle = (right + left)/2;
if( bookList[middle].referenceNumber.equals(input)){
Output2.setText("The book is " + bookList[middle].title);
}
}
}
Here is the class and the arrays
public class Book{
String referenceNumber, title;
public Book(String _referenceNumber, String _title){
referenceNumber = _referenceNumber;
title = _title;
}
}
ArrayList <Book> Books = new ArrayList <Book> ();
Book [] bookList;
Thanks for any help you may be able to offer, This is a bit tricky for me.
I had problems when I was learning to code binary search aswell. The first thing you should know is that you do not have to do a binary search and a linear search, you only need to do one or the other. Also to do a binary search you need to sort your array ex int[] array = {1,2,3,4,5,6,7,8,9,10};
What a binary search does is it looks at the middle element in the array and tests to see if the element is greater or less than the key. If it is less everything less then the middle element is ignored (same for bigger just everything bigger is thrown away). Then a new middle element is selected and half is thrown away, and this is done until the key is found. Below is the code for sorting a int array, you would need to modify it to return books (string? or the class book you may have written)
public static boolean binarySearch(int[] array, int key){
int partition = 0;
int right = array.length - 1;
boolean found = false;
int left = 0;
while(! found && left <= right){
if(array[partition] == key){
found = true;
}
if(array[partition] > key){//key less
right = partition - 1;
partition = (right + left) / 2;
}
if(array[partition] < key){//key greater
left = partition + 1;
partition = (left + right) / 2;
}
}
return found;
}
Also here is some code for sorting an array of ints. This is a bubble sort so it is slow On^2
public int[] bubbleSort(int[] array){
int temp;
boolean keepGoing = true;
while(keepGoing == true){
keepGoing = false;
for(int i=0; i < array.length - 1; i++){
if(array[i] > array [i + 1]){ //if i < i + 1 means greatest to smallest if
// if i > i + 1 means smallest to greatest
swap(array, i, i + 1);
keepGoing = true;
}
}
}
return array;
}
The code is simple would have to modify it to sort your books the method swap is below
public int[] swap(int[] array, int i, int j){
int temp = 0;
temp = array[i];
array[i] = array[j];
array[j] = temp;
return array;
}
There is nice visualisation of binary search at
http://balance3e.com/Ch8/search.html
For example try to enter FL and watch the algorithm looking for it step by step.
You will get it quickly :)
It works like looking up a word in a dictionary... You are looking for "cat" for example,
so you open your dictionary in half and see word "man" this is lexicographicaly bigger than "cat", so you will be looking to the left from "man" = in first half of the dictionary...
Then you only repeat this process of dividing into smaller parts until you find what you were looking for.
I've created a Sudoku solver that will solve a Sudoku as a human might- by checking possibilities + definite values in squares corresponding to the square being checked.
(Source: http://pastebin.com/KVrXUDBF)
However, I would like to create a random Sudoku generator (from a blank grid), and so have decided to use a backtracking algorithm. I understand the concept of backtracking, but am confused about one thing:
How do I know which previous node to return to (and change) once I know a certain solution is not allowed?
Should I simply return to the previous node and cycle through all possibilities? (And then if this yields no correct answers, return to the value before, etc.). This seems like a viable method, but also quite inefficient. Is this the correct way of implementing a backtracking method or is there a better way to go about it?
Thanks in advance.
More can be found about backtracking here: http://en.wikipedia.org/wiki/Backtracking
Sudoku Puzzle can be reduced to graph coloring problem which can be solved using simple backtracking like assigning colors to node (1-9) till the there is no violation that all directly connected nodes have no same color.
Constructing Graph from Sudoku : -
There is an direct edge between two grid points if they are in same
row or column or square.
Backtracking :-
Assign one color (1-9) to node
Check if there is no other directly connected node with same color
If valid color move to next node.
else change the color and recheck.
If all color exhausted backtrack to previous node.
Do recursion till all nodes are color.
Once You are done with it you can start removing numbers from the grid at random till you think the problem is unsolvable if any more numbers are removed.
A simple way to generate random Sudoku is that
1) generate a random completing Sudoku, that is, generate random Sudoku no square is blank.
2) Remove numbers from squares of 1).
3) Solve Sudoku of 2). If there are many solutions, then add a number removed at 2).
If there are still many solutions, then repeat 3).
1) sample source code:
public int[][] generateRandomCompleteSudoku() {
int[][] sudoku = new int[10];
for(int i = 1; i <= 9; i++) {
sudoku[i] = new int[10];
Arrays.fill(sudoku[i], 0);
}
generateRandomCompleteSudoku(sudoku, 1, 1);
return sudoku;
}
private boolean generateRandomCompleteSudoku(int[][] sudoku, int x, int y) {
if(x > 9) {
x = 1;
y++;
}
//sudoku of the argument is completing sudoku.
//so return true
if(y > 9) {
return true;
}
// enumerate the possible numbers of the pos(x,y).
List<Integer> possibleNumbers = new ArrayList<Integer>();
for(int i = 1; i <= 9; i++) {
boolean possible = true;
//check i is a possible number.
//check there isn't i in the raw of y .
for(int j = 1; j <= x - 1; j++) {
if(sudoku[j][y] == i) {
possible = false;
break;
}
}
//check there isn't i in the column of x(omitted).
//check there isn't i in the group of x,y(omitted).
if(possible) {
possibleNumbers.add(i);
}
}
//sudoku is wrong so return false.(There is no solution of sudoku)
if(possibleNumbers.size() <= 0) {
return false;
}
Collections.shuffle(possibleNumbers);// This gives sudoku randomness.
for(Integer possibleNumber : possibleNumbers) {
sudoku[x][y] = possibleNumber;
// a sudoku is generated, so return true
if(generateRandomCompleteSudoku(sudoku, x + 1, y)) {
return true;
}
}
// No sudoku is generated, so return false
return false;
}
For a backtracking solution, the first step is to define the state. So for this problem, I think the most straightforward way is (x,y, blank , num) with x , y is the position of the current state, blank is the number of blank position left, and num is the value you want to fill in that position (from 0 to 9 and 0 means blank).
And the return type should be boolean, which determine whether the move is valid or not (which means is there any valid solution for this move).
So, the state transition is column by column, row by row: x, y to x , (y + 1) or x , y to (x + 1), 0.
Similarly, the blank will be from a -> a - 1-> ... 0.
We have a draft solution here:
public boolean move(int x, int y, int blank, int num, int[][]sudoku){
sudoku[x][y] = num;
//checking condition and return if x,y is the last position, code omitted
if(y == sudoku[x].length){
x++;
y = 0;
}else{
y++;
}
for(int i = 1; i < 10; i++){
if(move(x,y,blank,i,sudoku){//Backtrack here
return true;
}
}
if(blank > 0){
if(move(x,y,blank - 1, 0, sudoku){//Backtrack here
return true;
}
}
return false;
}
So when ever there is a false return from the current state, it will backtrack to the last state , and the last state will continue to check for the next num until it find a correct solution (or return false).