can someone help with this?
I need the following function to do this...
$x = 'AAAABAA';
$x2 = 'ABBBAA';
function foo($str){
//do something here....
return $str;
}
$x3 = foo($x); //output: A4B1A2
$x4 = foo($x2);//output: A1B3A2
substr_count is your friend
or rather this
function foo($str) {
$out = '';
preg_match_all('~(.)\1*~', $str, $m, PREG_SET_ORDER);
foreach($m as $p) $out .= $p[1] . strlen($p[0]);
return $out;
}
function foo($str) {
$s = str_split($str);
if (sizeof($s) > 0) {
$current = $s[0];
$output = $current;
$count = 0;
foreach ($s as $char) {
if ($char != $current ) {
$output .= $count;
$current = $char;
$output .= $current;
$count = 1;
}
else {
$count++;
}
}
$output .= $count;
return $output;
}
else
return "";
}
Related
I'm trying ta make a program that will ask the user for a number and then show all the prime numbers between 0 to this number in an array.
<?php
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
/* YOUR CODE HERE */
function isPrime($n)
{
if ($n <= 1)
return false;
for ($i = 2; $i < $n; $i++)
if ($n % $i == 0)
return false;
return true;
}
function printPrime($n)
{
for ($i = 2; $i <= $n; $i++)
{
if (isPrime($i))
echo $i . " ";
}
}
$n = 7;
printPrime($n);
/*end of your code here */
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}
}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
This code work, but with a $n fixed.
I don't know how to use an input who ask the user a number
It's a code who verify itself and show us when it's ok
The code that i have to complete is this one (we only have this at first):
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
/* YOUR CODE HERE */
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}
}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
This is your script:
<?php
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
function isPrime($n) {
if ($n <= 1) return false;
for ($i = 2; $i < $n; $i++) if ($n % $i == 0) return false;
return true;
}
function printPrime($n) {
for ($i = 2; $i < $n; $i++) if (isPrime($i)) $result[] = $i;
return $result;
}
$result = printPrime($smaller_than);
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
function getSmallerPrimes($smaller_than) {
if ($smaller_than <= 2) {
return [];
}
$result = [2];
$sqrt = sqrt($smaller_than);
for ($n = 3; $n < $smaller_than; $n += 2) {
$isPrime = true;
foreach($result as $prime) {
if ($n % $prime == 0) {
$isPrime = false;
break;
}
if ($prime > $sqrt) {
break;
}
}
if ($isPrime) {
$result[] = $n;
}
}
return $result;
}
$input = 23;
echo implode(' ', getSmallerPrimes($input));
Result: 2 3 5 7 11 13 17 19
Here is python code:
def is_palindrome(s):
return revers(s) == s
def revers(s):
ret = ''
for ch in s:
ret = ch + ret
return ret
print is_palindrome('RACECAR')
# that will print true
when i convert that function to php.
function is_palindrome($string){
if (strrev($string) == $string) return true;
return false;
}
$word = "RACECAR";
var_dump(is_palindrome($word));
// true
Both functions works fine but, how can i revers string with php in loop ??
$string = str_split(hello);
$output = '';
foreach($string as $c){
$output .= $c;
}
print $output;
// output
hello
//i did this,
that's work find but is there any way to do that in better way ?
$string = "hello";
$lent = strlen($string);
$ret = '';
for($i = $lent; ($i > 0) or ($i == 0); $i--)
{
$ret .= $string[$i];
#$lent = $lent - 1;
}
print $output;
//output
olleh
Replace
$output .= $c;
with
$output = $c . $output;
Can't be shorter I guess. With a loop :)
$word = "Hello";
$result = '';
foreach($word as $letter)
$result = $letter . $result;
echo $result;
I don't try that code, but I think that it should work:
$string = "hello";
$output = "";
$arr = array_reverse(str_split($string)); // Transform "" to [] and then reverse => ["o","l","l,"e","h"]
foreach($arr as $char) {
$output .= $char;
}
echo $output;
Another way:
$string = "hello";
$output = "";
for($i = strlen($string); $i >= 0; $i--) {
$output .= substr($string, $i, 1);
}
echo $output;
strrev() is a function that reverses a string in PHP.
http://php.net/manual/en/function.strrev.php
$s = "foobar";
echo strrev($s); //raboof
If you want to check if a word is a palindrome:
function is_palindrome($word){ return strrev($word) == $word }
$s = "RACECAR";
echo $s." is ".((is_palindrome($s))?"":"NOT ")."a palindrome";
I find theese php codes here, but codes aren't working correctly. it seems that the if(isset($words[$word])) doesn't go through as I always get an empty results array
$boggle = "fxie
amlo
ewbx
astu";
$alphabet = str_split(str_replace(array("\n", " ", "\r"), "", strtolower($boggle)));
$rows = array_map('trim', explode("\n", $boggle));
$dictionary = file("C:/dict.txt");
$prefixes = array(''=>'');
$words = array();
$regex = '/[' . implode('', $alphabet) . ']{3,}$/S';
foreach($dictionary as $k=>$value) {
$value = trim(strtolower($value));
$length = strlen($value);
if(preg_match($regex, $value)) {
for($x = 0; $x < $length; $x++) {
$letter = substr($value, 0, $x+1);
if($letter == $value) {
$words[$value] = 1;
} else {
$prefixes[$letter] = 1;
}
}
}
}
$graph = array();
$chardict = array();
$positions = array();
$c = count($rows);
for($i = 0; $i < $c; $i++) {
$l = strlen($rows[$i]);
for($j = 0; $j < $l; $j++) {
$chardict[$i.','.$j] = $rows[$i][$j];
$children = array();
$pos = array(-1,0,1);
foreach($pos as $z) {
$xCoord = $z + $i;
if($xCoord < 0 || $xCoord >= count($rows)) {
continue;
}
$len = strlen($rows[0]);
foreach($pos as $w) {
$yCoord = $j + $w;
if(($yCoord < 0 || $yCoord >= $len) || ($z == 0 && $w == 0)) {
continue;
}
$children[] = array($xCoord, $yCoord);
}
}
$graph['None'][] = array($i, $j);
$graph[$i.','.$j] = $children;
}
}
function to_word($chardict, $prefix) {
$word = array();
foreach($prefix as $v) {
$word[] = $chardict[$v[0].','.$v[1]];
}
return implode("", $word);
}
function find_words($graph, $chardict, $position, $prefix, $prefixes, &$results, $words) {
$word = to_word($chardict, $prefix);
if(!isset($prefixes[$word])) return false;
**if(isset($words[$word])) {
$results[] = $word;
}**
foreach($graph[$position] as $child) {
if(!in_array($child, $prefix)) {
$newprefix = $prefix;
$newprefix[] = $child;
find_words($graph, $chardict, $child[0].','.$child[1], $newprefix, $prefixes, $results, $words);
}
}
}
$solution = array();
find_words($graph, $chardict, 'None', array(), $prefixes, $solution);
print_r($solution);
When you call find_words() at the end, you are only passing 6 parameters
find_words($graph, $chardict, 'None', array(), $prefixes, $solution);
The variable $words, is the 7th parameter in your definition of find_words()
function find_words($graph, $chardict, $position, $prefix, $prefixes, &$results, $words) {
Hence, $words will always be empty, and isset($words[$word]) will always be false
I have list of brands and want to provide a search function with highlighting. For example, there are the following brands
Apple
Cewe Color
L'Oréal
Microsoft
McDonald's
Tom Tailor
The user then types lor in search form. I'm using the following snippet for searching
class search {
private function simplify($str) {
return str_replace(array('&',' ',',','.','?','|','\'','"'), '', iconv('UTF-8', 'ASCII//TRANSLIT', $str));
}
public function do_search($search) {
$search = self::simplify($search);
$found = array();
foreach (self::$_brands as $brand) {
if (mb_strstr(self::simplify($brand['name']), $search) !== false) $found[]= $brand;
}
return $found;
}
}
That gives me:
Cewe Color
L'Oréal
Tom Tailor
How would be a highlighting possible? Like:
Cewe Co<b>lor</b>
L'<b>Oré</b>al
Tom Tai<b>lor</b>
Btw: I know, that most things can be done with str_replace(), but that fit my needs not in all cases
$highlighted = str_replace($search, "<b>$search</b>", $brand);
would be the simplest method.
:)
Works with FedEx also ;)
$_brands = array
(
"Apple",
"Cewe Color",
"L'Oréal",
"Microsoft",
"McDonald's",
"Tom Tailor"
);
$q = 'lor';
$search = clean($q);
foreach($_brands as $key => $brand){
$brand = clean($brand);
$x = stripos($brand, $search);
if($x !== false){
$regexp = NULL;
$l = strlen($q);
for($i = 0; $i < $l; $i++){
$regexp .= mb_strtoupper($q[$i]).'.?';
}
$regexp = substr($regexp, 0, strlen($regexp) - 2);
$new = $_brands[$key];
$new = preg_replace('#('.$regexp.')#ui', '<b>$0</b>', $new);
echo $new."<br />";
}
}
function clean($string){
$string = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $string);
$string = preg_replace('#[^\w]#ui', '', $string);
return $string;
}
self::$_brands contains result from database (containing columns name, name_lower, name_translit, name_simplified)
class search {
private function translit($str) {
return iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', str_replace(array('ä', 'ü', 'ö', 'ß'), array('a', 'u', 'o', 's'), mb_strtolower($str)));
}
private function simplify($str) {
return preg_replace('/([^a-z0-9])/ui', '', self::translit($str));
}
public function do_search($simplified) {
$found = array();
foreach (self::$_brands as $brand) {
if (mb_strstr($brand['name_simplified'], $simplified) !== false) $found[]= $brand;
}
return $found;
}
private function actionDefault() {
$search = $_POST['search_fld'];
$simplified = self::simplify($search);
$result = self::do_search($simplified);
$brands = array();
foreach ($result as $brand) {
$hl_start = mb_strpos($brand['name_simplified'], $simplified);
$hl_len = mb_strlen($simplified);
$brand_len = mb_strlen($brand['name']);
$tmp = '';
$cnt_extra = 0;
$start_tag = false;
$end_tag = false;
for ($i = 0; $i < $brand_len; $i++) {
if (($i - $cnt_extra) < mb_strlen($brand['name_simplified']) && mb_substr($brand['name_translit'], $i, 1) != mb_substr($brand['name_simplified'], $i - $cnt_extra, 1)) $cnt_extra++;
if (($i - $cnt_extra) == $hl_start && !$start_tag) {
$tmp .= '<b>';
$start_tag = true;
}
$tmp .= mb_substr($brand['name'], $i, 1);
if (($i - $cnt_extra + 1) == ($hl_start + $hl_len) && !$end_tag) {
$tmp .= '</b>';
$end_tag = true;
}
}
if ($start_tag && !$end_tag) $tmp .= '</b>';
$brands[] = "" . $tmp . "";
}
echo implode(' | ', $brands);
}
}
Is there a way to do this without writing my own function?
For example:
$text = 'Test <span><a>something</a> something else</span>.';
$text = cutText($text, 2, null, 20, true);
//result: Test <span><a>something</a></span>
I need to make this function indestructible
My problem is similar to
This thread
but I need a better solution. I would like to keep nested tags untouched.
So far my algorithm is:
function cutText($content, $max_words, $max_chars, $max_word_len, $html = false) {
$len = strlen($content);
$res = '';
$word_count = 0;
$word_started = false;
$current_word = '';
$current_word_len = 0;
if ($max_chars == null) {
$max_chars = $len;
}
$inHtml = false;
$openedTags = array();
for ($i = 0; $i<$max_chars;$i++) {
if ($content[$i] == '<' && $html) {
$inHtml = true;
}
if ($inHtml) {
$max_chars++;
}
if ($html && !$inHtml) {
if ($content[$i] != ' ' && !$word_started) {
$word_started = true;
$word_count++;
}
$current_word .= $content[$i];
$current_word_len++;
if ($current_word_len == $max_word_len) {
$current_word .= '- ';
}
if (($content[$i] == ' ') && $word_started) {
$word_started = false;
$res .= $current_word;
$current_word = '';
$current_word_len = 0;
if ($word_count == $max_words) {
return $res;
}
}
}
if ($content[$i] == '<' && $html) {
$inHtml = true;
}
}
return $res;
}
But of course it won't work. I thought about remembering opened tags and closing them if they were not closed but maybe there is a better way?
This works perfectly for me:
function trimContent ($str, $trimAtIndex) {
$beginTags = array();
$endTags = array();
for($i = 0; $i < strlen($str); $i++) {
if( $str[$i] == '<' )
$beginTags[] = $i;
else if($str[$i] == '>')
$endTags[] = $i;
}
foreach($beginTags as $k=>$index) {
// Trying to trim in between tags. Trim after the last tag
if( ( $trimAtIndex >= $index ) && ($trimAtIndex <= $endTags[$k]) ) {
$trimAtIndex = $endTags[$k];
}
}
return substr($str, 0, $trimAtIndex);
}
Try something like this
function cutText($inputText, $start, $length) {
$temp = $inputText;
$res = array();
while (strpos($temp, '>')) {
$ts = strpos($temp, '<');
$te = strpos($temp, '>');
if ($ts > 0) $res[] = substr($temp, 0, $ts);
$res[] = substr($temp, $ts, $te - $ts + 1);
$temp = substr($temp, $te + 1, strlen($temp) - $te);
}
if ($temp != '') $res[] = $temp;
$pointer = 0;
$end = $start + $length - 1;
foreach ($res as &$part) {
if (substr($part, 0, 1) != '<') {
$l = strlen($part);
$p1 = $pointer;
$p2 = $pointer + $l - 1;
$partx = "";
if ($start <= $p1 && $end >= $p2) $partx = "";
else {
if ($start > $p1 && $start <= $p2) $partx .= substr($part, 0, $start-$pointer);
if ($end >= $p1 && $end < $p2) $partx .= substr($part, $end-$pointer+1, $l-$end+$pointer);
if ($partx == "") $partx = $part;
}
$part = $partx;
$pointer += $l;
}
}
return join('', $res);
}
Parameters:
$inputText - input text
$start - position of first character
$length - how menu characters we want to remove
Example #1 - Removing first 3 characters
$text = 'Test <span><a>something</a> something else</span>.';
$text = cutText($text, 0, 3);
var_dump($text);
Output (removed "Tes")
string(47) "t <span><a>something</a> something else</span>."
Removing first 10 characters
$text = cutText($text, 0, 10);
Output (removed "Test somet")
string(40) "<span><a>hing</a> something else</span>."
Example 2 - Removing inner characters - "es" from "Test "
$text = cutText($text, 1, 2);
Output
string(48) "Tt <span><a>something</a> something else</span>."
Removing "thing something el"
$text = cutText($text, 9, 18);
Output
string(32) "Test <span><a>some</a>se</span>."
Hope this helps.
Well, maybe this is not the best solution but it's everything I can do at the moment.
Ok I solved this thing.
I divided this in 2 parts.
First cutting text without destroying html:
function cutHtml($content, $max_words, $max_chars, $max_word_len) {
$len = strlen($content);
$res = '';
$word_count = 0;
$word_started = false;
$current_word = '';
$current_word_len = 0;
if ($max_chars == null) {
$max_chars = $len;
}
$inHtml = false;
$openedTags = array();
$i = 0;
while ($i < $max_chars) {
//skip any html tags
if ($content[$i] == '<') {
$inHtml = true;
while (true) {
$res .= $content[$i];
$i++;
while($content[$i] == ' ') { $res .= $content[$i]; $i++; }
//skip any values
if ($content[$i] == "'") {
$res .= $content[$i];
$i++;
while(!($content[$i] == "'" && $content[$i-1] != "\\")) {
$res .= $content[$i];
$i++;
}
}
//skip any values
if ($content[$i] == '"') {
$res .= $content[$i];
$i++;
while(!($content[$i] == '"' && $content[$i-1] != "\\")) {
$res .= $content[$i];
$i++;
}
}
if ($content[$i] == '>') { $res .= $content[$i]; $i++; break;}
}
$inHtml = false;
}
if (!$inHtml) {
while($content[$i] == ' ') { $res .= $content[$i]; $letter_count++; $i++; } //skip spaces
$word_started = false;
$current_word = '';
$current_word_len = 0;
while (!in_array($content[$i], array(' ', '<', '.', ','))) {
if (!$word_started) {
$word_started = true;
$word_count++;
}
$current_word .= $content[$i];
$current_word_len++;
if ($current_word_len == $max_word_len) {
$current_word .= '-';
$current_word_len = 0;
}
$i++;
}
if ($letter_count > $max_chars) {
return $res;
}
if ($word_count < $max_words) {
$res .= $current_word;
$letter_count += strlen($current_word);
}
if ($word_count == $max_words) {
$res .= $current_word;
$letter_count += strlen($current_word);
return $res;
}
}
}
return $res;
}
And next thing is closing unclosed tags:
function cleanTags(&$html) {
$count = strlen($html);
$i = -1;
$openedTags = array();
while(true) {
$i++;
if ($i >= $count) break;
if ($html[$i] == '<') {
$tag = '';
$closeTag = '';
$reading = false;
//reading whole tag
while($html[$i] != '>') {
$i++;
while($html[$i] == ' ') $i++; //skip any spaces (need to be idiot proof)
if (!$reading && $html[$i] == '/') { //closing tag
$i++;
while($html[$i] == ' ') $i++; //skip any spaces
$closeTag = '';
while($html[$i] != ' ' && $html[$i] != '>') { //start reading first actuall string
$reading = true;
$html[$i] = strtolower($html[$i]); //tags to lowercase
$closeTag .= $html[$i];
$i++;
}
$c = count($openedTags);
if ($c > 0 && $openedTags[$c-1] == $closeTag) array_pop($openedTags);
}
if (!$reading) //read only tag
while($html[$i] != ' ' && $html[$i] != '>') { //start reading first actuall string
$reading = true;
$html[$i] = strtolower($html[$i]); //tags to lowercase
$tag .= $html[$i];
$i++;
}
//skip any values
if ($html[$i] == "'") {
$i++;
while(!($html[$i] == "'" && $html[$i-1] != "\\")) {
$i++;
}
}
//skip any values
if ($html[$i] == '"') {
$i++;
while(!($html[$i] == '"' && $html[$i-1] != "\\")) {
$i++;
}
}
if ($reading && $html[$i] == '/') { //self closed tag
$tag = '';
break;
}
}
if (!empty($tag)) $openedTags[] = $tag;
}
}
while (count($openedTags) > 0) {
$tag = array_pop($openedTags);
$html .= "</$tag>";
}
}
It's not idiot proof but tinymce will clear this thing out so further cleaning is not necessary.
It may be a little long but i don't think it will eat a lot of resources and it should be faster than regex.