Winkler's table in Java - java

I'm making a chat-bot, which will answer you by nearest value in dataset (treemaps). System is analog of AIML.
I need to make Winkler-table, which will give me array of result numbers. How to do that?
There is an image, which show how this table works:

You can do it in 3 easy steps.
Create a 2 dimensional array for the result matrix:
see question Syntax for creating a two-dimensional array.
Dimensions will have to match the input and key lengths of course. See https://docs.oracle.com/javase/10/docs/api/java/lang/String.html#length().
Loop over the characters of the input string, and the key as a nested loop. See https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.14.1 and https://docs.oracle.com/javase/10/docs/api/java/lang/String.html#charAt(int). Basically you have 2 indices which give you 2 char values.
Compare both characters using the == operator and store 0 or 1 in the two-dimensional array using the indices.

Okey, i made that table.
It looks like next:
String[] ts = new String[s2.length()];
int[][] table = new int[s1.length()][s2.length()];
char[] s1c = s1.toCharArray();
char[] s2c = s2.toCharArray();
for(int s1cl = 0; s1cl <= s1c.length - 1; s1cl++) {
for(int s2cl = 0; s2cl <= s2c.length - 1; s2cl++) {
if(s1c[s1cl] == s2c[s2cl]) {
table[s1cl][s2cl] = 0;
} else {
table[s1cl][s2cl] = 1;
}
}
}
for(int ts1 = 0; ts1 <= s1c.length - 1; ts1++) {
String res = "";
for(int ts2 = 0; ts2 <= s2c.length - 1; ts2++) {
res += ts2;
if(ts2 == s2c.length - 1) {
ts[ts1] = res;
res = "";
}
}
}
Thanks "herman" for your answer!

Related

Storing Reverse String in 2D Array

I am trying to get the contents of a string, and store it in the last row of my 2D array here is what I have so far:
char[][] square = new char[5][5];
String number = new String("three");
for(int k = number.length() - 1; k >= 0; k--)
{
square[4][k] = number.charAt(k);
}
The output the code is giving me is the string in non reversed order.
Isn't this the logic for reversing a string? All I am doing here is setting the fourth column, and all rows starting at the end of the string to it's value. What am I missing?
Thanks
just walk through the loop by hand.
The first time through, k is 4.
So, square[4][4] is set to the character returned by .charAt(4), which is an 'e'.
then square[4][3] becomes 'e', ... and square[4][0] becomes 't'.
square[4] now reads t,h,r,e,e.
You've basically reversed both ends. Try this:
for (int k = 0; k < number.length(); k++) {
square[4][k] = number.charAt(number.length() - k - 1);
}
Yes, because you're not reversing it. You're setting the same character back again at the same position. If you need it reversed then the logic should be
square[4][number.length() - (k + 1)] = number.charAt(k);
You need a different index beyond square[4][k] when you are also copying the value from number.charAt(k) - that is, you are copying the characters backwards (but into the array also backward). There is no need to call new String(String). You could do
char[][] square = new char[5][5];
String number = "three";
for (int i = 0; i < number.length(); i++) {
int k = number.length() - i - 1;
square[4][k] = number.charAt(i);
}
But I would prefer a StringBuilder and StringBuilder.reverse() myself. Like,
char[][] square = new char[5][5];
String number = "three";
square[4] = new StringBuilder(number).reverse().toString().toCharArray();

Algorithm for combinatorics (6 choose 2)

