In the library I'm working on, we have data sets (which may be subsets of other data sets) that are distributed in memory in three-dimensional rectangular strided arrays. That is, an array A can be subscripted as A(i,j,k), where each index ranges from zero to some upper bound, and the location of each element in memory is given by:
A(i,j,k) = A0 + i * A_stride_i + j * A_stride_j + k * A_stride_k
where A0 is a base pointer, and A_stride_i et al are dimensional strides.
Now, because these data sets may be subsets of other data sets rather than each occupying their own independent malloc'ed block of memory, it's entirely possible that they may overlap (where overlap means that A(i,j,k) < B(m,n,p) is neither always true nor always false), and if they overlap they may interleave with each other or they may collide with each other (where collide means that A(i,j,k) == B(m,n,p) for some sextet of indices).
Therein lies the question. Some operations on two data sets (for example, a copy) are only valid if the arrays do not collide with each other, but are valid if they overlap in an interleaved non-colliding fashion. I'd like to add a function for two data sets whether two data sets collide or not.
Is there an existing algorithm for doing this in a reasonably efficient and straightforward way?
It's fairly easy to check whether the data sets overlap or not, so the key question is: Given two data sets of this form that overlap, what is an efficient algorithm to determine if they interleave or collide?
Example:
As a simple example, suppose we have memory locations from 0 to F (in hex):
0 1 2 3 4 5 6 7 8 9 A B C D E F
I'll also consider only 2D arrays here, for simplicity. Suppose we have one of size 2,3 (that is, 0 <= i < 2 and 0 <= j < 3), with a stride_i = 1 and stride_j = 4, at a base address of 2. This will occupy (with occupied locations denoted by their i,j pair):
0 1 2 3 4 5 6 7 8 9 A B C D E F
* * * * * *
Likewise, if we have another array of the same sizes and strides, starting at a base address of 4, that will look like this:
0 1 2 3 4 5 6 7 8 9 A B C D E F
o o o o o o
In the terminology that I was using in describing the problem, these arrays "overlap", but they do not collide.
Restrictions and Assumptions:
We can assume that the strides are positive and, if desired, that they are in increasing order. Neither of things are true in the actual library, but it is reasonably simple to rearrange the array definition to get to this point.
We can assume that arrays do not self-interleave. This is also not enforced by the library, but would be a pathological case, and can be warned about separately. That is (assuming the strides are in increasing order, and i ranges from zero to max_i and so forth):
stride_j >= max_i * stride_i
stride_k >= max_j * stride_j
Points, of course, for methods that do not require these assumptions, as rearranging the array definition into a canonical order is a bit of work that's ideally avoided.
The two arrays cannot be assumed to have equal sizes or strides.
I don't think there's value in keeping track of things during construction -- there's no information occurring at construction that is not present when doing the test. Also, "construction" may simply be "consider the subset of this larger array with this base pointer, these strides, and these sizes."
Worst Likely Cases
svick's answer reminds me that I should probably add something about some typical "worse" cases that I expect this to see. One of the worst will be when we have an array that represents some very large number of complex values, stored in consecutive (real, imag) pairs, and then we have two sub-arrays containing the real and imaginary parts respectively -- so, you've got a few million elements in the array, alternating between the arrays. As this is not an unlikely case, it should be testable with something other than abysmal performance.
I think the following C# program should work. It uses the branch and bound method and works for arrays of any number of dimensions.
using System;
using System.Collections.Generic;
namespace SO_strides
{
sealed class Dimension
{
public int Min { get; private set; }
public int Max { get; private set; }
public int Stride { get; private set; }
private Dimension() { }
public Dimension(int max, int stride)
{
Min = 0;
Max = max;
Stride = stride;
}
public Dimension[] Halve()
{
if (Max == Min)
throw new InvalidOperationException();
int split = Min + (Max - Min) / 2;
return new Dimension[]
{
new Dimension { Min = Min, Max = split, Stride = Stride },
new Dimension { Min = split + 1, Max = Max, Stride = Stride }
};
}
}
sealed class ArrayPart
{
public int BaseAddr { get; private set; }
public Dimension[] Dimensions { get; private set; }
public int FirstNonconstantIndex { get; private set; }
int? min;
public int Min
{
get
{
if (min == null)
{
int result = BaseAddr;
foreach (Dimension dimension in Dimensions)
result += dimension.Min * dimension.Stride;
min = result;
}
return min.Value;
}
}
int? max;
public int Max
{
get
{
if (max == null)
{
int result = BaseAddr;
foreach (Dimension dimension in Dimensions)
result += dimension.Max * dimension.Stride;
max = result;
}
return max.Value;
}
}
public int Size
{
get
{
return Max - Min + 1;
}
}
public ArrayPart(int baseAddr, Dimension[] dimensions)
: this(baseAddr, dimensions, 0)
{
Array.Sort(dimensions, (d1, d2) => d2.Stride - d1.Stride);
}
private ArrayPart(int baseAddr, Dimension[] dimensions, int fni)
{
BaseAddr = baseAddr;
Dimensions = dimensions;
FirstNonconstantIndex = fni;
}
public bool CanHalve()
{
while (FirstNonconstantIndex < Dimensions.Length
&& Dimensions[FirstNonconstantIndex].Min == Dimensions[FirstNonconstantIndex].Max)
FirstNonconstantIndex++;
return FirstNonconstantIndex < Dimensions.Length;
}
public ArrayPart[] Halve()
{
Dimension[][] result = new Dimension[2][];
Dimension[] halves = Dimensions[FirstNonconstantIndex].Halve();
for (int i = 0; i < 2; i++)
{
result[i] = (Dimension[])Dimensions.Clone();
result[i][FirstNonconstantIndex] = halves[i];
}
return new ArrayPart[]
{
new ArrayPart(BaseAddr, result[0], FirstNonconstantIndex),
new ArrayPart(BaseAddr, result[1], FirstNonconstantIndex)
};
}
}
sealed class CandidateSet
{
public ArrayPart First { get; private set; }
public ArrayPart Second { get; private set; }
public CandidateSet(ArrayPart first, ArrayPart second)
{
First = first;
Second = second;
}
public bool Empty
{
get
{
return First.Min > Second.Max || Second.Min > First.Max;
}
}
public CandidateSet[] Halve()
{
int firstSize = First.Size;
int secondSize = Second.Size;
CandidateSet[] result;
if (firstSize > secondSize && First.CanHalve())
{
ArrayPart[] halves = First.Halve();
result = new CandidateSet[]
{
new CandidateSet(halves[0], Second),
new CandidateSet(halves[1], Second)
};
}
else if (Second.CanHalve())
{
ArrayPart[] halves = Second.Halve();
result = new CandidateSet[]
{
new CandidateSet(First, halves[0]),
new CandidateSet(First, halves[1])
};
}
else
throw new InvalidOperationException();
return result;
}
public static bool HasSolution(ArrayPart first, ArrayPart second)
{
Stack<CandidateSet> stack = new Stack<CandidateSet>();
stack.Push(new CandidateSet(first, second));
bool found = false;
while (!found && stack.Count > 0)
{
CandidateSet candidate = stack.Pop();
if (candidate.First.Size == 1 && candidate.Second.Size == 1)
found = true;
else
{
foreach (CandidateSet half in candidate.Halve())
if (!half.Empty)
stack.Push(half);
}
}
return found;
}
}
static class Program
{
static void Main()
{
Console.WriteLine(
CandidateSet.HasSolution(
new ArrayPart(2, new Dimension[] { new Dimension(1, 1), new Dimension(2, 4) }),
new ArrayPart(4, new Dimension[] { new Dimension(1, 1), new Dimension(2, 4) })
)
);
}
}
}
Related
Given number of partitons (usedSpace and its totalSpace) of a hard disk in the form of an list
Example usedSpace = [3,2,1,3,1]
totalSpace = [3,5,3,5,5]
Here usedSpace is the partition getting used out of total space on that partition.
Find the minimum number of partitions need to hold all the data if we move data around partition optimally.
In this cases
a) move data from 1st partion to 2nd partition and 1st partition will be empty
b) move data of 3rd and 5th partition to 4th partition and 3rd and 5th will be free.
Hence only 2 partition needed to hold all the data.
Since the number of moves doesn't matter, and since data can be split up, a greedy approach will work. Pseudocode:
partitionCount := 0
# We're only worried about the total space used vs the total space available
unallocatedDataSize := sum of elements in usedSpace
# Greedily use the largest available space
sort totalSpace by size, descending
while unallocatedDataSize > 0 and totalSpace is not empty
partitionSize := totalSpace.removeFirst()
partitionCount := partitionCount + 1
# Storing partitionSize data in this partition, remove it from our tracking
unallocatedDataSize = unallocatedDataSize - partitionSize
return partitionCount
An optimal and working solution in C#:
public int getMinDrives(int[] used, int[] total)
{
int hdQty = 1;
int pos = 0;
int currentTotal;
Array.Sort(total);
Array.Reverse(total);
int usedSum = used.Sum();
while (usedSum > 0)
{
currentTotal = total[pos];
usedSum = usedSum - currentTotal;
if (usedSum > 0)
{
hdQty++;
pos++;
continue;
}
}
return hdQty;
}
How this can be resolved by Java, if the function returning as Integer value containing args of the amount of used space on each partition and total capacity of each partition, like :
int minPartition(List<Integer> used, List<Integer> totalCapacity), how one can resolve by the above answer supplied by Greedy approach?
The below code responds to Heap space error if i checked with above:
import java.util.ArrayList;
import java.util.List;
public class Program3 {
public static void main(String[] args) {
List<Integer> used = new ArrayList<>();
List<Integer> totalCapacity = new ArrayList<>();
used.add(1);
used.add(2);
used.add(3);
totalCapacity.add(3);
totalCapacity.add(3);
totalCapacity.add(3);
System.out.println(minPartitions(used,totalCapacity));
}
public static int minPartitions(List<Integer> used, List<Integer> totalCapacity) {
// Write your code here
int sizeOfUsedPartion = used.size();
int sizeOfMemoryUsed = totalCapacity.size();
List<Integer> newMemory = new ArrayList<>();
while(sizeOfMemoryUsed != 0)
{
for(int i=0; i<sizeOfUsedPartion;i++)
{
for(int j=0; j<i;j++)
{
if((used.get(i)+used.get(j)) <= totalCapacity.get(i))
{
newMemory.add((used.get(i)+used.get(j)));
break;
}
}
}
}
return newMemory.size();
}
}
//You can use greedy approach. The below code is in c++.
#include<bits/stdc++.h>
using namespace std;
int minParts(vector<int>usedSpace,vector<int>totalSpace){
int q;
q=totalSpace.size();
sort(usedSpace.begin(),usedSpace.end());
sort(totalSpace.begin(),totalSpace.end());
int used=accumulate(usedSpace.begin(),usedSpace.end(),0);
int min=0;
for(int i=q-1;i>=0;i--){
if(used<=totalSpace[i]){
min=min+1;
break;
}
else{
used=used-totalSpace[i];
min=min+1;
}
}
return min;
}
int main(){
vector<int>usedSpace={3,2,1,3,1};
vector<int>totalSpace={3,5,3,5,5};
int m=minParts(usedSpace,totalSpace);
cout<<m;
return 0;
}
//modify the code to give user input
//I could not find a better approach
Here is one task, i was trying to solve. You must write the function
void merge(ArrayList a, ArrayList b) {
// code
}
The function recieves two ArrayLists with equal size as input parameters [a1, a2, ..., an], [b1, b2, ..., bn]. The execution result is the 1st ArrayList must contain elements of both lists, and they alternate consistently ([a1, b1, a2, b2, ..., an, bn]) Please read the bold text twice =)
Code must work as efficiently as possible.
Here is my solution
public static void merge(ArrayList a, ArrayList b) {
ArrayList result = new ArrayList();
int i = 0;
Iterator iter1 = a.iterator();
Iterator iter2 = b.iterator();
while ((iter1.hasNext() || iter2.hasNext()) && i < (a.size() + b.size())) {
if (i % 2 ==0) {
result.add(iter1.next());
} else {
result.add(iter2.next());
}
i++;
}
a = result;
}
I know it's not perfect at all. But I can't understand how to merge in the 1st list without creating tmp list.
Thanks in advance for taking part.
Double ArrayList a's size. Set last two elements of a to the last element of the old a and the last element of b. Keep going, backing up each time, until you reach the beginnings of a and b. You have to do it from the rear because otherwise you will write over the original a's values.
In the end i got this:
public static void merge(ArrayList<Integer> arr1, ArrayList<Integer> arr2) {
int indexForArr1 = arr1.size() - 1;
int oldSize = arr1.size();
int newSize = arr1.size() + arr2.size();
/*
decided not to create new arraylist with new size but just to fill up old one with nulls
*/
fillWithNulls(arr1, newSize);
for(int i = (newSize-1); i >= 0; i--) {
if (i%2 != 0) {
int indexForArr2 = i%oldSize;
arr1.set(i,arr2.get(indexForArr2));
oldSize--; // we reduce the size because we don't need tha last element any more
} else {
arr1.set(i, arr1.get(indexForArr1));
indexForArr1--;
}
}
}
private static void fillWithNulls(ArrayList<Integer> array, int newSize) {
int delta = newSize - array.size();
for(int i = 0; i < delta; i++) {
array.add(null);
}
}
Thanks John again for bright idea!
I have an array that I would like to iterate in random order. That is, I would like my iteration to visit each element only once in a seemingly random order.
Would it be possible to implement an iterator that would iterate elements like this without storing the order or other data in a lookup table first?
Would it be possible to do it for N-dimensional arrays where N>1?
UPDATE: Some of the answers mention how to do this by storing indices. A major point of this question is how to do it without storing indices or other data.
I decided to solve this, because it annoyed me to death not remembering the name of solution that I had heard before. I did however remember in the end, more on that in the bottom of this post.
My solution depends on the mathematical properties of some cleverly calculated numbers
range = array size
prime = closestPrimeAfter(range)
root = closestPrimitiveRootTo(range/2)
state = root
With this setup we can calculate the following repeatedly and it will iterate all elements of the array exactly once in a seemingly random order, after which it will loop to traverse the array in the same exact order again.
state = (state * root) % prime
I implemented and tested this in Java, so I decided to paste my code here for future reference.
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
public class PseudoRandomSequence {
private long state;
private final long range;
private final long root;
private final long prime;
//Debugging counter
private int dropped = 0;
public PseudoRandomSequence(int r) {
range = r;
prime = closestPrimeAfter(range);
root = modPow(generator(prime), closestPrimeTo(prime / 2), prime);
reset();
System.out.println("-- r:" + range);
System.out.println(" p:" + prime);
System.out.println(" k:" + root);
System.out.println(" s:" + state);
}
// https://en.wikipedia.org/wiki/Primitive_root_modulo_n
private static long modPow(long base, long exp, long mod) {
return BigInteger.valueOf(base).modPow(BigInteger.valueOf(exp), BigInteger.valueOf(mod)).intValue();
}
//http://e-maxx-eng.github.io/algebra/primitive-root.html
private static long generator(long p) {
ArrayList<Long> fact = new ArrayList<Long>();
long phi = p - 1, n = phi;
for (long i = 2; i * i <= n; ++i) {
if (n % i == 0) {
fact.add(i);
while (n % i == 0) {
n /= i;
}
}
}
if (n > 1) fact.add(n);
for (long res = 2; res <= p; ++res) {
boolean ok = true;
for (long i = 0; i < fact.size() && ok; ++i) {
ok &= modPow(res, phi / fact.get((int) i), p) != 1;
}
if (ok) {
return res;
}
}
return -1;
}
public long get() {
return state - 1;
}
public void advance() {
//This loop simply skips all results that overshoot the range, which should never happen if range is a prime number.
dropped--;
do {
state = (state * root) % prime;
dropped++;
} while (state > range);
}
public void reset() {
state = root;
dropped = 0;
}
private static boolean isPrime(long num) {
if (num == 2) return true;
if (num % 2 == 0) return false;
for (int i = 3; i * i <= num; i += 2) {
if (num % i == 0) return false;
}
return true;
}
private static long closestPrimeAfter(long n) {
long up;
for (up = n + 1; !isPrime(up); ++up)
;
return up;
}
private static long closestPrimeBefore(long n) {
long dn;
for (dn = n - 1; !isPrime(dn); --dn)
;
return dn;
}
private static long closestPrimeTo(long n) {
final long dn = closestPrimeBefore(n);
final long up = closestPrimeAfter(n);
return (n - dn) > (up - n) ? up : dn;
}
private static boolean test(int r, int loops) {
final int array[] = new int[r];
Arrays.fill(array, 0);
System.out.println("TESTING: array size: " + r + ", loops: " + loops + "\n");
PseudoRandomSequence prs = new PseudoRandomSequence(r);
final long ct = loops * r;
//Iterate the array 'loops' times, incrementing the value for each cell for every visit.
for (int i = 0; i < ct; ++i) {
prs.advance();
final long index = prs.get();
array[(int) index]++;
}
//Verify that each cell was visited exactly 'loops' times, confirming the validity of the sequence
for (int i = 0; i < r; ++i) {
final int c = array[i];
if (loops != c) {
System.err.println("ERROR: array element #" + i + " was " + c + " instead of " + loops + " as expected\n");
return false;
}
}
//TODO: Verify the "randomness" of the sequence
System.out.println("OK: Sequence checked out with " + prs.dropped + " drops (" + prs.dropped / loops + " per loop vs. diff " + (prs.prime - r) + ") \n");
return true;
}
//Run lots of random tests
public static void main(String[] args) {
Random r = new Random();
r.setSeed(1337);
for (int i = 0; i < 100; ++i) {
PseudoRandomSequence.test(r.nextInt(1000000) + 1, r.nextInt(9) + 1);
}
}
}
As stated in the top, about 10 minutes after spending a good part of my night actually getting a result, I DID remember where I had read about the original way of doing this. It was in a small C implementation of a 2D graphics "dissolve" effect as described in Graphics Gems vol. 1 which in turn is an adaption to 2D with some optimizations of a mechanism called "LFSR" (wikipedia article here, original dissolve.c source code here).
You could collect all possible indices in a list and then remove a random indece to visit. I know this is sort of like a lookup table, but i don't see any other option than this.
Here is an example for a one-dimensional array (adaption to multiple dimensions should be trivial):
class RandomIterator<T> {
T[] array;
List<Integer> remainingIndeces;
public RandomIterator(T[] array) {
this.array = array;
this.remainingIndeces = new ArrayList<>();
for(int i = 0;i<array.length;++i)
remainingIndeces.add(i);
}
public T next() {
return array[remainingIndeces.remove((int)(Math.random()*remainingIndeces.size()))];
}
public boolean hasNext() {
return !remainingIndeces.isEmpty();
}
}
On a side note: If this code is performance relevant, this method would perform worse by far, as the random removing from the list triggers copies if you use a list backed by an array (a linked-list won't help either, as indexed access is O(n)). I would suggest a lookup-structure (e.g. HashSet in Java) that stores all visited indices to circumvent this problem (though that's exactly what you did not want to use)
EDIT: Another approach is to copy said array and use a library function to shuffle it and then traverse it in linear order. If your array isn't that big, this seems like the most readable and performant option.
You would need to create a pseudo random number generator that generates values from 0 to X-1 and takes X iterations before repeating the cycle, where X is the product of all the dimension sizes. I don't know if there is a generic solution to doing this. Wiki article for one type of random number generator:
http://en.wikipedia.org/wiki/Linear_congruential_generator
Yes, it is possible. Imagine 3D array (you not likely use anything more than that). This is like a cube and where all 3 lines connect is a cell. You can enumerate your cells 1 to N using a dictionary, you can do this initialization in loops, and create a list of cells to use for random draw
Initialization
totalCells = ... (xMax * yMax * zMax)
index = 0
For (x = 0; x < xMax ; x++)
{
For (y = 0; y < yMax ; y++)
{
For (z = 0; z < zMax ; z++)
{
dict.Add(i, new Cell(x, y, z))
lst.Add(i)
i++
}
}
}
Now, all you have to do is iterate randomly
Do While (lst.Count > 0)
{
indexToVisit = rand.Next(0, lst.Count - 1)
currentCell = dict[lst[indexToVisit]]
lst.Remove(indexToVisit)
// Do something with current cell here
. . . . . .
}
This is pseudo code, since you didn't mention language you work in
Another way is to randomize 3 (or whatever number of dimensions you have) lists and then just nested loop through them - this will be random in the end.
I am trying to use apache commons math for kernel density estimation for a group of values. One bin happens to have only one value, and when I try to call cumulativeProbability() I get a NotStrictlyPositiveException. Is there any way to prevents this? I can't be sure that all the bins will have at least one value.
Thanks.
Given that this bug is still there, I wrote my own implementation of the EmpiricalDistribution class, following their guidelines.
I only re-implemented the functionality that I needed, i.e. computing the entropy of a distribution, but you can easily extend it to your needs.
public class EmpiricalDistribution {
private double[] values;
private int[] binCountArray;
private double maxValue, minValue;
private double mean, stDev;
public EmpiricalDistribution(double[] values) {
this.values = values;
int binCount = NumberUtil.roundToClosestInt(values.length / 10.0);
binCountArray = new int[binCount];
maxValue = Double.NEGATIVE_INFINITY;
minValue = Double.POSITIVE_INFINITY;
for (double value : values) {
if (value > maxValue) maxValue = value;
if (value < minValue) minValue = value;
}
double binRange = (maxValue - minValue) / binCount;
for (double value : values) {
int bin = (int) ((value - minValue) / binRange);
bin = Math.min(binCountArray.length - 1, bin);
binCountArray[bin]++;
}
mean = (new Mean()).evaluate(values);
stDev = (new StandardDeviation()).evaluate(values, mean);
}
public double getEntropy() {
double entropy = 0;
for (int valuesInBin : binCountArray) {
if (valuesInBin == 0) continue;
double binProbability = valuesInBin / (double) values.length;
entropy -= binProbability * FastMath.log(2, binProbability);
}
return entropy;
}
public double getMean() {
return mean;
}
public double getStandardDeviation() {
return stDev;
}
}
I get the same error with one of my distributions.
Reading the Javadoc of this class, it says the following:
USAGE NOTES:
The binCount is set by default to 1000. A good rule of thumb
is to set the bin count to approximately the length of the input
file divided by 10.
I've initialised my EmpiricalDistribution with a binCount equals to 10% of my initial data length and now everything is working ok:
double[] baseLine = getBaseLineValues();
...
// Initialise binCount
distribution = new EmpiricalDistribution(baseLine.length/10);
// Load base line data
distribution.load(baseLine);
// Now you can obtain random values based on this distribution
double randomValue = distribution.getNextValue();
I've got an IndexOutOfBounds exception in the following program. It consists of three files:
Important are only two of them, the GUI is working fine. Here is the first one:
interface SudokuObserver {
public void modified(int i, int j);
}
public class SudokuData
{
public int[][] feld = new int[9][9];
public SudokuObserver obs = null;
public SudokuData()
{
int i,j;
for (i=0; i<9; i++) {
for (j=0; j<9; j++) {
feld[i][j] = 0;
}
}
}
public int getNumber(int x, int y)
{
return feld[x][y];
}
public void setNumber(int x, int y, int v)
{
feld[x][y] = v;
if (obs != null)
obs.modified(x, y);
}
public void setObserver(SudokuObserver o)
{
obs = o;
}
So the Sudoku field is allocated as a 9x9 integer array. The following file is called SudokuSolver and has an algorithm to write the possible numbers for each square into an ArrayList. Then the second algorithm works as following: He finds the square which has the minimum of possible numbers, sets the first of the numbers saved in the ArrayList on that square and does this recursive, so he starts again at defining the possible numbers for each square, taking the one with the smallest number of possibilities and picks the first one to put it into that field. A for-loop runs over the possible Numbers for each square while doing that.
import java.util.*;
public class SudokuSolver
{
SudokuData data;
public SudokuSolver(SudokuData d)
{
data = d;
}
{
/*Pseudoalgorithm:
- Inserts the numbers 1-9 into a Collection called res
- Looks at line x, which numbers are in there and erases them out of the
collection
- Looks at column y, which numbers are in there and erases them out of the
collection
- Looks in the 3x3 Square (x,y) which numbers are already in there and erases
them out of the collection
- Gives back the possible candidates for that field
*/
Here i initialize my ArrayList.
public ArrayList<Integer> offen(int x, int y)
{
ArrayList<Integer> res = new ArrayList<Integer>();
/* The collection is saved in an ArrayList */
int k = 0;
Here I just fill in the numbers 1-9 in my ArrayList.
for (int i=1;i<10;i++)
{
res.add(i);
}
Now comes the difficult part: I loop over j from zero to nine, then over k. The line is constant with the given x, the j runs over the columns, so i got every square in the given line, and in every square i check for every number from 1-9. Care: the index goes from 0-9 while the elements go from 1-9 so k has to be 0-9 cause the get()-method takes an index as input. If there is any compliance I remove the element from the ArrayList.
for (int j=0;j<9;j++)
{
for (k=0;k<9;k++)
{
if (this.data.feld[x][j] == (res.get(k)))
res.remove(k);
}
Same stuff as above for the columns, constant column and j loops.
for (k=0;k<9;k++)
{
if (this.data.feld[j][y] == res.get(k))
res.remove(k);
}
}
Now i get my inputs in two new variables, just because i had typed the code part below before with wrong variable names.
int m = x;
int n = y;
Here is the part for the 3x3 squares, i do this with if conditions, so this is just one of the 9 parts, I didn't want to post them all here, cause they just differ in a few constants. I check in which square my input x,y is, and then I loop over the square and check which numbers are there, which are also still in my ArrayList and remove them.
if (m<=2 && n<=2)
{
for (m=0;m<3;m++)
{
for (n=0;n<3;n++)
{
for (k=0;k<9;k++)
{
if (this.data.feld[m][n] == res.get(k))
res.remove(k);
}
}
}
}
Now I return the ArrayList
return res;
}
//findSolution() finds a Solution
public boolean findSolution()
{
/*Possible Strategy:
- Find the square, which has the fewest possible candidates
- If there are more than one candidates, who have the minimum of candidates,
take any of them
- If there are no more open candidates, there is a solution found. Return
true
- Loop over the candidates of this square and by setting the first possible
candidate into this square[x][y]
- Call the method findSolution() recursive to find in dependence of the set
value the values for the other fields
If there is a blind alley, take the next possible candidate (Backtracking!)
*/
int j = 0;
int k = 0;
int x = 0; // x coordinate of the field with the fewest open candidates
int y = 0; // y coordinate of the field with the fewest open candidates
int counter_offene_felder = 0; // counts the number of open fields
int min = 9;
I'm looping over j and k, looking if the number of possible candidates is more than 0, that means I'm running through the whole sudoku field and count the number of open fields.
for (j=0;j<9;j++)
{
for (k=0;k<9;k++)
{
if ( this.offen(j,k).size() >= 0)
{
counter_offene_felder += 1;
}
If the number is < than min = 9 possible candidates, i take it as the min and save the coordinates of that field
if ( (this.offen(j,k)).size() < min )
{
x = j;
y = k;
}
}
}
now i initialize and ArrayList for the field with the fewest possible candidates and put them into this ArrayList with my offen-method
ArrayList<Integer> candidate_list = this.offen(x,y);
for (k=0;k<this.offen(x,y).size();k++)
{ // runs over candidates
int v = this.offen(x,y).get(k); // takes the first candidate
this.data.setNumber(x,y,v); // writes the first candidate into square [x][y]
this.findSolution(); // calls findSolution() recursive
}
If there are no more open fields, I've found a solution
if (counter_offene_felder == 0)
{
return true;
}
else return false;
}
}
The problem is, that I get an IndexOutOfBounds Exception at line 39, at Index 8 Size 8. But I don't know why. :(
Not positive that this is where you are getting your error... but you could run into an issue when you do something like this.
for (k=0;k<9;k++)
{
if (this.data.feld[j][y] == res.get(k))
res.remove(k);
}
For instance, say that at k=1 the if statement evaluates to true. Then you will remove an element from the ArrayList. Then when k=8, and IndexOutOfBounds exception will be thrown because the ArrayList only contains 8 elements (0-7)
Assuming that no other threads will be modifying this.data.feld[][], you will only ever get one match when going through this loop.. so you could do something like this...
int match = -1;
for (k=0;k<res.size();k++) {
if (this.data.feld[j][y] == res.get(k)){
match = k;
break;
}
}
if(match != -1)
res.remove(match);
I think the contains() method will help eliminate your exceptions for this loop.
Try replacing your code with this:
for (m=0;m<3;m++)
{
for (n=0;n<3;n++)
{
if (res.contains(this.data.field[m][n]))
res.remove(res.indexOf(this.data.field[m][n]));
}
}
It will iterate over the data.field, and check the ArrayList to see if it contains the value at m,n. If it does, it will remove it.