Home » Php » php – Computing sum of strings while accounting for swapped characters

php – Computing sum of strings while accounting for swapped characters

Posted by: admin February 25, 2020 Leave a comment

Questions:

I’m providing some code that seemingly works at the bottom that I’m unsure of.

Suppose I had a list of strings, in my case, class names that I save in an array: ClassName_1, ClassName_2, ClassName_3, I wanna compute the sum of these items such that if the order was to change to ClassName_2, ClassName_1, ClassName_3 the output would be the same.

As such, input: ClassName_1, ClassName_2, ClassName_3, output: 542.

Biggest problem, however, is that if we compute it naively by just taking each character’s integer representation and keep adding it to the sum, if ClassName_1 changes to ClasseamN_1, we still get the same sum, but…the item changed, let’s see that in action: input: ClassName_1, ClassName_2, ClassName_3, output: 542…that’s not right. Clearly, the item itself has changed.

What I’m trying to achieve is ensure integrity of a list, to compare if it changed between requests. In other words, I’m asking the program, in my case PHP Hey, PHP, has this list [of strings] changed (new/removed member) from last time you saw it?.

Code working that showcases this (I changed FirstClass to FirstlCass:

$classes = ['FirstClass', 'Second_Class', 'Third_Class'];
$sum = array_map( function( $item ) {
    return ord( $item );
}, $classes );

var_dump( array_sum( $sum ) );

will output 237.

$classes = ['FirstlCass', 'Second_Class', 'Third_Class'];
$sum = array_map( function( $item ) {
    return ord( $item );
}, $classes );

var_dump( array_sum( $sum ) );

will output 237 even if clearly it’s not the same item.

The reason why I need a sum is that it’s easier to store just that sum instead of a string of 1000 %%Class strings or even longer. I have a variant that seemingly works but…it’s so simple that I feel like I’m missing some edge-cases with weird strings here:

$combos = [
    //Test case 1: normally written.
    ['FirstClass_1', 'FirstClass_2', 'FirstClass_3'],
    //Test case 2: swapped 'l' with 'C' inside 'FirstClass_1' to make it 'FirstlCass1'.
    ['FirstlCass_1', 'FirstClass_2', 'FirstClass_3'],
    //Test case 3: swapped positions.
    ['FirstClass_2', 'FirstClass_3', 'FirstlCass_1']
];

public static function computeSum( $array )
{
    $sum = 0;

    foreach( $array as $item ) {
        $sum += crc32( $item );
    }

    return $sum;
}

Am I missing anything here or what seemed like a very complex issue turned out to be solved by a very simple solution?

How to&Answers:

We can make use of Trie data structure to check if the current array exists in the collection or not.

We first define a class Node which is basically holds the current value, it’s children and whether it’s an end of current array or not.

class Node{
    public $val;
    public $children;
    public $end_of_data;
    function __construct($val){
        $this->val = $val;
        $this->children = [];
        $this->end_of_data = false;
    }
}

We now make a class say DataManager which has a root node of the Trie with a method named putIfAbsent which adds the current array if not present and returns appropriate status codes.

  • Status code 1 => This means that current array was not visited and is added in the Trie.

  • Status code 2 => This means that current array was visited before.

DataManager:

class DataManager{
    private $root;
    private const INSERTED = 1;
    private const EXISTS   = 2;
    function __construct(){
        $this->root = new Node('~');
    }

    public function putIfAbsent($data){
        sort($data); // to make different combinations/anagrams of same values as one 
        $node = $this->root;
        $status = self::EXISTS;

        foreach($data as $value){
            if(!isset($node->children[$value])){
                $node->children[$value] = new Node($value);
                $status = self::INSERTED;
            }

            $node = $node->children[$value];
        }

        $node->end_of_data = true;
        return $status;
    }
}

Demo: https://3v4l.org/KXvBs