Following this question, I want to now code "6 choose 2" times "4 choose 2." By that I mean, lets say I have 6 characters "A B C D E F." The first time I choose any two characters to delete. The 2nd time I want to choose 2 different letters to delete and then I append the results of these two trials. Hence, I will receive 90("6 choose 2" times "4 choose 2") eight character strings. The characters in the pattern are from the same pattern {1,2,3,4,5, 6}. All the characters are unique and no repetition.
Here is what I have so far.
public String[] genDelPatterns(String design){
char[] data = design.toCharArray();
String[] deletionPatterns = new String[15];
int x = 0;
StringBuilder sb = new StringBuilder("");
int index = 0;
for(int i = 0; i < (6-1); i++){
for(int j = i+1; j < 6; j++){
for(int k= 0; k < 6; k++){
if((k != j) && (k != i))
sb.append(String.valueOf(data[k]));
}
deletionPatterns[x++] = sb.toString();
sb = new StringBuilder("");
}
}
return deletionPatterns;
}
public String[] gen8String(String[] pattern1, String[] pattern2){
String[] combinedPatterns = new String[225];
int k = 0;
for(int i = 0; i < 15; i++)
{
for(int j = 0; j < 15; j++)
combinedPatterns[k++] = pattern1[i] + pattern2[j];
}
return combinedPatterns;
}
I will be calling the methods like this:
gen8String(genDelPatterns("143256"), genDelPatterns("254316"));
Currently, I am generating all the possible 8 letter strings. But I want to only generate the 8 character strings according to the aforementioned specifications. I am really stuck on how I can elegantly do this multiplication. The only way I can think of is to make another method that does "4 choose 2" and then combine the 2 string arrays. But this seems very roundabout.
EDIT: An example of an 8 character string would be something like "14322516", given the inputs I have already entered when calling gen8String, (143256,254316). Note that the first 4 characters are derived from 143256 with the 5 and 6 deleted. But since I deleted 5 and 6 in the first trail, I am no longer allowed to delete the same things in the 2nd pattern. Hence, I deleted the 3 and 4 from the 2nd pattern.
you have a chain of methods , each one called a variation itself.
For so, my advice is to use a recursive method!
to achieve your goal you have to have a little experience with this solution.
A simple example of a method that exploits the recursion:
public static long factorial(int n) {
if (n == 1) return 1;
return n * factorial(n-1);
}
I can also suggest you to pass objects (constructed to perfection) for the method parameter, if is too complex to pass simple variables
This is the heart of this solution in my opinion.
While what you tried to do is definitely working, it seems you are looking for other way to implement it. Here is the skeleton of what I would do given the small constrains.
// Very pseudo code
// FOR(x,y,z) := for(int x=y; x<z;x++)
string removeCharacter(string s, int banA, int banB){
string ret = "";
FOR(i,1,7){
if(i != banA && i != banB){
ret += s[i];
}
}
return ret;
}
List<string> Generate(s1,s2){
List<string> ret = new List<string>();
FOR(i,1,7) FOR(j,i+1,7) FOR(m,1,7) FOR(n,m+1,7){
if(m != i && m != j && n != i && n != j){
string firstHalf = removeCharacter(s1,i,j);
string secondHalf = removeCharacter(s2,m,n);
ret.Add(firstHalf + secondHalf);
}
}
return ret;
}
This should generate all possible 8-characters string.
Here is the solution I came up with. Doesn't really take "mathematical" approach, I guess. But it does the job.
//generating a subset of 90 eight character strings (unique deletion patterns)
public static String[] gen8String(String[] pattern1, String[] pattern2){
String[] combinedSubset = new String[90]; //emty array for the subset of 90 strings
String combinedString = ""; //string holder for each combined string
int index = 0; //used for combinedSubset array
int present = 0; //used to check if all 6 characters are present
for(int i = 0; i < 15; i++){
for(int j = 0; j < 15; j++){
combinedString = pattern1[i] + pattern2[j]; //combine both 4 letter strings into 8 char length string
char[] parsedString = combinedString.toCharArray(); //parse into array
//check if all 6 characters are present
for(int k = 1; k <= 6; k++)
{
if(new String(parsedString).contains(k+"")) {
present++;
}
else
break;
//if all 6 are present, then add it to combined subset
if(present == 6)
combinedSubset[index++] = combinedString;
}
present = 0;
}
}
return combinedSubset;
}

Storing in an array

