0

I am creating a program that will output the letters of a string, but scrambled. It works, but there is no way to prevent a letter from appearing more than once. How would i go about this?

my code:

import java.util.Random;


public class Final {

    public static void main(String[] args) {
        Random rand = new Random();
        String str = "pumpkinpie";

        String[] split = str.split("");
        for(int i = 0; i < split.length; i++){
            int randomLet = rand.nextInt(split.length);
            System.out.print(split[randomLet]);
        }

    }

}
sirnomnomz
  • 623
  • 1
  • 7
  • 20
  • You will need to use a mutable data structure that allows you to remove items. In Java, ArrayList is a good bet. – Mephy May 15 '14 at 18:14
  • 1
    There are some good answers here: http://stackoverflow.com/q/1519736/436282 – Andrew May 15 '14 at 18:14
  • 1
    @sirnomnomz - Your current code may not scramble properly ,since it is not guaranteed to returning unquie for small range. in your sample you have two "i" , are you asking to display only 1 time or display two time but in different place – Mani May 15 '14 at 18:50

4 Answers4

5

You can add each character from the String into an ArrayList and shuffle it using the Collections.shuffle() method, which also accepts a Random instance:

    //1. initiate the string you want to shuffle
    String originalString = "pumkinpie";
    //2. initiate a List into which the characters will be added
    List<Character> characterList= new ArrayList<Character>();
    //3. add each character from the String to the List
    for (char character : originalString.toCharArray()) {
        characterList.add(character);
    };
    //4. shuffle using Collections.shuffle
    Collections.shuffle(characterList, new Random());
    //5. print each character
    for (Character character : characterList) {
        System.out.println(character);
    }
Gabriel Ruiu
  • 2,753
  • 2
  • 19
  • 23
  • and the output comes out like [u, e, p, n, m, k, i] How would i get just the letters? – sirnomnomz May 15 '14 at 18:29
  • Those are the letters. You tried printing the instance of ArrayList – Gabriel Ruiu May 15 '14 at 18:32
  • @sirnomnomz, I edited the answer explaining each line – Gabriel Ruiu May 15 '14 at 18:36
  • AFAICT - This will mean that words that have multiple occurrences of the same letter (`comodo` in my example) will come out without the repeating letters (`modc` instead of, say `omodco`), is this what the OP desires? – Mike May 15 '14 at 19:10
  • It actually isnt. How would i be able to change the code to be able to display multiple of the same character? – sirnomnomz May 15 '14 at 23:52
  • 1
    You said yourself -> "but there is no way to prevent a letter from appearing more than once". I am confused as to what your end-goal is. Do you, or do you not want to display the unique letters? – Gabriel Ruiu May 16 '14 at 04:32
  • @GabrielRuiu i want it to scramble the letters, and if there are repeats, then yes, show repeats of just that letter, if not then dont. So for Happy, give a result like hpypa, But for a word with no repeats, dont show multiples, such as cat -> tac. – sirnomnomz May 16 '14 at 14:45
  • 1
    It is sufficient to say "display all letters from a word in a random order". I have updated the answer. Do not forget to set it as correct please :) – Gabriel Ruiu May 16 '14 at 16:09
0

Add the letters to an array/Set/List, and print only only if the array/Set/List does not contain the letter:

Set<String>...
for(int i = 0; i < split.length; i++){
    int randomLet = rand.nextInt(split.length);
    if(set does not contain split[randomLet]){
        System.out.print(split[randomLet]);
        add split[randomLet] to set
    }
}
Nivas
  • 18,126
  • 4
  • 62
  • 76
0

Mostly Conceptual Answer

If you are trying to randomize the string, recognize then that putting a logical filter that letters can not repeat actually lowers entropy, and thus security or base randomness for any purpose. Also, this will be very difficult as it would require re-scrambling if a repeat is detected.

Take for instance:

randomize "add" - characters as 123
a   - 1
ad  - 13
add - 132
! back to drawing block

As a human we know that only one non-repeating string can come of this, dad (in the character order of 312 and 213), but the system will hit every option until it hits one of those, starting over each time...

add > add > dad > dad > dda > dda 
123 > 132 > 213 > 312 > 321 > 231 

Or a word like sorry: There are 120 permutations, of those, there are 8 different ways in which 3rd and 4th letters repeat (rr) in either 34, or 43 fashion (2 ways, and four positions in the resulting string). Of the 120 possibilities, this accounts for 48 permutations, and many of those permutations are not discovered until many characters in.

In words with more repeating characters (like, for instance comodo, with 6 different doubles of o, this covers 576 permutations of the possible 720) you get into conditions where your script becomes woefully inefficient due to thrashing...

But, if you need this, your best bet would be to write a function that randomizes a word, checks, then randomizes again. Doing it by hand (one character at a time) will be slower for easier words, and you will have about as much luck as anything else for troublesome words. Let Lady Luck guide you...

Mike
  • 1,968
  • 18
  • 35
0

If OP just wanted to scramble and not wanted to remove any characters.

in other words pmieupnpki is one of the valid out put

then,

instead of blindly take the random Swap the elements in that array. since Random within small range could be same.

Random rand = new Random();
        String str = "pumpkinpie";

        char[] split = str.toCharArray();
        for(int i = 0; i < str.length(); i++){
            int randomLet = rand.nextInt(split.length);
            char c = split[randomLet];
            split[randomLet] =  split[i];
            split[i] = c;
        }
        System.out.println(String.valueOf(split));
Mani
  • 3,274
  • 2
  • 17
  • 27