Sort with If statement in while - php

i have got a mysql database with words. I am printing all the words with a while statement. So i get like:
potato
tomato
lettace
This is all working fine, but i want to sort the words by length. I have tried:
if(strlen($go['words']) == 4 ){ echo "this are the 4 letter words:"; }
but this will print the sentence before every 4 letter word. Whereas, I want it to be printed only 1 time as a header for all 4 letter words. Of course i want to do this also for 5,6,7 letter words.
I have thought about making multiple sql query's but thats too much for the server to handle with a lot of visitors.

you can use a temporary variable like this:
$tempLen = 0;
while(...)
{
if(strlen($go['words']) == 1 && $tempLen < 1){
echo "this are the 1 letter words:";
$tempLen = 1;
}
...
if(strlen($go['words']) == 4 && $tempLen < 4){
echo "this are the 4 letter words:";
$tempLen = 4;
}
...
}

Is this what you want?
$words = array("fish", "mouse", "rabbit", "turtle", "duck");
sort($words);
$last_letter_count = 0;
foreach($words as $word)
{
if ( strlen($word) != $last_letter_count )
{
$last_letter_count = strlen($word);
echo "These are the $last_letter_count letter words:\n";
}
echo $word . "\n";
}
output:
These are the 4 letter words:
duck
fish
These are the 5 letter words:
mouse
These are the 6 letter words:
rabbit
turtle

Related

php generate string combinations of missing letters

I have some word lets say BKOO.
I need to remove all combinations of missing letters to generate sub words of this initial word. First remove only 1 letter, then n letters to build at least 2 letters words.
So from our example it means to make words like KOO, BOO, OO, BK, BO.
My current algorithm btw says it is possible to generate 7 combinations out of BKOO. (I also include the initial word).
Array
(
[0] => BKOO
[1] => Array
(
[0] => BKOO
[1] => KOO
[2] => OO
[3] => KO
[4] => BOO
[5] => BO
[6] => BKO
[7] => BK
)
)
Note there isnt words like BOK or OOK because that would mean do the reorder, but i dont want to do this. I want just leave letters out of current word, and don't do reorder.
Now problem is, this very slow for lenght like 15. It takes forever. How to speed it up?
function comb($s, $r = [], $init = false) {
if ($init) {
$s = mb_strtoupper($s);
$r[] = $s;
}
$l = strlen($s);
if (!$s || $l < 3) return [];
for ($i=0; $i<$l; $i++) {
$t = rem_index($s, $i);
$r[] = $t;
$r = array_merge($r, comb($t));
}
$ret = array_unique((array)$r);
return $init ? array_values($ret) : $ret;
}
// remove character at position
function rem_index($str, $ind)
{
return substr($str,0,$ind++). substr($str,$ind);
}
$s = 'BKOO';
print_r(comb($s, [], true));
https://www.tehplayground.com/62pjCAs70j7qpLJj
NERD SECTION: 🤓 😄
Interesting note - first i thought i will generate array of some dropping indexes eg, first drop only 1 letter so say drop 0 then 1 etc etc, then 2-combinations so drop 1 and 2, 1 and 3 etc, but then i thought it would be quite difficult to drop N letters out of string at once, so i came with idea that i always drop some letter from the string, and recursively call the function again if you get me, so the next level is one char dropped already and does the drop iteration again. Problem is it is very slow for some reason.
Btw if you have also the math background, what is equation to compute the resulting combinations? To me the rough computation is lets say for 15 letters word 14 * 13 * 12 or at least it does such iteration, but that would be milions of combinations and obviously its not like that even for shorter words like 8.
Thanks.
You can iterate the string to get it.
function foo(&$res,$str,$min_length){
if(strlen($str) <= $min_length){
return;
}
$remains=[];
for($i=0; $i<strlen($str); $i++){
$remain = substr($str,0,$i) . substr($str,$i+1);
if(!isset($res[$remain])) { // only process unprocessed sub string
$res[$remain] = $remain;
$remains[] = $remain;
}
}
foreach($remains as $remain){
if(strlen($remain) == $min_length){
$res[$remain] = $remain;
}else {
foo($res, $remain, $min_length);
}
}
return;
}
$str = "BKOO";
$res = [];
foo($res,$str,2);
var_dump(array_values($res));

Extract and merge strings between different positions

