I am currently writing some code that is supposed to solve a sudoku puzzle for an assignment. The code I currently have written should be isolating the row and column where we need to insert a value, and then testing values 1-9 to see which ones already appear in either the row or the column. The problem is, the binary search is not detecting some numbers and I do not know why. Here is my code. All you need to no is that A.grid is an array containing the unsolved puzzle, and the set value method is one that I have written to plug a value into the array with the fromat setValue(xLocation, yLocation, value)
int currentVal = 0;
int j;
int [] currentRow = new int [9];
int [] currentCol = new int [9];
for (i = 0; i<9 ; i++) {
for (j = 0; j<9 ; j++){
currentVal=A.grid[i][j];
boolean keepGoing = true;
int newVal=1;
if (currentVal==0) {
for( int k = 0; k < 9; k++)
{currentCol[k] = A.grid[k][j];
}
currentRow = A.grid[i];
log(Arrays.toString(currentRow));
log(Arrays.toString(currentCol));
log("");
while (keepGoing) {
int indexRow=Arrays.binarySearch(currentRow, newVal);
int indexCol=Arrays.binarySearch(currentCol, newVal);
log(indexRow);
log(indexCol);
log("");
if (indexRow<0 && indexCol<0) {
keepGoing = false;
}
newVal++;
}
A.setValue(j, i, newVal-1);
Thanks!
I'm not sure if this is your only problem, but you need to make sure that your arrays are sorted if you're going to use a binary search algorithm. Otherwise, you're going to get garbage results.
That being said, why do you think you need to do a binary search on arrays with only 9 elements? It would very likely be faster just to do the search yourself manually and forget about using a binary search at all.
int indexRow = -1;
for (int z = 0; z < 9; ++z)
{
if (currentRow[z] == newVal)
{
indexRow = z;
break;
}
}
// indexRow is now the index of newVal in currentRow
For that matter, it would probably be clearer if that whole routine was wrapped up in a separate function:
int search(int[] source, int val)
{
for (int z = 0; z < source.length; ++z)
{
if (source[z] == val)
{
// z is the position of val in the source array
return z;
}
}
// Return -1 if val is not present
return -1;
}
You would then replace your binarySearch() calls with calls to search().
I hope this helps!
Related
I've array of N integers in not-decreasing order. Need to find any specific element in array, if found then return the position of that array otherwise returns -1
public static int find(int[] v, int bb) {
int N = v.length;
if (N == 0) {
return -1;
}
int l = 0;
int r = N - 1;
while (l < r) {
int m = (l + r) / 2;
if (v[m] > bb) {
r = m - 1;
} else {
l = m;
}
}
if (v[l] == bb) {
return l;
}
return -1;
}
there's one bug I need to find out, which is about that this will not work for some inputs. I gave up.
Any suggestions ?
If you want to locate the index of the first specific numerical element within the array then you can do something like this:
public static int find(int[] v, int bb) {
int found = -1;
for (int i = 0; i < v.length; i++) {
if (v[i] == bb) {
found = i;
break;
}
}
return found;
}
If there are multiple values in the array that are the same as bb then the method above will only provide the first one found. If you want to return the index values for all values of bb found in the array then you would want to return an array of index values, for example:
public static int[] find(int[] v, int bb) {
List<Integer> list = new ArrayList<>();
int found = -1;
for (int i = 0; i < v.length; i++) {
if (v[i] == bb) {
found = i;
list.add(found);
}
}
if (found == -1) {
list.add(found);
}
return list.stream().mapToInt(d -> d).toArray();
}
The List Interface is used in the above example because it can grow dynamically since we have no idea how many values of bb are actually going to be contained within the Array. The List is converted to an int[] array before it is returned.
First of all, I think you should name your variables with a proper name, and not just with a single characters, it'll make your code easier to understand.
Second, you are using a binary serach algorithm for increasing ordered arrays, if you want that code to work correctly you have to use an increasing ordered array. Here you have a binary search method that should work with increasing ordered arrays:
public static int binarySeacrh(int [] list, int numSearched) {
boolean found = false;
int start = 0;
int end = list.length - 1;
int pos = -1;
while(start <= end && !found){
int middle=((start + end) / 2);
if (numSearched == list[middle]){
found = true;
pos = middle;
}
else if (list[middle] < numSearched){
start = middle + 1;
}else{
end = middle - 1;
}
}
return pos;
}
If you want to search for the position in a unordered array, you must use another type of serach algorithm or order the array first.
I'm trying to check whether an array of arrays has any duplicate values. The end goal would be an if statement saying:
if (arr does NOT have duplicate values) {continue code}
int [][] arr = new int[3][2];
int [] x = new int[1];
arr[0][0] = 1;
arr[0][1] = 1;
arr[1][0] = 1;
arr[1][1] = 2;
arr[2][0] = 1;
arr[2][1] = 2;
x = arr.getUnique(); /I assume it'll use getUnique() but I can't even get that to work
Any help would be awesome! Thanks
Java has a HashSet you can use to have a collection without duplicates.
Find a way to convert your array into a HashSet and compare the number of their elements. If they have the same number of elements, each element in your array is unique, if the HashSet is smaller, it means some duplicates have been removed.
You could create a helper function of your own like this:
private static boolean arrayHasDuplicates(int[][] arr) {
for (int i = 0; i < arr.length; i++)
{
for (int y = 0; y < arr.length; y++)
{
if (arr[i].length != arr[y].length) continue;
if (i == y) continue;
boolean same = true;
for (int x = 0; x < arr[y].length; x++)
{
if (arr[i][x] != arr[y][x]) {
same = false;
break;
}
}
if (same) return same;
}
}
return false;
}
I'm trying to make a method that counts the number of unique elements in an array. For example, if the array contains [1,2,3,4,5,1,5] there are 3 unique elements and my method should return the number 3.
This is what I´ve got so far:
static int numberOfUniqueIntegers(int[] number, int len) {
int unique = 0;
for (int i = 0; i < len; i++){
int j;
for (j = 0; j < i; j ++) {
if (number[i] == number[j]) {
break;
}
}
if (i == j);
unique++;
}
return unique;
}
The method takes in the array number and an integer len (which is the length of the array).
But in this case: [1,2,3,4,5,1,5] my method would return 5, instead of 3. I somehow need to check if the number has been repeated before, and if not unique++.
You can create a frequency Map and then get the number of keys that have only one occurrence.
static int numberOfUniqueIntegers(int[] number) {
Map<Integer, Long> freq = Arrays.stream(number).boxed().collect(
Collectors.groupingBy(x -> x, Collectors.counting()));
return (int) freq.entrySet().stream().filter(e -> e.getValue().equals(1L))
.map(Map.Entry::getKey).count();
}
Demo
This one should work, just retain the elements already seen in a separate array :
static int numberOfUniqueIntegers(int[] number, int len) {
int unique = 0;
List<Integer> temp = new ArrayList<>();
for (int i = 0; i < len; i++){
if (!temp.contains(number[i]))
{
unique ++;
temp.add(number[i]);
}
}
return unique;
}
static int numberOfUniqueIntegers(int[] number, int len) {
int unique = 0;
boolean isRepeated;
for (int i = 0; i < len; i++){
isRepeated = false;//setting to defalut value
int j;
for (j = 0; j < len; j ++) {
if(j == i) continue;
if (number[i] == number[j]) {
isRepeated = true;//if caught duplicate
break;
}
}
//if not caught duplicate then increment unique ++
if(!isRepeated) unique++;
}
return unique;
}
What wen wrong?
You have to match every value with everyother value which you did not as because you are just using an array and there is no way to figure if futures values had a match in past. So, you have to cover the length of array and check each value against every value in it. if it was to be written using java collections then it be would much simpler and with less time complexity
If you need to do this without using any additional space, e.g. a Set, then you have no option but to compare each element in the array against all others, an O(n^2) solution.
static int numberOfUniqueIntegers(int[] number, int len)
{
int unique = 0;
for (int i = 0; i < len; i++)
{
int j = 0;
for (; j < len; j++)
if (i != j && number[i] == number[j]) break;
if (j == len) unique++;
}
return unique;
}
If you can use additional space then are options that use a Set.
You can try this with O(2n) complexity
static int numberOfUniqueIntegers() {
//int[] abc = { 1, 2, 3, 4, 5, 1, 5 };
int[] abc = { 1, 1, 1 };
Map<Integer, Integer> st = new HashMap();
int unique = 0;
for (int i = 0; i < abc.length; i++) {
if (st.isEmpty() || st.containsKey(abc[i])) {
Integer vl = st.get(abc[i]);
st.put(abc[i], Objects.nonNull(vl) ? (vl + 1) : 1);
} else {
st.put(abc[i], 1);
}
}
for (int i : st.keySet()) {
if (st.get(i) == 1) {
unique = unique + 1;
}
}
System.out.println(st);
return unique;
}
The easiest way is to just use Set.
int[] s = { 1, 2, 1, 5, 3, 4, 5, 1, 1, 5 };
int count = numberOfUniqueIntegers(s);
System.out.println("Count = " + count);
Prints
Count = 3
Set#add returns false if element exists, true otherwise
if seen doesn't contain it, add to unique.
if it has already been seen, remove from unique.
only the unique ones will remain.
static int numberOfUniqueIntegers(int[] number) {
Set<Integer> seen = new HashSet<>();
Set<Integer> unique = new HashSet<>();
for (int i : number) {
if (!seen.add(i)) {
unique.remove(i);
continue;
}
unique.add(i);
}
return unique.size();
}
Due to the nature of Set the above works in O(n) and no explicit counting of elements needs to be done.
Normally asking questions like this, many stack overflow answers will give you solutions, however, that might not be conducive to working through the problem yourself.
Keep in mind there are multiple ways to solve this kind of problem.
Use a Set (a data structure to deal specifically to deal with uniques)
Sort and count. On duplicates, move on.
Just want to point out a potential issue with your code. You are using a terminator on your conditional clause if(i == j);
Your code will compile and run correctly, however it will simply check the comparison and run count++ every time. You will want to fix this clause.
The correct syntax should be
if (i == j) {
count++
}
Check comment for the exact lines:
static int numberOfUniqueIntegers(int[] number, int len) {
int unique = 0;
for (int i = 0; i < len; i++){
int j;
for (j = 0; j < i; j ++) {
if (number[i] == number[j]) {
break;
}
}
if (i == j); // This comparison is always ignored.
unique++; // This line is always happening
}
return unique;
}
You can use set
public static int numberOfUniqueIntegers(int[] number, int len) {
Set<Integer> st = new HashSet();
int unique = 0;
for (int i = 0; i < len; i++) {
if (!st.add(number[i])) {
unique = unique - 1;
} else {
unique = unique + 1;
}
}
return unique;
}
I am trying to implement an iterative Sudoku solver. To avoid recursion I used a stack, but I'm having problems with its management. The starting board is represented by a String array (variable 'input' in the following code) in which each element is composed of 3 numbers: the [row, col] and its value (i.e, "006" means that the element in the 1st line and 1st col is 6) and is translated into an array of int by the constructor. When I run it, I cannot get a solution, so there are probably mistakes in the nested for cycles. Any help is appreciated.
import java.util.ArrayList;
public class SudokuSolver {
private int[][] matrix = new int[9][9];
private String[] input = { "006", "073", "102", "131", "149", "217",
"235", "303", "345", "361", "378", "422", "465", "514", "521",
"548", "582", "658", "679", "743", "752", "784", "818", "883" };
private ArrayList<int[][]> stack = new ArrayList<>();
public SudokuSolver() {
// Building the board based on input array
for (int n = 0; n < input.length; ++n) {
int i = Integer.parseInt(input[n].substring(0, 1));
int j = Integer.parseInt(input[n].substring(1, 2));
int val = Integer.parseInt(input[n].substring(2, 3));
matrix[i][j] = val;
}
stack.add(matrix);
}
private boolean isSolution(int[][] cells) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if(cells[i][j] == 0)
return false;
}
}
return true;
}
private boolean isValid(int i, int j, int val, int[][] cells) {
for (int k = 0; k < 9; k++)
if (val == cells[k][j])
return false;
for (int k = 0; k < 9; k++)
if (val == cells[i][k])
return false;
return true;
}
private boolean iterativeSudokuSolver() {
int[][] current = null;
while(stack.size() > 0 && !isSolution(stack.get(0))) {
current = stack.remove(0);
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
if (current[row][col] == 0) {
for (int val = 1; val <= 9; val++) {
if (isValid(row, col, val, current)) {
current[row][col] = val;
stack.add(0, current);
break;
}
}
}
}
}
}
if (current != null && isSolution(current))
return true;
else
return false;
}
public static void main(String [] args) {
SudokuSolver sudokuSolver = new SudokuSolver();
boolean result = sudokuSolver.iterativeSudokuSolver();
if (result)
System.out.println("Sudoku solved");
else
System.out.println("Sudoku not solved");
}
}
A stack implementation by adding and removing the 0-th element of an ArrayList is a very bad idea: it forces the whole content of the array to be shifted back an forth every time. Use LinkedList or modify the end of the list.
When you add and remove the same instance of the matrix back and forth to the stack, it is still the same matrix object, even though you may call it "current" or any other name. This means that when you change something in the matrix and then remove it from your stack, the change stays there (and in every other element of your stack, which are identical links to the same object). The logic of your solution looks like it needs to store the previous state of the solution on the stack, if so - allocate a new array every time and copy the data (also not very efficient, but try starting there).
A good question has to be specific. "Why this doesn't work?" is a bad question. Fix the obvious problems first, debug, and if puzzled provide more information about the state of your program (data in, data on step #1...N, for example)
I'm trying to write a method that reverses the inputs in an array between two specific indexes. However, it keeps returning the original array as though nothing changed when it is tested. Any thoughts?
public static void reverse (char[] ar, int i, int j) {
char[] arTwo= new char[ar.length];
for (int x =0; x < ar.length; x++){
arTwo[x]= ar[x];
}
int up =i;
int down = j;
while (up> j ) {
ar[up] = arTwo[down];
up++;
down--;
}
}
The while loop loops while the condition is true, but assuming i < j, up > j is false from the start, so no iterations take place.
Try
while (up < down) {
so up meets down in the middle.
Why not just swap the items in the original array?
for (int x=0; x<(j-i)/2; x++)
{
int index1 = i+x;
int index2 = j-x;
char temp = ar[index1];
ar[index1] = ar[index2];
ar[index2] = temp;
}