Im trying to solve one challenge where you have to check all string substrings are they anagrams. The condition is basically For S=abba, anagramic pairs are: {S[1,1],S[4,4]}, {S[1,2],S[3,4]}, {S[2,2],S[3,3]} and {S[1,3],S[2,4]}
Problem is that I have string with 100 chars and execution time should be below 9 secs. My time is around 50 secs... Below is my code, I will appreciate any advice - if you give me only directions or pseudo code it is even better.
$time1 = microtime(true);
$string = 'abdcasdabvdvafsgfdsvafdsafewsrgsdcasfsdfgxccafdsgccafsdgsdcascdsfsdfsdgfadasdgsdfawdascsdsasdasgsdfs';
$arr = [];
$len = strlen($string);
for ($i = 0; $i < strlen($string); $i++) {
if ($i === 0) {
for ($j = 1; $j <= $len - 1; $j++) {
$push = substr($string, $i, $j);
array_push($arr, $push);
}
} else {
for ($j = 1; $j <= $len - $i; $j++) {
$push = substr($string, $i, $j);
array_push($arr, $push);
}
}
}
$br = 0;
$arrLength = count($arr);
foreach ($arr as $key => $val) {
if ($key === count($arr) - 1) {
break;
}
for ($k = $key + 1; $k < $arrLength; $k++) {
if (is_anagram($val, $arr[$k]) === true) {
$br++;
}
}
}
echo $br."</br>";
function is_anagram($a, $b)
{
$result = (count_chars($a, 1) == count_chars($b, 1));
return $result;
}
$time2 = microtime(true);
echo "Script execution time: ".($time2-$time1);
Edit:
Hi again, today I had some time so I tried to optimize but couldnt crack this... This is my new code but I think it got worse. Any advanced suggestions ?
<?php
$string = 'abdcasdabvdvafsgfdsvafdsafewsrgsdcasfsdfgxccafdsgccafsdgsdcascdsfsdfsdgfadasdgsdfawdascsdsasdasgsdfs';
$arr = [];
$len = strlen($string);
for ($i = 0; $i < strlen($string); $i++) {
if ($i === 0) {
for ($j = 1; $j <= $len - 1; $j++) {
$push = substr($string, $i, $j);
array_push($arr, $push);
}
} else {
for ($j = 1; $j <= $len - $i; $j++) {
$push = substr($string, $i, $j);
array_push($arr, $push);
}
}
}
$br = 0;
$arrlen = count ($arr);
foreach ($arr as $key => $val) {
if (($key === $arrlen - 1)) {
break;
}
for ($k = $key + 1; $k < $arrlen; $k++) {
$result = stringsCompare($val,$arr[$k]);
if ($result === true)
{
$br++;
}
}
echo $br."\n";
}
function stringsCompare($a,$b)
{
$lenOne = strlen($a);
$lenTwo = strlen ($b);
if ($lenOne !== $lenTwo)
{
return false;
}
else {
$fail = 0;
if ($lenOne === 1) {
if ($a === $b) {
return true;
}
else
{
return false;
}
}
else
{
for ($x = 0; $x < $lenOne; $x++)
{
$position = strpos($b,$a[$x]);
if($position === false)
{
$fail = 1;
break;
}
else
{
$b[$position] = 0;
$fail = 0;
}
}
if ($fail === 1)
{
return false;
}
else
{
return true;
}
}
}
}
?>
You should think of another rule that all anagrams of a certain string can meet. For example, something about the number of occurrences of each character.
Related
I would like to make a program which can calculate first 5000 primary numbers whos ends with 9 :
I tried this but it didn't work :
$div9 = [];
$x = 2;
while (count($div9) <= 5000) {
function findPrime($x)
{
for ($i = 2; $i < ($x / 2); $i++) {
$rest = $x % $i;
if ($rest == 0) {
break;
}
}
return $x;
}
$primeList[] = $x;
for ($j = 0; $j < count($primeList); $j++) {
$array = array_map('intval', str_split($primeList[$j]));
if (end($array[$j]) === 9) {
return $primeList[$j];
$div9[] = $primeList[$j];
}
}
$x++;
}
any hints please?
You should not define a function inside your while loop
This should help
function check_prime($num)
{
if ($num == 1)
return false;
for ($i = 2; $i <= $num/2; $i++)
{
if ($num % $i == 0)
return false;
}
return true;
}
$div9 = [];
$i = 0;
while(count($div9) < 5000) {
if($i%10 === 9 && check_prime($i)) {
$div9[] = $i;
}
$i++;
}
Another variation on the theme, the isPrime function was ported from Javascript cryptoJS library.
# Adapted from CryptoJS v3.1.2
function isPrime( $n=0 ){
$r=sqrt( $n );
for( $f=2; $f <= $r; $f++ ){
if( !( $n % $f ) )return false;
}
return true;
}
function isFactor($n,$f){
return $n % 10 == $f;
}
$limit=5000;
$primes=[];
$x=2;
$f=9;
while( count( $primes ) < $limit ){
if( isPrime( $x ) && isFactor( $x, $f ) )$primes[]=$x;
$x++;
}
printf('<pre>%s</pre>',print_r($primes,true));
Problem Find the smallest positive integer that does not occur in a given sequence.
So what is the best implementation in PHP for this problem of codility!
Solution below results 66%, causing performance issue.
function solution($A)
{
sort($A);
$end = count($A);
$flag = false;
for ($k = 0; $flag == false; $k++, $flag = false) {
for ($i = 0; $i < $end; $i++) {
if ($k + 1 == $A[$i]) {
$flag = $A[$i];
break;
}
}
if($flag == false){
return $k +1;
}
}
}
A simple solution using an associative array as a set:
function solution($A) {
$set = array_flip($A);
for ($n = 1; ; ++$n) {
if (!isset($set[$n])) {
return $n;
}
}
}
Here is the Best solution for the codility problem implemented in PHP, scoring 100%
function solution($A)
{
sort($A);
$end = count($A);
$flag = false;
for ($k = 1, $i = 0; $i < $end; $i++) {
if ($A[$i] == $k) {
$k++;
continue;
} elseif ($A[$i] < $k)
continue;
else return $k;
}
return $k;
}
I have a PHP code. The code is supposed to print the output followed by a new line.
The code works fine but i have unneccesary new line at the end. There should be only one newline at the end, but my code prints several new lines. What could be the issue? Please help.
<?php
/* Read input from STDIN. Print your output to STDOUT*/
$fp = fopen("php://stdin", "r");
//Write code here
$loop = 0;
$n = 0; $arr = [];
while(!feof($fp)) {
$arr = []; $n = 0;
if($loop == 0) {
$total = fgets($fp);
}
else {
if($loop%2 == 1) {
$n = fgets($fp);
}
else {
$arr = fgets($fp);
}
}
if($loop > 0 && $loop%2 == 0) {
$arr = explode(" ", $arr);
$m = [];
for($i = 0; $i < 1<<10; $i++) {
$m[$i] = -1;
}
$n = count($arr);
$r = 0;
for($i = 0; $i < 1<<10; $i++) {
$r = max($r, fd_sum($i, $m, $arr, $n));
}
echo $r."\n";
}
$loop++;
}
fclose($fp);
?>
<?php
function fd_sum($i, $m, $arr, $n) {
if($i == 0) {
return $m[$i] = 0;
}
else if($m[$i] != -1) {
return $m[$i];
}
else {
$rr = 0;
for($j = 0; $j < $n; $j++) {
$num = (int)$arr[$j];
$b = save($num);
if(($i | $b) == $i) {
$z = $i^save($num);
$y = fd_sum($z, $m, $arr, $n);
$v = ($y + $num);
$rr = max($v, $rr);
}
}
return $m[$i] = $rr;
}
}
?>
<?php
function save($nm)
{
$x = 0;
for($i = 1; $nm/$i > 0; $i *= 10) {
$d = ($nm/$i) % 10;
$x = $x | (1 << $d);
}
return $x-1;
}
?>
My input is
3
4
3 5 7 2
5
121 3 333 23 4
7
32 42 52 62 72 82 92
My output is
17
458
92
-
-
-
-
The expected output is
17
458
92
-
Note : I have used '-' to indicate a new line
What am i doing wrong? Please help.
The PHP interpreter is reading the new lines after the closing tags and just spitting it right back out as output. Removing the extra opening/closing tags should remove the extra new lines.
Also, php closing tags are not necessary and i recommend omitting them.
<?php
/* Read input from STDIN. Print your output to STDOUT*/
$fp = fopen("php://stdin", "r");
//Write code here
$loop = 0;
$n = 0; $arr = [];
while(!feof($fp)) {
$arr = []; $n = 0;
if($loop == 0) {
$total = fgets($fp);
}
else {
if($loop%2 == 1) {
$n = fgets($fp);
}
else {
$arr = fgets($fp);
}
}
if($loop > 0 && $loop%2 == 0) {
$arr = explode(" ", $arr);
$m = [];
for($i = 0; $i < 1<<10; $i++) {
$m[$i] = -1;
}
$n = count($arr);
$r = 0;
for($i = 0; $i < 1<<10; $i++) {
$r = max($r, fd_sum($i, $m, $arr, $n));
}
echo $r."\n";
}
$loop++;
}
fclose($fp);
function fd_sum($i, $m, $arr, $n) {
if($i == 0) {
return $m[$i] = 0;
}
else if($m[$i] != -1) {
return $m[$i];
}
else {
$rr = 0;
for($j = 0; $j < $n; $j++) {
$num = (int)$arr[$j];
$b = save($num);
if(($i | $b) == $i) {
$z = $i^save($num);
$y = fd_sum($z, $m, $arr, $n);
$v = ($y + $num);
$rr = max($v, $rr);
}
}
return $m[$i] = $rr;
}
}
function save($nm)
{
$x = 0;
for($i = 1; $nm/$i > 0; $i *= 10) {
$d = ($nm/$i) % 10;
$x = $x | (1 << $d);
}
return $x-1;
}
I have a form in my website. I am reviewing the form values on ui panel. Function is doing if the the word length is greater than 12 it puts a space to next to it. But when I print the value I am getting error if value is utf8.
$text= 'üğqwoweğofkeiasş övafevpğeüqrg qğekqrğofteölzfs';
function parser($str, $parse) {
$strlength = strlen($str);
$counter = 0;
$query = '';
if($strlength > $parse) {
for($i = 0; $i < $strlength; $i++) {
if($str[$i] != ' ') {
$counter++;
}
if($counter == $parse) {
$query.=$str[$i];
$query.=' ';
$counter = 0;
}
if($counter != $parse) {
$query.=$str[$i];
}
if($counter != $parse & $str[$i] == ' ') {
$counter = 0;
}
}
return $query;
}
else {
return $str;
}
}
echo parser($text,12);
Output is:
'üğqwoweğo ofkeiasş övafevpğe� üqrg qğekqrğoft teölzfs'
and it's not happening all the times just sometimes; I can't understand why is that.
Code:
function parser($string, $max_length = 12)
{
$chars = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
$i = 0;
foreach ($chars as $index => $char)
{
if ($char === ' ') { $i = 0; }
else { $i++; }
if ($i >= $max_length)
{
$chars[$index] = $char . ' ';
$i = 0;
}
}
return implode('', $chars);
}
$result = parser('üğqwoweğofkeiasş övafevpğeüqrg qğekqrğofteölzfs');
result: üğqwoweğofke iasş övafevpğeüqr g qğekqrğofteö lzfsuser
Been racking my brains on how to write this better AND make it loop depending on the $count value:
if($count == 2){
$thenode = $tree[$splitnode[0]][$splitnode[1]];
} elseif($count == 3){
$thenode = $tree[$splitnode[0]][$splitnode[1]][$splitnode[2]];
}
Any ideas? Thanks!
$thenode = $tree;
for ($i = 0; $i < $count; $i++) {
$thenode = $thenode[$splitnode[$i]];
}
var_dump($thenode);
or
$thenode = array_reduce(
range(0, $count - 1),
function ($thenode, $i) use ($splitnode) { return $thenode[$splitnode[$i]]; },
$tree
);
or maybe
$thenode = $tree;
foreach ($splitnode as $i => $sn) {
if ($i >= $count) {
break;
}
$thenode = $thenode[$sn];
}