Related
I'm comparing elements in two arrays and printing those elements, plus the number of comparisons.
In the "findCommonElements" method, I can't have empty arrays, or I get a NullPointerException (of course) error.
I can't just declare them, or I get the "variable may have not been initialized" error.
I have to use multiple versions of these arrays for testing, but I'm not sure how to go about this. The program is only reading the first instances of the arrays.
Code:
import java.util.*;
public class CommonElements {
private static int comparisons = 0;
public static void main(String[] args) {
new CommonElements().firstTest();
//new CommonElements().secondTest();
//new CommonElements().thirdTest();
}
public void setComparisons(int comparisons) {
this.comparisons = comparisons;
}
public int getComparisons() {
return comparisons;
}
public static Comparable[] findCommonElements(Comparable[][] collections) {
Comparable[] arr1 = {'A', 'B', 'C', 'D'};
Comparable[] arr2 = {'C', 'D', 'E', 'F', 'G'};
Comparable[] hashArray;
Comparable[] searchArray;
if(arr1.length < arr2.length) {
hashArray = arr1;
searchArray = arr2;
}
else {
hashArray = arr2;
searchArray = arr1;
}
HashSet<Comparable> intersection = new HashSet<>();
HashSet<Comparable> hashedArray = new HashSet<>();
for(Comparable element : hashArray) {
hashedArray.add(element);
}
for(Comparable element : searchArray) {
if(hashedArray.contains(element)) {
intersection.add(element);
comparisons++;
}
}
return intersection.toArray(new Comparable[0]);
}
public void firstTest() {
Comparable[] array1 = {'A', 'B', 'C', 'D', 'E'};
Comparable[] array2 = {'E', 'F', 'G', 'H'};
Comparable[][] collections = {array1, array2};
Comparable[] commonStuff = CommonElements.findCommonElements(collections);
System.out.println("First Test");
System.out.println("Comparisons: " + getComparisons());
System.out.print("Common Elements: ");
for(Comparable element : commonStuff) {
System.out.print(element.toString() + " ");
}
System.out.println();
}
/*
public void secondTest() {
Comparable[] array1 = {'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'};
Comparable[] array2 = {'D', 'E', 'F', 'G', 'H'};
Comparable[][] collections = {array1, array2};
Comparable[] commonStuff = findCommonElements(collections);
System.out.println("Second Test");
System.out.println("Comparisons: " + getComparisons());
for(Comparable element : commonStuff) {
System.out.print(element.toString() + " ");
}
System.out.println();
}
public void thirdTest() {
Comparable[] array1 = {'1', '2', '3', '3'};
Comparable[] array2 = {'3', '2', '4', '5', '6'};
Comparable[][] collections = {array1, array2};
Comparable[] commonStuff = findCommonElements(collections);
System.out.println("Third Test");
System.out.println("Comparisons: " + getComparisons());
for(Comparable element : commonStuff) {
System.out.print(element.toString() + " ");
}
System.out.println();
}
*/
}
This is the output, and it's reading the arrays in the findCommonElements method, rather than the firstTest() method (The other test methods are identical, except for the values in the arrays, so they're commented out):
First Test
Comparisons: 2
Common Elements: C D
NOTE
Yes, I have an unused parameter in the findCommonElements method. It was a requirement, and I didn't understand how to incorporate the 2D array into this.....at least not yet.
Yes, the arrays are of type Comparable. That's another requirement.
Also, if any of my logic is incorrect in this code, my apologies. I'm just trying to figure this one problem out for now.
Instead of
public static Comparable[] findCommonElements(Comparable[][] collections) {
Comparable[] arr1 = {'A', 'B', 'C', 'D'};
Comparable[] arr2 = {'C', 'D', 'E', 'F', 'G'};
Write this (assuming you always get exactly 2 elements):
public static Comparable[] findCommonElements(Comparable[][] collections) {
Comparable[] arr1 = collections[0];
Comparable[] arr2 = collections[1];
Then your tests start to work.
To declare an array you should use this syntax:
// Type[] array = new Type[arrayLenght];
For example if you want to create an array of Comparable of 10 lenght you should do something like this:
Comparable[] myArray = new Comparable[10];
You can check your parameter for null and if any of it is null you can return an empty Comparablearray (which is a true thing in an empty case).
public static Comparable[] findCommonElements(Comparable[][] collections) {
if((collections[0]==null) || (collections[1]==null)){
return new Comparable[0];
}
Comparable[] arr1 = collections[0];
Comparable[] arr2 = collections[1];
Comparable[] hashArray;
Comparable[] searchArray;
if(arr1.length < arr2.length) {
[...]
Btw. since you have a field for comparisons. Make sure you handle it right. Set it to 0 whenever you start a new findCommonElements or something else.
How do I create a random password that meets the system's length and character set requirements in Java?
I have to create a random password that is 10-14 characters long and has at least one uppercase, one lowercase, and one special character. Unfortunately, some special characters are too special and cannot be used, so I cannot use just printed ASCII.
Many of the examples on this site generate a random password or session key without enough entropy in the characters or without realistic requirements in a business setting like the ones given above, so I'm asking more pointed question to get a better answer.
My character set, every special character on a standard US keyboard except for a space:
A-Z
a-z
0-9
~`!##$%^&*()-_=+[{]}\|;:'",<.>/?
I suggest using apache commons RandomStringUtils. Use something what is already done.
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!##$%^&*()-_=+[{]}\\|;:\'\",<.>/?";
String pwd = RandomStringUtils.random( 15, characters );
System.out.println( pwd );
If you are using maven
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
otherwise download jar
UPDATE
Version with secure random. So matter of required characters left and can be solved as in comment, generate required parts separately and normal ones. Then join them randomly.
char[] possibleCharacters = (new String("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!##$%^&*()-_=+[{]}\\|;:\'\",<.>/?")).toCharArray();
String randomStr = RandomStringUtils.random( randomStrLength, 0, possibleCharacters.length-1, false, false, possibleCharacters, new SecureRandom() );
System.out.println( randomStr );
I recently learned about Passay. It provides the required functionality needed in its PasswordGenerator class. It randomly generates passwords meeting the requirements similar to what is written below using CharacterRules rather than PasswordCharacterSets as I have done below. Instead of holding a list of unused indexes for random character insertion, it simply shuffles the character buffer after inserting characters that meet the requirements.
Below is left over from before, I recommend using Passay if your licensing allows it, this code should work otherwise and provides details of why the generated passwords are crytographically strong
I ended up writing this code twice. Once to get a random character result, but it turned out the distribution of characters depended on the size of the character set(whoops!). I rewrote it and now you should just copy/paste the code and change the Main.java to the character sets you want. Although it could have been done differently, I think this is a relatively straightforward approach to get the correct result and I encourage reuse, comments, criticisms, and well-thought edits.
The controls of the PasswordGenerator code is as follows:
Min/Max Length: Set using a random number
PasswordCharacterSet: It is assumed that all PasswordCharacterSets passed into PasswordGenerator consist of unique character sets, if not, the random characters will have a skew towards the duplicates.
PasswordCharacterSet Min Characters: The min characters to use for this character set.
The main bits for the actual password generation:
Randomness of Random: We're using SecureRandom which is backed by a cryptographically strong PRNG, rather than the Random class which is not.
Random character order for the password: All the indexes of the pw char array are added to the remainingIndexes array. As we call addRandomCharacters, it removes an index randomly and we use the removed index to populate the array.
Random characters: In addRandomCharacters, a random index from the character index we're using is chosen and added to the pw array.
Guaranteeing minimum characters of each type are set: We simply carve out the minimum character amount first. We choose the minimum amount of random values from each character set and then move on.
Random distribution for the remaining characters: After the minimum values have been set, we want to make the rest of the characters random across all character sets. All the characters are added to a single array. The remaining slots are filled using the same strategy for the previous character sets.
Description of password complexity: Password complexity is usually talked about in bits of entropy. Here are the number of possibilities for your keyspace:
There is at least one uppercase alpha character (out of 26), one lowercase alpha character(out of 26), one digit (out of 10), and one special character (out of 32), the way you calculate the number of possibilities is the number of possibilities for each character multiplied by the number of characters since they are randomly placed in the string. So we know the possibilities for four of the characters are:
Required Characters = 26*26*10*32=216,320
All remaining characters have 94 (26+26+10+32) possibilities each
Our calculation is:
Characters Possibilities Bits of Entropy
10 chars 216,320*94^6 = 149,232,631,038,033,920 ~2^57
11 chars 216,320*94^7 = 14,027,867,317,575,188,480 ~2^63
12 chars 216,320*94^8 = 1,318,619,527,852,067,717,120 ~2^70
13 chars 216,320*94^9 = 123,950,235,618,094,365,409,280 ~2^76
14 chars 216,320*94^10 = 11,651,322,148,100,870,348,472,320 ~2^83
With this is mind, if you want the most secure passwords, you should always choose the highest amount of characters possible which is 14 in this case.
Main.java
package org.redtown.pw;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import org.redtown.pw.PasswordGenerator.PasswordCharacterSet;
public class Main {
public static void main(String[] args) {
Set<PasswordCharacterSet> values = new HashSet<PasswordCharacterSet>(EnumSet.allOf(SummerCharacterSets.class));
PasswordGenerator pwGenerator = new PasswordGenerator(values, 10, 14);
for(int i=0; i < 10; ++i) {
System.out.println(pwGenerator.generatePassword());
}
}
private static final char[] ALPHA_UPPER_CHARACTERS = { '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' };
private static final char[] ALPHA_LOWER_CHARACTERS = { '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' };
private static final char[] NUMERIC_CHARACTERS = { '0', '1', '2', '3', '4',
'5', '6', '7', '8', '9' };
private static final char[] SPECIAL_CHARACTERS = { '~', '`', '!', '#', '#',
'$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{',
']', '}', '\\', '|', ';', ':', '\'', '"', ',', '<', '.', '>', '/',
'?' };
private enum SummerCharacterSets implements PasswordCharacterSet {
ALPHA_UPPER(ALPHA_UPPER_CHARACTERS, 1),
ALPHA_LOWER(ALPHA_LOWER_CHARACTERS, 1),
NUMERIC(NUMERIC_CHARACTERS, 1),
SPECIAL(SPECIAL_CHARACTERS, 1);
private final char[] chars;
private final int minUsage;
private SummerCharacterSets(char[] chars, int minUsage) {
this.chars = chars;
this.minUsage = minUsage;
}
#Override
public char[] getCharacters() {
return chars;
}
#Override
public int getMinCharacters() {
return minUsage;
}
}
}
PasswordGenerator.java
package org.redtown.pw;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class PasswordGenerator {
private final List<PasswordCharacterSet> pwSets;
private final char[] allCharacters;
private final int minLength;
private final int maxLength;
private final int presetCharacterCount;
public PasswordGenerator(Collection<PasswordCharacterSet> origPwSets, int minLength, int maxLength) {
this.minLength = minLength;
this.maxLength = maxLength;
// Make a copy of the character arrays and min-values so they cannot be changed after initialization
int pwCharacters = 0;
int preallocatedCharacters = 0;
List<PasswordCharacterSet> pwSets = new ArrayList<PasswordCharacterSet>(origPwSets.size());
for(PasswordCharacterSet origpwSet : origPwSets) {
PasswordCharacterSet newPwSet = new PwSet(origpwSet);
pwSets.add(newPwSet);
pwCharacters += newPwSet.getCharacters().length;
preallocatedCharacters += newPwSet.getMinCharacters();
}
this.presetCharacterCount = preallocatedCharacters;
this.pwSets = Collections.unmodifiableList(pwSets);
if (minLength < presetCharacterCount) {
throw new IllegalArgumentException("Combined minimum lengths "
+ presetCharacterCount
+ " are greater than the minLength of " + minLength);
}
// Copy all characters into single array so we can evenly access all members when accessing this array
char[] allChars = new char[pwCharacters];
int currentIndex = 0;
for(PasswordCharacterSet pwSet : pwSets) {
char[] chars = pwSet.getCharacters();
System.arraycopy(chars, 0, allChars, currentIndex, chars.length);
currentIndex += chars.length;
}
this.allCharacters = allChars;
}
public char[] generatePassword() {
SecureRandom rand = new SecureRandom();
// Set pw length to minLength <= pwLength <= maxLength
int pwLength = minLength + rand.nextInt(maxLength - minLength + 1);
int randomCharacterCount = pwLength - presetCharacterCount;
// Place each index in an array then remove them randomly to assign positions in the pw array
List<Integer> remainingIndexes = new ArrayList<Integer>(pwLength);
for(int i=0; i < pwLength; ++i) {
remainingIndexes.add(i);
}
// Fill pw array
char[] pw = new char[pwLength];
for(PasswordCharacterSet pwSet : pwSets) {
addRandomCharacters(pw, pwSet.getCharacters(), pwSet.getMinCharacters(), remainingIndexes, rand);
}
addRandomCharacters(pw, allCharacters, randomCharacterCount, remainingIndexes, rand);
return pw;
}
private static void addRandomCharacters(char[] pw, char[] characterSet,
int numCharacters, List<Integer> remainingIndexes, Random rand) {
for(int i=0; i < numCharacters; ++i) {
// Get and remove random index from the remaining indexes
int pwIndex = remainingIndexes.remove(rand.nextInt(remainingIndexes.size()));
// Set random character from character index to pwIndex
int randCharIndex = rand.nextInt(characterSet.length);
pw[pwIndex] = characterSet[randCharIndex];
}
}
public static interface PasswordCharacterSet {
char[] getCharacters();
int getMinCharacters();
}
/**
* Defensive copy of a passed-in PasswordCharacterSet
*/
private static final class PwSet implements PasswordCharacterSet {
private final char[] chars;
private final int minChars;
public PwSet(PasswordCharacterSet pwSet) {
this.minChars = pwSet.getMinCharacters();
char[] pwSetChars = pwSet.getCharacters();
// Defensive copy
this.chars = Arrays.copyOf(pwSetChars, pwSetChars.length);
}
#Override
public char[] getCharacters() {
return chars;
}
#Override
public int getMinCharacters() {
return minChars;
}
}
}
Here is a utility that uses just vanilla Java and implements the requirements. It basically gets one of each of the required character sets. Then populates the rest with random chars from the whole set. Then shuffles it all up.
public class PasswordUtils {
static char[] SYMBOLS = "^$*.[]{}()?-\"!##%&/\\,><':;|_~`".toCharArray();
static char[] LOWERCASE = "abcdefghijklmnopqrstuvwxyz".toCharArray();
static char[] UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
static char[] NUMBERS = "0123456789".toCharArray();
static char[] ALL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789^$*.[]{}()?-\"!##%&/\\,><':;|_~`".toCharArray();
static Random rand = new SecureRandom();
public static String getPassword(int length) {
assert length >= 4;
char[] password = new char[length];
//get the requirements out of the way
password[0] = LOWERCASE[rand.nextInt(LOWERCASE.length)];
password[1] = UPPERCASE[rand.nextInt(UPPERCASE.length)];
password[2] = NUMBERS[rand.nextInt(NUMBERS.length)];
password[3] = SYMBOLS[rand.nextInt(SYMBOLS.length)];
//populate rest of the password with random chars
for (int i = 4; i < length; i++) {
password[i] = ALL_CHARS[rand.nextInt(ALL_CHARS.length)];
}
//shuffle it up
for (int i = 0; i < password.length; i++) {
int randomPosition = rand.nextInt(password.length);
char temp = password[i];
password[i] = password[randomPosition];
password[randomPosition] = temp;
}
return new String(password);
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(getPassword(8));
}
}
}
Using the random functionality of java.util package of rt.jar, we can create a random password of any length. below is the snippet for the same.
public class GeneratePassword {
public static void main(String[] args)
{
int length = 10;
String symbol = "-/.^&*_!#%=+>)";
String cap_letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String small_letter = "abcdefghijklmnopqrstuvwxyz";
String numbers = "0123456789";
String finalString = cap_letter + small_letter +
numbers + symbol;
Random random = new Random();
char[] password = new char[length];
for (int i = 0; i < length; i++)
{
password[i] =
finalString.charAt(random.nextInt(finalString.length()));
}
System.out.println(password);
}
}
I know it is an old question, but maybe my solution will help someone with the same problem.
I'm using RandomStringUtils for password generator and then I check did password fulfilled conditions (at least one symbol, one capital letter, one small letter and one number and 8 characters long) with regex and if it didn't then I call again password generator with recursion until condition is not fulfilled. I can say that method is not gonna be called more than 3 times for sure!
public String generatePassword() {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#!#$%&";
String password = RandomStringUtils.random( 8, characters );
String regex = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[#!#$%&])(?=\\S+$).{8,}$";
Pattern pattern = Pattern.compile( regex );
Matcher matcher = pattern.matcher( password );
if (matcher.matches()) {
return password;
} else {
return generatePassword(); // recursion
}
}
Maven dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
public static final Character[] ALPHA_UPPER_CHARACTERS = {'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'};
public static final Character[] ALPHA_LOWER_CHARACTERS = {'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'};
public static final Character[] NUMERIC_CHARACTERS = {'0', '1', '2', '3', '4',
'5', '6', '7', '8', '9'};
public static final Character[] SPECIAL_CHARACTERS = {'#', '#',
'$', '%', '^', '&', '*', '|', ';', ':', '?'};
**Note: I copied char set from #summer**
final List<Character[]> charSets = new ArrayList<>();
charSets.add(Constant.ALPHA_UPPER_CHARACTERS);
charSets.add(Constant.ALPHA_LOWER_CHARACTERS);
charSets.add(Constant.NUMERIC_CHARACTERS);
charSets.add(Constant.SPECIAL_CHARACTERS);
public String getFilterPassword() {
StringBuilder passBuilder = new StringBuilder();
final int charSetLen = charSets.size();
for (int i = 0; i < 10; i++) {
int randomLength = new Random().nextInt(charSetLen - 1);
Character[] newAlpha = charSets.get(randomLength);
int randomSetLen = newAlpha.length;
int randomAlphaLen = new Random().nextInt(randomSetLen - 1);
passBuilder.append(newAlpha[randomAlphaLen]);
}
return passBuilder.toString();
}
i am trying to solve this question
https://www.hackerrank.com/challenges/pangrams
and here's my code
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Pangram {
public static String alltrim(String s)
{ String s1="";
int i,j,k=0;
for(i=0;i<s.length();i++)
{
char ch=s.charAt(i);
if(ch!=' ')
break;
}
for(j=s.length()-1;j>=0;j--)
{
char ch=s.charAt(j);
if(ch!=' ')
break;
}
for(k=i;k<j+1;k++)
s1 = s1 + s.charAt(k);
return s1;
}
public static void main(String[] args)
{
Scanner reader = new Scanner(System.in);
String input = reader.nextLine();String s,s1;
s = input.toLowerCase();
s1 = alltrim(s);
if( check(s1) )
System.out.println("pangram");
else
System.out.println("not pangram");
}
public static boolean check(String input)
{
int [] count = new int[26];
for( int i = 0; i < input.length(); i++ )
{
char ch = input.charAt(i);
count[ch-'a']++;
}
for( int cnt:count )
{
if( cnt ==0 )
return false;
}
return true;
}
}
i always get this error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -65
at Pangram.check(Pangram.java:46)
at Pangram.main(Pangram.java:35)
i am trying to find out where the problem is but i coudn't ... can anyone help me?
Here's one way
public static void main(final String[] args) throws IOException {
Scanner reader = new Scanner(System.in);
String line = reader.nextLine();
// Verify input argument length.
final char[] allCharacters = new char[] { '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' };
final TreeSet<Character> charactersPresent = new TreeSet<Character>();
// Parse the line into letters.
final char[] letters = line.toLowerCase().toCharArray();
// Keep a set of those that are present.
for (final char letter : letters) {
charactersPresent.add(letter);
}
// Print the letters present in the alphabet but not in the input.
final StringBuilder missingLettersBuilder = new StringBuilder();
for (final char character : allCharacters) {
if (!charactersPresent.contains(character)) {
missingLettersBuilder.append(character);
}
}
if (missingLettersBuilder.length() == 0) {
System.out.println("This is a PANGRAM");
} else {
System.out.println("Not a PANGRAM because it doesn't have "+missingLettersBuilder.toString());
}
}
The problem is in
count[ch-'a']++;
where ch is 6(as you entered) and you are subtracting '6'-'1' so its generating a value by subtracting the ASCII values and give
count[-43]++;
The java.lang.ArrayIndexOutOfBoundsException: -65 happen because you subtract a(97) to a space character which is represented by 32 in the ASCII table (32-97=-65).
Which mean that the problem is in your allTrim method which does not replace all spaces as you probably expected.
If you want to replace all spaces of your string, you can use the replaceAll method of String.
Discard the s1 = alltrim(s); line and replace it by s1 = s.replaceAll(" ", "");.
Now entering the input you gave me in comments
aaabbb ab abc mnop xyyx xaxbbbxx
Won't give any exception.
As for the other exception you had (out of bound -43), it is simply because you entered
6 aaabbb ab abc mnop xyyx xaxbbbxx
6 is represented by 54 in the ASCII table, 54-97 = 43. Looking at the requirement on the link you gave us, you should only compare alphabetical letter so I suppose this is a mistake.
Note that you can easily remove all number of a String, your replace line would become :
s1 = s.replaceAll(" ", "").replaceAll("\\d", "");
Now it would not give any error even when entering
6 aaabbb ab abc mnop xyyx xaxbbbxx
how to delete specified character in array and copy the elements of the first array to the second array ?
i tried to convert the array to a list to be able to check if the array contain this specified character, then i tried to remove this character and create another array by copying the element of the first array but without the specified character.
the system display this error:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:375)
at java.util.AbstractCollection.remove(AbstractCollection.java:269)
at test4.test4.main(Question4.java:21)
this is my code:
package test4;
import java.util.Arrays;
public class test4 {
public static void main(String[] args) {
String[] a = new String[]{ "A", "b", "C", "$", "$", "$", "d", "s", "w", "t", "Z",
"r", "I", "o", "A", "b", "C", "$", "$", "$", "d", "s", "w", "t" };
String[] b = new String[a.length];
int num = 0;
for(int i =0; i<a.length; i++){
if(Character.isUpperCase(i)){
num++;
}
if(Arrays.asList(a).contains("$")){
Arrays.asList(a).remove("$");
b[i] =a[i];
}
}
System.out.println("number os uperCase is: " + num);
System.out.println();
System.out.println("this is the new Array: " + Arrays.toString(b));
}
}
can anyone help me to fix this problem??
Arrays.asList(a) returns a list of fixed length, so Arrays.asList(a).remove("$"); can't work.
You can iterate over the array instead :
int count = 0;
for(int i =0; i<a.length; i++){
if(Character.isUpperCase(a[i].charAt(0))){
num++;
}
if(!a[i].equals("$")){ // copy only non "$" Strings to the output array
b[count] =a[i];
count++;
}
}
Note that your count of upper case characters was also wrong, since you were calling Character.isUpperCase on indices of the array instead of the characters contained in it.
Another thing you should consider is changing String[] a to char[] a, since it looks like you only have single character Strings in that array.
I'm REALLY new at Java and this is the first Question I've answered, so I'm sorry if I'm wrong. Here it goes:
Character.isUpperCase() can not check against a String. It can only check against a char. So I would change the array from a String to char (' instead of " for each character).
Second, the if statement needs to check a[i] not just i.
Third, I would make your second array an ArrayList and convert each char to be added toString so that the size of the second array wouldn't matter and can be used with different arrays.
import java.util.ArrayList;
import java.util.Arrays;
public class test4 {
public static void main(String[] args) {
char[] a = new char[]{ 'A', 'b', 'C', '$', '$', '$', 'd', 's', 'w', 't', 'Z',
'r', 'I', 'o', 'A', 'b', 'C', '$', '$', '$', 'd', 's', 'w', 't' };
ArrayList<String> b = new ArrayList<>();
int num = 0;
for(int i = 0; i<a.length; i++){
if(Character.isUpperCase(a[i])){
num++;
}
if(Arrays.asList(a[i]).contains('$')){
}
else{
String conv = Character.toString(a[i]);
b.add(conv);
}
}
System.out.println("number of upperCase is: " + num);
System.out.println();
System.out.print("This is the new Array: " );
for(String value: b ){
System.out.print(value + " ");
}
}
}
I have a list of 75200 words. I need to give a 'unique' id to each word, and the length of each id could be 3 letters or less. I can use numbers, letters or even symbols but the max length is 3.
Below is my code.
import java.io.*;
import java.util.*;
public class HashCreator {
private Map completedWordMap;
private String [] simpleLetters = {"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"};
private String[] symbols = {"!","#","#","$","%","^","&","*","~","?"};
private String indexNumber;
String currentlyUsingLetter, currentlyUsingSymbol;
private int currentlyActiveSimpleLetter = 0, currentlyActiveSymbol = 0, currentlyActiveSimpleLetter2 = 0, currentlyActiveSymbol2 = 0;
private boolean secondaryNumberIsHundred = false;
public HashCreator()
{
completedWordMap = createWordNumberingMap();
}
private Map createWordNumberingMap()
{
int number = 0;
int secondaryNumber = 0;
int thirdinoryNumber = 0;
Map wordMap = new HashMap();
BufferedReader br = null;
String str = "";
boolean reset = false;
//First Read The File
File readingFile = new File("WordList/NewWordsList.txt");
try
{
br = new BufferedReader(new FileReader(readingFile));
while((str=br.readLine())!=null)
{
if(number<1000) //Asign numbers from 0 t0 999
{
indexNumber = String.valueOf(number);
wordMap.put(indexNumber, str);
number++;
System.out.println(indexNumber);
}
else // It is 1000 now. Length exceeds so find another way.
{
if(indexNumber.length()<4)
{
if(currentlyActiveSimpleLetter<simpleLetters.length) //Start using simple letter array
{
if(secondaryNumber<100) //Start combining numbers with letters. Results will look like 'a0', a1', 'a2'......'x98',x99'
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter]+secondaryNumber;
wordMap.put(indexNumber, str);
secondaryNumber++;
System.out.println(indexNumber);
}
else
{
//If the number is 100, that means the last result is something like 'a99','b99'...'x99'
//Time to use a new letter and set the counter back to 0 and select the next letter
secondaryNumber = 0;
currentlyActiveSimpleLetter++;
}
}
else
{
if(currentlyActiveSymbol<symbols.length) //We have used the entire alphabet. Start using sybmols now.
{
if(currentlyActiveSymbol==0) //If this is the first time we are reaching this step, reset the counter to 0
{
secondaryNumber = 0;
}
if(secondaryNumber<100)
{
indexNumber = symbols[currentlyActiveSymbol]+secondaryNumber;
wordMap.put(indexNumber, str);
secondaryNumber++;
System.out.println(indexNumber);
}
else
{
//If the number is 100, that means the last result is something like '!99','#99'...'*99'
//Time to use a new letter and set the counter back to 0 and select the next symbol
secondaryNumber = 0;
currentlyActiveSymbol++;
}
}
else
{
//We have used entire list of numbers (0-999), entire list of letters (a0-z99) and entire set of symbols (!0 - ?99)
//Now we need to combine all 3 together.
if(thirdinoryNumber<10)//We are starting with a new 'Number' counter
{
//We again start with replacing numbers. Here the first few and last few results will look like a!0'.....'a!9'
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
thirdinoryNumber++;
}
else
{
//We have used number from 0-9. Time to start replacing letters
if(currentlyActiveSimpleLetter2<simpleLetters.length)
{
if(currentlyActiveSimpleLetter2==0) //If this is the 'first' time we reach this point, reset the number counter.
{
thirdinoryNumber = 0;
}
if(thirdinoryNumber<10)
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
}
else
{
thirdinoryNumber = 0;
currentlyActiveSimpleLetter2++; //If we are at the peek of usable numbers (0-9) reset simpleletter array position to
// 0 and numbercounter to 0
}
}
else
{
//We have used number from 0-9. Time to start replacing symbols
if(currentlyActiveSymbol2<symbols.length)
{
if(currentlyActiveSymbol2==0) //If this is the 'first' time we reach this point, reset the number counter.
{
thirdinoryNumber = 0;
}
if(thirdinoryNumber<10)
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
}
else
{
thirdinoryNumber = 0;
currentlyActiveSymbol2++; //If we are at the peek of usable numbers (0-9) reset symbol array position to
// 0 and numbercounter to 0
}
}
}
}
}
}
}
else
{
System.out.println("Error in Somewhere. Length Exceeded");
}
}
}
br.close();
System.out.println("Completed");
System.out.println(wordMap.get(0));
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
br.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
return wordMap;
}
}
Unfortunately this doesn't work. It prints the results, and it is bunch of !0 after the result 'z99'. Below is a small piece of it:
!0
!0
!0
!0
...
Completed
null
Apart from that, after k99, it has generated ids from 10-199 then started back with m0 properly. You can find the result file from here.
As you can see, wordMap.get(0) also generated null. What is wrong here? If there is any other simple method for generating 75000 unique ids with maximum 3 digits/letters/symbols length, I am more than happy to move with it.
Here is generator with enough IDs.
public class Main {
private char[] A;
void init()
{
A = new char[] {
'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',
'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'
};
System.out.println("digits = " + A.length);
//for (int i = 0; i < A.length; i++)
// System.out.print(A[i] + " ");
//System.out.println();
}
public void generate(int length, String id)
{
if (length == 3) {
System.out.println(id);
} else {
for (int i = 0; i < A.length; i++)
generate(length + 1, id + A[i]);
}
}
public static void main(String[] args) {
Main test = new Main();
test.init();
test.generate(0, "");
}
}
The number of unique IDs is (26 + 26 + 10) ^ 3 = 62^3 = 238328.
Obviously you need to adapt it to fit your particular problem.
Actually only 43 characters are needed since 43 ^ 3 = 79507 > 75200.
EDIT: Explanation of the generate() method.
This method implements a recursive algorithm to generate combinations of characters (the keys). The meaning of the parameters is the following:
length The length of the key.
id stores the combination of characters.
The following picture can help to understand the algorithm.
This is similar to how the decimal (or any other base) numbers are formed.
A thing that I don't noticed is that you are trying to first create all the possible keys of length 1, then all possible keys of length 2, and so on. My generator creates keys of exactly 3 character only. That behavior can be achieved modifying the generate() method as follows:
public void generate(int count, String id)
{
if (count == 0) {
System.out.println(id);
} else {
for (int i = 0; i < A.length; i++)
generate(count - 1, id + A[i]);
}
}
And then call the method tree times:
test.generate(1, "");
test.generate(2, "");
test.generate(3, "");
Some keys contains leading zeros but that shouldn't be a problem since this keys are identifiers, not numbers. The number of possible keys increases by length(alphabet) + length(alphabet) ^ 2, i.e. we have 62 + 62^2 additional keys.
Since the length of the key is at most 3 the iterative version can be easily implemented using for loops:
public void iterative_generator()
{
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A.length; j++) {
for (int k = 0; k < A.length; k++) {
System.out.println("" + A[i] + A[j] + A[k]);
}
}
}
}
I think you get the idea.
You could create a method that basically converts a decimal number to a base of your choice. Here I have 46 symbols for example, which gives 97336 unique sequences:
private static final String[] symbols = { "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", "!", "#", "#", "$", "%", "^", "&",
"*", "~", "?" };
public static String getSequence(final int i) {
return symbols[i / (symbols.length * symbols.length)] + symbols[(i / symbols.length) % symbols.length]
+ symbols[i % symbols.length];
}
(Posted on behalf of the question author).
This is how I wrote my code according to the answer of Stack Overflow user "Keppil".
import java.io.*;
import java.util.*;
public class HashCreator
{
private Map completedWordMap;
private String[]simpleLetters = {"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"};
private char[] A;
private static final String[] symbols = { "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", "!", "#", "#", "$", "%", "^", "&",
"*", "~", "?" };
public HashCreator()
{
for(int i=0;i<75001;i++)
{
System.out.println(getSequence(i));
}
}
public static String getSequence(final int i) {
return symbols[i / (symbols.length * symbols.length)] + symbols[(i / symbols.length) % symbols.length]
+ symbols[i % symbols.length];
}
}