I want to print three random characters, chosen from a given string. But I have no idea how to do random things like this!
See the "Bonus Opportunity" in this question.
Here is my code, split into 2 parts with the extra credit part being on the right side.
It depends on what "random" means in this case.
Weighted probability
If repeating characters should be given a higher chance of being chosen, simply concatenate the first name, middle name, and last name into one string:
String s = first + middle + last;
Then generate a random number between 0 and the length of the string:
Random r = new Random();
int R = r.nextInt(s.length());
Use this random number to index the particular character:
output_character = s.charAt(R);
Repeat as many times as desired.
Equal probability
If each of the characters are to have the same probability as the others, you will need to push unique characters into a list and repeat the same procedure as described above.
It is a little dishonest, academically, to ask for the solution to a homework question. It would be a bit less problematic if you'd do a little thinking on your own.
As #Zar mentioned in the comment above, asking something like "How do I get a random character in Java" would be simpler, and would give you what you need to answer the question without asking someone else to hand it to you.
import java.util.Random;
public class RandomAddingTest {
public static void main(String[] args){
System.out.println(returnNewPass("abcabc"));
//display something like:[abcabcwMS][abcabcCln][abcabc?p=]...so on
}
public static String returnNewPass(String oldPass){
StringBuilder sb = new StringBuilder(oldPass);
Random ran = new Random();
char c ;
for (int i = 0; i<3; i++){
c = (char)(ran.nextInt(93)+33);//ran will generate A~Z,a~z,0~9,##$%^&*...so on
sb.append(c);
}
return sb.toString();
}
}
Related
This question already has answers here:
Using Regex to generate Strings rather than match them
(12 answers)
Closed 9 months ago.
This post was edited and submitted for review 9 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I am trying to write a program that would ask the user how many security codes he wants to generate, then it would output as many codes as he requested in an array.
The security code should be 7 characters long and have the following format: NNNNLLL, where N is a random number and L is a random upper case letter.
The method should create security codes with the above format by randomly selecting the characters, i.e. numbers and letters.
I am expecting the program to output something like this if a user selects to generate 4 codes:
“2394QAB”
“2821TSZ”
“7173AAY”
“2236WQA”
I can only use the methods for this code learned in my course and I cannot use other libraries like regex, that is why I am trying it like this.
This is the code I have done so far:
import java.util.Random;
public class ItemChecker{
private StringBuffer strBuff;
private String[] codes;
private String CodeLetters, CodeNumbers;
private int[] RandomNums;
public ItemChecker(){
strBuff=new StringBuffer();
}
public String[] getCodes(int[] amount){
codes=new String[amount.length];
for(int i=0;i<amount.length;i++)
{
CodeLetters="";
strBuff=new StringBuffer();
for(int j=0;j<4;j++)
{
Random RandomNumber=new Random();
int randomIndex=RandomNumber.nextInt(RandomNums.length);
CodeNumbers.append(RandomNumber[randomIndex]);
}
for(int j=0;j<3;j++)
{
Random RandomLetter=new Random();
char c =(char)(RandomLetter.nextInt(26)+'a');
CodeLetters+=c;
}
codes[i]=CodeNumbers+CodeLetters;
}
}
}
My intention is to create 4 random digits and 3 random letters and add them together in a string to make the code. However, the code doesn't generate the random codes and I have no clue how to proceed from here.
Within your getCodes method there are a couple of mistakes. A StringBuiler would be more appropriate for this task, instead of using a StringBuffer or chaining strings with the + operator. As a matter of fact, each time you're performing a concatenation with the + operator you're creating a new string in memory, rather than working on a same instance, this is not that efficient. Also, when you're adding an offset to the random value representing an upper case letter, you're adding the lower case 'a', instead of the upper case 'A'.
In your program, you could define a static method to offer the code generation service as a general utility and then invoke it within your getCodes method.
In the utility method, you could declare a Random object to get random int values. Then, with a first for loop, you could generate random values between 0 included and 10 excluded, and append them to a StringBuilder object. The String class represents immutable objects, so you need to use a StringBuilder to build one. As said above, chaining strings with the + operator will create new instances at each concatenation, you're not working on the same object.
Then, with a second for loop you could generate random values from 0 to 27 excluded, add to every value the offset 65, representing the upper case 'A' letter (lower case 'a' has value 97), and then cast this int value to a char to get its character representation. Finally, append the char to your StringBuilder instance.
Here is an implementation:
public class Main {
public static void main(String[] args) {
System.out.println(getSecurityCode());
}
public String[] getCodes(int[] amount) {
String[] codes = new String[amount.length];
for (int i = 0; i < codes.length; i++) {
codes[i] = getSecurityCode();
}
return codes;
}
public static String getSecurityCode() {
Random rand = new Random();
StringBuilder strBuilder = new StringBuilder();
//Appending 4 random digits
for (int i = 0; i < 4; i++) {
//nextInt(10) returns a value between 0 (included) and 10 (excluded)
strBuilder.append(rand.nextInt(10));
}
//Appending 3 random upper case letters
for (int i = 0; i < 3; i++) {
//rand.nextInt(27) returns a random value between 0 and 26 included to represent an alphabet letter.
//This value is added with the offset 65 which represents the upper case A letter.
//Finally, this value is cast as a char or else it would append its int value
strBuilder.append((char)(65 + rand.nextInt(27)));
}
return strBuilder.toString();
}
}
To simplify your code that generate the password you could use RandomStringUtils from org.apache.commons.lang3.RandomStringUtils like described in this great tutorial https://www.baeldung.com/java-random-string.
You just have to generate 2 strings :
One with 4 digits
One with 3 letters to uppercase
And concat both.
Here's How
public static String getSecurityCode() {
//generate 4 numbers only
String generatedNumbers = RandomStringUtils.random(4, false, true);
//generate 3 letters only
String generatedLetters = RandomStringUtils.random(3, true, false).toUpperCase();
return generatedNumbers + generatedLetters;
}
Or with StringBuilder
public static String getSecurityCode2() {
StringBuilder stb=new StringBuilder(7);
//generate 4 numbers only
stb.append(RandomStringUtils.random(4, false, true));
//generate 3 letters only
stb.append( RandomStringUtils.random(3, true, false).toUpperCase());
return stb.toString();
}
Another way of doing this is to utilize StringBuilder's appendCodePoint method for this:
int number= random.nextInt(10000); //generate any number between 0 to 9999
StringBuilder builder=new StringBuilder();
for(int i=0;i<3;i++) {
builder.appendCodePoint(65+random.nextInt(26));
}
String result=number+builder.toString();
System.out.println(result);
What I am trying to do is take a hidden String and then display it letter by letter in a random sequence every time the user presses the hint button. Currently, every time the hint button is pressed the entire solution displays once per character of the solution.
I am trying to make it so that when the hint button is pressed a random character from the string solution appears in the correct location. I am unsure about how to compare the location of the generated character to the string location.
public String letterGenerator(int count, String word) {
//String word is taken from another function and it is based on the current displayed card and associated answer
StringBuilder string = new StringBuilder();
Random rng = new Random();
char[] letters = word.toCharArray();
char[] answers = new char[letters.length];
int selected = rng.nextInt(letters.length);
for (int i = 0; i < word.length(); i++) {
if (i == selected) {
letters[i] = answers[i];
}
string.append(letters);
}
return string.toString();
}
For example if the answer is "a wallet" this code outputs the solution as "a walleta walleta walleta walleta walleta walleta walleta walleta" (It displays the output 8 times because it prints the solution once per character including blank spaces)
What it should be doing for each press of the hint button would be to display each character in a random order like so:
Press 1: "_ _ _ l_ _ _"
Press 2: "a _ _ l_ _ _"
Press 3: "a _ _ l _e _", and so on until the entire word appears on screen
Any help is appreciated!
Well, you append(letters) to your output for each iteration of your loop, and letters is an array of all your letters, not just one of them. So of course you end up with that output that you got.
But I think you can design this in a more elegant, and more object-oriented way. Instead of two character arrays for the answer and what is displayed, maybe make just one array of 'Letters'. This means you create a custom class Letter, which could hold the information whether it is 'solved' or not. Like so:
public class Letter{
char character;
boolean solved;
// ... Constructor, Getters, Setters
}
Then, you can just pass your array of letters to a method that selects a random letter that is not solved yet, and simply switch its solved property to true. Your code for displaying the thing to your user would then be something like this:
for(Letter letter : letterArray){
System.out.print(letter.isSolved() ? letter.getCharacter() : "_");
}
If I've understood correctly, then here's a few things to change;
1) You want to remember the last revealed hint, but you've stored it in a local variable.
You'll want a way to store the revealed letters. How you do that depend on how the rest of your class is setup, but either passing it back as part of the method return or setting a global variable should do
2) Since you are remembering the previous hints, you'll want to make sure that 'selected' has not been revealed before. Perhaps store what letter positions have been revealed before and compare against them.
3) I would put the internal of the loop more as
for (int i = 0; i < word.length(); i++) {
if(i == selected){
string.append(letters[i]);
}else{
string.append("_");
}
}
I hope this helps
Edit:
I've changed the for loop, now it should work as you wanted. Sorry I should have been more careful to start with.
As for storing the previously revealed letters, if you are using a Singleton class then it would be acceptable to store this values in another list. My suggestion would be to keep an ArrayList of revealed values, then do something like;
List<Integer> revealed = new ArrayList<>();
Random rng = new Random();
public int getNextSelected(int length){
int selected = rng.nextInt(length);
if(revealed.contains(selected)){
return getNextSelected(length);
}
return selected;
}
public String letterGenerator(int count, String word) {
...
int selected = getNextSelected(letters.length);
for (int i = 0; i < word.length(); i++) {
if (i == selected){
string.append(letters[i]);
} else if (revealed.contains(i)) {
string.append(letters[i]);
} else{
string.append("_");
}
}
revealed.add(selected);
return string.toString();
}
This should do what you need. There's plenty of ways to clean up the code, the suggestion by user3237736 is quite nice as it follows the 'tell don't ask' principle, but the design decisions of the class is up to you
public class SOEN_student {
public static void letterGenerator(String word) {
//String word is taken from another function and
//it is based on the current displayed card and associated answer
StringBuilder string;
Random rng = new Random();
char[] letters = word.toCharArray();
char[] answers = new char[letters.length];
boolean[] visited=new boolean[letters.length];
int selected;
for (int i = 0; i < word.length(); i++) {
do{
selected=rng.nextInt(letters.length);
}while(visited[selected]);
string=new StringBuilder();
for(int j=0;j<word.length();j++){
if(visited[j] | j==selected){
visited[selected]=true;
string.append(letters[j]);
}else{
string.append("_");
}
}
System.out.print(string.toString()+" ");
}
}
public static void main(String... args){
letterGenerator("a wallet");
}
}
This is what the program should do:
The word, zatabracabrac, is not square free, since it has subword, abrac twice start-
ing at position 4 of the word.
We are not allowed to use strings, breaks or other complex stuff. I get the square and square not part but am unable to find its place. I think I went wrong some place like I can't figure it out.
public static void main(String[] args) {
// part (a) of the main
Scanner keyboard = new Scanner(System.in);
System.out.println("***************************");
System.out.println(" Part (a)");
System.out.println("***************************");
do{
System.out.println("Enter a word and then press enter:");
String str=keyboard.next();
char[] word = str.toCharArray();
isSquareFree(word);
System.out.println("Do you want to test another word? Press y for yes, or another key for no");
}while(keyboard.next().charAt(0)=='y');
public static void isSquareFree(char[] word){
int z = 0;
for(int i=0; i<word.length; i++){
for(int j=0; j<word.length-1;j++){
if (word[j] == word[j+1]){
z = 1;
j = word.length;
}
else{
z = 2;
}
}
}
if (z == 1){
System.out.println();
System.out.println("Not Square Free");
}
else{
System.out.println();
System.out.println("Square Free");
}
}
}
Downvotes on the question: this is not where you solve your homework... we all went through having homeworks and solved them (well, most of us), and that's partly why we're capable of helping you.
You're checking whether the word contains two consecutive characters which are the same.
That's not what you want, try another solution.
Here's why it does what I said above:
The outer for loop doesn't have an effect on the inner one, since i is not used inside
Index j and j+1 in the same iteration as a character and the next one
Other notes:
j = word.length is the same as break here, try using that, it stops your loop like the end condition was satisfied; read more: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
For easier testing, you might want to use another main function containing only calls like isSquareFree("zatabracabrac".toCharArray());, even multiple ones to see multiple test results at once
This will greatly reduce the change-compile-run-check cycle's length.
You can use a debugger in an IDE (Eclipse or IntelliJ) to see what your program does.
Without debugging you can use println/print/printf calls to see how many iterations you have and what your values during those iterations.
Hints on solution:
As I see you're essentially looking for consecutive k-length subword duplicates
You phrased it right in the comment, the arbitrary length is giving it another level
At each position i try to look for a subword with length k which has a corresponding match starting at i + k (this helps the consecutive constraint)
k can be anything between a letter and half of the string (more than that is overkill since it cannot repeat twice)
I didn't code it, but it would be my first try
In your examples:
borborygmus
^=>
i
borborygmus
^=>
i+k
With k = 3 there is a match
zatabracabrac
^===>
i
zatabracabrac
^===>
i+k
With k = 5 there is a match
I feel like my logic is decent here; I don't feel like I'm completely lost. However, I do know what exactly I'm doing wrong. I can always find the index of the start of the substring, but I can never find the full count (ex. 3,4,5,6) of the index of whatever word the user enters as the substring.
I have been struggling with this for about a week trying to figure out how to do it on my own, I can't get it right.
import java.util.Scanner;
public class midterm
{
public static void main (String[] args)
{
Scanner keyboard = new Scanner(System.in);
String simplePhrase;
String portionPhrase;
int portionIndex;
int portionCount;
int portionIndexTotal;
System.out.println("Enter a simple phrase:");
simplePhrase = keyboard.nextLine();
int phraseLength = simplePhrase.length();
System.out.println("Phrase length:" +phraseLength);
System.out.println("Enter a portion of previous phrase:");
portionPhrase = keyboard.nextLine();
String portionPhraseSub = simplePhrase.substring(portionPhrase);
portionIndex = simplePhrase.indexOf(portionPhraseSub);
for (portionIndex; portionIndex <= portionPhrase; portionIndex++)
{
System.out.println("Portion phrase index:"+portionIndex);
}
}
}
I'm still confused on what you want. There are just two simple things to know and you seem to be making this more complicated than it needs to be.
To get the index of a single character, such as "c" in the word "acorn", you would do this:
String s = "acorn";
int cIndex = s.indexOf("c");
System.out.println("The index of c is: " + cIndex);
If you want to see if the string contains a chunk, you use the exact same method. So if we are looking at the word "acorn" again and you want to see where "orn" happens, you'd do this:
String s = "acorn";
int ornIndex = s.indexOf("orn");
System.out.println("The index of orn is: " + ornIndex);
Remember that indexes start from 0 in java, so the index of "a" in "acorn" is 0, of "c" is 1, of "o" is 2, and so on.
I hope that helps. Good luck :)
EDIT: You just commented this:
"I guess, my question is one i get my code to compile, How would I go about counting every single letter of my substring?"
I'll answer that as best as I can, though again, that still is a confusing question.
What do you even mean by count" every letter? If you want to break your word into individual letters, you can do something like this:
String s = "acorn";
char[] characters = new char[s.length()-1];
for(int i = 0; i < s.length() - 1; i++) {
char[i] = s.charAt(i);
}
But I have no clue why you'd want to do that...you can always access any character in a string at a given index with STRING.charAt(index), or if you want to have a String result, STRING.substring(index, index+1)
I am creating a program that prompts a first and last name then prints a string composed of the first letter of the user’s first name, followed by the first five characters of the user’s last name, followed by a random number in the range 10 to 99.
I know how to prompt for the name and find the random number but I'm not sure how to
"print a string composed of the first letter of the first name, followed by the first five letters of the last name."
Can anyone help me? I am a very elementary Java programmer.
So I am really close to finishing this but it keeps saying "illegal start of expression" for line 55 and I can't figure it out. Here is my code, sorry, I know it's a mess:
Random generator = new Random();
int num1;
num1 = generator.nextInt(10-99);
line 55: public String substring; <<<
String result;
System.out.println("Result:" + (beginIndex) + (firstname.substring(0,1) + lastname. substring (0,5)) + (num1) );
Seems like homework to me, so I will give a hint. look for the method substring() and charAt() for the first part, and the Random class for the second.
I am a .NET developer so I can't help you with the syntax but you would need to grab the first char of the first name, usually accessible via an indexer - firstName.charAt(0), and a substring of the second one that ranges from the first character (ordinal 0) to the 5th character (ordinal 4), likely something like lastName.substring(0, 4); and concatenate these two strings -
concatenatedName = firstName.charAt(0) + lastName.substring(0, 4);
Something like this will do
import java.lang.String;
import java.io.*;
import java.util.Random;
class Name {
public static void main(String args[]) {
Random rnd = new Random(); // Initialize number generator
String firstname = "Jessica"; // Initialize the strings
String lastname = "Craig";
String result; // We'll be building on this string
// We'll take the first character in the first name
result = Character.toString(firstname.charAt(0)); // First char
if (lastname.length() > 5)
result += lastname.substring(0,5);
else
result += lastname; // You did not specify what to do, if the name is shorter than 5 chars
result += Integer.toString(rnd.nextInt(99));
System.out.println(result);
}
}
You're missing a closing parentheses for println.
I would recommend removing all the parentheses around the string concats they just make it hard to read.
System.out.println("Result:" + beginIndex + firstname.substring(0,1) + lastname.substring(0,5) + num1 );
Also what happens if the user enters a last name with only 4 characters?
Take a look at String.substring()
See how easy it is? I gave 4 simple names which can be replaced with words and such. The "4" in the code represents the number of names in the String. This is about as simple as it gets. And for those who want it even shorter(all I did was decrease the spacing):
import java.util.*;
public class characters{
public static void main(String[] args){
Random generate = new Random();
String[] name = {"John", "Marcus", "Susan", "Henry"};
System.out.println("Customer: " + name[generate.nextInt(4)]); }}