I'm trying to get a string to read a file, that then stores all the digits in an array that can be recalled one by one in another loop. Name the array digitStorage please :D Here's my current bit of code:
for (int i = 0; i <= 40000 ; i++) {
String digit;
if ( i <=39998)
digit = pictureFile.substring(i, i+1);
else
digit = pictureFile.substring(39998,39999);
My question :
What to do, how could I do this, how would I get it to read each digit (single integers) 1 by 1 and then store them 1 by 1 in an array that could be later recalled, each number corresponds to a color that would be used to sketch a picture in a graphics window (there are 40,000 single digit integers in a file that i've already worked out how to read) ?
Cheers.
As you have mentioned that you have already read the file and you want to store it in some kind of array. Below code will work.
List<String> list = new ArrayList<String>();
for (int i = 0; i <= 40000 ; i++) {
String digit;
if ( i <=39998)
list.add(pictureFile.substring(i, i+1));
else
list.add(pictureFile.substring(39998,39999));
}
If you want List of Integer then us.
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i <= 40000 ; i++) {
String digit;
if ( i <=39998)
list.add(Integer.parseInt(pictureFile.substring(i, i+1)));
else
list.add(Integer.parseInt(pictureFile.substring(39998,39999)));
}
You can iterate through list after this.
Your question is not very clear, but I believe this should do it:
int [] digitStorage = new int[40000];
for (int i = 0; i <= 40000 ; i++) {
if ( i <=39998)
int[i] = Integer.parseInt(pictureFile.substring(i, i+1));
else
int[i] = Integer.parseInt(pictureFile.substring(39998,39999));
Based on your comments and question, the easiest solution I can think of is to use String.toCharArray() and Character.digit(char, int) like
char[] chars = pictureFile.toCharArray();
int[] digitStorage = new int[chars.length];
for (int i = 0; i < chars.length; i++) {
digitStorage[i] = Character.digit(chars[i], 10);
}
System.out.println(Arrays.toString(digitStorage));

How would I add array index's together?

I've read data from a text file and stored them in an array called 'boat1'.
There are nine values and I am trying to add together index's [4] to [9] to get a total value.
How would I go about doing this?
Here is my code:
String[] boat1 = new String[9];
int i = 0;
while(reader.hasNextLine() && i < boat1.length) {
boat1[i] = reader.nextLine();
i++;
}
I've tried to change the values to an integer but it doesn't seem to be working..?
Thank you.
You got to parse before adding:
int a = Integer.parseInt(boat1[3]);
int b = Integer.parseInt(boat1[8]);
int c = a + b;
Your array boat1 is a String array and not an int array. You need to convert it. Note that boat1 is size of 9 meaning that it has indexes from 0 to 8. Java is 0 based.
If you want to add up a sequence of numbers (ex. 3,4,...,7,8), just loop through the indexes you want to add up and keep track of a total.
Because your array is an String type it needs to be converted to int, After you do that you will have something like this example assuming that I'm making up those values , but it should still work for your code :). Don't forget to add the for loop at the end as I have it on my code so it can find the sum of your indexes. Hope it can help you!
int sum = 0;
int[] boat = new int[9];
boat[0] = 2;
boat[1] = 4;
boat[2] = 6;
boat[3] = 8;
boat[4] = 10;
boat[5] = 12;
boat[6] = 14;
boat[7] = 16;
boat[8] = 18;
for(int i = 3; i < boat.length ; i++){
sum += boat[i];
}
System.out.println(sum);

int array to int number in Java

I'm new on this site and, if I'm here it's because I haven't found the answer anywhere on the web and believe me: I've been googling for quite a time but all I could find was how to convert a number to an array not the other way arround.
I'm looking for a simple way or function to convert an int array to an int number. Let me explain for example I have this :
int[] ar = {1, 2, 3};
And I want to have this:
int nbr = 123;
In my head it would look like this (even if I know it's not the right way):
int nbr = ar.toInt(); // I know it's funny
If you have any idea of how I could do that, that'd be awesome.
Start with a result of 0. Loop through all elements of your int array. Multiply the result by 10, then add in the current number from the array. At the end of the loop, you have your result.
Result: 0
Loop 1: Result * 10 => 0, Result + 1 => 1
Loop 2: Result * 10 => 10, Result + 2 => 12
Loop 3: Result * 10 >= 120, Result + 3 => 123
This can be generalized for any base by changing the base from 10 (here) to something else, such as 16 for hexadecimal.
You have to cycle in the array and add the right value.
The right value is the current element in the array multiplied by 10^position.
So: ar[0]*1 + ar[1]*10 + ar[2] *100 + .....
int res=0;
for(int i=0;i<ar.length;i++) {
res=res*10+ar[i];
}
Or
for(int i=0,exp=ar.length-1;i<ar.length;i++,exp--)
res+=ar[i]*Math.pow(10, exp);
First you'll have to convert every number to a string, then concatenate the strings and parse it back into an integer. Here's one implementation:
int arrayToInt(int[] arr)
{
//using a Stringbuilder is much more efficient than just using += on a String.
//if this confuses you, just use a String and write += instead of append.
StringBuilder s = new StringBuilder();
for (int i : arr)
{
s.append(i); //add all the ints to a string
}
return Integer.parseInt(s.toString()); //parse integer out of the string
}
Note that this produce an error if any of the values past the first one in your array as negative, as the minus signs will interfere with the parsing.
This method should work for all positive integers, but if you know that all of the values in the array will only be one digit long (as they are in your example), you can avoid string operations altogether and just use basic math:
int arrayToInt(int[] arr)
{
int result = 0;
//iterate backwards through the array so we start with least significant digits
for (int n = arr.length - 1, i = 1; n >= 0; n --, i *= 10)
{
result += Math.abs(arr[n]) * i;
}
if (arr[0] < 0) //if there's a negative sign in the beginning, flip the sign
{
result = - result;
}
return result;
}
This version won't produce an error if any of the values past the first are negative, but it will produce strange results.
There is no builtin function to do this because the values of an array typically represent distinct numbers, rather than digits in a number.
EDIT:
In response to your comments, try this version to deal with longs:
long arrayToLong(int[] arr)
{
StringBuilder s = new StringBuilder();
for (int i : arr)
{
s.append(i);
}
return Long.parseLong(s.toString());
}
Edit 2:
In response to your second comment:
int[] longToIntArray(long l)
{
String s = String.valueOf(l); //expand number into a string
String token;
int[] result = new int[s.length() / 2];
for (int n = 0; n < s.length()/2; n ++) //loop through and split the string
{
token = s.substring(n*2, (n+2)*2);
result[n] = Integer.parseInt(token); //fill the array with the numbers we parse from the sections
}
return result;
}
yeah you can write the function yourself
int toInt(int[] array) {
int result = 0;
int offset = 1;
for(int i = array.length - 1; i >= 0; i--) {
result += array[i]*offset;
offset *= 10;
}
return result;
}
I think the logic behind it is pretty straight forward. You just run through the array (last element first), and multiply the number with the right power of 10 "to put the number at the right spot". At the end you get the number returned.
int nbr = 0;
for(int i = 0; i < ar.length;i++)
nbr = nbr*10+ar[i];
In the end, you end up with the nbr you want.
For the new array you gave us, try this one. I don't see a way around using some form of String and you are going to have to use a long, not an int.
int [] ar = {2, 15, 14, 10, 15, 21, 18};
long nbr = 0;
double multiplier = 1;
for(int i = ar.length-1; i >=0 ;i--) {
nbr += ar[i] * multiplier;
multiplier = Math.pow(10, String.valueOf(nbr).length());
}
If you really really wanted to avoid String (don't know why), I guess you could use
multiplier = Math.pow(10,(int)(Math.log10(nbr)+1));
which works as long as the last element in the array is not 0.
Use this method, using a long as your input is to large for an int.
long r = 0;
for(int i = 0; i < arr.length; i++)
{
int offset = 10;
if(arr[i] >= 10)
offset = 100;
r = r*offset;
r += arr[i];
}
This checks if the current int is larger than 10 to reset the offset to 100 to get the extra places required. If you include values > 100 you will also need to add extra offset.
Putting this at end of my post due to all the downvotes of Strings...which is a perfectly legitimate answer...OP never asked for the most efficient way to do it just wannted an answer
Loop your array appending to a String each int in the array and then parse the string back to an int
String s = "";
for(int i = 0; i < arr.length; i++)
s += "" + arr[i];
int result = Integer.parseInt(s);
From your comment the number you have is too long for an int, you need to use a long
String s = "";
for(int i = 0; i < arr.length; i++)
s += "" + arr[i];
long result = Long.parseLong(s);
If you can use Java 1.8, stream API makes it very simple:
#Test
public void arrayToNumber() {
int[] array = new int[]{1,2,3,4,5,6};
StringBuilder sb = new StringBuilder();
Arrays.stream(array).forEach(element -> sb.append(element));
assertThat(sb.toString()).isEqualTo("123456");
}
you can do it that way
public static int[] plusOne(int[] digits) {
StringBuilder num= new StringBuilder();
PrimitiveIterator.OfInt primitiveIterator = Arrays.stream(digits)
.iterator();
while (primitiveIterator.hasNext()) {
num.append(primitiveIterator.nextInt());
}
int plusOne=Integer.parseInt(String.valueOf(num))+1;
return Integer.toString(plusOne).chars().map(c -> c-'0').toArray();
}
BE SIMPLE!!!
public static int convertToInteger(int... arr) {
return Integer.parseInt(Arrays.stream(arr)
.mapToObj(String::valueOf)
.collect(Collectors.joining()));
}
this also possible to convert an Integer array to an int array
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
result[i] = arr[i].intValue();
}

Categories

Resources