Pangram, Perfect Pangram, Neither - java

I am supposed to read from a text file and figure if a sentence is a PANGRAM (uses all characters in the alphabet), a PERFECT pangram (uses every character in the alphabet once), or NEITHER.
The guide says that I am supposed to initialize x with '0', then go through each letter in the sentence, and if the letter matches with a character in the alphabet, I increment x by 1; then at the end, if the value x for each sentence has a '0', it's NEITHER, if it's all '1', it's PERFECT ,if there is no '0', it's PANGRAM.
Scanner pangram = new Scanner (
PerfectPangram.class.getResourceAsStream ( "pangram.txt" ));
while (pangram.hasNext())
{
String text = pangram.nextLine().toUpperCase();
char [] alphabet = {'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'};
char txt[] = text.toCharArray();
int zero[] = new int [text.length()];
for(int i = 0; i < zero.length; i++)
{
zero[i] = 0;
for (int a = 0; a < text.length(); a++)
{
zero[i] = txt[a];
for (int array = 0; array < alphabet.length; array++)
{
if (alphabet[array] == text.charAt(i))
{
zero[i]++;
}
}
}
if (zero[i] == 1)
{
}
}
}
Output should be like this:
PANGRAM: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
NEITHER: ALL YOUR BASE ARE BELONG TO US; SOMEONE SET US UP THE BOMB.
PERFECT: NEW JOB: FIX MR GLUCK'S HAZY TV, PDQ.

You got it all wrong I guess. First of all your counter array (zero) is initialized with wrong length. Its fixed length should be 'Z'(90) - 'A'(65) + 1 = 26 as is the count of the letters in the latin alphabet. Then you should increment the index of that counter array representing the characters position in the alphabet (c - 'A'), but only if the character is part of the alphabet (c >= 'A' && c <= 'Z'). Once you do this for each of the symbols in a sentence you should now iterate throughout the members of zero and find if any of them is lower then 1: not a pangram; or any is higher then 1: not a perfect pangram;
I will post some crappy code of mine just to demonstrate it but I will not advise you to go with it as your final homework ;) I hope you get the basics and you are able to do it on your own now.
public static void main(String[] args) {
String test = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.\nALL YOUR BASE ARE BELONG TO US; SOMEONE SET US UP THE BOMB.\nNEW JOB: FIX MR GLUCK'S HAZY TV, PDQ.";
Scanner pangram = new Scanner (test);
int zero[] = new int ['Z' - 'A' + 1];
while (pangram.hasNextLine())
{
Arrays.fill(zero, 0);
String text = pangram.nextLine().toUpperCase();
for (char c : text.toCharArray())
{
if (c >= 'A' && c <= 'Z') {
zero[c - 'A']++;
}
}
boolean isPangram = true;
boolean isPerfectPangram = true;
for (int i : zero) {
if (i < 0) {
isPangram = false;
break;
}
if (i > 1) {
isPerfectPangram = false;
}
}
System.out.println(isPerfectPangram ? "Prefect Pangram" : isPangram ? "Pangram" : "Neither");
}
}

Related

How to create an array that contains 26 english letters but the order to be set by an input