I'm trying to make this works. I want to replace some parts of a sentence between given positions and then show the full sentence with the changes. With the following code, I'm able to make the changes but I don't know how to put together the rest of the sentence.
I have two arrays, one with the positions where a woman name appears and another one with men names. The code replaces the pronoun "his" by "her" when a woman is before a man between the intervals. The last thing I need is to reconstruct the sentence with the changes made but I don't know how to extract the rest of the sentence (the result, in the example, is from positions 0 to 20 (Maria her dress but) and 36 to 51 (Lorena her dog) but I need to extract from 20 to 36 (Peter his jeans) and 51 to the end (Juan his car) to merge them in their positions).
The result should be: "Maria her dress but Peter his jeans Lorena her dog Juan his car". I'll appreciate any help with this, I've been looking for other similar questions but I found nothing.
<?php
$womenpos = array("0","36"); //these arrays are just examples of positions
$menpos = array("20","51"); //they will change depending on the sentence
$sentence = "Maria his dress but Peter his jeans Lorena his dog Juan his car";
echo $sentence."\n";
foreach ($womenpos as $index => $value) {
$value2 = $menpos[$index];
if($value < $value2) {
echo "\nWoman(" . $value . ") is before man(" . $value2 . ")\n";
$end = ($value2 - $value);
$improved = str_replace(' his ', ' her ',
substr($sentence, $value, $end));
echo $improved."\n";
} else {
$improved = "Nothing changed";
echo $improved;
}
}
Ok, how about this:
$womenpos = array("0","36");
$menpos = array("20","51");
$bothpos = array_merge($womenpos,$menpos);
sort ($bothpos);
print_r($bothpos);
$sentence = "Maria his dress but Peter his jeans Lorena his dog Juan his car";
echo $sentence."\n";
for ($i = 0; $i<sizeof($bothpos); $i++) {
$start = $bothpos[$i];
if ($i ==sizeof($bothpos)-1) {
$end = strlen($sentence);
}
else {
$end = $bothpos[$i+1];
}
$length = $end-$start;
$segment = substr($sentence, $start, $length);
if (in_array($start, $womenpos)) {
$new_segment = str_replace (' his ', ' her ', $segment);
}
else { $new_segment = $segment; }
$improved .= $new_segment;
print "<li>$start-$end: $segment : $new_segment </li>\n";
}
print "<p>Improved: $improved</p>";
This combines the men's and women's position arrays to consider each stretch of text as one that might have an error. If that stretch of text starts at one of the womenpos points, then it changes 'his' to 'her'. If not it leaves it alone.
Does this get you in the direction you want to go in? I hope so!
This approaches the problem differently, but I wonder if it would provide the solution you're looking for:
$sentence = "Maria his dress but Peter his jeans Lorena his dog Juan his car";
$women = array ("Maria", "Lorena");
$words = explode (" ", $sentence);
for ($i=0; $i< sizeof($words); $i++) {
if ($words[$i] == "his" && in_array($words[$i-1], $women)) {
$words[$i] = "her";
}
}
print (join(" ", $words));
This goes through the words one at a time; if the preceding word is in the $women array and the current word is "his", it changes the word to "her". Then it spits out all the words in order.
Does this do what you need, or do you really want a complex string positioning answer?

Loop a 2 letter range

I'm trying to achieve a loop over all possible 2 letter combinations.
Something like
foreach(range(aa,zz) as $i) {...}
My current solution is:
foreach (range(a, z) as $first) {
foreach (range(a, z) as $second) {
//all 2 letter combinations
echo $first.$second;
}
}
This makes me worry that if I needed all possible 10 letter combinations, there would be 10 loops involved.
Is there a better way to achieve this?
You could loop over letters using a simple for loop :
for ($letter = 'aa'; $letter != 'aaa'; ++$letter) {
echo $letter . '<br>';
}
Output :
aa
ab
...
zy
zz
$a = array(1,2,3,4,5,6,7,8,9,0);
$b = array('q','r','s','t','u','v','w','x','y','z');
for($i = 26;$i <= 1000;$i++)
echo str_replace($a,$b,base_convert ( $i, 10 , 26))."<br />";
just put in the right starting and end positions.

Searching if letters in a word are found in another word PHP Strings

