My problem is that I am trying to make (for example) String "asdf" changed to "sdfa" by using Random() and .toCharArray().
How do I not get duplicate random numbers?
I figure that I am supposed to create a new Char array in order to randomly store the char's without changing my original array because if I do, then the new string will be messed up, if that makes any sense.
I didn't do it here in this code, but that might be an alternative???
edit: I have made it into a main class, which should make it easier. Thank You.
import java.util.Random;
public class Scramble {
public static void main(String[] args) {
String str = "asdf";
Random randomGenerator = new Random();
int lengthOfStr = str.length();
char[] chars = str.toCharArray();
// do for length of str
for (int i=0; i < lengthOfStr; i++)
{
int n = randomGenerator.nextInt(lengthOfStr);
chars[i] = chars[n];
String newStr = new String(chars);
str = newStr;
}
System.out.println(str);
}
}
Look up the Fisher-Yates shuffle for how to correctly randomly scramble an array. (That algorithm, by the way, is perfectly suited to how Java's random number generators provide you with random numbers, and doesn't require making your random numbers unique.)
As to your first question, you can avoid (to a large extent) duplicated random numbers by making the random number generator a member of your class, as opposed to a local variable in your method. The following code should generate a fairly random distribution of scrambled words. You can blame its length on the lack of a shuffle method that can work with primitive arrays. Adapt as appropriate to your needs:
public class Flipper {
Random randomGenerator = new Random();
public static void main(String[] args) {
final String sample = "Hello World";
final Flipper flipper = new Flipper();
for (int i = 0; i < 100; i++) {
System.out.println(flipper.scramble(sample));
}
}
public String scramble(String str) {
if (str == null)
return null;
char[] arr = str.toCharArray();
List<Character> charList = new ArrayList<Character>(arr.length);
for (final char c : arr) {
charList.add(c);
}
Collections.shuffle(charList, randomGenerator);
char[] converted = new char[charList.size()];
for (int i = 0; i < charList.size(); i++) {
converted[i] = charList.get(i).charValue();
}
return new String(converted);
}
}
Here is a simple one with a O(n) duration order. The loop has only 3 instructions:
It appends the random char in a new string and removes it from the original one, so when the next random char is obtained, the previously obtained chars are not eligible.
I noticed after writing this function that it seems it is a form of the Fisher–Yates shuffle algorithm.
public class Scramble {
public static String scramble(String str) {
StringBuilder newStringBuilder = new StringBuilder();
StringBuilder stringBuilder = new StringBuilder(str);
while (stringBuilder.length() > 0) {
int n = (int)(Math.random() * stringBuilder.length()));
newStringBuilder.append(stringBuilder.charAt(n));
stringBuilder.deleteCharAt(n);
}
return newStringBuilder.toString();
}
public static void main(String[] args) {
System.out.println(scramble("hola"));
}
}
Related
I need to create a program that will take a word without spaces, punctuation, and all lowercase, and rearranges the letters randomly. It needs to have substrings or charAt, I cannot use an array since we have not learned them yet. It also hsa to be different everytime, really n! times I think. This is what I have so far-
public static void main(String[] args) {
Scanner kboard = new Scanner(System.in);
System.out.println("Enter a word that is less than 11 lowercase letters and has no punctuation or spaces: ");
String word = kboard.next();
while(word.length()>1)
{
System.out.print(word.charAt(1));
System.out.print(word.charAt(0));
word = word.substring(2);
}
System.out.println(word);
}
This rearranges the words, but it does not do it random every time. I thought I could do something like this, but I think it is messy and doesn't make much sense.
public static void main(String[] args) {
Scanner kboard = new Scanner(System.in);
String word, pt1 = "", pt2 = "", pt3 = "";
System.out.println("Enter a word that is less than 11 lowercase letters and has no punctuation or spaces: ");
word = kboard.nextLine();
int num1 = 0, num2 = 0, thing = 0;
while(thing<4)
{
thing = thing + 1;
num1 = (int)(word.length() * Math.random() + 1);
num2 = (word.length() - (word.length() % num1));
}
pt1 = word.substring(num1, num2);
pt2 = word.substring(num1, num2);
pt3 = word.substring(num1, num2);
System.out.print(pt1);
System.out.print(pt2);
System.out.print(pt3);
So what can I do to randomize the letters?
A simple solution to all "how do I randomize" a fixed set of elements is: shuffling.
Simply turn your String into a List of Character, to then shuffle that list.
( creating that list boils down to new ArrayList<>(yourWord.toCharArray() ).
GhostCat beat me in a few seconds :)
char[] arr = "abcdefg".toCharArray();
List<Character> list = new LinkedList<>(); // copy the chars to a list
for (int i = 0; i < arr.length; i++) {
list.add(arr[i]);
}
Collections.shuffle(list); // use to shuffle
for (int i = 0; i < arr.length; i++) { // copy the shuffled chars back to the array
arr[i] = list.get(i);
}
System.out.println(new String(arr));
This could be implemented very easily using standard libraries,
but it seems you cannot use arrays and lists,
which makes this exercise a bit harder than it needs to be.
You can implement the following algorithm:
Initialize the output as an empty string
while the word is not empty
Pick a character randomly
Append the character to the output
Remove the selected character from the word, by replacing word with the part before the index + the part after the index
This can be implemented reasonably efficiently using a StringBuilder:
String shuffled(Random random, String word) {
StringBuilder result = new StringBuilder(word.length());
StringBuilder rest = new StringBuilder(word);
while (rest.length() > 0) {
int index = random.nextInt(rest.length());
result.append(rest.charAt(index));
rest.deleteCharAt(index);
}
return result.toString();
}
If you cannot use a StringBuilder,
then you can work with strings,
but this will be less efficient,
and normally not recommended in Java.
(Because it involves many string concatenations, which is inefficient.)
String shuffled(Random random, String word) {
String result = "";
String rest = word;
while (!rest.isEmpty()) {
int index = random.nextInt(rest.length());
result += rest.charAt(index);
rest = rest.substring(0, index) + rest.substring(index + 1);
}
return result;
}
You can call this with:
String shuffled = shuffled(new Random(), word);
What about this :
public static void main(String[] args) {
String test = "onetwothree";
Random random = new Random();
for (int i=0;i<test.length();i++){
int randomCharacterPosition = random.nextInt(test.length());
String start = test.substring(0,randomCharacterPosition);
String end = test.substring(randomCharacterPosition);
test = end.concat(start);
}
System.out.println(test);
}
Basically you getting a string, randomly choose a position in string.
Using this position you dividing input string into two strings and swaping them.
Nothing more than random, substring and concat (which can be replaced with + operator)
I need to, using an already defined set of 2-4 letters, create a string that is completely randomized. How would one take letters, combine them into one string, randomize the position of each character and then turn that large string into two randomly sized (but >= 2) other strings. Thanks for everyone's help.
My code so far is:
//shuffles letters
ArrayList arrayList = new ArrayList();
arrayList.add(fromFirst);
arrayList.add(fromLast);
arrayList.add(fromCity);
arrayList.add(fromSong);
Collections.shuffle(arrayList);
But I found that this shuffles the Strings and not the individual letters. It also, being an array, has the brackets that wouldn't be found in regular writing and I do want it to look like a randomish assortment of letters
This is a pretty brute force approach, but it works. It shuffles index positions and maps them to the original position.
final String possibleValues = "abcd";
final List<Integer> indices = new LinkedList<>();
for (int i = 0; i < possibleValues.length(); i++) {
indices.add(i);
}
Collections.shuffle(indices);
final char[] baseChars = possibleValues.toCharArray();
final char[] randomChars = new char[baseChars.length];
for (int i = 0; i < indices.size(); i++) {
randomChars[indices.get(i)] = baseChars[i];
}
final String randomizedString = new String(randomChars);
System.out.println(randomizedString);
final Random random = new Random();
final int firstStrLength = random.nextInt(randomChars.length);
final int secondStrLength = randomChars.length - firstStrLength;
final String s1 = randomizedString.substring(0, firstStrLength);
final String s2 = randomizedString.substring(firstStrLength);
System.out.println(s1);
System.out.println(s2);
You can build a string and then shuffle the characters from that string. Using Math.rand() you cano generate a random number within the range of the character's length. Generating it for each character will get you the shuffled string. Since your code is unclear, I will just write an example
public class ShuffleInput {
public static void main(String[] args) {
ShuffleInput si = new ShuffleInput();
si.shuffle("input");
}
public void shuffle(String input){
List<Character> chars = new ArrayList<Character>();
for(char c:input.toCharArray()){
chars.add(c);
}
StringBuilder output = new StringBuilder(input.length());
while(chars.size()!=0){
int rand = (Integer)(Math.random()*characters.size());
output.append(characters.remove(rand));
}
System.out.println(output.toString());
}
}
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 want to create a program that gives a random 24 digit number. I have tried different ways but I can't figure out how to make it. An example response would be 392834756843456012349538, which is just a random twenty four digit number.
Here's the easiest way I can think of:
#Test
public void random24Numbers() {
String random = RandomStringUtils.random(24, false, true);
System.out.println(random);
}
This uses RandomStringUtils.random. The first parameter is the length, the second says, "no letters". The third says, "give me numbers". Here's an example output:
564266161898194666197908
Yes, it's a String, but I'm going to assume you know how to convert a String into a number.
This sample works for generating numbers of 'digits' length including leading zeros and doesn't require any external jar files.
private String generateInt(int digits) {
StringBuilder str = new StringBuilder();
Random random = new Random();
for(int i = 0; i < digits; i++) {
str.append(random.nextInt(10));
}
return str.toString();
}
An example response would be:
081140561664657769754888
The following uses only core java.lang stuff and seems to get the job done. As in other solutions, the result is a string rather than a java numeric type because none of the basic java datatypes can store 23-digit decimal numbers.
import java.lang.Math;
import java.lang.StringBuilder;
public class random24 {
static char digits[] = {'0','1','2','3','4','5','6','7','8','9'};
public static char randomDecimalDigit() {
return digits[(int)Math.floor(Math.random() * 10)];
}
public static String randomDecimalString(int ndigits) {
StringBuilder result = new StringBuilder();
for(int i=0; i<ndigits; i++) {
result.append(randomDecimalDigit());
}
return result.toString();
}
public static void main(String[] args) {
System.out.println(randomDecimalString(24));
}
}
int[] randomNumbers = new int[24];
for(int i = 0; i < 24; i++) {
randomNumbers[i] = (int)Math.floor(Math.random() * 10);
System.out.println(randomNumbers[i]);
}
Added in response to the comment below, code to set a label with this random number sequence:
String randomString = "";
for(int i = 0; i < 24; i++) {
randomString = randomString.concat(String.valueOf((int)Math.floor(Math.random() * 10)));
}
NumbersLabel.setText(randomString);
See How to generate a random BigInteger value in Java? where code is provided which does generate a BigInteger random number not greater than n:
BigInteger r;
do {
r = new BigInteger(n.bitLength(), rnd);
} while (r.compareTo(n) >= 0);
Been a while since I posted a question! Basically I'm starting a new project in University with Java! Basically what is needed of me is to generate a object to store items inside them. This includes product codes, item names, prices, etc. Basically for the product code I am in charge of deciding what length to have it BUT it must start with a Letter not a number. I was thinking of 6 characters. But how do I tell Java to keep the first character a letter and not a number?
Much Appreciated :D
public String getProductCode(){
Random random = new Random();
int first = random.nextInt(26) + 65; //Get random ASCII code in letter range
char firstChar = new Character((char) first); //Convert to char
int suffix = 10000 + random.nextInt(89999); //Get 5 digit suffix
return Character.toString(firstChar) + String.valueOf(suffix);
}
store them seperatly in an object and return the combination in a different getter
public class Product {
protected char id;
protected int code;
public String getFullcode() {
return id + code.toString();
}
//regular getters and setters
}
Try something like this, it's hacky but you get the point:
import java.util.Random;
public class foo {
public static void main(String args[]) {
String chars = "abcdefghijklmnopqrstuvwxyz0123456789";
Random r = new Random();
int limit = 5;
StringBuffer buf = new StringBuffer();
buf.append(chars.charAt(r.nextInt(26)));
for (int i = 0; i < limit ; i++) {
buf.append(chars.charAt(r.nextInt(chars.length())));
}
System.out.println(buf);
}
}
Just make two different random variables one that selects a random letter and the another that picks any random character. Then add them in the obvious way. Hope this helps
public static void main(String[] args) {
//random arrays
String[] randomLetters = {"a", "b", "c", "d", "e", "f", "g", "h", etc...}
String[] randomNumbers = {"08724 ","13876 ","29238 ","37534 ","40182 ","57532 ","69273 ", etc...};
//chooses random element from the letters
Random r = new Random();
int randl = r.nextInt(8);
String randomLetter = randomLetters[randl];
//chooses random element from the numbers
Random a = new Random();
int randn = a.nextInt(7);
String randomNumber = randomNumbers[randn];
//turns into one string and presents it
String str1 = randomLetter + randomNumber;
System.out.print(str1);
}
}
I don't know if this is what you wanted exactly -- it's sort of a one time thing. I was just trying to do it in simple form.