I want to know how to create an array that contains 26 english letters but the order of them to be: e.g.
INPUT: problem
and the array would be:
'p','r','o','b','l','e','m','a','c','d','f','g','h','i','j','k','n','q','s','t','u','v','w','x','y','z'.
I tried to do it but i couldnt
My code is here
import javax.swing.JOptionPane;
public class TabelaEShkronjave {
public static void main(String[] args) {
char[][] square = new char[26][26];
/*char[] fjalaKyqe = {'p','r','o','b','l','e','m','a','c','d','f',
'g','h','i','j','k','n','q','s','t','u','v','w','x','y','z'};
*/
String word = JOptionPane.showInputDialog("Write a word: ");
char[] wordArray = word.toCharArray();
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
}
}
First off, you need to guard against bad input, such as non-letters, repeated letters, and uppercase vs. lowercase letters.
One way to build the desired result is to rely on behavior of LinkedHashSet, which will ignore duplicate inserts, so if we first add the letters of the input text, then all letters of alphabet, duplicates will be eliminated for us. The main problem is that the Set has to work with boxed Character objects, not plain char values.
private static char[] wordPrefixedAlphabet(String word) {
Set<Character> letters = new LinkedHashSet<>();
for (char c : word.toLowerCase().toCharArray())
if (c >= 'a' && c <= 'z')
letters.add(c);
for (char c = 'a'; c <= 'z'; c++)
letters.add(c);
char[] alphabet = new char[26];
int i = 0;
for (char c : letters)
alphabet[i++] = c;
return alphabet;
}
Another way is to keep track of which letters have already been added, using a boolean[26]:
private static char[] wordPrefixedAlphabet(String word) {
boolean[] used = new boolean[26];
char[] alphabet = new char[26];
int i = 0;
for (char c : word.toLowerCase().toCharArray())
if (c >= 'a' && c <= 'z' && ! used[c - 'a']) {
used[c - 'a'] = true;
alphabet[i++] = c;
}
for (char c = 'a'; c <= 'z'; c++)
if (! used[c - 'a'])
alphabet[i++] = c;
return alphabet;
}
Testing both with the input "That is NOT a problem!!" produces:
[t, h, a, i, s, n, o, p, r, b, l, e, m, c, d, f, g, j, k, q, u, v, w, x, y, z]
You could:
create an array, the size of the alphabet
copy into the array the characters of the word
selectively copy the characters of the alphabet not yet used
Something like this:
char[] wordArray = word.toCharArray();
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
char[] target = new char[alphabet.length];
System.arraycopy(wordArray, 0, target, 0, wordArray.length);
boolean[] used = new boolean[alphabet.length];
for (char c : wordArray.toCharArray()) {
used[c - 'a'] = true;
}
for (int k = 0, t = wordArray.length; t < target.length; ++k) {
char c = alphabet.chatAt(k);
int pos = c - 'a';
if (!used[pos]) {
target[t++] = c;
}
}
Psuedocode:
Get the length of the input string
Does the input string contain any duplicate characters?
Tip: Use stringName.charAt(i) and a for loop to test individual characters in string
If it doesn't contain any duplicate characters
For loop through string length (i)
For loop through alphabet length (j)
Find array position of stringName.charAt(i) in the alphabet array (j)
Swap this array character with current loop position (i).
(so 'a' and 'p' in problem swap)
Break
For loop through the alphabet array swapped out starting at string length (i)
if the (int) character is less than the next (int) character in loop
swap them and set (i) to string length to restart the for loop
Else
Print an error saying they don't have all unique characters in input
While this isn't the most efficient way to do it, it doesn't require any outside classes besides what you're already given, so it is useful if you are a beginner and need more practice in array manipulation and for loops.
After you read the input and got an array of chars from the input you can use the following logic to achieve desired result:
boolean contains(char[] arr, value) {
if (arr == null) {
return false;
}
for (char c : arr) {
if (c == value) {
return true;
}
}
return false;
}
...
char[] myOrderedAlphabet = new char[26];
int alphabetPosition = 0;
for (char c : wordArray) {
}
for (char c = 'a'; c <= 'z'; c++) {
if (!contains(myOrderedAlphabet, c) {
myOrderedAlphabet[alphabetPosition] = c;
alphabetPosition++;
}
}
Please note that this snippet does not check if character from wordArray is alphabetic. Hence if you will have characters which are not lowercase latin letters this code will cause an IndexOutOfRangeException. You might want to add some additional checks to the code above to prevent errors.
you could do it like this:
String word = JOptionPane.showInputDialog("Write a word: ");
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
char[] result = new char[alphabet.length];
int start = 0;
for (; start < word.length(); start++) {
result[start] = word.toCharArray()[start];
}
for (int i = 0; i < alphabet.length; i++) {
if(word.indexOf(alphabet[i]) == -1) {
result[start++] = alphabet[i];
}
}

In a String, how can I separate & store the characters and integers?

My task is to create a Bubble Breaker type game, I broke my task into several smaller tasks, and I hit a wall.
I created a 2D Array Grid which will, whenever the program starts, be randomized with different coloured Bubbles. Each Line and Each Column is numbered, Lines range in Numbers, Columns range in Letters.
My goal is to have the user input choosing a String (Note I can only use String, as I'm programming in a pre-designed console), for example B10, B9 or 10B.
I'm able to check if the characters are numbers or letters via
command.charAt(i) >= '0' && command.charAt(i) <= '9' // i is a counter in a for
The above allows me to find if it's a digit or a number, the problem is that to select the Exact grid position, I need to, and can't:
Separate the String into Integrers AND character
Join the two Integrers
(note they can be B9, B10 or 10B)
This is an example of the duality B10 and 10B
You only need two lines:
int num = Integer.parseInt(str.replaceAll("\\D", ""));
String letter = str.replaceAll("\\d", "");
The order of letters and digits in the string is irrelevant - this will work either way.
Edited to cater for requirements as per comments below
To process a series of letter-digit pairs in larger string, parsing the letter to an int x (where A=1, B=2, etc) and assigning the digit(s) to int y, you can split the string up on whitespace and use code similar to above:
for (String pair : command.toUpperCase().split("\\s+")) {
int x = pair.replaceAll("\\d", "").charAt(0) - '#';
int y = Integer.parseInt(pair.replaceAll("\\D", ""));
}
Using split() means not having to sully yourself with the tedium of using a loop variable.
The reason for subtracting '#' is that is the character one before 'A', so subtracting that will convert A to 1, B to 2, etc.
Here's some test code:
String command = "A5 B10 11C 20D";
for (String pair : command.split("\\s+")) {
int x = pair.replaceAll("\\d", "").charAt(0) - '#';
int y = Integer.parseInt(pair.replaceAll("\\D", ""));
System.out.format("X = %d, Y = %d\n", x, y);
}
Output:
X = 1, Y = 5
X = 2, Y = 10
X = 3, Y = 11
X = 4, Y = 20
To answer the question, just use an if loop. (If the first char is a digit, parse all but the last as an integer, otherwise parse all starting from the second as an integer.) (use String.substring(start, end) to separate it if that's all you want to know)
Also, you can use Character.isDigit() instead of
command.charAt(i) >= '0' && command.charAt(i) <= '9'
(just for code legibility)
Loop through the String
Check if character is a letter
Save that letter to a variable (char letter)
Replace the original String such that the letter is replace with nothing (String numString)
Now you have them separated: letter and numString
This will work with B10 or 10B. And set that has only one letter and the rest numbers
See code
String code = "10B";
char letter;
for (char c : code.toCharArray()){
if (Character.isLetter(c)){ // if the character is a letter, save if the "letter"
letter = c;
break;
}
}
String numString = code.replace(letter, ""); // replace the original string, letter for ""
// Parse if you need to
int num = Integer.parseInt(numString);
// You have the letter by itself, and the number by itself
System.out.println("Letter: " + letter + ", Number: " + num);
Edit: Try the code below. I had a couple errors in one above
String code = "10B";
char letter = ' '; // <-- initialize
for (char c : code.toCharArray()) {
if (Character.isLetter(c)) { // if the character is a letter, save if the "letter"
letter = c;
break;
}
}
String numString = code.replace(String.valueOf(letter), ""); <-- String valueOf
int num = Integer.parseInt(numString);
System.out.println("Letter: " + letter + ", Number: " + num);
Result : Letter: B, Number: 10
public class StringSpliter {
public static void main(String[] args) {
ArrayList<Character> chars = new ArrayList<>();
ArrayList<Integer> ints = new ArrayList<>();
String str = "T23his i43s a Stin4g Whi12ch C1on3431tains Ch 5ara32cter2343s and Alphabets";
char[] mychars = str.toCharArray();
for (int i = 0; i < mychars.length; i++) {
if (mychars[i] >= 33 && !(mychars[i] <= '9' && mychars[i] >= '0')) {
chars.add(mychars[i]);
} else if (mychars[i] >= '0' && mychars[i] <= '9') {
ints.add((Integer.parseInt(""+mychars[i])));
}
}
for (int i = 0; i < chars.size() + ints.size(); i++) {
if (i < chars.size()) {
System.out.println(chars.get(i));
} else {
System.out.println(ints.get(i - chars.size()));
}
}
}
}
Try the above code

Treating a bidimensional text (Ruzzle solver)

I am trying to program a Ruzzle solver Java application for learning purpose.
I have a little problem in th ematter of "finding words" in a Ruzzle-type map.
Example of a Ruzzle map (it is composed of 4 rows and 4 columns of 1 letter in each cell) :
Z O O H
E Y L H
I E L I
H O F M
http://www.maclife.com/files/imagecache/futureus_imagegallery_fullsize/gallery/ruzzle1.jpg
I would like to obtain a list of all possible words you can find in such a map.
The difficulty : you can find a word by appending letters vertically, horizontally and diagonally (example : "HELLO").
So far, I created 3 classes :
Ruzzlesolver.java
Letter.java
Map.java
The Letter class
Describes a single Letter of the map, its fields are the X and Y positions and the character of the cell.
The Ruzzlesolver class
This is the main class.
it reads the Ruzzle map (an line by line input in the console)
it reads the dictionnary.txt file
it compares the map with the dictionnary file
it writes into the results.txt file
Each line is stored in a char array.
Then I create a new Map object from the 4 obtained arrays.
The Map class
This is the constructor of the Map objects :
public Map(final char[] pTab1, final char[] pTab2, final char[] pTab3, final char[] pTab4)
{
this.aLettres = new ArrayList<Letter>();
for (int i = 0 ; i < 4 ; i++) {
this.aLettres.add(new Letter(1, i+1, pTab1[i]));}
for (int i = 0 ; i < 4 ; i++) {
this.aLettres.add(new Letter(2, i+1, pTab2[i]));}
for (int i = 0 ; i < 4 ; i++) {
this.aLettres.add(new Letter(3, i+1, pTab3[i]));}
for (int i = 0 ; i < 4 ; i++) {
this.aLettres.add(new Letter(4, i+1, pTab4[i]));}
}
this.aLettres is the ArrayList that contains each of the 16 letters of the map.
Each Letter knows its column (X position : "i+1"), its row (Y position : "1, 2, 3 and 4") and its character ("pTab[i]").
Now that we know the map and the place of each letter, we can begin to find the words.
The contains() method
This is my problem : I am stuck using the following method :
How it is called
I pick a word from the dictionnary in the Ruzzlesolver class.
I call the contains() method on my Map object, with this word as a parameter :
if (this.aMap.contains(vMot)) {/*print vMot in the result.txt file*/}
How does the contains() method work
Variables :
char[] vChars = new char[pMot.length()];
ArrayList<Letter> vFoundCharS1 = new ArrayList<Letter>();
Stocking each characters of pMot in an ArrayList :
for (int i = 0 ; i < pMot.length() ; i++) {
vChars[i] = pMot.charAt(i);
}
Searching for the first character of pMot :
for (Letter vL : this.aLettres) {
if (vL.getChar() == vChars[0]) {
vFoundCharS1.add(vL);
return true;
}
}
I am stuck.
If I continue this method, I will have to create longer and longer blocks as I progress. Besides, I would need to write 16 blocks to consider every length possibility.
I am sure this is a wrong method. How would you implement such a treatment ?
Thanks a lot in advance for your help.
PS : I apologize for grammar/English mistakes, English is not my natal language.
If I understand the problem correctly, you can pick every adjacent cell for the next letter, right? In that case, the code below would (I think) solve your problem.
I changed the constructor of Map, because it is easier to work with a two-dimensional array of char.
The function contains does just what your step 3 described: find the first letter and try searching on from there. The function findRecursively searches for the rest of the word recursively.
public class Map {
private char[][] board;
public Map(final char[] pTab1, final char[] pTab2,
final char[] pTab3, final char[] pTab4) {
board = new char[4][4];
for (int i = 0 ; i < 4 ; i++) {
board[0][i] = pTab1(i);
board[1][i] = pTab2(i);
board[2][i] = pTab3(i);
board[3][i] = pTab4(i);
}
}
public boolean contains(String word) {
char[] array = word.toCharArray();
// empty string is trivial
if (array.length == 0)
return true;
for(int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j] == array[0] && findRecursively(i, j, array, 1))
return true;
}
}
return false;
}
public boolean isValid(int i, int j) {
return (0 <= i && i < 4) && (0 <= j && j < 4);
}
public boolean findRecursively(int i, int j, char[] array, int index) {
// reached end of word
if (index == array.length) {
return true;
} else {
// loop over all neighbors
for (int di = -1; di <= 1; di++) {
for (int dj = -1; dj <= 1; dj++) {
// skip cell itself and invalid cells
if (!(di == 0 && dj == 0) && isValid(i+di, j+dj)) {
if (board[i+di][j+dj] == array[index]
&& findRecursively(i+di, j+dj, array, index+1))
return true;
}
}
}
return false;
}
}
}

