Replace number with repeated characters [closed] - regex

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Say I have a string: 8, and I wanted to replace numbers [0-9] with a . that would repeat as many times as the number. What regex string would I use?
e.g.: input string
8
output
........

You can't do this using only regular expressions so you'll have to rely on a language or library feature which allows substitution of matched strings with the result of calling a function with the match as an argument.
In Ruby:
"8".gsub(/[0-9]/) { |x| '.' * x.to_i } # => "........"
"812".gsub(/[0-9]/) { |x| '.' * x.to_i } # => "..........."
"a1b2".gsub(/[0-9]/) { |x| '.' * x.to_i } # => "a.b.."
In JavaScript:
function replaceNumbersWithDots(str) {
return (''+str).replace(/[0-9]/g, function(m) {
var s='', num=parseInt(m, 10);
for (i=0; i<num; i++) { s+= '.'; }
return s;
});
}
replaceNumbersWithDots('8'); // => "........"
replaceNumbersWithDots('812'); // => ".........."
replaceNumbersWithDots('a1b2'); // => "a.b.."
In Java:
public static void main(String args[]) throws Exception {
System.out.println(replaceNumbersWithDots("8")); // => "........"
System.out.println(replaceNumbersWithDots("812")); // => "..........."
System.out.println(replaceNumbersWithDots("a1b2")); // => "a.b.."
}
public static String replaceNumbersWithDots(String s) {
Pattern pattern = Pattern.compile("[0-9]");
Matcher matcher = pattern.matcher(s);
StringBuffer buf = new StringBuffer();
while (matcher.find()) {
int x = Integer.parseInt(matcher.group());
matcher.appendReplacement(buf, stringOfDots(x));
}
return buf.toString();
}
public static String stringOfDots(int x) {
String s = "";
for (int i=0; i<x; i++) { s += "."; }
return s;
}

This can't be done with standard regular expressions alone. As #m.buettner points out, you can in certain languages specify a function that processes the replacement. For example, with Python
>>> import re
>>> s = '8'
>>> re.sub(r'\d', lambda m: '.'*int(m.group()), s)
'........'
But maybe you don't even need a regex? Since you're only looking for single-character matches (namely \d), you can perhaps do something like this:
Initialize some sort of string buffer to hold the resultant string
Loop over the characters of your input string
If the character is a digit, parse it as an integer and append that many .s to your buffer.
Otherwise, append the character itself to your buffer.
Here's an implementation of this in Java:
String s = "8";
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) {
int n = c - '0';
for (int i = 0; i < n; i++)
sb.append('.');
} else {
sb.append(c);
}
}
System.out.println(sb);
........

AS you didn't provide a lang, i made an exemple of solving it in php
$tr = array();
foreach(range(0, 9) as $nr)
{
$tr[$nr] = str_repeat('.', $nr);
}
echo strtr("Hello 8", $tr);
// Gives: "Hello ........"

Related

How to check if String contains only operators and numbers in as3?

How to check if String contains only operators and numbers.
The string which may contains 0-9 and +,-,.,/,*,X,=
For example : 28+30-22*5 = when i check this it should return true. If this contains a character then it will return false.
Can we use regexp for this.
This is totally primitive and straightforward, but it should do the trick:
// A collection of valid characters.
const VALID:String = "0123456789+-*/=X ";
function check(sample:String):Boolean
{
for (var i:int = 0; i < sample.length; i++)
{
// Let's iterate the given String, char by char.
var aChar:String = sample.charAt(i);
// The .indexOf(...) method returns -1 if there's no match.
if (sample.indexOf(aChar) < 0)
{
return false;
}
}
// If we got as far as here, it means
// there's no invalid characters in the sample.
return true;
}
trace(check("28+30-22*5 =")); // true
trace(check("a = 100 * 3 / 10")); // false
Of course you can do it the RegExp way, but it will probably be the same logic, just less readable, more difficult to handle, and not measurably faster.

Split string by "],["