Just like the title of this post says, I would to be able to check if every letter of a word is found in another word. So far these are the lines of codes that I was able to come up with:
<?php
$DBword = $_POST['DBword'];
$inputWords = $_POST['inputWords'];
$inputCount = str_word_count($inputWords,1);
echo "<b>THE WORD:</b>"."<br/>".$DBword."<br/><br/>";
echo "<b>WORDS ENTERED:</b><br/>";
foreach($inputCount as $outputWords)
{
echo $outputWords."<br/>";
}
foreach($inputCount as $countWords)
{
for($i=0; $i<strlen($countWords); $i++)
{$count = strpos( "$DBword", $countWords[$i]);}
if($count === false)
{
$score++;
}
}
echo "<b><br/>TOTAL SCORE: </b>";
echo $score;
?>
My point in having the foreach with the $outputWords is to just output the letters entered.
As for the other foreach that has $countWords, I am using it to really check if all letters in the word entered are found in the $DBword. I am using the for loop to check every letter.
So far, I am not getting the output that I want and I just ran out of ideas. Any ideas please?
function contains_letters($word1, $word2) {
for ($i = 0; $i < strlen($word1); $i++)
if (strpos($word2, $word1{$i}) === false)
return false;
return true;
}
//example usage
if (contains_letters($_POST['inputWords'], $_POST['DBword']))
echo "All the letters were found.";
If this check should be case-insensitive (i.e. 'A' counts as a usage of 'a'), change strpos to stripos.
Since you are overwriting $count in the for loop for each letter in $countWords, $count will contain the position of the last letter of $countWord only. Also, I am not sure why you increase score when the letter wasn't found.
In any case, you are making your life more difficult than necessary.
PHP has a function for counting chars in a string:
return count_chars($dbWord, 3) === count_chars($inputWord, 3);
will return true if the same letters are found in both strings.
Example to find all the words having exactly the same letters:
$dbWord = count_chars('foobar', 3);
$inputWords = 'barf boo oof raboof boarfo xyz';
print_r(
array_filter(
str_word_count($inputWords, 1),
function($inputWord) use ($dbWord) {
return count_chars($inputWord, 3) === $dbWord;
}
)
);
will output "raboof" and "boarfo" only.

Check words if they are composed of Consecutive Alphabetic Characters

I take a sentence as input like this:
abcd 01234 87 01235
Next, I have to check every word to see if its characters are consecutive in the alphabet. The output looks like this:
abcd 01234
Well, 01235 contains consecutive chars, but the whole word ALSO contains non-consecutive chars (35), so it's not printed on the screen.
So far I wrote this:
function string_to_ascii($string)
{
$ascii = NULL;
for ($i = 0; $i < strlen($string); $i++)
{
$ascii[] = ord($string[$i]);
}
return($ascii);
}
$input = "abcd 01234 87 01235";
//first, we split the sentence into separate words
$input = explode(" ",$input);
foreach($input as $original_word)
{
//we need it clear
unset($current_word);
//convert current word into array of ascii chars
$ascii_array = string_to_ascii($original_word);
//needed for counting how many chars are already processed
$i = 0;
//we also need to count the total number chars in array
$ascii_count = count($ascii_array);
//here we go, checking each character from array
foreach ($ascii_array as $char)
{
//if IT'S THE LAST WORD'S CHAR
if($i+1 == $ascii_count)
{
//IF THE WORD HAS JUST 1 char, output it
if($ascii_count == 1)
{
$current_word .= chr($char);
}
//IF THE WORDS HAS MORE THAN 1 CHAR
else
{
//IF PREVIOUS CHAR CODE IS (CURRENT_CHAR-1) (CONSECUTIVE, OUTPUT IT)
if(($char - 1) == $ascii_array[($i-1)])
{
$current_word .=chr($char);
}
}
}
//IF WE AREN'T YET AT THE ENDING
else
{
//IF NEXT CHAR CODE IS (CURRENT_CHAR+1) (CONSECUTIVE, OUTPUT IT)
if(($char + 1) == ($ascii_array[($i+1)]))
{
$current_word .=chr($char);
}
}
$i++;
}
//FINALLY, WE CHECK IF THE TOTAL NUMBER OF CONSECUTIVE CHARS is the same as THE NUMBER OF CHARS
if(strlen($current_word) == strlen($original_word))
{
$output[] = $current_word;
}
}
//FORMAT IT BACK AS SENTENCE
print(implode(' ',$output));
But maybe there is another way to do this, more simple?
sorry for bad spelling
This works...
$str = 'abcd 01234 87 01235';
$words = explode(' ', $str);
foreach($words as $key => $word) {
if ($word != implode(range($word[0], chr(ord($word[0]) + strlen($word) - 1)))) {
unset($words[$key]);
}
}
echo implode(' ', $words);
CodePad.
Basically, it grabs the first character of each word, and creates the range of characters which would be the value if the word consisted of sequential characters.
It then does a simple string comparison.
For a more performant version...
$str = 'abcd 01234 87 01235';
$words = explode(' ', $str);
foreach($words as $key => $word) {
foreach(str_split($word) as $index => $char) {
$thisOrd = ord($char);
if ($index > 0 AND $thisOrd !== $lastOrd + 1) {
unset($words[$key]);
break;
}
$lastOrd = $thisOrd;
}
}
echo implode(' ', $words);
CodePad.
Both these examples rely on the ordinals of the characters being sequential for sequential characters. This is the case in ASCII, but I am not sure about other characters.

Categories