I am trying to take each characters in a sentence and change them to a different one to "encode" the sentence (More like just make it unreadable).
The idea is to take this string : "abc" and turn each characters in it into the next one in the alphabet, giving "bcd". So on an 'A' becomes a 'B' and a 'Z' becomes an 'A' when you reach the end. I created this code which indeed works, but only if you're trying to turn a 'B' into an 'A' which is going backwards in the alphabet.
Here is the code that works (turns B's into A's) :
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
$ModifiedAlphabet="zabcdefghijklmnopqrstuvwxy";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<26;$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
}
}
}
echo $SentenceToEncode;
?>
Which results in this when I run it :
gdkkn rsybjnudqeknv, sghr hr lx ehqrs ptdrshnm. sgymjr enq gdkohmf!
But when I try this second block that turns A's into B's (which is what I want) :
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
$ModifiedAlphabet="bcdefghijklmnopqrstuvwxyza";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<26;$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
}
}
}
echo $SentenceToEncode;
?>
I get this :
aaaaa aaaaaaaaaaaaa, aaaa aa aa aaaaa aaaaaaaa. aaaaaa aaa aaaaaaa!
Where did I go wrong? The only difference being the modified alphabet's first and last two letters.
Thanks in advance!
You have to add a break; in your if statement (I would do it for both scripts to save some iterations)! Like this:
if($SentenceToEncode[$i]===$Alphabet[$j]) {
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
break;
}
Why?
Because if you don't do this it runs the inner loop 26 times for every character! So what that means is:
It first searches the letter h in the normal alphabet and it will find it at position 7. So now it's going to replace the first letter with the letter in the modified alphabet at position 7 which is i. BUT now you don't break the inner loop and it's going for the next iteration to search the first letter, which is now i in the normal alphabet and i is exactly the next letter in the inner loop.
So you replace every character to the end of the modified alphabet! (This didn't happened to you in the first time, because you moved it backwards so it couldn't find it again)
You can do it much easier using str_replace function.
$decoded = array("a", "b", "c", ...., "z");
$encoded = array("z", "a", "b", ...., "y");
$encoded_text = str_replace($decoded, $encoded, $original_text);
$decoded_text = str_replace($encoded, $decoded, $encoded_text);
You can also create initial arrays from strings using str_split function
Try this. You need to execute the second loop as soon it matches the alphabet.
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
//$ModifiedAlphabet="zabcdefghijklmnopqrstuvwxy";
$ModifiedAlphabet="bcdefghijklmnopqrstuvwxyza";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<strlen($ModifiedAlphabet);$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
break;
}
}
}
echo $SentenceToEncode;
?>
Related
I have an array of arrays like:
$array = [["1.","COTV_LITE(1800)"],["2.","COTV_PREMIUM(2200)"]]
Now, I want to implode this array such that it would return something like this:
COTV_LITE(1800)
COTV_PREMIUM(2200)
How do I achieve this? Calling just the implode() function did not work:
implode ('<br>', $array);
You can call array_map() to implode the nested arrays:
echo implode('<br>', array_map(function($a) { return implode(' ', $a); }, $array));
DEMO
output:
1. COTV_LITE(1800)<br>2. COTV_PREMIUM(2200)
You can use variable length arguments variadic in PHP >= 5.6
Option1
$items = [["1.","COTV_LITE(1800)"],["2.","COTV_PREMIUM(2200)"]];
echo implode(' ',array_merge(...$items));
Output
1. COTV_LITE(1800) 2. COTV_PREMIUM(2200)
This is more of a precursor for the next option.
Option2
If you want to get a bit more creative you can use preg_replace too:
$items = [["1.","COTV_LITE(1800)"],["2.","COTV_PREMIUM(2200)"]];
$replace = [
'/^(\d+\.)$/' => '<li>\1 ',
'/^(\w+\(\d+\))$/' => '\1</li>'
];
echo '<ul>'.implode(preg_replace(array_keys($replace),$replace,array_merge(...$items))).'</ul>';
Output
<ul><li>1. COTV_LITE(1800)</li><li>2. COTV_PREMIUM(2200)</li></ul>
Option3
And lastly using an olordered list, which does the numbers for you. In this case we only need the second item from the array (index 1):
$items = [["1.","COTV_LITE(1800)"],["2.","COTV_PREMIUM(2200)"]];
echo '<ol><li>'.implode('</li><li>',array_column($items,1)).'</li></ol>';
Output
<ol><li>COTV_LITE(1800)</li><li>COTV_PREMIUM(2200)</li></ol>
Personally, I would put it in the ol that way you don't have to worry about the order of the numbers, you can let HTML + CSS handle them. Also it's probably the easiest and most semantically correct way, But I don't know if the numbering in the array has any special meaning or not.
In any case I would most definitely put this into a list to render it to HTML. This will give you a lot more options for styling it, later.
Update
want to use option 1. But how do I put each option on a different line using <br>
That one will put the <br> between each array element:
echo implode('<br>',array_merge(...$items));
Output
1.<br>COTV_LITE(1800)<br>2.<br>COTV_PREMIUM(2200)
The only way to easily fix that (while keeping the array_merge) is with preg_replace, which is the second one. So I will call this:
Option 1.2
$items = [["1.","COTV_LITE(1800)"],["2.","COTV_PREMIUM(2200)"]];
echo implode(preg_replace('/^(\w+\(\d+\))$/',' \1<br>',array_merge(...$items)));
Output
1. COTV_LITE(1800)<br>2. COTV_PREMIUM(2200)<br>
Sandbox
Basically there is no way to tell where the end item is after merging them. That operation effectively flattens the array out and gives us something like this:
["1.","COTV_LITE(1800)","2.","COTV_PREMIUM(2200)"]
So that Regex does this 'COTV_PREMIUM(2200)' becomes ' COTV_PREMIUM(2200)<br>'. This is just a way of changing that without having to dip into the array with some logic or something. WE wind up with this modification to the array:
["1."," COTV_LITE(1800)<br>","2."," COTV_PREMIUM(2200)<br>"]
Then with implode we just flatten it again into a string:
"1. COTV_LITE(1800)<br>2. COTV_PREMIUM(2200)<br>"
The Regex ^(\w+\(\d+\))$
^ - Match start of string
(...) - capture group 1
\w+ - match any working character a-zA-Z0-9_ one or more, eg. COTV_PREMIUM
\( - match the ( literally
\d+ - match digits 0-9 one or more, eg 2200
\) - match the ) literally
$ - match end of string
So this matches the pattern of the second (or even) items in the array, then we replace that with this:
The Replacement ' \1<br>'
{space} - adds a leading space
\1 - the value of capture group 1 (from above)
<br> - append a line break
Hope that makes sense. This should work as long as they meet that pattern. Obviously we can adjust the pattern, but with such a small sample size it's hard for me to know what variations will be there.
For example something as simple as (.+\))$ will work TestIt. This one just looks for the ending ). We just need somethng to capture all of the even ones, while not matching the odd. Regular expressions can be very confusing the first few times you see them, but they are extremely powerful.
PS - I added a few links to the function names, these go the the PHP documentation page for them.
Cheers!
Try this
$items = [["1.","COTV_LITE(1800)"],["2.","COTV_PREMIUM(2200)"]];
$imploded = [];
foreach($items as $item) {
$item_entry = implode(' ', $item);
echo $item_entry . '<br/>'; // display items
$imploded[] = $item_entry;
}
// your desired result is in $imploded variable for further use
I have multiple random strings, and I'm trying to pull "SpottedBlanket" out of the string. Some of them work fine:
DarkBaySpottedBlanket --
DarkBay
BaySpottedBlanket --
Bay
but others are cutting out more than it should.
RedRoanSpottedBlanket --
RedR
BlackSpottedBlanket --
Blac
DunSpottedBlanket --
Du
this is the code I'm using, but I thought it would be self explanatory:
$AppyShortcut = chop($AppyColor,"SpottedBlanket");
$AppyColor would obviously be the random generated string. Any clue why this is happening?
The chop function takes the string in the second argument - which in this case is "SpottedBlanket", and removes any contiguous characters that it finds from the right hand side.
So for the case of "RedRoanSpottedBlanket", you'd get back "RedR" because "o", "a", and "n" are letters that can be found in the string "SpottedBlanket".
chop() is usually used to remove trailing white space - a way of cleaning user input before performing some action on it.
Give your array:
$strings = ["DarkBaySpottedBlanket", "RedRoanSpottedBlanket", "BlackSpottedBlanket", "DunSpottedBlanket"];
What you might be looking for is somerthing like this:
foreach ($strings as $string) {
print substr($string, 0, strrpos($string, "SpottedBlanket")) . "\n";
}
This finds the position of the string from the end using strrpos(), then returns the start of the string until that position, using substr().
Using PHP I sometimes have strings that look like the following:
111
110
011
1111
0110012
What is the most efficient way (preferably without regex) to determine if a string contains any character other then the character 1?
Here's a one-line code solution that can be put into a conditional etc.:
strlen(str_replace('1','',$mystring))==0
It strips out the "1"s and sees if there's anything left.
User Don't Panic commented that str_replace could be replaced by trim:
strlen(trim($mystring, '1'))==0
which removes leading and trailing 1s and sees if there's anything left. This would work for the particular case in OP's request but the first option will also tell you how many non-"1" characters you have (if that information matters). Depending on implementation, trim might run slightly faster because PHP doesn't have to check any characters between the first and last non-"1" characters.
You could also use a string like a character array and iterate through from the beginning until you find a character which is not =='1' (in which case, return true) or reach the end of the array (in which case, return false).
Finally, though OP here said "preferably without regex," others open to regexes might use one:
preg_match("/[^1]/", $mystring)==1
Another way to do it:
if (base_convert($string, 2, 2) === $string) {
// $string has only 0 and 1 characters.
}
since your $string is basically a binary number, you can check it with base_convert.
How it works:
var_dump(base_convert('110', 2, 2)); // 110
var_dump(base_convert('11503', 2, 2)); // 110
var_dump(base_convert('9111111111111111111110009', 2, 2)); // 11111111111111111111000
If the returned value of base_convert is different from the input, there're something other characters, beside 0 and 1.
If you want checks if the string has only 1 characters:
if(array_sum(str_split($string)) === strlen($string)) {
// $string has only 1 characters.
}
You retrieve all the single numbers with str_split, and sum them with array_sum. If the result isn't the same as the length of the string, then you've other number in the string beside 1.
Another option is treat string like array of symbols and check for something that is not 1. If it is - break for loop:
for ($i = 0; $i < strlen($mystring); $i++) {
if ($mystring[$i] != '1') {
echo 'FOUND!';
break;
}
}
I want to limit the number of "b" between 1 and 6, for which I'm using the following code:
<?php
$str="Big black books being kept in a black bag of a beautiful babe";
$pattern="/(b){1,6}/";
if(!preg_match($pattern,$str,$matches))
{
echo "Please use six bs";
}else
{/*do nothing*/}
print_r($matches);
?>
But It's not working. What am I doing wrong?
Through regex alone..
$str="Big black books being kept in a black bag of a beautiful babe";
$pattern="/^([^b]*b){1,6}[^b]*$/";
if(!preg_match($pattern,$str,$matches))
{
echo "Please use upto six bs";
}else
{/*do nothing*/}
print_r($matches);
and note that this must except atleast one single b. If you want to match also the line which don't have any single b then use /^([^b]*b){0,6}[^b]*$/
Add case-insensitive modifier i if you want to count also for capital B's.
Explanation:
^ start of the line.
([^b]*b){1,6} It matches (zero or more non-b characters and a b)(from 1 to 6 times). So this ensures that there must be character b exists min of 1 time and a max of 6 times.
[^b]* Matches any char but not of b, zero or more times. This ensures that there are no more further b exists.
$ End of the line boundary..
Try using match count.
<?php
$str="Big black books being kept in a black bag of a beautiful babe";
preg_match_all("/(b)/i",$str,$matches);
if(isset($matches[1]) && count($matches[1]) > 6 )
{
echo "Please use six bs";
}else
{/*do nothing*/}
print_r($matches);
?>
I think you want to count the number of Bs in the whole string while your regular expression counts them only in rows. i.e. "bbb" or just "b" would return a match.
Try using substr_count to achieve what I think you want. Here's an example.
<?php
$str = "Big black books being kept in a black bag of a beautiful babe";
if(substr_count($str, "b") > 6)
echo "Six is the limit...";
else
echo "Doing nothing...";
?>
But of course, it won't really help if you want to see the found matches.
So I'm working on a project that will allow users to enter poker hand histories from sites like PokerStars and then display the hand to them.
It seems that regex would be a great tool for this, however I rank my regex knowledge at "slim to none".
So I'm using PHP and looping through this block of text line by line and on lines like this:
Seat 1: fabulous29 (835 in chips)
Seat 2: Nioreh_21 (6465 in chips)
Seat 3: Big Loads (3465 in chips)
Seat 4: Sauchie (2060 in chips)
I want to extract seat number, name, & chip count so the format is
Seat [number]: [letters&numbers&characters] ([number] in chips)
I have NO IDEA where to start or what commands I should even be using to optimize this.
Any advice is greatly appreciated - even if it is just a link to a tutorial on PHP regex or the name of the command(s) I should be using.
I'm not entirely sure what exactly to use for that without trying it, but a great tool I use all the time to validate my RegEx is RegExr which gives a great flash interface for trying out your regex, including real time matching and a library of predefined snippets to use. Definitely a great time saver :)
Something like this might do the trick:
/Seat (\d+): ([^\(]+) \((\d+)in chips\)/
And some basic explanation on how Regex works:
\d = digit.
\<character> = escapes character, if not part of any character class or subexpression. for example:
\t
would render a tab, while \\t would render "\t" (since the backslash is escaped).
+ = one or more of the preceding element.
* = zero or more of the preceding element.
[ ] = bracket expression. Matches any of the characters within the bracket. Also works with ranges (ex. A-Z).
[^ ] = Matches any character that is NOT within the bracket.
( ) = Marked subexpression. The data matched within this can be recalled later.
Anyway, I chose to use
([^\(]+)
since the example provides a name containing spaces (Seat 3 in the example). what this does is that it matches any character up to the point that it encounters an opening paranthesis.
This will leave you with a blank space at the end of the subexpression (using the data provided in the example). However, his can easily be stripped away using the trim() command in PHP.
If you do not want to match spaces, only alphanumerical characters, you could so something like this:
([A-Za-z0-9-_]+)
Which would match any letter (within A-Z, both upper- & lower-case), number as well as hyphens and underscores.
Or the same variant, with spaces:
([A-Za-z0-9-_\s]+)
Where "\s" is evaluated into a space.
Hope this helps :)
Look at the PCRE section in the PHP Manual. Also, http://www.regular-expressions.info/ is a great site for learning regex. Disclaimer: Regex is very addictive once you learn it.
I always use the preg_ set of function for REGEX in PHP because the PERL-compatible expressions have much more capability. That extra capability doesn't necessarily come into play here, but they are also supposed to be faster, so why not use them anyway, right?
For an expression, try this:
/Seat (\d+): ([^ ]+) \((\d+)/
You can use preg_match() on each line, storing the results in an array. You can then get at those results and manipulate them as you like.
EDIT:
Btw, you could also run preg_match_all on the entire block of text (instead of looping through line-by-line) and get the results that way, too.
Check out preg_match.
Probably looking for something like...
<?php
$str = 'Seat 1: fabulous29 (835 in chips)';
preg_match('/Seat (?<seatNo>\d+): (?<name>\w+) \((?<chipCnt>\d+) in chips\)/', $str, $matches);
print_r($matches);
?>
*It's been a while since I did php, so this could be a little or a lot off.*
May be it is very late answer, But I am interested in answering
Seat\s(\d):\s([\w\s]+)\s\((\d+).*\)
http://regex101.com/r/cU7yD7/1
Here's what I'm currently using:
preg_match("/(Seat \d+: [A-Za-z0-9 _-]+) \((\d+) in chips\)/",$line)
To process the whole input string at once, use preg_match_all()
preg_match_all('/Seat (\d+): \w+ \((\d+) in chips\)/', $preg_match_all, $matches);
For your input string, var_dump of $matches will look like this:
array
0 =>
array
0 => string 'Seat 1: fabulous29 (835 in chips)' (length=33)
1 => string 'Seat 2: Nioreh_21 (6465 in chips)' (length=33)
2 => string 'Seat 4: Sauchie (2060 in chips)' (length=31)
1 =>
array
0 => string '1' (length=1)
1 => string '2' (length=1)
2 => string '4' (length=1)
2 =>
array
0 => string '835' (length=3)
1 => string '6465' (length=4)
2 => string '2060' (length=4)
On learning regex: Get Mastering Regular Expressions, 3rd Edition. Nothing else comes close to the this book if you really want to learn regex. Despite being the definitive guide to regex, the book is very beginner friendly.
Try this code. It works for me
Let say that you have below lines of strings
$string1 = "Seat 1: fabulous29 (835 in chips)";
$string2 = "Seat 2: Nioreh_21 (6465 in chips)";
$string3 = "Seat 3: Big Loads (3465 in chips)";
$string4 = "Seat 4: Sauchie (2060 in chips)";
Add to array
$lines = array($string1,$string2,$string3,$string4);
foreach($lines as $line )
{
$seatArray = explode(":", $line);
$seat = explode(" ",$seatArray[0]);
$seatNumber = $seat[1];
$usernameArray = explode("(",$seatArray[1]);
$username = trim($usernameArray[0]);
$chipArray = explode(" ",$usernameArray[1]);
$chipNumber = $chipArray[0];
echo "<br>"."Seat [".$seatNumber."]: [". $username."] ([".$chipNumber."] in chips)";
}
you'll have to split the file by linebreaks,
then loop thru each line and apply the following logic
$seat = 0;
$name = 1;
$chips = 2;
foreach( $string in $file ) {
if (preg_match("Seat ([1-0]): ([A-Za-z_0-9]*) \(([1-0]*) in chips\)", $string, $matches)) {
echo "Seat: " . $matches[$seat] . "<br>";
echo "Name: " . $matches[$name] . "<br>";
echo "Chips: " . $matches[$chips] . "<br>";
}
}
I haven't ran this code, so you may have to fix some errors...
Seat [number]: [letters&numbers&characters] ([number] in chips)
Your Regex should look something like this
Seat (\d+): ([a-zA-Z0-9]+) \((\d+) in chips\)
The brackets will let you capture the seat number, name and number of chips in groups.