I am learning Java and looking for a comprehensive code of multiplying the elements from 2 arrays, possibly without importing anything to achieve it.
In Python it's quite easy:
a=['a','b','c','d']
b=[1,2,3,4]
[x*y for x,y in zip(a,b)]
['a', 'bb', 'ccc', 'dddd']
How can I achieve the same thing in Java, when the first array is an array of strings and the second is integers?
I'm afraid Java isn't going to support this kind of thing natively, and you'll need to perform some of your own logic to implement it. Let's say you've got your String[]..
String[] a = {"a", "b", "c", "d"};
And you've got your int[]..
int[] b = {1,2,3,4};
Next, you'll need to check that the arrays are the same size.
if(a.length == b.length) {
// Continue.
}
Then you need to implement a loop, to go through each item in the arrays.
for(int x = 0; x < a.length; x++)
{
// Some looping code.
}
And you're going to grab each item.
String value = a[x];
int multiplier = b[x];
If you're not importing anything, you declare the total value:
String total = "";
But if you're allowing for a StringBuilder, then you'll import it and declare..
StringBuilder total = new StringBuilder();
NOTE: StringBuilder is strongly recommended here.
And then you're looping multiplier amount of times..
for(int y = 0; y < multiplier; y++)
{
// If you use StringBuilder..
total.append(value);
// If you don't..
total += value;
}
// If you use StringBuilder..
a[x] = total.toString();
// If you don't...
a[x] = total;
This will set the value of a[x] to the repeated String.
NOTE: Something that's also important is leaning good practise. If you're using Java code, it's considered terrible practise to repeatedly concatenate String objects. StringBuilder is more efficient, and is the Java standard. I would strongly recommend using this.
Have fun putting it all together!!
To create string filled with multiple instances of same character like "ccc" you can firs create array of characters which will hold only 3 characters like
char[] myCharacters = new char[3];
Now this array is filled with zeroes ('\0'), so you need to fill it with desired character 'c'. You simply do it using for loop
for (int i = 0; i<myCharacters; i++){
myCharacters[i] = 'c';
}
After this your array will contain ['c', 'c', 'c'].
Now you can use this array to create string using characters from it. To do so you just need to pass this array to String constructor like
String myString = new String(myCharacters);
And there you go. Now you have "ccc" String. Repeat these steps for each pair of elements from a and b arrays.
You can also use shorter version which kinds of do the same
String myString = new String(new char[3]).replace('\0','c');//will produce "ccc"
Related
There is a string "hello-world!". Any character except A-Z and a-z has to stay in the same place, but letters have to be reversed. So, output would be "dlrow-olleh!".
I used string builder to design the solution, but I am curious if a string of length 12 can be declared and its characters filled in indices 5 and 11, then fill remaining with reversed letters.
Any other techniques or ideas to perform the same would be appreciated.
StringBuilder sb = new StringBuilder();
for(int i=S.length()-1; i >= 0; i--) {
String c = ""+S.charAt(i);
if(c.matches("[A-Za-z]")) {
sb.append(c);
}
}
for(int i = 0; i < S.length(); i++) {
String c = ""+S.charAt(i);
if(!c.matches("[A-Za-z]"))
sb.insert(i,c);
}
I got the output this way, but is there any way to use String here instead of StringBuilder?
You can't use String in the way you suggest, because String is immutable.
Another option, instead of StringBuilder, is to use a raw array of char. You know that the resultant string will have the same length as the source string, so you can do it like this:
Create an array using String.toCharArray.
Iterate from both ends simultaneously using indices i and j. Start index i from 0 moving forwards, and j from array length - 1, moving backwards.
Check the elements at i and j for a letter using Character.isLetter. If it's not a letter, just skip it by advancing i forwards or j backwards.
Swap the array elements at i and j.
Repeat while i < j.
Create the new string using new String(charArray)
As this looks like an exercise, I'll leave the actual coding to you.
Caveat: the above only works for strings where the Unicode code points are in the Basic Multilingual Plane (i.e. most strings to you and me). It won't work for tricky situations containing certain characters such as smileys (for more info on this potential problem, see https://dzone.com/articles/the-right-way-to-reverse-a-string-in-java).
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 tried two different ways to reverse a char array
//method 1
char c[] = {'A', 'B', 'C', 'D'};
char c_rev[] = new char[4];
for (int i = 3; i >= 0; i--) {
c_rev[i] = c[3 - i];
}
System.out.println(Arrays.toString(c_rev));
//method 2
char c[] = {'A', 'B', 'C', 'D'};
Stack<Character> st = new Stack();
for (int i = 0; i < 4; i++) {
st.push(c[i]);
}
for (int i = 0; i < 4; i++) {
c[i] = st.pop();
}
System.out.println(Arrays.toString(c));
I just wondered what will be the most efficient one. Method 1 or Method 2 ?
Can anyone help me or give any suggestions ?
In terms of time complexity, they're both O(n). Performance wouldn't be significant here.
Which to choose? None. I would use a ready method StringBuilder#reverse:
String reversed = new StringBuilder(new String(c)).reverse().toString();
If I wanted to choose one from the two methods you posed, I would have choose the first one, it have only one loop and it's straightforward, no methods will be called, no helper objects will be created; you simply create a new array and directly push to it the new elements.
#MarounMaroun's answer will work for char arrays that are really strings. If you are worried only about those two methods then the first involves less heap allocations and GC.
However in general for an array I would use neither of your methods, but instead:
int len = c.length;
for(int i = 0; i < len / 2; i++) {
char ch = c[i];
c[i] = c[len - i - 1];
c[len - i - 1] = ch;
}
It is:
shorter to type than method 2
only iterates for half the array length (it is still O(n) due to the ops per iteration)
will work for any array type
doesn't need extra object allocations (vs Method 2) or two arrays (vs Method 1)
I would, however, be careful of micro-optimizations like this. The difference between this and Method 1 is probably minimal for small array allocations so you are better off using the one that is easiest for you to understand. (Similarly I only pulled the len variable out for clarity - some microbenchmarks claim it speeds up loops, but the downside is it pollutes your local variables with something that is only used inside the loop).
I'd say that method 1 is probably faster since it doesn't require the creation, allocation, and destruction of new objects (i.e. the Stack and its internal objects). For the same reason it should also have a lower impact on the garbage collector.
If this is a frequent operation in your code, you can benchmark both methods using something like Google caliper. Otherwise, I wouldn't worry about it :)
Logical operators works more efficiently than using a method of assignment operators (swapping) using third variable:
public static char[] reverseArray(char[] array) {
for(int i=0; i<array.length/2; i++)
{
array[i]^=array[array.length-i-1];
array[array.length-i-1]^=array[i];
array[i]^=array[array.length-i-1];
}
return array;
}
public static void main(String[] args) {
char[] input = {'H','e','l','l','o'};
System.out.println(reverseArray(input));
char[] input2 = {'J','a','v','a'};
System.out.println(reverseArray(input2));
}
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;
}
So, I'm in need of help on my homework assignment. Here's the question:
Write a static method, getBigWords, that gets a String parameter and returns an array whose elements are the words in the parameter that contain more than 5 letters. (A word is defined as a contiguous sequence of letters.) So, given a String like "There are 87,000,000 people in Canada", getBigWords would return an array of two elements, "people" and "Canada".
What I have so far:
public static getBigWords(String sentence)
{
String[] a = new String;
String[] split = sentence.split("\\s");
for(int i = 0; i < split.length; i++)
{
if(split[i].length => 5)
{
a.add(split[i]);
}
}
return a;
}
I don't want an answer, just a means to guide me in the right direction. I'm a novice at programming, so it's difficult for me to figure out what exactly I'm doing wrong.
EDIT:
I've now modified my method to:
public static String[] getBigWords(String sentence)
{
ArrayList<String> result = new ArrayList<String>();
String[] split = sentence.split("\\s+");
for(int i = 0; i < split.length; i++)
{
if(split[i].length() > 5)
{
if(split[i].matches("[a-zA-Z]+"))
{
result.add(split[i]);
}
}
}
return result.toArray(new String[0]);
}
It prints out the results I want, but the online software I use to turn in the assignment, still says I'm doing something wrong. More specifically, it states:
Edith de Stance states:
⇒ You might want to use: +=
⇒ You might want to use: ==
⇒ You might want to use: +
not really sure what that means....
The main problem is that you can't have an array that makes itself bigger as you add elements.
You have 2 options:
ArrayList (basically a variable-length array).
Make an array guaranteed to be bigger.
Also, some notes:
The definition of an array needs to look like:
int size = ...; // V- note the square brackets here
String[] a = new String[size];
Arrays don't have an add method, you need to keep track of the index yourself.
You're currently only splitting on spaces, so 87,000,000 will also match. You could validate the string manually to ensure it consists of only letters.
It's >=, not =>.
I believe the function needs to return an array:
public static String[] getBigWords(String sentence)
It actually needs to return something:
return result.toArray(new String[0]);
rather than
return null;
The "You might want to use" suggestions points to that you might have to process the array character by character.
First, try and print out all the elements in your split array. Remember, you do only want you look at words. So, examine if this is the case by printing out each element of the split array inside your for loop. (I'm suspecting you will get a false positive at the moment)
Also, you need to revisit your books on arrays in Java. You can not dynamically add elements to an array. So, you will need a different data structure to be able to use an add() method. An ArrayList of Strings would help you here.
split your string on bases of white space, it will return an array. You can check the length of each word by iterating on that array.
you can split string though this way myString.split("\\s+");
Try this...
public static String[] getBigWords(String sentence)
{
java.util.ArrayList<String> result = new java.util.ArrayList<String>();
String[] split = sentence.split("\\s+");
for(int i = 0; i < split.length; i++)
{
if(split[i].length() > 5)
{
if(split[i].matches("[a-zA-Z]+"))
{
result.add(split[i]);
}
if (split[i].matches("[a-zA-Z]+,"))
{
String temp = "";
for(int j = 0; j < split[i].length(); j++)
{
if((split[i].charAt(j))!=((char)','))
{
temp += split[i].charAt(j);
//System.out.print(split[i].charAt(j) + "|");
}
}
result.add(temp);
}
}
}
return result.toArray(new String[0]);
}
Whet you have done is correct but you can't you add method in array. You should set like a[position]= spilt[i]; if you want to ignore number then check by Float.isNumber() method.
Your logic is valid, but you have some syntax issues. If you are not using an IDE like Eclipse that shows you syntax errors, try commenting out lines to pinpoint which ones are syntactically incorrect. I want to also tell you that once an array is created its length cannot change. Hopefully that sets you off in the right directions.
Apart from syntax errors at String array declaration should be like new String[n]
and add method will not be there in Array hence you should use like
a[i] = split[i];
You need to add another condition along with length condition to check that the given word have all letters this can be done in 2 ways
first way is to use Character.isLetter() method and second way is create regular expression
to check string have only letter. google it for regular expression and use matcher to match like the below
Pattern pattern=Pattern.compile();
Matcher matcher=pattern.matcher();
Final point is use another counter (let say j=0) to store output values and increment this counter as and when you store string in the array.
a[j++] = split[i];
I would use a string tokenizer (string tokenizer class in java)
Iterate through each entry and if the string length is more than 4 (or whatever you need) add to the array you are returning.
You said no code, so... (This is like 5 lines of code)