Wednesday, March 13, 2013

Palindromes search

The task is to find all the palindromes (spells the same from right and left) in the given text and print them with the number of occurrences. Minimum length of string is 2 since a character is a palindrome.

Here is an updated solution (thx Denis & Tim for pointing it out.):


<?php
// Given a string, test it for Palindromes, then output them along with the number of times they occur?
//sample string
$s = 'cd111 ana 876 qqqqqwq 00112 čćčćććččć把ŠŠđđđđđĐĐĐĐĐđččć';


//array to store results
$res = array();

mb_regex_encoding('UTF-8');
mb_internal_encoding('UTF-8');

//borrowed from http://www.codigomanso.com/en/2009/02/convert-utf8-string-to-array-in-php/
// using mb_check_encoding instead of mb_substr ;)
function getCharArray ($jstring) {
  if (mb_strlen($jstring, 'UTF-8') == 0)
    return array();

  $ret = array();
  $alen = strlen($jstring);
  $char = '';
  for ($i = 0; $i < $alen; $i++) {
    $char .= $jstring[$i];
    if (mb_check_encoding($char, 'UTF-8')) {
      array_push($ret, $char);
      $char = '';
    }
  }
  return $ret;
}

//mimumum lenght is 2
for ($l = 2; $l < mb_strlen($s) + 1; $l++) {
  //get all the posible subsrings with lenght above 2
  for ($i = 0; $i < (mb_strlen($s) + 1 - $l); $i++) {
    $g = mb_substr($s, $i, $l);

    //reverse $g string,
    //could use strrev but it is not multibyte safe
    //$rg = strrev($g);
    //multibyte safe version
    $t = getCharArray($g);
    $t = array_reverse($t);
    $rg = implode($t);

    //compare and store to result array
    if ($g == $rg) {
      //if match
      if (array_key_exists($g, $res)) {
        $res[$g] = $res[$g] + 1;
      }
      else {
        $res[$g] = 1;
      }
    }
  }
}

//output the results
foreach ($res as $r => $v) {
  echo "$r:$v\n";
}
?>

Reverse order of words

Here is a simple programming problem. Take the string "Done is better than perfect" and reverse the order of the words. Final output should be "Perfect than better is done"

Here is a very simple solution written in PHP.


<?php 

//original string
$s= 'Done is better than perfect';
//put all the words to lowercase
$s= mb_strtolower($s); 

//split the string by spaces and put in in an array
$arr = explode(" ", $s);
//reverse sort the array
$arr = array_reverse($arr);


//Put the first char of first word to uppercase
$arr[0]=ucfirst($arr[0]);

//print the output
echo implode(' ', $arr);
?>

Tuesday, March 5, 2013

PHP getopt alternative

Are you using getopt. It works but if you are stuck in legacy version of PHP you will miss long options. And what if you do not wan't to use '-' as separator. We could use the idea from Bash and array_shift parameters. See the sample bellow.

<?php
function DisplayHelp () {
  echo "Usage:\n";
  echo "     -f, --folder folder to produce output to  \n";
  echo "     -s, --server ftp server to use \n";
  echo "     -u, --user ftp server user  \n";
  echo "     -p, --pass ftp server password  \n";
  echo "     --port ftp server port, defaults to 21  \n";
  echo "     -d, --debug debug mode \n";
  echo "     -l, --log location";
  echo "     -h, --help display this help and exit";
  echo "\n";
  exit();
}

$options = array();

if (!(php_sapi_name() == 'cli')) {
  echo 'You need to run this from console.';
  exit();
}

//remove the name of the executing script
array_shift($argv);

//no options chosen
if (!is_array($argv))
  DisplayHelp();

//parse parameters
while (($param = array_shift($argv)) !== NULL) {
  switch ($param) {
    case '--folder':
    case '-f':
      $options['folder'] = array_shift($argv);
      break;
    case '--server':
    case '-s':
      $options['server'] = array_shift($argv);
      break;
    case '--user':
    case '-u':
      $options['user'] = array_shift($argv);
      break;
    case '--pass':
    case '-p':
      $options['pass'] = array_shift($argv);
      break;
    case '--port':
      $options['port'] = array_shift($argv);
      break;
    case '--debug':
    case '-d':
      $options['debug'] = TRUE;
      break;
    case '--log':
    case '-l':
      $options['log'] = array_shift($argv);
      break;
    case '--help':
    case '-h':
      DisplayHelp();
      break;
    default:
      DisplayHelp();
      break;
  }
}

//show options
print_r($options)
?>

Friday, February 1, 2013

Get all the possible substrings of length

Below is a simple code that will get all the possible substrings with length 2 and above.

<?php
$s='0123456789';

for ($l=2;$l<strlen($s)+1;$l++){
    for ($i=0;$i<(strlen($s)+1-$l);$i++) {
        echo substr ( $s,$i,$l) . "\n";
    }
}
?>

Predefined or Hash Sort

Sometimes you want to sort values in i.e. array. Of course you ca use bubble, merge ... sort algorithm. But what if you know your set of values (the key)? Than you can define a hash table (associative array) of predefined values in the order that you require. This solution will reduce the number of operations to N+K where N is number of elements to sort and K is the key length. Perl solution can be found here.

<?php
//Some random string
$s="the revelation of saint john the divine"; 

//let us remove all the chars that 
//are not defined in the dictionary
$s=preg_replace('/[ -@]/', '', $s);
$s=preg_replace('/[[ -_]/', '', $s);

//let us define the hash 
//table with sort order
$key=array( "a" => 0,
            "b" => 0,
            "c"=> 0,
            "d"=> 0,
            "e"=> 0,
            "f"=> 0,
            "g"=> 0,
            "h"=> 0,
            "i"=> 0,
            "j"=> 0,
            "k"=> 0,
            "l"=> 0,
            "m"=> 0,
            "n"=> 0,
            "o"=> 0,
            "p"=> 0,
            "q"=> 0,
            "r"=> 0,
            "s"=> 0,
            "t"=> 0,
            "u"=> 0,
            "v"=> 0,
            "w"=> 0,
            "x"=> 0,
            "y"=> 0,
            "z"=> 0,
          );

//split the string to chars
$chars = str_split($s,1);

//do a loop and add increase the key by 1 for each found
echo "Total number of chars:" . count($chars) . "\n" ;
foreach ($chars as $c) {
    $key[$c] = $key[$c] +1; 
}
//loop through key
foreach ($key as $c=>$count){
    if($count>0){
        echo $c. '=>' . $count . "\n";
        //echo str_repeat($c, $count);
    }
    echo "\n";
}
?>