Generate all possible string from a given length

I would like to be able to generate all possible strings from a given length, and I frankly don't know how to code that. So for further explanation, I and a friend would like to demonstrate some basic hacking techniques, so bruteforcing comes up. Of course, he will be my victim, no illegal thing there.
However, the only thing he told me is that his PW will be 4-char-long, but I'm pretty sure his PW won't be in any dictionnary, that would be toi easy.
So I came up with the idea of generating EVERY 4-char-long-string possible, containing a-z characters (no caps).
Would someone have a lead to follow to code such an algorithm ? I don't really bother with performances, if it takes 1 night to generate all PW, that's no problem.
Don't forget, that's only on demonstration purposes.
You can do it just how you'd do it with numbers. Start with aaaa. Then increment the 'least significant' part, so aaab. Keep going until you get to aaaz. Then increment to aaba. Repeat until you get to zzzz.
So all you need to do is implement is
String getNext(String current)
To expand on this; It possibly isnt the quickest way of doing things, but it is the simplest to get right.
As the old adage goes - 'first make it right, then make it fast'. Getting a working implementation that passes all your tests (you do have tests, right?) is what you do first. You then rewrite it to make it fast, using your tests as reassurance you're not breaking the core functionality.
The absolutely simplest way is to use four nested loops:
char[] pw = new char[4];
for (pw[0] = 'a' ; pw[0] <= 'z' ; pw[0]++)
for (pw[1] = 'a' ; pw[1] <= 'z' ; pw[1]++)
for (pw[2] = 'a' ; pw[2] <= 'z' ; pw[2]++)
for (pw[3] = 'a' ; pw[3] <= 'z' ; pw[3]++)
System.out.println(new String(pw));
This does not scale well, because adding extra characters requires adding a level of nesting. Recursive approach is more flexible, but it is harder to understand:
void findPwd(char[] pw, int pos) {
if (pos < 0) {
System.out.println(new String(pwd));
return;
}
for (pw[pos] = 'a' ; pw[pos] <= 'z' ; pw[pos]++)
findPwd(pw, pos-1);
}
Call recursive method like this:
char[] pw = new char[4];
findPwd(pw, 3);
private static void printAllStringsOfLength(int len) {
char[] guess = new char[len];
Arrays.fill(guess, 'a');
do {
System.out.println("Current guess: " + new String(guess));
int incrementIndex = guess.length - 1;
while (incrementIndex >= 0) {
guess[incrementIndex]++;
if (guess[incrementIndex] > 'z') {
if (incrementIndex > 0) {
guess[incrementIndex] = 'a';
}
incrementIndex--;
}
else {
break;
}
}
} while (guess[0] <= 'z');
}
public class GenerateCombinations {
public static void main(String[] args) {
List<Character> characters = new ArrayList<Character>();
for (char c = 'a'; c <= 'z'; c++) {
characters.add(c);
}
List<String> allStrings = new ArrayList<String>();
for (Character c : characters) {
for (Character d : characters) {
for (Character e : characters) {
for (Character f : characters) {
String s = "" + c + d + e + f;
allStrings.add(s);
}
}
}
}
System.out.println(allStrings.size()); // 456 976 combinations
}
}
This is something you can do recursively.
Lets define every (n)-character password the set of all (n-1)-character passwords, prefixed with each of the letters a thru z. So there are 26 times as many (n)-character passwords as there are (n-1)-character passwords. Keep in mind that this is for passwords consisting of lower-case letters. Obviously, you can increase the range of each letter quite easily.
Now that you've defined the recursive relationship, you just need the terminating condition.
That would be the fact that there is only one (0)-character password, that being the empty string.
So here's the recursive function:
def printNCharacterPasswords (prefix, num):
if num == 0:
print prefix
return
foreach letter in 'a'..'z':
printNCharacterPasswords (prefix + letter, num - 1)
to be called with:
printNCharacterPasswords ("", 4)
And, since Python is such a wonderful pseudo-code language, you can see it in action with only the first five letters:
def printNCharacterPasswords (prefix, num):
if num == 0:
print prefix
return
for letter in ('a', 'b', 'c', 'd', 'e'):
printNCharacterPasswords (prefix + letter, num - 1)
printNCharacterPasswords ("", 2)
which outputs:
aa
ab
ac
ad
ae
ba
bb
bc
bd
be
ca
cb
cc
cd
ce
da
db
dc
dd
de
ea
eb
ec
ed
ee
A aroth points out, using a digit counter approach is faster. To make this even faster, you can use a combination of an inner loop for the last digit and a counter for the rest (so the number of digits can be variable)
public static void main(String... args) {
long start = System.nanoTime();
int letters = 26;
int count = 6;
final int combinations = (int) Math.pow(letters, count);
char[] chars = new char[count];
Arrays.fill(chars, 'a');
final int last = count - 1;
OUTER:
while (true) {
for (chars[last] = 'a'; chars[last] <= 'z'; chars[last]+=2) {
newComination(chars);
chars[last]++;
newComination(chars);
}
UPDATED:
{
for (int i = last - 1; i >= 0; i--) {
if (chars[i]++ >= 'z')
chars[i] = 'a';
else
break UPDATED;
}
// overflow;
break OUTER;
}
}
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds to generate %,d combinations%n", time / 1e9, combinations);
}
private static void newComination(char[] chars) {
}
prints
Took 0.115 seconds to generate 308,915,776 combinations
Note: the loop is so simple, its highly likely that the JIT can eliminate key pieces of code (after in-lining newCombination) and the reason its so fast is its not really calculating every combination.
A simpler way to generate combinations.
long start = System.nanoTime();
int letters = 26;
int count = 6;
final int combinations = (int) Math.pow(letters, count);
StringBuilder sb = new StringBuilder(count);
for (int i = 0; i < combinations; i++) {
sb.setLength(0);
for (int j = 0, i2 = i; j < count; j++, i2 /= letters)
sb.insert(0, (char) ('a' + i2 % letters));
// System.out.println(sb);
}
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds to generate %,d combinations%n", time / 1e9, combinations);
prints
aaaa
aaab
aaac
....
zzzx
zzzy
zzzz
Took 0.785 seconds to generate 456,976 combinations
It spends most of its time waiting for the screen to update. ;)
If you comment out the line which prints the combinations, and increase the count to 5 and 6
Took 0.671 seconds to generate 11,881,376 combinations
Took 15.653 seconds to generate 308,915,776 combinations
public class AnagramEngine {
private static int[] anagramIndex;
public AnagramEngine(String str) {
AnagramEngine.generate(str);
}
private static void generate(String str) {
java.util.Map<Integer, Character> anagram = new java.util.HashMap<Integer, Character>();
for(int i = 0; i < str.length(); i++) {
anagram.put((i+1), str.charAt(i));
}
anagramIndex = new int[size(str.length())];
StringBuffer rev = new StringBuffer(AnagramEngine.start(str)+"").reverse();
int end = Integer.parseInt(rev.toString());
for(int i = AnagramEngine.start(str), index = 0; i <= end; i++){
if(AnagramEngine.isOrder(i))
anagramIndex[index++] = i;
}
for(int i = 0; i < anagramIndex.length; i++) {
StringBuffer toGet = new StringBuffer(anagramIndex[i] + "");
for(int j = 0; j < str.length(); j++) {
System.out.print(anagram.get(Integer.parseInt(Character.toString(toGet.charAt(j)))));
}
System.out.print("\n");
}
System.out.print(size(str.length()) + " iterations");
}
private static boolean isOrder(int num) {
java.util.Vector<Integer> list = new java.util.Vector<Integer>();
String str = Integer.toString(num);
char[] digits = str.toCharArray();
for(char vecDigits : digits)
list.add(Integer.parseInt(Character.toString(vecDigits)));
int[] nums = new int[str.length()];
for(int i = 0; i < nums.length; i++)
nums[i] = i+1;
for(int i = 0; i < nums.length; i++) {
if(!list.contains(nums[i]))
return false;
}
return true;
}
private static int start(String str) {
StringBuffer num = new StringBuffer("");
for(int i = 1; i <= str.length(); i++)
num.append(Integer.toString(i));
return Integer.parseInt(num.toString());
}
private static int size(int num) {
int size;
if(num == 1) {
return 1;
}
else {
size = num * size(num - 1);
}
return size;
}
public static void main(final String[] args) {
final java.util.Scanner sc = new java.util.Scanner(System.in);
System.out.printf("\n%s\t", "Entered word:");
String word = sc.nextLine();
System.out.printf("\n");
new AnagramEngine(word);
}
}
Put all the characters you expect the password to contain into an array. Write a stub function to test if your algorithm finds the correct password. Start with passwords of length 1, work your way up to 4 and see if your fake password is found on each iteration.
you can use the following code for getting random string. It will return you a string of 32 chars. you can get string of desired length by using substring(). Like if you want a string with 10 chars then:
import java.security.SecureRandom;
import java.math.BigInteger;
SecureRandom srandom = new SecureRandom();
String rand = new BigInteger(176, srandom).toString(32);
rand.substring(0,7);

