1

I need to find/calculate 1 word from a list of 20 words with following conditions:

  1. If longest word in array is 5 characters then result will be 5 char. (Word I am looking for will always be 4, 5 or 6 chars long.)
  2. Count/recognise every char and its position in word for later calculation.
  3. Words in array contains uppercase letters A-Z and/or digits 0-9.

Here is the 20 words I have:

$words = array( 'MVW',
                'MWAH',
                'MWAH',
                'MYW',
                'MW',
                'MY9AH',
                'MYQAH',
                'MYQAH',
                'MY9AH',
                'MYQAH',
                'MYQAH',
                'MWAH',
                'MYQAH',
                'MYSWI',
                'MYQAH',
                'MYQAH',
                'MW',
                'MW',
                'MW',
                'MW');

I need to count chars in row and find higest occurency of char to get this result:

    1. char is: M - occurred 20 times as 1. character in words.
    2. char is: Y - 11 times.
    3. char is: Q - 7 times.
    4. char is: A - 10 times.
    5. char is: H - 9 times.    

Result from Array $words I want is: MYQAH

I have tried this code:

<?php

$words = array( 'MVW',
                'MWAH',
                'MWAH',
                'MYW',
                'MW',
                'MY9AH',
                'MYQAH',
                'MYQAH',
                'MY9AH',
                'MYQAH',
                'MYQAH',
                'MWAH',
                'MYQAH',
                'MYSWI',
                'MYQAH',
                'MYQAH',
                'MW',
                'MW',
                'MW',
                'MW');


$newarray = array();
$cc2 = 0;
$cc3 = 0;
$cc4 = 0;
$cc5 = 0;
$cc6 = 0;

foreach($words as $run) {

    if (isset($run['1']) && !isset($run['2'])) {
        $newarray[] = array($run['0'],$run['1']);
        $cc2++;
    }

    if (isset($run['2']) && !isset($run['3'])) {
        $newarray[] = array($run['0'],$run['1'],$run['2']);
        $cc3++;
    }

    if (isset($run['3']) && !isset($run['4'])) {
        $newarray[] = array($run['0'],$run['1'],$run['2'],$run['3']);
        $cc4++;
    }

    if (isset($run['4']) && !isset($run['5'])) {
        $newarray[] = array($run['0'],$run['1'],$run['2'],$run['3'],$run['4']);
        $cc5++;
    }

    if (isset($run['5']) && !isset($run['6'])) {
        $newarray[] = array($run['0'],$run['1'],$run['2'],$run['3'],$run['4'],$run['5']);
        $cc6++;
    }

}

echo "Length / Found words<br>\n";
echo "2 chars / $cc2<br>\n";
echo "3 chars / $cc3<br>\n";
echo "4 chars / $cc4<br>\n";
echo "5 chars / $cc5<br>\n";
echo "6 chars / $cc6<br>\n";

echo "<pre>";
var_dump($newarray);
echo "</pre>";
?>

And I get this results:

Length / Found words
2 chars / 5
3 chars / 2
4 chars / 3
5 chars / 10
6 chars / 0
array(20) {
  [0]=>
  array(3) {
    [0]=>
    string(1) "M"
    [1]=>
    string(1) "V"
    [2]=>
    string(1) "W"
  }
  [1]=>
  array(4) {
    [0]=>
    string(1) "M"
    [1]=>
    string(1) "W"
    [2]=>
    string(1) "A"
    [3]=>
    string(1) "H"
  }
  [2]=>
  array(4) {
    [0]=>
    string(1) "M"
    [1]=>
    string(1) "W"
    [2]=>
    string(1) "A"
    [3]=>
    string(1) "H"
  }
  [3]=>
  array(3) {
    [0]=>
    string(1) "M"
    [1]=>
    string(1) "Y"
    [2]=>
    string(1) "W"
  }
  [4]=>
  array(2) {
    [0]=>
    string(1) "M"
    [1]=>
    string(1) "W"
  }
  [5]=>
  array(5) {
    [0]=>
    string(1) "M"
    [1]=>
    string(1) "Y"
    [2]=>
    string(1) "9"
    [3]=>
    string(1) "A"
    [4]=>
    string(1) "H"
  }
  [6]=>
  array(5) {
    [0]=>
    string(1) "M"
    .........

Question: What would be the best way to get result: MYQAH from the words above in array?

Thank you so much for helping.

Cyborg
  • 1,437
  • 19
  • 40

1 Answers1

1

I have a clever little one-liner for you!

Code: (Demo)

echo implode(
        array_map(function(){
                $occurrences=count_chars(implode(func_get_args()),1);
                arsort($occurrences);
                return chr(key($occurrences));
            },
            ...array_map('str_split',$words)
        )
    );

Output:

MYQAH

The breakdown: (I won't bloat this page with all of the output, go to this Demo)

$words=['MVW','MWAH','MWAH','MYW','MW','MY9AH','MYQAH','MYQAH','MY9AH','MYQAH',
        'MYQAH','MWAH','MYQAH','MYSWI','MYQAH','MYQAH','MW','MW','MW','MW'];

echo "*** Step #1:  Replace each word with an array of its characters ***\n";
var_export(array_map('str_split',$words));        
echo "\n\n---\n\n";

echo "*** Step #2:  Pass the characters through array_map with the splat operator and func_get_args() to isolate columnar data including NULLs where no character exists in the column ***\n";
var_export(array_map(function(){return func_get_args();},...array_map('str_split',$words)));
echo "\n\n---\n\n";

echo "*** Step #3:  Convert column data to strings with the added benefit of eliminating NULLs ***\n";
//var_export(array_map(function(){return implode(func_get_args());},...array_map('str_split',$words)));
echo "\n\n---\n\n";

echo "*** Step #4:  Count the occurrences of each character; stored as ord values as keys, and occurrences as values ***\n";
var_export(array_map(function(){return count_chars(implode(func_get_args()),1);},...array_map('str_split',$words)));
echo "\n\n---\n\n";

echo "*** Step #5:  Sort DESC while preserving keys ***\n";
var_export(array_map(function(){$occurrences=count_chars(implode(func_get_args()),1); arsort($occurrences); return $occurrences;},...array_map('str_split',$words)));
echo "\n\n---\n\n";

echo "*** Step #6:  Target the first (highest occurring) value/character in the array ***\n";
var_export(array_map(function(){$occurrences=count_chars(implode(func_get_args()),1); arsort($occurrences); return key($occurrences);},...array_map('str_split',$words)));
echo "\n\n---\n\n";

echo "*** Step #7:  Convert the targeted character from ord() to chr() ***\n";
var_export(array_map(function(){$occurrences=count_chars(implode(func_get_args()),1); arsort($occurrences); return chr(key($occurrences));},...array_map('str_split',$words)));

p.s. To isolate the "fancy trick" of rotating the array of letters "90 degrees" have a look at this other post where I use the same method.


This is the same general method using a loop construct that will be more forgiving of earlier PHP versions:

Code: (Demo)

$words=['MVW','MWAH','MWAH','MYW','MW','MY9AH','MYQAH','MYQAH','MY9AH','MYQAH',
        'MYQAH','MWAH','MYQAH','MYSWI','MYQAH','MYQAH','MW','MW','MW','MW'];

$chars=array_map('str_split',$words);
usort($chars,function($a,$b){return sizeof($b)-sizeof($a);});

$result='';
foreach($chars[0] as $col=>$not_used){
    $occurrences=array_count_values(array_column($chars,$col));  // no NULL values
    arsort($occurrences);
    $result.=key($occurrences);
}
echo $result;  // same output: MYQAH
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • Amazing, yes please. It would be nice to understand how this method works. Is really short and clever! – Cyborg Feb 20 '18 at 02:39
  • I know this may be a lot to conceptualize. I am going to be thorough in my explanation. That is why it is taking me some time. – mickmackusa Feb 20 '18 at 02:40
  • @Cyborg Okay have a look at this and let me know if you require any further clarifications. – mickmackusa Feb 20 '18 at 02:55
  • The wordlist input is not Array in this function. How can I convert Array I already have to such format: `$words=['', '']` or can I use Array as input? – Cyborg Feb 20 '18 at 03:08
  • @Cyborg I don't think I understand you. I am using an array of 20 words as an input, just as you have posted in your question. Are you referring to my square bracket syntax? ...it is the same as `array()` syntax. – mickmackusa Feb 20 '18 at 03:15
  • 1
    You are right, its working 100% as expected. Thank a million for sharing code and giving so detailed information. I will for sure read it couple of more times :) – Cyborg Feb 20 '18 at 03:27