I'm attempting to convert the characters at a specific String index to an integer.
This is the function I have:
public int[] digitsOfPi(int n) {
{
String piDigits = Double.toString(Math.PI);
int[] piArray = new int[n];
for (int i = 0; i < n; i++)
{
piArray[i] = Character.digit(piDigits.charAt(i), n);;
}
return piArray;
}
}
Unfortunately, when I test this function with digitsOfPi(3), I got
[I#15db9742
Any help would be much appreciated.
Use Arrays.toString(arg)
System.out.println(Arrays.toString(digitsOfPi(3)));
... to get pretty result output like
[1, 2, 3]
What you have printed is a reference to the array, not its content. That is why I asked first about the way youre outputting the result.
Thi signature of Character.digit() is (char ch, int RADIX). So you use ternary number system or how to call it. Moreover, it returns -1 when the char ch does not contain valid number, it is your case 3.1415... is [invalid, invalid, 1]. You need to use 10 as an argument and skip 2nd position.
Or you can simply do
piArray[i] = piDigits.charAt(i) - '0';
You are using System.out.pritln(digitsOfPi(3) for getting the element at 3rd position, but actually its returning an array of int
So try to use the following code snippet, instead -
public static int digitsOfPi(int n) {
String piDigits = Double.toString(Math.PI);
char[] array = piDigits.toCharArray();
return Character.getNumericValue(array[3]);
}
Related
I'm stuck with a loop issue here, I'm working on a script who will receive let's say the String "geij" or "abab" and will have to turn it into a double like "6478" or "0101". I do the conversion from letter to number thanks to a two-dimensional array :
String crypt = "geij";
char twoD[][] = {{'a','b','c','d','e','f','g','h','i','j'}, {'0','1','2','3','4','5','6','7','8','9'}};
First I pass the String into a char array :
char tab[] = crypt.toCharArray();
Then I use a loop to convert from letter to number :
for(int c=0;c<tab.length;c++) {
for(int z=0;z<twoD.length;z++) {
if(tab[c] == twoD[0][z]) {
tab[c] = twoD[1][z];
}
}
Then I create a new instance of String named 'second' to turn the array into a String
String second = new String(tab);
And I turned this String into a double
double finalC = Double.parseDouble(second);
The issue is with this loop, If the String crypt is "abab", the loop will return 0101 as it is supposed to, but if the String contains any letter after "a" or "b" from the first array of the two-dimensional array, like for example the String "geij" the program will simply return "geij".
I don't understand why the program doesn't go further than b and it is starting to give me an egghead. If anyone has an idea I'll be grateful !
Here is an example of the inside of the tab array after the loop for the String "abcd" :
Indice : 0 value: 0
Indice : 1 value: 1
Indice : 2 value: c
Indice : 3 value: d
Kevin Cruijssen resolves your problem but you can more:
Use HashMap to this problem. For now, your algorithm time complexity is O(n*m) (n-base string length, m - amount of letters in the table) because you must iterate through the whole array of letters for each letter.
Using HashMap you can find the right letter in O(1). A lot faster. So now your algorithm has O(n) time complexity.
Simple example:
Map<Character, Integer> encoding = new HashMap<>();
encoding.put('a', 0);
encoding.put('b', 1);
encoding.put('c', 2);
encoding.put('d', 3);
String toEncode = "abcd";
char[] chars = toEncode.toCharArray();
StringBuilder sb = new StringBuilder();
for(char c : chars){
int newInt = encoding.getOrDefault(c, -5); //-5 is just a flag that there is no char to encode
if(newInt == -5){
continue; //or do something else, e.g throw exception;
}
sb.append(newInt);
}
System.out.println(sb.toString());
//Parse double if you want, but remember that what *Nikolas* said in the comments under your post.
//Double.parseDouble(sb.toString());
The problem is in your inner loop: twoD.length is 2, because twoD contains your two inner array of characters.
You should use twoD[0].length instead:
for(int c=0; c<tab.length; c++) {
for(int z=0; z<twoD[0].length; z++) {
...
However, since you are using all ten digits, perhaps better to use that instead:
char twoD[][] = {{'a','b','c','d','e','f','g','h','i','j'}, {'0','1','2','3','4','5','6','7','8','9'}};
int amountOfDigitsUsed = 10; // Equal to `twoD[0].length` or `twoD[1].length`.
for(int c=0; c<tab.length; c++) {
for(int z=0; z<amountOfDigitsUsed; z++) {
...
Regardless whether you use a hard-coded twoD conversion and amountOfDigits used or not. In your current implementation your twoD.length is 2, causing the issues you have right now.
Length of your twoD array is 2. Your second loop should iterate from z = 0 to twoD[0].length.
Try naming your variables meaningfully so it will be easier to find bugs like this. Also check out foreach loops so you don't have to worry about indexes. Java Maps could be better for mapping characters to numbers.
Since it seems as though in your case the characters are incrementing along with their int values, you don't need a map at all. You can cast the character to an int, and then subtract a's int value. This is a slight variation of B_Osipiuk's answer:
String toEncode = "abcd";
char[] chars = toEncode.toCharArray();
StringBuilder sb = new StringBuilder();
for(char c : chars){
int newInt = c - 'a';
if (newInt < 0 || newInt > ('j'-'a')) {
continue; //or do something else, e.g throw exception;
}
sb.append(newInt);
}
System.out.println(sb.toString());
I want my code whenever I input a base from 2-36 , It can output a number which is decimal. here is my code
package code;
public class solution{
public static int x2ten(String s, int base){
String[] bits = s.split("");
int result = 0;
for(int i=0; i < bits.length; i++ ){
int val = (Integer.parseInt(bits[bits.length-1-i])) * ((int)Math.pow(base,i));
val = charToInt(Integer.parseInt(bits[bits.length-1-i]))* ((int)Math.pow(base,i));
result += val;
}
return result;
}
public static int charToInt(char c){
char[] characters = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G',
'H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for(int j = 0; j<characters.length; j++){
if(characters[j] == c){
return j;
}
}
return -1;
}
public static void main(String[] args)
{
System.out.println(x2ten("1101",2));
}
}
There is a problem at first appear charToInt, it said that I should change charToInt(char c) to charToInt(int c). But whats purpose of charToInt is convert whatever I input a Character like 1A, then it can output 26 in decimal.
This is a wheel that's already been invented:
public static int x2ten(String s, int base) {
return Integer.parseInt(s, base);
}
I would advise deleting your method entirely in favour of the one from the JDK, which even has the same signature.
If you insist on using your own code, you should maybe take in mind following things:
If you want to get an array for all characters in a string, use the toCharArray() method. This gives you a char[], which will also be more useful in the rest of your program
What's the point of assigning a value to val if you never use that value and immediately get another value in there. Get rid of that first line. It doesn't seem to be very useful, does it?
Be careful with Integer.parseInt(String s) if you use literals in your numbers. It should throw a NumberFormatException.
If you can notice that in the function call to the function charToInt(), you are passing an integer as an argument but if you see the definition of your function, it is expecting a character.Hence it is suggesting you to change it to int. Hope this helps :)
I have been working on the Project Euler problem 4. I am new to java, and believe I have found the answer (906609 = 993 * 913, by using Excel!).
When I print the line commented out, I can that my string manipulations have worked. I've researched a few ways to compare strings in case I had not understoof something, but this routine doesn't give me a result.
Please help me identify why it is not printing the answer?
James
public class pall{
public static void main(String[] args){
int i;
int j;
long k;
String stringProd;
for(i=994;i>992; i--){
for (j=914;j>912; j--){
k=(i*j);
stringProd=String.valueOf(k);
int len=stringProd.length();
char[] forwards=new char[len];
char[] back = new char[len];
for(int l=0; l<len; l++){
forwards[l]=stringProd.charAt(l);
}
for(int m=0; m<len;m++){
back[m]=forwards[len-1-m];
}
//System.out.println(forwards);
//System.out.println(back);
if(forwards.toString().equals(back.toString())){
System.out.println(k);}
}
}
}
}
You are comparing the string representation of your array. toString() doesn't give you what you think. For example, the below code makes it clear:
char[] arr1 = {'a', 'b'};
char[] arr2 = {'a', 'b'};
System.out.println(arr1.toString() + " : " + arr2.toString());
this code prints:
[C#16f0472 : [C#18d107f
So, the string representation of both the arrays are different, even though the contents are equal. This is because arrays don't override toString() method. It inherits the Object#toString() method.
The toString method for class Object returns a string consisting of
the name of the class of which the object is an instance, the at-sign
character #, and the unsigned hexadecimal representation of the hash
code of the object. In other words, this method returns a string equal
to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
So, in the above output, [C is the output of char[].class.getName(), and 18d107f is the hashcode.
You can't also compare the arrays using forward.equals(back), as arrays in Java don't override equals() or hashCode() either. Any options? Yes, for comparing arrays you can use Arrays#equals(char[], char[]) method:
if (Arrays.equals(forward, back)) {
System.out.println(k);
}
Also, to get your char arrays, you don't need those loops. You can use String#toCharArray() method. And also to get the reverse of the String, you can wrap the string in a StringBuilder instance, and use it's reverse() method:
char[] forwards = stringProd.toCharArray();
char[] back = new StringBuilder(stringPod).reverse().toString().toCharArray();
And now that you have found out an easy way to reverse a string, then how about using String#equals() method directly, and resist creating those character arrays?
String stringPod = String.valueOf(k);
String reverseStringPod = new StringBuilder(stringPod).reverse().toString()
if (stringPod.equals(reverseStringPod)) {
System.out.println(k);
}
Finally, since it is about project euler, which is about speed and mostly mathematics. You should consider avoiding String utilities, and do it with general division and modulus arithmetic, to get each individual digits, from beginning and end, and compare them.
To convert a string to char[] use
char[] forward = stringProd.toCharArray();
To convert a char[] to String, use String(char[]) constructor:
String backStr = new String(back); // Not the same as back.toString()
However, this is not the most performant solution, for several reasons:
You do not need to construct a back array to check if a string is a palindrome - you can walk the string from both ends, comparing the characters as you go, until you either find a difference or your indexes meet in the middle.
Rather than constructing a new array in a loop, you could reuse the same array - in case you do want to continue with an array, you could allocate it once for the maximum length of the product k, and use it in all iterations of your loop.
You do not need to convert a number to string in order to check if it is a palindrome - you can get its digits by repeatedly taking the remainder of division by ten, and then dividing by ten to go to the next digit.
Here is an illustration of the last point:
boolean isPalindrome(int n) {
int[] digits = new int[10];
if (n < 0) n = -n;
int len = 0;
while (n != 0) {
digits[len++] = n % 10;
n /= 10;
}
// Start two indexes from the opposite sides
int left = 0, right = len-1;
// Loop until they meet in the middle
while (left < right) {
if (digits[left++] != digits[right--]) {
return false;
}
}
return true;
}
I'm utterly boggled as to why charAt() works in some scenarios but not others. I am doing exercises while learning Java and one of them was to take a string, and return it in reverse order.
My working code:
public String reverseString(String tempStr){
int initialindex = tempStr.length()-1;
int reverseindex = 0;
char tmp;
char[] array = new char[tempStr.length()];
for(int tempchar : array){
tmp = tempStr.charAt(initialindex);
array[reverseindex] = tmp;
initialindex--;
reverseindex++;
}
String returnstr = new String(array);
return returnstr;
}
The problem I ran into is using the following for statement prints gibberish:
for(int tempchar : array){
array[reverseindex] = tempStr.charAt(initialindex);
initialindex--;
reverseindex++;
}
There were perhaps a dozen different variants of using while loops, standard for loops and a few other versions of code that were ugly and didn't work. Why did my making a char tmp field, putting the inspected characrer in said field, and then using said field to enter the data into an array work?
Also, why am I unable to just return the string using return array.toString();?
Edit: I'm using the latest Eclipse I downloaded today, switched from netbeans.
I copied your code into my editor and it performed fine using either version, with tmp field or without. You must have made some other error using the other method.
Java doesn't support pretty .toString() for arrays; any object which does not override toString will produce the hashCode of the object rather than the contents/fields of the object, and arrays are no exception here. Whilst it might seem sensible for character arrays, the same operation on an int array would produce nonsense; See the difference between Arrays.toString() and String.valueOf(array). In this case, you probably want to use the String.valueOf method.
The array.toString() return string representation of the object. You need to use char[] constructor of String new String(array) to create String from the char[].
As a hint to get you started: if you want to convert a char array into a String use the String constructor that takes a char array.
Update: I see you already did that in your edit. Does it work as expected now?
Your loop looks a little bit weird since you never use your loop variable. you could try this:
char[] initialArray = initialStr.toCharArray();
char[] array = new char[tempStr.length()];
for(int srcIndex = 0, destIndex = array.length-1; destIndex >= 0; srcIndex++, destIndex--) {
array[destIndex] = initialArray[srcIndex];
}
public String reverse(String str)
{
if(str == null)
{
return null;
}
byte[] byteArray= str.getBytes();
int arrayLastIndex = byteArray.length -1 ;
for(int i=0 ; i < byteArray.lenght/2: i++)
{
byte temp = byteArray[i];
byteArray[i] = byteArray[arrayLastIndex -i ]
byteArray[arrayLastIndex - i] = temp;
}
return new String(byteArray);
}
So I am reading in a line from a file, that looks like:
Snowman:286:355:10
And this is the first part of the code I wrote to separate the data and place it into arrays.
for (int i = 0 ; i<manyItems; i++)
{
a = 0;
temp = scan.nextLine();
System.out.println(temp);
b = temp.indexOf(':');
System.out.println(b);
items[i] = temp.substring(a,b);
System.out.println(items[i]);
System.out.println(temp);
a = b;
System.out.println(temp);
b = temp.indexOf(a+1,':');
System.out.println(b);
rawX[i] = temp.substring(a+1,b);
System.out.println(rawX[i]);
}
It separates "Snowman" places it into the array, however, when I try to find the second colon, indexOf() keeps returning -1. Does anyone know why it is not finding the second colon?
You could save all that code and use String#split to split the line:
String[] parts = temp.split(":");
I think you have the arguments backwards:
b = temp.indexOf(a+1,':');
Should be...
b = temp.indexOf(':', a+1);
From docs.oracle.com:
public int indexOf(int ch,
int fromIndex)
The first argument is the character, the second if the fromIndex.
Because you swapped the arguments of the indexOf call. It expects the character, then the index to start looking at. Remember that chars are ints, you're looking for the char 7 starting at the int value of ':'.
There's a method under String class that will handle the job for you. Split(regEx pattern) is what you may want to use. The following code will do the job you're trying to perform:
String input = "Snowman:286:355:10";
String tokens [] = input.split(":");
for (int i = 0; i < tokens.length; i++)
System.out.println(tokens[i]);