I know one back slash / can be used to escape some special characters like (, . and double back slash // can be used to escape special characters in a string directly.
I want to split:
"[[0,0,1,0,0],[0,0,0,0,0],[0,0,0,1,0],[1,1,0,1,1],[0,0,0,0,0]]"
by ],[ between each sub array.
What should I do if I want to get all the sub arrays by splitting them to be "[[0,0,1,0,0", "0,0,0,0,0","0,0,0,1,0","1,1,0,1,1", "0,0,0,0,0]]" first.
If you have better idea on how to convert them directly into sub arrays including numbers only like "0,0,1,0,0", "0,0,0,0,0","0,0,0,1,0","1,1,0,1,1", "0,0,0,0,0" that will be even better.
Since both [ and ] at special characters in regex you need to escape them.
you can try with below:
str.split("\\],\\[");
Test code:
String str="[[0,0,1,0,0],[0,0,0,0,0],[0,0,0,1,0],[1,1,0,1,1],[0,0,0,0,0]]";
String[] strs = str.split("\\],\\[");
for(String s:strs){
System.out.println(s);
}
Output result:
[[0,0,1,0,0
0,0,0,0,0
0,0,0,1,0
1,1,0,1,1
0,0,0,0,0]]
If you want to remove the duplicate [[ and ]],just add below codes before split:
str = str.substring(2);
str = str.substring(0, str.length()-2);
Updated answer,if you want to eliminate all the brackets in between and at both ends by regex,you write regex like \[?\[((\d,)+\d) then fetch the first group of each match record data, below is the code:
String str = "[[0,0,1,0,0],[0,0,0,0,0],[0,0,0,1,0],[1,1,0,1,1],[0,0,0,0,0]]";
String regex = "\\[?\\[((\\d,)+\\d)";
Pattern r = Pattern.compile(regex);
Matcher m = r.matcher(str);
while (m.find()) {
System.out.println(m.group(1));
}
The output is
0,0,1,0,0
0,0,0,0,0
0,0,0,1,0
1,1,0,1,1
0,0,0,0,0
Your input is valid JSON, so I suggest using a JSON parser.
The code would look like this:
import javax.json.*;
JsonReader jsonReader = Json.createReader(new StringReader("[[0,0,1,0,0],[0,0,0,0,0],[0,0,0,1,0],[1,1,0,1,1],[0,0,0,0,0]]"));
JsonArray array = jsonReader.readArray();
jsonReader.close();
System.out.println("Array #2: " + array.getJsonArray(1)); // should give [0,0,0,0,0]
System.out.println("Array #3, 4th value: " + array.getJsonArray(2).getInt(3)); // should give 1
If you want the String to convert into a 2d-Array, you can use below functions that takes the String and returns the 2d-Array of ints:
private static int[][] getMatrixFromString(String arrayStrinng) {
String arrayString = arrayStrinng.substring(1, arrayStrinng.length() - 1);
String[] splitMajor = arrayString.split("],");
int rowCount = splitMajor.length, colCount = 0;
int[][] matrix = new int[rowCount][];
for (int row = 0; row < splitMajor.length; row++) {
String[] splitMinor = splitMajor[row].split(",");
if (colCount == 0) {
colCount = splitMinor.length;
matrix = new int[rowCount][colCount];
}
for (int i = 0; i < colCount; i++) {
if (splitMinor[i].startsWith("["))
splitMinor[i] = splitMinor[i].substring(1);
if (splitMinor[i].endsWith("]"))
splitMinor[i] = splitMinor[i].substring(0, splitMinor[i].length() - 1);
matrix[row][i] = Integer.parseInt(splitMinor[i]);
}
}
return matrix;
}

C++ calculator and for loop

string Expression::addevaluate(string x){
stringrep = x; //Stringrep is the string that user typed in,
//it might be 5+6+7-8-9*3/(2+5)
int totalnum = stringrep.length();
for(int i=0;i < totalnum;i++){ //This for loop will seperate the
//string by "+" and output a vector
//with seperate string
int addop = stringrep.find("+");
addvector.push_back(stringrep.substr(0,addop));
string a =stringrep.substr(0,addop);
totalnum=totalnum-(a.length());
stringrep = stringrep.substr(addop+1,totalnum);
}
int vectorlength = addvector.size();
for(int i = 0;i<vectorlength;i++){
cout << i+1<<":"<<addvector[i]<<",";
}
subevaluate(addvector);
return stringrep;
}
string Expression::subevaluate(vector<string> &v){
int totalnum = v.size();
//This is the question, I have no idea how can i set the value totalnum
//If it's the size of vector,it's too small. If it's the last totalnum
//from last function. Then there is a error. In addition,I do not know
//what the error is.
for(int i=0;i < totalnum;i++){
int addop = v[i].find("-");
if(addop > 0){
subtvector.push_back(v[i].substr(0,addop));
string a =v[i].substr(0,addop);
totalnum=totalnum-a.length();
v[i] = v[i].substr(addop+1,totalnum);
}
}
int vectorlength = subtvector.size();
for(int i = 0;i<vectorlength;i++){
cout << i+1<<":"<<subtvector[i]<<",";
}
return stringrep;
}
I do not know why I did wrong for the second for loop. Please help me solve the for loop. In addition,how can i seperate all the string by."+","-","*","/". Then calculate the answer like a calculator. Thanks.
This implementation will not work... suppose you have
"1+2*(3+4)"
the first split (even when written correctly) will get
"1"
"2*(3"
"4)"
What are you going to do with "2*(3" ?
At the very minimum to write a calculator with this approach you need:
add "(" front and add ")" at the end (i.e. change to "(1+2*(3+4))"
look for last OPEN parenthesis
move from there to the first CLOSED parenthesis
process what is in-between (i.e. "3+4") and replace the whole parenthesized expression it in the original string with the result (i.e. get from "1+2*(3+4)" to "(1+2*7)")
repeat until there are no more parenthesis
For splitting a string on a given character you should write a dedicated function, for example:
std::vector<std::string> split(const std::string& text, char sep) {
std::vector<std::string> result;
size_t pos = text.find(sep);
while(pos != std::string::npos) {
result.push_back(text.substr(0, pos));
text = text.substr(pos + 1);
}
result.push_back(text);
return result;
}
then you can write
std::vector<std::string> res = split(text, '+');
to get from "1+2*3+4" to a vector containing "1", "2*3", "4".
PS: Note that this way of computing expression is not what normally is done, but it can be made working so you should in my opinion keep working on it until it's done.
I think it will be difficult to make the code work when you split the string into a vector. The operator precedence will be too hard to handle, I think.
How about a recursive process?
In this way you can simplify the original string step by step. You just keep calling the evaluate function with substrings until they are turned into simple expressions.
Example:
exp = 12/(5+1)
call 1: call f("12/(5+1)")
call 1: f identifies the substring "5+1" and call itself (recursive)
call 2: call f("5+1")
call 2: simple expression calculates into "6" which is returned
call 1: The substring "(5+1)" is replaced by the returned "6"
call 1: exp now looks "12/6"
call 1: simple expression calculates into "2" which is returned
More complex expressions like "48/(5 + (2*3/(3-1))) would just result in more calls so that the string is simplified step by step.
The code could look like the code below. Only the structure is include - it is for OP to fill in the actual code.
bool isSimpleExpression(string& s)
{
// Return true if s is simple, i.e. X+Y, X-Y, X*Y, X/Y
// Otherwise false
}
string evaluateString(string& exp)
{
while(!isSimpleExpression(exp))
{
// exp must be broken into smaller part as it isn't simple yet
if (ExpContainsParanthesis() )
{
// Example: exp is "12/(5+1)"
string s1 = FindSubstringInMostInnerMatchingParanthesis(exp);
// Example: s1 is "5+1"
// Example: call evaluateString("5+1")
strint s2 = evaluateString(s1); // Recursive call
// Example: s2 is 6
ReplaceS1WithS2(exp, s1, s2);
// Example: exp is "12/6"
}
else if (ExpContainsMultiplication())
{
// Find the substring with multiplication
// Call this function with the substring
// Replace the substring with the returned result
}
else if ....
{
// division
}
// ... and so on
}
// Calculate the simple expression
string result;
// ..
// ..
return result;
}

Anti-Digest operation on string always returning the same value [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am looking for some way to "digest" a string, but always return the same 32 (or 64) byte long value (as a hex string or plain characters). Something like the following code does:
std::string digest(const std::string& input)
{
std::string result = "";
// do something with the input string, update result accordingly
return result;
}
and a little bit more details: I want exactly the opposite of what a classical digest function does which is that for each different string it returns a different but always the same (1 to 1) value. I want a function which for each string returns every time the same value (n to 1).
Obviously, "easy" solutions as return the same constant result every time are not considered a solution :) The code should actually digest the input string and build up the result as a result of the operation.
And an example:
digest ("fox") == digest ("whale")
should be true.
Or mathematically speaking:
for ∀ a and b if a != b => digest (a) == digest(b). That is why i called this anti-digest.
A long mathematical demonstration
Your requirement is:
a!=b => digest(a)==digest(b)
Let's take another message any other message c, and suppose it's different from a and b:
a!=c => digest(a)==digest(c)
b!=c => digest(b)==digest(c)
From this you see that the digest will be constant for any c unless it is equal to a or b.
Now take another message x whatever it may be:
c!=x => digest(c)==digest(x)
By contraposing this implication, this is equivalent to :
digest(x)!=digest(c) => c==x
So suppose there would be an x with a digest different from the constant digest(c). The we have:
digest(x)!=digest(c) and digest(x)!=digest(a)
=> x==c and x==a
=> c==a
=> digest(c)!=digest(a)
But this contradict out original hypothesis about a, c, digest(a) and digest(c), so there can't be such an x. So you can conclude that your digest MUST BE a strictly constant function.
Now suppose your function would not be constant:
digest(x)!=digest(a) => x==a
but if digest is a function, it will always return the same result for the same input, meaning that x==a => digest(x) ==digest(a). This demonstrates that there is no other solution than a constant function.
In short and in C++
A function will return the same result for the same parameter, unless there are side effet (static variable or whatever). Your requirement of having same result for different values, but different result for same values is simply not feasible in a function with only one parameter.
It seems, I was somehow unclear on what I want to achieve ...
Anyway, I came up with the following:
static const size_t DIGEST_SIZE = 32;
std::string antiDigest(const std::string& a)
{
if(a.empty()) { throw "cannot digest empty string"; }
char r[DIGEST_SIZE ] = {0};
int block_size = std::min(DIGEST_SIZE, a.length());
int block_count = 1 + DIGEST_SIZE / a.length();
for(int i=0; i<block_size; i++)
{
int hlp = 0, bc = 0;
while(bc < block_count)
{
int idx = i + bc * block_size;
if(idx >= a.length()) break;
hlp += a[idx];
bc ++;
}
hlp = (int)(hlp << 3) + hlp;
unsigned int hlp2 = 0;
while(hlp)
{
int t = hlp - ((hlp/10) * 10);
hlp2 += t;
hlp /= 10;
}
bc = 0;
while(bc < block_count)
{
int idx = i + bc * block_size;
if(idx >= DIGEST_SIZE) break;
r[idx] = ( (hlp2 / 10) + (hlp2-(hlp2/10)*10)) ;
bc++;
}
}
std::stringstream result;
for(int i=0; i<DIGEST_SIZE; i++)
{
result << int_to_hex(r[i]) ;
}
return result.str();
}
On ideone: http://ideone.com/t4dibL
Obviously, this can be obfuscated even more with replacing the mathematical operations with bitwise operations, but for a proof of concept this does it.

Match a structure against set of patterns

I need to match a structure against set of patterns and take some action for each match.
Patterns should support wildcards and i need to determine which patterns is matching incoming structure, example set:
action=new_user email=*
action=del_user email=*
action=* email=*#gmail.com
action=new_user email=*#hotmail.com
Those patterns can be added/removed at realtime. There can be thousands connections, each have its own pattern and i need to notify each connection about I have received A structure which is matching. Patterns are not fully regex, i just need to match a string with wildcards * (which simple match any number of characters).
When server receives message (lets call it message A) with structure action=new_user email=testuser#gmail.com and i need to find out that patterns 1 and 3 are matching this message, then i should perform action for each pattern that match (send this structure A to corresponding connection).
How this can be done with most effecient way? I can iterate this patterns and check one-by-one, but im looking for more effecient and thread-safe way to do this. Probably its possible to group those patterns to reduce checking.. Any suggestions how this can be done?
UPD: Please note i want match multiplie patterns(thousands) aganst fixed "string"(actually a struct), not vice versa. In other words, i want to find which patterns are fitting into given structure A.
Convert the patterns to regular expressions, and match them using RE2, which is written in C++ and is one of the fastest.
Actually, if I understood correctly, the fourth pattern is redundant, since the first pattern is more general, and includes every string that is matched by the fourth. That leaves only 3 patterns, which can be easly checked by this function:
bool matches(const char* name, const char* email)
{
return strstr(name, "new_user") || strstr(name, "del_user") || strstr(email, "#gmail.com");
}
And if you prefer to parse whole string, not just match the values of action and email, then the following function should do the trick:
bool matches2(const char* str)
{
bool match = strstr(str, "action=new_user ") || strstr(str, "action=del_user ");
if (!match)
{
const char* emailPtr = strstr(str, "email=");
if (emailPtr)
{
match = strstr(emailPtr, "#gmail.com");
}
}
return match;
}
Note that the strings you put as arguments must be escaped with \0. You can read about strstr function here.
This strglobmatch supports * and ? only.
#include <string.h> /* memcmp, index */
char* strfixstr(char *s1, char *needle, int needle_len) {
int l1;
if (!needle_len) return (char *) s1;
if (needle_len==1) return index(s1, needle[0]);
l1 = strlen(s1);
while (l1 >= needle_len) {
l1--;
if (0==memcmp(s1,needle,needle_len)) return (char *) s1;
s1++;
}
return 0;
}
int strglobmatch(char *str, char *glob) {
/* Test: strglobmatch("almamxyz","?lmam*??") */
int min;
while (glob[0]!='\0') {
if (glob[0]!='*') {
if ((glob[0]=='?') ? (str[0]=='\0') : (str[0]!=glob[0])) return 0;
glob++; str++;
} else { /* a greedy search is adequate here */
min=0;
while (glob[0]=='*' || glob[0]=='?') min+= *glob++=='?';
while (min--!=0) if (*str++=='\0') return 0;
min=0; while (glob[0]!='*' && glob[0]!='?' && glob[0]!='\0') { glob++; min++; }
if (min==0) return 1; /* glob ends with star */
if (!(str=strfixstr(str, glob-min, min))) return 0;
str+=min;
}
}
return str[0]=='\0';
}
If all you want is wildcart matching, then you might try this algorithm. The point is to check all substrings that is not a wildcart to be subsequent in a string.
patterns = ["*#gmail.com", "akalenuk#*", "a*a#*", "ak*#gmail.*", "ak*#hotmail.*", "*#*.ua"]
string = "akalenuk#gmail.com"
preprocessed_patterns = [p.split('*') for p in patterns]
def match(s, pp):
i = 0
for w in pp:
wi = s.find(w, i)
if wi == -1:
return False
i = wi+len(w)
return i == len(s) or pp[-1] == ''
print [match(string, pp) for pp in preprocessed_patterns]
But it might be best to still use regexp in case you would need something more than a wildcart in a future.