views:

2012

answers:

6

A string will be made up of certain symbols (ax,bx,dx,c,acc for example) and numbers.

ex: ax 5 5 dx 3 acc c ax bx

I want to replace one or all of the symbols (randomly) with another symbol of the same set. ie, replace one of {ax,bx,dx,c,acc} with one of {ax,bx,dx,c,acc}.

replacement example: acc 5 5 dx 3 acc c ax bx or c 5 5 dx 3 acc c ax ax

Is there a way to do this with regexes? In Java? If so, which methods should I use?

+1  A: 

To answer the first question: no.

Since you are doing a random replace, regex will not help you, nothing about regex is random. * Since your strings are in an array, you don't need to find them with any pattern matching, so again regex isn't necessary.

*Edit: the question has been edited so it no longer says the strings are in an array. In this case, assuming they are all in one big string, you might build a regex to find the parts you want to replace, as shown in other answers.

postfuturist
A: 

Use the Random class to generate a random int to choose the index of the symbols.

    String text = "ax 5 5 dx 3 acc c ax bx";
    System.out.println("Original: " + text);
    String[] tokens = text.split(" ");
    List<Integer> symbols = new ArrayList<Integer>();
    for(int i=0; i<tokens.length; i++) {
        try {
            Integer.parseInt(tokens[i]);
        } catch (Exception e) {
            symbols.add(i);
        }
    }
    Random rand = new Random();
    // this is the part you can do multiple times
    int source = symbols.get((rand.nextInt(symbols.size())));
    int target = symbols.get((rand.nextInt(symbols.size())));
    tokens[target] = tokens[source];

    String result = tokens[0];
    for(int i=1; i<tokens.length; i++) {
        result = result + " " + tokens[i];
    }
    System.out.println("Result: " + result);

Make as many replacements as you need before you join the tokens back together.

There are two parts here that might seem tricky. First is the try catch to identify those tokens that are not integers. I recommend you pull that part out into its own method, since it works, but it's a bit hacky.

The second part is where I set the source and target variables. What I'm doing there is getting a randomly selected index of one of the non-numeric symbols. Once I have two random indexes, I can swap them in the next line.

An alternative to swapping would be to build up a new String from randomly selected symbols once you've split the original String into an array.

Bill the Lizard
A: 

@Bill

the question is not to replace strings in an array with other strings, it is to replace the symbols in the string with other random symbols.

@steveth45

aw crap.

i was thinking i can just do it the normal way: split the string into symbols and numbers, and then go over element and replace them (or not) with a string in a lookup table.

Dove
You can respond to answers with comments, which is preferred if not offering your own answer to the question.
Julie
Okay, see the changes I made to my original answer.
Bill the Lizard
Now you can remove this non-answer.
Brad Gilbert
+1  A: 
  1. Yes, this can be done with regexes. Probably not very prettily, not without a loop or two
  2. Yes, this can be implemented in Java.
  3. See Random, the regex package
  4. The implementation is left as an exercise for the student.
Ken Gentle
A: 

I think this is the most clean solution for replacing a certain set of symbols from a string containing a superset of them. appendreplacement is the key to this method. one important caveat: do not include any unescped dollar characters ($) in your elements list. escape them by using "\$" eventually use
.replaceall("\$","\\$"); on every string before adding it to the list. see also the javadoc in doubt about the $ signs.

import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class ReplaceTokens {
public static void main(String[] args) {
    List<String> elements = Arrays.asList("ax", "bx", "dx", "c", "acc");
    final String patternStr = join(elements, "|"); //build string "ax|bx|dx|c|acc" 
    Pattern p = Pattern.compile(patternStr);
    Matcher m = p.matcher("ax 5 5 dx 3 acc c ax bx");
    StringBuffer sb = new StringBuffer();
    Random rand = new Random();
    while (m.find()){
        String randomSymbol = elements.get(rand.nextInt(elements.size()));
        m.appendReplacement(sb,randomSymbol);
    }
    m.appendTail(sb);
    System.out.println(sb);
}

/**
 * this method is only needed to generate the string ax|bx|dx|c|acc in a clean way....
 * @see org.apache.commons.lang.StringUtils.join    for a more common alternative...
 */
public static String join(List<String> s, String delimiter) {
    if (s.isEmpty()) return "";
    Iterator<String> iter = s.iterator();
    StringBuffer buffer = new StringBuffer(iter.next());
    while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
    return buffer.toString();
}
Andreas Petersson
A: 

thanks a bunch guys. here's what i came up with. see if you can come up with a more efficient way.

private final String[] symbolsPossible = {"ax","bx","cx","dx","foo"};
private boolean exists;
private final String mutate(String s)
{
String[] tokens=s.split(" ");
for(int j=0; j<tokens.length; j++)
if(Math.random()<.1) //10% chance of mutation per token
{
//checking to see if the token is a supported symbol
exists=false;
for(int i=0; i<symbolsPossible.length; i++)
    if(tokens[j].equals(symbolsPossible[i]))
       exists=true;
if(exists)
    tokens[j]=symbolsPossible[(int)Math.random()*symbolsPossible.length];
}
StringBuffer result=new StringBuffer();
for(String t:tokens)
    result.append(t);
return result;
}
Dove