public static ArrayList<ArrayList<String>> hoops(ArrayList<String> a) {
ArrayList<ArrayList<String>> list = new ArrayList<ArrayList<String>>(26);
for (char x = 'a'; x <= 'z'; x++) {
list.add(new ArrayList<String>());
}
for (int y = 0; y < a.size(); y++) {
for (char x = 'a'; x <= 'z'; x++) {
if (String.valueOf(x).equals(a.get(y).substring(0, 1))) {
list.get(x - 97).add(a.get(y));
}
}
}
return list;
}
This is code meant to "Write and test a method that takes a List words, which contains Strings of alphabetic characters, throws them into 26 "buckets", according to the first letter, and returns the ArrayList of buckets. Each bucket should be represented by an ArrayList. The first bucket should contain all the Strings from words that start with an 'a', in the same order as they appear in words; the second bucket should contain all the Strings that start with a 'b'; and so on. Your method should traverse the list words only once and leave it unchanged."
When I run the following code...
public static void main(String[] args) {
ArrayList<String> a = new ArrayList<String>(Arrays.asList("cat", "dog", "person", "beetle", "insect"));
ArrayList<Integer> b = new ArrayList<Integer>(Arrays.asList(1, 3, 2, 5, 3, 0, 1, 3));
System.out.print(hoops(a).get('a'));
}
I get an error message...
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 97, Size: 26
at java.util.ArrayList.rangeCheck(ArrayList.java:659)
at java.util.ArrayList.get(ArrayList.java:435)
at marcoB.Reverse.main(Reverse.java:13)
How can I fix this?
PS. I just asked a question similar to this but I edited my code and implemented x - 97
An 'IndexOutOfBoundsException' occurs when you try to reference or "get" a value at an index of the array that it doesn't have. You are seeing 97 come up in the error message because of this line in your main method:
System.out.print(hoops(a).get('a'));
'a' in this case turns into it's ASCII value of 97 (see http://www.asciitable.com/ for more), which is out of the range of the ArrayList you are referencing (26). So either do a get(0) or a get('a'-97) if you want to keep the rest of your implementation the same and get the list which contains the 'a' characters.
There are definitely fancier ways to go about printing the list at a certain character if you go deeper into this.
I would also suggest making your variable names more meaningful in your loops. For example, changing x to letter and y to word might be easier for you to keep track of rather than x and y, especially when you start working with more complicated looping structures.
Related
I have an arraylist which has a list of characters. Now I want to append another character to a certain character from the list (not to form a String,but a character). How do I do that?
Example- Suppose my arraylist has the elements [E,X,Y,M,...]. Now I want to concat another character called 'X' with E.
My code:
for (int i = 0; i < ar.length; i++) {
if (i == 1) {
list.add(ar[i-1]+'X');
}
}
How can I concat two characters to form another character?
You can't. A character is just that: one character.
When you want to concat characters, you automatically, by definition create a string (which represents a sequence of characters).
As you already know the index you care about, a simple
String result = yourList.get(0) + "X";
should do. (iterating a list to retrieve one element at a known index is a bad idea, just get the value at the index you already know).
And note: lists and array in java start at index 0, not 1. 'E' in your example list has index 0, not 1!
Try below code,
char[] ar = { 'E', 'X', 'Y', 'M' };
List<String> list = new ArrayList<>();
for (int i = 0; i < ar.length; i++) {
if (i == 1) {
list.add(String.valueOf(ar[i - 1]) + 'X');
}
}
System.out.println(list);
Output
[EX]
You can use this code
ArrayList<String> list = new ArrayList<String>();
list.add("E");
list.add("X");
list.add("Y");
list.add("M");
//Printing List
for(int i=0;i<list.size();i++)
{
System.out.print(list.get(i));
}
System.out.println();
//Adding Character X with E
list.add(1, "X");
//Printing List
for(int i=0;i<list.size();i++)
{
System.out.print(list.get(i));
}
It will make the list elements as follows - {E, X, X, Y, M}
"char" is just a "char"!
char holds up to 16-bits (2 bytes) of a single Unicode character.
That means you cannot combine two chars as a "char" (Impossible!)
Your list is qualified to hold "chars" only not "Strings".
"String" make sense!
You can use "StringBuilder" to concatenate two chars, but that would produce a "String", not a "char".
My advice to you is to strengthen your conceptual knowledge of Java.
This question already has answers here:
Memory efficient power set algorithm
(5 answers)
Closed 8 years ago.
I'm trying to find every possible anagram of a string in Java - By this I mean that if I have a 4 character long word I want all the possible 3 character long words derived from it, all the 2 character long and all the 1 character long. The most straightforward way I tought of is to use two nested for loops and iterare over the string. This is my code as of now:
private ArrayList<String> subsets(String word){
ArrayList<String> s = new ArrayList<String>();
int length = word.length();
for (int c=0; c<length; c++){
for (int i=0; i<length-c; i++){
String sub = word.substring(c, c+i+1);
System.out.println(sub);
//if (!s.contains(sub) && sub!=null)
s.add(sub);
}
}
//java.util.Collections.sort(s, new MyComparator());
//System.out.println(s.toString());
return s;
}
My problem is that it works for 3 letter words, fun yelds this result (Don't mind the ordering, the word is processed so that I have a string with the letters in alphabetical order):
f
fn
fnu
n
nu
u
But when I try 4 letter words, it leaves something out, as in catq gives me:
a
ac
acq
acqt
c
cq
cqt
q
qt
t
i.e., I don't see the 3 character long word act - which is the one I'm looking for when testing this method. I can't understand what the problem is, and it's most likely a logical error I'm making when creating the substrings. If anyone can help me out, please don't give me the code for it but rather the reasoning behind your solution. This is a piece of coursework and I need to come up with the code on my own.
EDIT: to clear something out, for me acq, qca, caq, aqc, cqa, qac, etc. are the same thing - To make it even clearer, what happens is that the string gets sorted in alphabetical order, so all those permutations should come up as one unique result, acq. So, I don't need all the permutations of a string, but rather, given a 4 character long string, all the 3 character long ones that I can derive from it - that means taking out one character at a time and returning that string as a result, doing that for every character in the original string.
I hope I have made my problem a bit clearer
It's working fine, you just misspelled "caqt" as "acqt" in your tests/input.
(The issue is probably that you're sorting your input. If you want substrings, you have to leave the input unsorted.)
After your edits: see Generating all permutations of a given string Then just sort the individual letters, and put them in a set.
Ok, as you've already devised your own solution, I'll give you my take on it. Firstly, consider how big your result list is going to be. You're essentially taking each letter in turn, and either including it or not. 2 possibilities for each letter, gives you 2^n total results, where n is the number of letters. This of course includes the case where you don't use any letter, and end up with an empty string.
Next, if you enumerate every possibility with a 0 for 'include this letter' and a 1 for don't include it, taking your 'fnu' example you end up with:
000 - ''
001 - 'u'
010 - 'n'
011 - 'nu'
100 - 'f'
101 - 'fu' (no offense intended)
110 - 'fn'
111 - 'fnu'.
Clearly, these are just binary numbers, and you can derive a function that given any number from 0-7 and the three letter input, will calculate the corresponding subset.
It's fairly easy to do in java.. don't have a java compiler to hand, but this should be approximately correct:
public string getSubSet(string input, int index) {
// Should check that index >=0 and < 2^input.length here.
// Should also check that input.length <= 31.
string returnValue = "";
for (int i = 0; i < input.length; i++) {
if (i & (1 << i) != 0) // 1 << i is the equivalent of 2^i
returnValue += input[i];
}
return returnValue;
}
Then, if you need to you can just do a loop that calls this function, like this:
for (i = 1; i < (1 << input.length); i++)
getSubSet(input, i); // this doesn't do anything, but you can add it to a list, or output it as desired.
Note I started from 1 instead of 0- this is because the result at index 0 will be the empty string. Incidentally, this actually does the least significant bit first, so your output list would be 'f', 'n', 'fn', 'u', 'fu', 'nu', 'fnu', but the order didn't seem important.
This is the method I came up with, seems like it's working
private void subsets(String word, ArrayList<String> subset){
if(word.length() == 1){
subset.add(word);
return;
}
else {
String firstChar = word.substring(0,1);
word = word.substring(1);
subsets(word, subset);
int size = subset.size();
for (int i = 0; i < size; i++){
String temp = firstChar + subset.get(i);
subset.add(temp);
}
subset.add(firstChar);
return;
}
}
What I do is check if the word is bigger than one character, otherwise I'll add the character alone to the ArrayList and start the recursive process. If it is bigger, I save the first character and make a recursive call with the rest of the String. What happens is that the whole string gets sliced in characters saved in the recursive stack, until I hit the point where my word has become of length 1, only one character remaining.
When that happens, as I said at the start, the character gets added to the List, now the recursion starts and it looks at the size of the array, in the first iteration is 1, and then with a for loop adds the character saved in the stack for the previous call concatenated with every element in the ArrayList. Then it adds the character on its own and unwinds the recursion again.
I.E., with the word funthis happens:
f saved
List empty
recursive call(un)
-
u saved
List empty
recursive call(n)
-
n.length == 1
List = [n]
return
-
list.size=1
temp = u + list[0]
List = [n, un]
add the character saved in the stack on its own
List = [n, un, u]
return
-
list.size=3
temp = f + list[0]
List = [n, un, u, fn]
temp = f + list[1]
List = [n, un, u, fn, fun]
temp = f + list[2]
List = [n, un, u, fn, fun, fu]
add the character saved in the stack on its own
List = [n, un, u, fn, fun, fu, f]
return
I have been as clear as possible, I hope this clarifies what was my initial problem and how to solve it.
This is working code:
public static void main(String[] args) {
String input = "abcde";
Set<String> returnList = permutations(input);
System.out.println(returnList);
}
private static Set<String> permutations(String input) {
if (input.length() == 1) {
Set<String> a = new TreeSet<>();
a.add(input);
return a;
}
Set<String> returnSet = new TreeSet<>();
for (int i = 0; i < input.length(); i++) {
String prefix = input.substring(i, i + 1);
Set<String> permutations = permutations(input.substring(i + 1));
returnSet.add(prefix);
returnSet.addAll(permutations);
Iterator<String> it = permutations.iterator();
while (it.hasNext()) {
returnSet.add(prefix + it.next());
}
}
return returnSet;
}
Problem solved, I ended up need a seperate counter for the array position. Thanks for the help!
I'm writing a small app that takes a string, processes each string into 7-bits of binary code and then fills in a musical scale based on the string. For instance, if I had the binary 1000100, in the key of C Major that would give me the notes C and G(C 0 0 0 G 0 0).
I'm having an issue with a specific piece of code that takes an input of String[] (in which each element is a single character worth of binary, 7-bits) and processes each individual character in the strings themselves and stores the index number of where 1's occur in the string. For example, the string 1000100 would output 1 and 5.
Here's the method that does that:
public static String[][] convertToScale(String[] e){
String[][] notes = new String[e.length][]; //create array to hold arrays of Strings that represent notes
for(int i = 0; i < e.length; i++){
notes[i] = new String[findOccurancesOf(e[i])]; //create arrays to hold array of strings
for(int x = 0; x < e[i].length(); x++){
if((e[i].charAt(x)) != 48){ //checks to see if the char being evaluated is 0(Ascii code 48)
notes[i][x] = Integer.toString(x + 1); // if the value isn't 0, it fills in the array for that position.the value at x+1 represents the position of the scale the note is at
}
}
}
return notes;
}
Here is the code that is uses to get the occurrences of 1 in e[1]:
public static int findOccurancesOf(String s){
int counter = 0;
for(int i = 0; i < s.length(); i++ ) {
if( s.charAt(i) == 1 ) {
counter++;
}
}
return counter;
}
The issue I'm having is with the convertToScale method. When using "Hello world" as my input(the input gets converted into 7-bit binary before it gets processed by either of these methods) it passes through the 2nd for-each loop just fine the first time around, but after it tries to fill another spot in the array, it throws
java.lang.ArrayIndexOutOfBoundsException: 3
EDIT:It occurs in the line notes[i][x] = Integer.toString(x + 1); of the convertToScale method. I've run the debugger multiple times through after trying the proposes changes below and I still get the same error at the same line. The findOccurancesOf method returns the right value(When evaluating H(1001000) it returns 2.) So the thing that confuses me is that the out of bounds exception comes up right when it fills the 2nd spot in the array.
Also, feel free to tell me if anything else is crazy or my syntax is bad. Thanks!
In findOccurancesOf():
if( s.charAt(i) == 1 ) { should be if( s.charAt(i) == '1' ) { to check for the character '1'.
Otherwise it's looking for the character with ASCII value 1.
There is an out of bounds exception because if findOccuranceOf() returns the wrong value, then notes[i] is not constructed with the correct length in the following line of convertToScale():
notes[i] = new String[findOccurancesOf(e[i])];
In addition, you probably want to use something like:
notes[i][c++] = Integer.toString(x + 1);
with some counter c initialized to 0, if I understand your intentions correctly.
The reason for AIOOBE lies in this line:
notes[i] = new String[findOccurancesOf(e[i])]; //create arrays to hold array of strings
Where you call findOccurancesOf method to find occurance of 1 in your String say Hello which you dont find and return 0 and then you call notes[i][x] = Integer.toString(x + 1); with x as 0. Now since you never allocated space, you get array index out of bound exception.
I would suggest the folowing:
Validate your string before assigning the index say to be greater than 0 or something.
Initialize you notes[i] as notes[i] = new String[e[i].length];
Checking character with single quotes like a == '1' rather than a == 1
The exception is caused by what almas mentioned, note however, that your logical error is most likely inside findOccurencesOf method, if the idea was to find all the '1' chars inside a string you must change to what I outlined below, note the apostrohes. Otherwise a char is getting converted to a byte ascii code, and unless matched with a code of ascii code one, the method will return 0, causing your exception
if( s.charAt(i) == '1' ) {
I have a string as an input eg. Testerty. I want to find the count of each alphabet in the string. I have tried using a HashMap. But I want to implement this using array.
Can you please suggest some way.
You can use ASCII to assign the letters number values:
int[] letters = new int[128]; // There are 128 different possible characters.
for(int i = 0; i < input.length; i++) {
char current = input.charAt(i);
int index = Character.getNumericValue(char);
letters[index]++;
}
ArrayList<Character> ch = new ArrayList<Character>();
ArrayList<Integer> count = new ArrayList<Integer>();
someMethod(String input) {
for(char c : input.toCharArray()) {
if(ch.indexOf(c) != -1) {
i.set(ch.indexOf(c), i.get(ch.indexOf(c))+1);
} else {
ch.add(c);
i.add(1);
}
}
}
doing it with a Map is easier, where the letters are keys and the values are counts. Using an array is more tricky; you could assign each letter a number, and use that number as an index into the array, and store the counts in the array. So 'A' is 1, 'B' is 2, etc....The algorithm is
Get next letter of string.
Get the index for the letter.
Increment the value at that index in the array by 1.
Of course you need to do null checking and whatever.
Note that this is logically a Map. It's just when you use a Map, the Map does step 2 above for you.
You should use a collection implementing Multiset iunterface, i.e. HashMultiset (both taken from Google Guava library). Multiset is designed to hold counts for objects in collection:
Multiset<String> m = HashMultiset.create(Arrays.asList("a", "a", "b", "c", "b", "a"));
// m.toString() prints "a x 3, b x 2, c x 1"
// m.count() gives 6
One way could be, you first create an array, then traverse string using charAt(index) method ,match the current char against those in the array.If you find the match ,increment the value there,or add it as a new entry in the array.
As a challenge to my beginner programming ability I thought it would be fun to see if I could code a simple brute force password thing. So I've started writing an application which generates, given a value for the length of the string, every alphanumeric permutation it could take. However, as I am a complete programming newbie I am having troubles.
Firstly, despite having imported java.lang.Math, I'm getting errors saying cannot find symbol: pow. I managed to fix this by writing out in full java.lang.Math.pow(); when I use the function instead, but why that works but import does not is beyond me.
Secondly, regardless of the length input, after inputting I get the runtime error:
aaException in thread "main" java.lang.ArrayIndexOutOfBoundsException: 98
at combination.main(combination.java:53)
Which suggests that in line 53:
current[j] = alphanum[((int)current[j])+1];
I'm apparently trying to access index 98 in either current[] or alphanum[]?
Which as far as I can see shouldn't be happening...
I'm fairly stumped by this development. Anyway, here's my code:
//48-57 65-90 97-122
import java.util.Scanner;
import java.lang.Math;
public class combination {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//Alphanum will be an array of chars: the lowercase letters of the alphabet, the uppercase, and the numbers 0-9.
char[] alphanum = new char[62];
//Set indexes 0-25 as lowercase a-z, and indexes 26-51 as uppercase A-Z, using ascii conversion.
for (int i=0; i<26; i++) {
alphanum[i] = (char)(i+97);
alphanum[i+26] = (char)(i+65);
}
//Set indexes 51-61 as 0-9.
for (int i=0; i<10; i++) {
alphanum[i+52] = (char)(i+48);
}
//Take in variable for length.
System.out.print("Enter length: ");
int length = in.nextInt();
//Current will be an array of chars: it will hold the current permutation being generated.
char[] current = new char[length];
//Set all indexes in current to "a" by default, and print this string as the first permutation.
for (int i=0; i<length; i++) {
current[i] = alphanum[0];
System.out.print(current[i]);
}
//power will be a temporary double, used to calculate the number of iterations needed, as the pow function works with doubles.
double power = (java.lang.Math.pow(62.00, ((double)length)));
//Convert power to an integer, iterations, and subtract 1 because one iteration was already printed previously.
int iterations = ((int)power)-1;
/*The loop works like this. The rightmost char is checked, and if it is the maximum value of the idex
it is reverted to idex 0 again and the index value of the char to the left of it is increased by 1,
if it is not the maximum then it is just increased by 1. This is iterated the right number of times such
that every alphanumeric permutation of that length has been returned.*/
for (int i=0; i<iterations; i++) {
for (int j=(length-1); j>=0; j--) {
if ((j!=0) && (((int)current[j])==122)) {
current[j] = alphanum[0];
current[j-1] = alphanum[((int)current[j-1])+1];
} else if (j!=0) {
current[j] = alphanum[((int)current[j])+1];
} else {
System.out.println("This has looped too many times. Something is wrong.");
}
}
//At the end of each iteration, print the string.
for (int l=0; l<length; l++) {
System.out.print(current[l]);
}
}
}
}
I'd be really thankful for any help or insight you could offer. ^_^
Your alphanum array has size 62, and the meaning of ((int)current[j-1])+1 is 98 (> 62).
The int value of char 'a' is 97.
I'm apparently trying to access index 98 in either current[] or
alphanum[]? Which as far as I can see shouldn't be happening...
This is perfectly possible since you try to access an element in alphanum at a certain index, where the index is derived from the contents of your current array. I suggest you print out the contents of those arrays at different steps and you will quickly discover where exactly your code behaves not as you thought it would
current[j] = alphanum[((int)current[j])+1];
Here you try to access
int index = ((int)current[j])+1;
current[j] = alphanum[index];
where index seems to be 98