uppercase random number of characters from a random alphanumeric string

I have some random string with unknown content, what is known is that the content is alphanumeric and in lower case.
I am looking for a simple method to upper case a random number of the alpha characters in that string. The higher the randomness the better.
I can think of a few ways to do this, but none of them seem very optimal.
alright first solution:
public String randomizeCase(String myString){
Random rand = new Random();
StringBuilder build = new StringBuilder();
for(char c: myString.toCharArray()){
String s = new String(c);
if(Character.isLetter(c) && rand.nextBoolean()){
s = s.toUpperCase();
}
build.append(s);
}
return build.toString();
}
I dont like this solution because:
50% chance that every char is uppercased does not equal 50% chance that 50% of the chars are uppercased
There is a chance that nothing is upped cased
char to string conversion is ugly
The solution depends on the probabilistic model you choose. If for example you decide on binomial distribution, then you can traverse the chars, and switch every char to uppercase with a fixed probability p. The expected number of uppercase letters will be p * str.length():
public static String randomUpper(String str, double p) {
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (Character.isLetter(c) && Math.random() < p)
c = Character.toUpperCase(c);
sb.append(c);
}
return sb.toString();
}
If on the other hand you want to decide on the exact number of upercase letters for a given string, then the problem becomes a random sample problem (i.e. choose M positions to switch out of N positions in the string). This can be much faster than the first approach, when M is much smaller than N (though with Java's immutable strings the difference becomes minor because you have to copy the whole string anyway).
-- edit --
Now that you clarified the requirements, consider the following:
public static String randomUpper2(String str, double p) {
int letters = 0;
for (int i = 0; i < str.length(); i++) {
if (Character.isLetter(str.charAt(i)))
letters++;
}
int toChoose = (int) (p * letters);
StringBuilder sb = new StringBuilder(str.length());
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (Character.isLetter(c)) {
if (Math.random() < (toChoose/(double)letters)) {
c = Character.toUpperCase(c);
toChoose--;
}
letters--;
}
sb.append(c);
}
return sb.toString();
}
This code performs a random sample "on the fly", considering only alpha chars, as required. Use p=0.5 to switch exactly half of the letters.
Here is the code snippet for random sample problem (thanks Eyal for naming it). Not sure if that is what you are looking for.
Be aware, that this solution would run into an infinete loop if not enough lowercase letters are in the string. So you would need to tackle that as well, but I guess it is a starting point. ;-)
String myString = "9aie3ra3nr23rr5r21t";
System.out.println(upperCaseRandom(myString, 10));
public static String upperCaseRandom(String input, int n) {
StringBuilder output = new StringBuilder(input);
Random r = new Random();
for (int i = 0; i < n; i++) {
// Pick a place
int position = r.nextInt(input.length());
// Check if lowercase alpha
if (Character.isLowerCase(output.charAt(position))) {
output.setCharAt(position, Character.toUpperCase(output.charAt(position)));
} else {
i--;
}
}
return output.toString();
}
Edit:
Here is an improved version. It does change exactly n lowercase letters into uppercase letters (if there are enough, otherwise it changes all of them). The programm does not run into infinite loops, but still running time is a problem though.
public static String upperCaseRandom(String input, int n) {
final int length = input.length();
final StringBuilder output = new StringBuilder(input);
final boolean[] alreadyChecked = new boolean[length];
final Random r = new Random();
for (int i = 0, checks = 0; i < n && checks < length; i++) {
// Pick a place
int position = r.nextInt(length);
// Check if lowercase alpha
if (!alreadyChecked[position]) {
if (Character.isLowerCase(output.charAt(position))) {
output.setCharAt(position, Character.toUpperCase(output.charAt(position)));
} else {
i--;
}
checks++;
alreadyChecked[position] = true;
} else {
i--;
}
}
return output.toString();
}
I tried with
String lowerCasedRandomString = "4210281f-76ac-96b5-ed54-5458abf788d0";
String upperCasedRandomString = "4210281F-76AC-96B5-ED54-5458ABF788D0";
System.out.println(lowerCasedRandomString.toUpperCase());
System.out.println(upperCasedRandomString.toLowerCase());
I got the output
4210281F-76AC-96B5-ED54-5458ABF788D0
4210281f-76ac-96b5-ed54-5458abf788d0

Categories

Resources