I have a test for a class that displays a word randomly chosen from an array.
I'm trying to display the word with several chars hidden
I have taken the string, then converted it to an array of chars, but I'm confused as to where to go from here.
import java.util.Scanner;
public class wordTest {
public static void main (String args[])
{
Scanner scanner = new Scanner(System.in);
String readString = scanner.nextLine();
char[] stringArray;
String [] gamewords = { "dog", "cat", "coffee", "tag", "godzilla", "gamera", "lightning", "flash", "spoon", "steak", "moonshine", "whiskey", "tango", "foxtrot", "ganymede"
, "saturn", "enterprise", "reliant", "defiant", "doom", "galapagos", "jidai", "sengoku"};
arrayWords wl = new arrayWords();
// Words w = new Words();
Word n = new Word();
int a = 0;
int b = gamewords.length;
RandNum rand = new RandNum(a,b);
n.setWord(gamewords[rand.nextRandomIntegerInRange()]);
stringArray = n.getWord().toCharArray();
int blank1 = 1;
int blank2 = 4;
RandNum blanks = new RandNum(blank1,blank2);
n.setWord(gamewords[rand.nextRandomIntegerInRange()]);
do{
int i = 0;
//scanner.nextLine();
for( i = 0; i < stringArray.length; i++){
for( i = 0 ; i < blanks.nextRandomIntegerInRange() ; i++ ){
stringArray[i] = '*';
}
System.out.println(stringArray[i]);
}
}while(scanner.nextLine().equals(""));
}
}
Since you haven't given clear definition on what you want to do, here I assume for every string, you are randomly masking 2 characters, in pseudo code, it looks like:
if inputString.length < 2 {
mask all character
} else {
loop until 2 character masked {
r = random from 0 to inputString.length-1
if (inputString[r] is not masked) {
set inputString[r] to mask character
}
}
}
some hints:
to make "inputString" modifiable, make use of a StringBuilder
Way to check if certain position is masked, you can either simply check if the character in the string == mask character, or you can use a Set to keep all masked position
In order to find out number of position masked, you can keep a counter, or simply use the size of the Set in 2 if you choose to use a Set.
Okay, so I think I've found the solution:
for (int i = 0; i < stringArray.length ; i++) {
stringArray[blanks.nextRandomIntegerInRange()] = '_';
System.out.print(stringArray[i] + " " );
}
Related
I'm trying to get a printout of all variations of a certain String. For example, we have this input: AB0C0. The 0 in the 3rd and 5th spots should be treated as variables. The variable characters are 1, 2, and 3 to be placed in the spot of 0. This means there would be all possible variations of this input:
AB1C1
AB2C1
AB3C1
AB1C2
AB1C3
AB2C2
AB2C3
AB3C2
AB3C3
This is just an example. A 5-character long string is a place for 1 to 5 variables. The issue I'm facing is, that it should generate all variations no matter how many variables are in the input in no matter in which place they are.
Scanner scanner = new Scanner (System.in);
System.out.println("Enter the key consisting of 5 characters:");
String input = scanner.next();
String strOutput1 = input.replaceFirst("0","1");
String strOutput1A = input.replace("0","1");
String strOutput2 = input.replaceFirst("0","2");
String strOutput3 = input.replaceFirst("0","3");
String strOutput4 = input.replaceFirst("0","4");
String strOutput5 = input.replaceFirst("0","5");
System.out.println(strOutput1.toUpperCase());
System.out.println(strOutput1A.toUpperCase());
System.out.println(strOutput2.toUpperCase());
System.out.println(strOutput3.toUpperCase());
System.out.println(strOutput4.toUpperCase());
System.out.println(strOutput5.toUpperCase());
What about this:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the key consisting of 5 characters:");
String input = scanner.next();
//find positions of '0' in input
List<Integer> varPositions = findVarPositions(input);
//create permutations
List<String> permutations = new ArrayList<>();
permutations.add(input);//AB0C0
for (int position : varPositions) {
permutations = permutateAtPosition(permutations, position);
}
//print permutations
for (String permutation : permutations) {
System.out.println(permutation.toUpperCase());
}
}
private static List<Integer> findVarPositions(String input) {
List<Integer> varPositions = new ArrayList<>();
int lastVarPosition = -1;
while ((lastVarPosition = input.indexOf('0', lastVarPosition + 1)) != -1) {
varPositions.add(lastVarPosition);
}
return varPositions;
}
private static List<String> permutateAtPosition(List<String> partialyPermutated, int position) {
List<String> result = new ArrayList<>();
char[] replacements = {'1', '2', '3', '4', '5'};
for (String item : partialyPermutated) {
for (int i = 0; i < replacements.length; i++) {
String output = replaceCharAt(item, position, replacements[i]);
result.add(output);
}
}
return result;
}
private static String replaceCharAt(String input, int position, char replacement) {
//converting to char array, because there's no method like
//String.replaceAtPosition(position, char)
char[] charArray = input.toCharArray();
charArray[position] = replacement;
return new String(charArray);
}
}
It's not fixed to a number of variables.
The idea is to extract positions of '0' and subsequently call the method permutateAtPosition, which takes a partially permutated list and permutates it by one more level.
For "a0b0c0" and values 1-2 it would be ['a0b0c0'], then ['a1b0c0','a2b0c0'], then ['a1b1c0','a1b2c0','a2b1c0','a2b2c0'], and finally ['a1b1c1','a1b1c2','a1b2c1','a1b2c2','a2b1c1','a2b1c2','a2b2c1''a2b2c2'].
This solution keeps everything in memory, so in the general case (unlimited input string) it would be wiser to go with depth-first instead.
I've got another solution for you.
First step, getting the amount of variables:
int variableCount = 0;
for (int i = 0; i < 5; i++) {
if (input.charAt(i) == '0') {
variableCount++;
}
}
Then calculating the amount of results we are expecting:
int countMax = (int)Math.pow(4,variableCount);
Lastly, count up in base 4. Pad the number with 0's and replace the original input 0's:
for (int i = 0; i < countMax; i++) {
String paddedNumbers = format("%" + variableCount + "s",Integer.toString(i, 4)).replace(" ", "0");
int replacedCount = 0;
char[] outputChars = input.toCharArray();
for (int j = 0; j < 5; j++) {
if (input.charAt(j) == '0') {
outputChars[j] = paddedNumbers.charAt(replacedCount);
replacedCount++;
}
}
System.out.println(outputChars);
}
I am trying to create a program that outputs ten lowercase letter characters - five vowels and five consonants. In order to do this, I have started by creating a char array with a range between 'a' and 'z' called letters[] with size 10. Once the array is filled, I will print the output with the use of a format string containing everything in the array.
My question is, how would I make the program output exactly five of each type (and keep the order of the characters printed completely random)? I have considered using the switch statement with a case each for consonants and vowels, but my ideas so far seem over-complicated and inelegant.
Code so far:
char letters[] = new char[10];
for(int i = 0; i < letters.length; i++){ //Open for
letters[i] = (char)(97 + Math.random() * 26);
char idx = letters[i];
System.out.printf("%s",idx);
} //End for
If you don't mind a somewhat more String-related solution, here is one. I am assuming that you don't want any consonant or vowel repeated in the output string, so this algorithm removes letters for consideration once they've been used. It also provides a bit more of a generic letter picker routine that's not really limited to vowels and consonants.
import java.lang.StringBuilder;
public class Shuffler {
public static String CONSONANTS = "bcdfghjklmnpqrstvwxyz";
public static String VOWELS = "aeiou";
/*
* Returns a new string that is a combination of the current string and 'count'
* characters from the source string (using any character in the source string
* no more than one time).
*/
public static String shuffleIntoString(String current, String source, int count) {
if (current == null || source == null || count < 0 || count > source.length()) {
System.out.println("Error in parameters to shuffleIntoString");
return null;
}
StringBuilder retval = new StringBuilder(current); // build up by inserting at random locations
StringBuilder depletedSource = new StringBuilder(source); // remove characters as they are used
for (int i = 0; i < count; i++) {
int pick = (int) (Math.random() * depletedSource.length());
int whereToInsert = (int) (Math.random() * retval.length());
retval = retval.insert(whereToInsert, depletedSource.charAt(pick));
depletedSource.deleteCharAt(pick);
}
return retval.toString();
}
public static void main(String[] args) {
Shuffler shuf = new Shuffler();
for (int i = 0; i < 10; i++) {
String result = shuf.shuffleIntoString("", shuf.CONSONANTS, 5);
result = shuf.shuffleIntoString(result, shuf.VOWELS, 5);
System.out.println(result);
}
}
}
And the output looks like this:
kqoibauzed
uhcawoerib
afdzoemius
yuagocibej
eiuhaokcyq
ouveiawrxn
uyaiveomxn
ruxeoalhij
uraliwfeoc
afoutiesmr
This will achieve what you desire if you are content with using ArrayLists. To generate the random chars you could generate a number within the index of the corresponding char Strings and add the value to the ArrayList. Collections is a helpful Class that you can use to shuffle the list.
List<Character> list = new ArrayList<>();
String consonants = "bcdfghjklmnpqrstvwxyz";
String vowels = "aeiou";
Random r = new Random();
for (int i = 0; i < 5; i++) {
list.add(consonants.charAt(r.nextInt(consonants.length()))); // Add consonant
list.add(vowels.charAt(r.nextInt(vowels.length()))); // Add vowel
}
Collections.shuffle(list);
for (Character c : list) {
System.out.println(c);
}
I don't seen any rules about duplicated but if you want you can remove latters from arrays after selection.
List<Character> vowels = Arrays.asList('a', 'e', 'i', 'o', 'u');
List<Character> consonants = new ArrayList<>();
for (char latter = 'a'; latter <= 'z'; latter++) {
if(!vowels.contains(latter)) {
consonants.add(latter);
}
}
final Random random = new Random();
int vowelsRemain = 5;
int consonantsRemain = 5;
List<Character> result = new ArrayList<>();
while (vowelsRemain > 0 && consonantsRemain > 0) {
final boolean generateVowel = random.nextBoolean();
final char randomLatter;
if(generateVowel) {
randomLatter = vowels.get(random.nextInt(vowels.size()));
vowelsRemain--;
} else {
randomLatter = consonants.get(random.nextInt(consonants.size()));
consonantsRemain--;
}
result.add(randomLatter);
}
while (vowelsRemain > 0) {
final Character randomVowel = vowels.get(random.nextInt(vowels.size()));
result.add(randomVowel);
vowelsRemain--;
}
while (consonantsRemain > 0) {
final Character randomConsonant = consonants.get(random.nextInt(consonants.size()));
result.add(randomConsonant);
consonantsRemain--;
}
System.out.println(result);
I need to get a new string based on an old one and a lag. Basically, I have a string with the alphabet (s = "abc...xyz") and based on a lag (i.e. 3), the new string should replace the characters in a string I type with the character placed some positions forward (lag). If, let's say, I type "cde" as my string, the output should be "fgh". If any other character is added in the string (apart from space - " "), it should be removed. Here is what I tried, but it doesn't work :
String code = "abcdefghijklmnopqrstuvwxyzabcd"; //my lag is 4 and I added the first 4 characters to
char old; //avoid OutOfRange issues
char nou;
for (int i = 0; i < code.length() - lag; ++i)
{
old = code.charAt(i);
//System.out.print(old + " ");
nou = code.charAt(i + lag);
//System.out.println(nou + " ");
// if (s.indexOf(old) != 0)
// {
s = s.replace(old, nou);
// }
}
I commented the outputs for old and nou (new, but is reserved word) because I have used them only to test if the code from position i to i + lag is working (and it is), but if I uncomment the if statement, it doesn't do anything and I leave it like this, it keeps executing the instructions inside the for statmement for code.length() times, but my string doesn't need to be so long. I have also tried to make the for statement like below, but I got lost.
for (int i = 0; i < s.length(); ++i)
{
....
}
Could you help me with this? Or maybe some advices about how I should think the algorithm?
Thanks!
It doesn't work because, as the javadoc of replace() says:
Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
(emphasis mine)
So, the first time you meet an 'a' in the string, you replace all the 'a's by 'd'. But then you go to the next char, and if it's a 'd' that was an 'a' before, you replace it once again, etc. etc.
You shouldn't use replace() at all. Instead, you should simply build a new string, using a StringBuilder, by appending each shifted character of the original string:
String dictionary = "abcdefghijklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder(input.length());
for (int i = 0; i < input.length(); i++) {
char oldChar = input.charAt(i);
int oldCharPositionInDictionary = dictionary.indexOf(oldChar);
if (oldCharPositionInDictionary >= 0) {
int newCharPositionInDictionary =
(oldCharPositionInDictionary + lag) % dictionary.length();
sb.append(dictionary.charAt(newCharPositionInDictionary));
}
else if (oldChar == ' ') {
sb.append(' ');
}
}
String result = sb.toString();
Try this:
Convert the string to char array.
iterate over each char array and change the char by adding lag
create new String just once (instead of loop) with new String passing char array.
String code = "abcdefghijklmnopqrstuvwxyzabcd";
String s = "abcdef";
char[] ch = s.toCharArray();
char[] codes = code.toCharArray();
for (int i = 0; i < ch.length; ++i)
{
ch[i] = codes[ch[i] - 'a' + 3];
}
String str = new String(ch);
System.out.println(str);
}
My answer is something like this.
It returns one more index to every character.
It reverses every String.
Have a good day!
package org.owls.sof;
import java.util.Scanner;
public class Main {
private static final String CODE = "abcdefghijklmnopqrstuvwxyz"; //my lag is 4 and I added the first 4 characters to
#SuppressWarnings("resource")
public static void main(String[] args) {
System.out.print("insert alphabet >> ");
Scanner scanner = new Scanner(System.in);
String s = scanner.next();
char[] char_arr = s.toCharArray();
for(int i = 0; i < char_arr.length; i++){
int order = CODE.indexOf(char_arr[i]) + 1;
if(order%CODE.length() == 0){
char_arr[i] = CODE.charAt(0);
}else{
char_arr[i] = CODE.charAt(order);
}
}
System.out.println(new String(char_arr));
//reverse
System.out.println(reverse(new String(char_arr)));
}
private static String reverse (String str) {
char[] char_arr = str.toCharArray();
for(int i = 0; i < char_arr.length/2; i++){
char tmp = char_arr[i];
char_arr[i] = char_arr[char_arr.length - i - 1];
char_arr[char_arr.length - i - 1] = tmp;
}
return new String(char_arr);
}
}
String alpha = "abcdefghijklmnopqrstuvwxyzabcd"; // alphabet
int N = alpha.length();
int lag = 3; // shift value
String s = "cde"; // input
StringBuilder sb = new StringBuilder();
for (int i = 0, index; i < s.length(); i++) {
index = s.charAt(i) - 'a';
sb.append(alpha.charAt((index + lag) % N));
}
String op = sb.toString(); // output
import java.util.Scanner;
/**
*
* #author Cutuk
*/
public class JavaApplication3 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
String a;
Scanner in = new Scanner (System.in);
a = in.nextLine();
char first = a.charAt(0);
System.out.print(first);
int v= a.length()-1;
char last = a.charAt(v);
int k= a.length();
int random=0;
char x='\u0000';
char middle= '\u0000' ;
for (int i=1; i<a.length()-1;i++){
random= (int )(Math.random() * (k-2) + 1);
middle=a.charAt(random);
x=middle;
System.out.print(x);
}
System.out.print(last);
}
}
I am supposed to take a word, shuffle the letters inside, but keep the first and the last letter unchanged. I managed to randomize, but I cannot keep it from repeating.
Your approach is incorrect: when you pick middle letters at random, it is impossible to guarantee that all letters from the middle of the word would be printed (and as a consequence, that other letters would not be repeated).
There are several ways of fixing this:
Each time you generate a random index, mark that index in an array of booleans. The length of the array is equal to the length of the word. Check the array before using each new index that you generate; if the index is marked, continue generating new random indexes until you hit an empty one.
Create an array of integer indexes of letters inside the word (i.e. 1 through length-1, inclusive). Do a random shuffle on the array, and use the shuffled indexes to pick middle letters.
Similar to 2, except you put all middle letters in an array, and shuffle it.
If I understand your question, I would suggest you start by building a List<Character> and then use Collections.shuffle(List) and finally build your return String with a StringBuilder like
private static String shuffleLetters(String in) {
if (in == null || in.length() < 3) {
return in;
}
char first = in.charAt(0);
char last = in.charAt(in.length() - 1);
List<Character> chars = new ArrayList<>();
for (char ch : in.substring(1, in.length() - 1).toCharArray()) {
chars.add(ch);
}
Collections.shuffle(chars);
StringBuilder sb = new StringBuilder();
sb.append(first);
for (char ch : chars) {
sb.append(ch);
}
sb.append(last);
return sb.toString();
}
Assuming "shuffling" can allow a middle character to sometimes be swapped with itself, you can do something like:
private static final String[] TEST_WORDS = {"apple", "banana", "pear", "raspberry", "cucumber", "watermelon", "a", "ab", "", null};
public static void main(String[] args)
{
for (String word: TEST_WORDS)
{
System.out.println(shuffleInside(word));
}
}
private static String shuffleInside(String word)
{
String ret = word;
if (word != null)
{
Random r = new Random();
int strLen = word.length();
if (strLen > 2)
{
char[] middleChars = word.substring(1, strLen - 1).toCharArray();
shuffle(middleChars, r);
ret = word.charAt(0) + new String(middleChars) + word.charAt(strLen - 1);
}
}
return ret;
}
private static void shuffle(char[] chars, Random r)
{
for (int i = chars.length - 1; i > 0; i--)
{
int index = r.nextInt(i + 1);
char c = chars[index];
chars[index] = chars[i];
chars[i] = c;
}
}
Which handles the case where the word is null, one character, two characters, or two or more characters and produces the following output on a single run:
apple
bnaana
paer
rerrsbpay
cbuemucr
waomteerln
a
ab
null
You could simply create a List<Integer> for storing the random numbers that you generated.
Here is your code from above, cleaned up, with meaningful naming and the List for looking up the history:
public class Main {
public static void main(String[] args) {
final Scanner in = new Scanner(System.in);
final Random rnd = new Random(System.currentTimeMillis());
final List<Integer> rndHistory = new LinkedList<>(); // <-- your history
System.out.print("Please type a word: ");
final String input = in.nextLine();
System.out.print(input.charAt(0));
for (int i = 1, random = 0; i < input.length() - 1; i++) {
do {
random = rnd.nextInt(input.length() - 2) + 1;
} while (rndHistory.contains(random)); // check the history
rndHistory.add(random); // add to the history
System.out.print(input.charAt(random));
}
System.out.println(input.charAt(input.length() - 1));
}
}
Main differences:
final Random rnd = new Random(System.currentTimeMillis()); Using
the the java.util.Random class is a better way for generating
random numbers.
final List<Integer> rndHistory = new LinkedList<>(); This is the actual difference, part of the mechanism to prevent double shuffles
System.out.print("Please type a word: "); a meaningful prompt for
the user (who is going to know what to do, when you program is
executed and there is nothing on the screen?)
and finally:
do {
random = rnd.nextInt(input.length() - 2) + 1;
} while (rndHistory.contains(random)); // check the history
rndHistory.add(random); // add to the history
The 'prevent a random number from being used twice' mechanics
For your random try this: Random generator = new Random(System.currentTimeMillis());
I have written a code for random password generation.There are a string from where i have to make the password.so i try to categorize the string according to uppercase array , lower case array and digit array. but here comes a problem when..
for(int k=0;k<Length;k++){
if(asc[k]>=65 && asc[k]<=90){
UpperCase[k]=(char)asc[k];
}
else if(asc[k]>=48 && asc[k]<=57){
Digit[k]=(char)asc[k];
}
else {
Mixed[k]=(char)asc[k];
}
}
is executed it counts some space which i don't want.coding looks like ugly sry for my poor coding.i know there is a lot more way to solve it but i want to go through this.here is my code. here is my code
import java.util.Random;
public class Randompassgeneration
{
final int MAX_LENGTH = 20;
final int MIN_LENGTH = 3;
char[] password=new char[25];
int [] asc=new int[18];
char[] UpperCase=new char[25];
char[] Digit=new char[25];
char[] Mixed=new char[25];
public void generate(String allowedCharacters)
{
int Length=allowedCharacters.length();
for (int i=0;i<Length;i++)
{
asc[i]=(int)allowedCharacters.charAt(i);
}
for (int k=0;k<Length;k++)
{
if (asc[k]>=65 && asc[k]<=90)
{
UpperCase[k]=(char)asc[k];
}
else if (asc[k]>=48 && asc[k]<=57)
{
Digit[k]=(char)asc[k];
}
else
{
Mixed[k]=(char)asc[k];
}
}
String rp=null;
StringBuilder Strbld=new StringBuilder();
Random rnd=new Random();
int ranStrLen=rnd.nextInt(MAX_LENGTH - MIN_LENGTH + 1) + MIN_LENGTH;
Strbld.append(UpperCase[rnd.nextInt(UpperCase.length)]);
Strbld.append(Digit[rnd.nextInt(Digit.length)]);
for (int m=0; m<ranStrLen-2; m++)
{
Strbld.append(Mixed[rnd.nextInt(Mixed.length)]);
}
System.out.print(ranStrLen +"->"+ Strbld.toString());
}
public static void main(String[] args)
{
String allowedCharacters = "weakPasSWorD1234$*";
Randompassgeneration t=new Randompassgeneration();
t.generate(allowedCharacters);
}
}
Any kind of suggestion?
I would generate the minimum number of characters, digits and symbols. Fill the other characters randomly and shuffle the result. This way it will comply with your minimum requirements with a minimum of effort.
public static String passwordGenerator() {
List<Character> chars = new ArrayList<>();
Random rand = new Random();
// min number of digits
for (int i = 0; i < 1; i++) chars.add((char) ('0' + rand.nextInt(10)));
// min number of lower case
for (int i = 0; i < 2; i++) chars.add((char) ('a' + rand.nextInt(26)));
// min number of upper case
for (int i = 0; i < 1; i++) chars.add((char) ('A' + rand.nextInt(26)));
// min number of symbols
String symbols = "!\"$%^&*()_+{}:#~<>?,./;'#][=-\\|'";
for (int i = 0; i < 1; i++) chars.add(symbols.charAt(rand.nextInt(symbols.length())));
// fill in the rest
while (chars.size() < 8) chars.add((char) ('!' + rand.nextInt(93)));
// appear in a random order
Collections.shuffle(chars);
// turn into a String
char[] arr = new char[chars.size()];
for (int i = 0; i < chars.size(); i++) arr[i] = chars.get(i);
return new String(arr);
}
public static void main(String... args) {
for (int i = 0; i < 100; i++)
System.out.println(passwordGenerator());
}
"is executed it counts some space which i don't want"
The white space is beacuse of your For loop
You were using the variable k for all the arrays,which resulted into the incremented value of k each time.So,this was making "gaps" between your arrays.
Change it to:
int point1=0,point2=0,point3=0;
for (int k=0;k<Length;k++)
{
if (asc[k]>=65 && asc[k]<=90)
{
UpperCase[point1]=(char)asc[k];point1++;
continue;
}
else if (asc[k]>=48 && asc[k]<=57)
{
Digit[point2]=(char)asc[k];point2++;
continue;
}
else
{
Mixed[point3]=(char)asc[k];point3++;
}
}
System.out.println(UpperCase);
System.out.println(Digit);
System.out.println(Mixed);
OutPut:
PSWD
1234
weakasor$*
Ok if not mistaken you want to parse the password generated and want put them in separate array. Here is the snippet for uppercase.
ArrayList<Character> uppercase = new ArrayList<Character>();
char pass[] = password.toCharArray();
for(char c: pass){
if(Character.isUpperCase(c))
uppercase.add(c);
}
If you want a random string, you could do:
public String getRandomString(){
return UUID.randomUUID().toString();
}
If you want to make it consistent with some source String, you could do:
public String getConsistentHash(String source){
return UUID.nameUUIDFromBytes(source.getBytes()).toString();
}
This latter method will return the same String for the same source String.
If there is a only a limited set of characters you want to use, you could just replace the unwanted chars. Suppose you have have created "randomString" as above, you create "randomString1" with:
randomString1 = UUID.fromString(randomString);
Now replace the unwanted chars in "randomString" with the chars in "randomString1". You could repeat this if necessary.
If you do not care for a minimum size/spread, you could just remove the chars.
Good luck.