Codewars: Help the bookseller
Codewars: Help the bookseller
Glossary overview

Codewars: Help the bookseller

You will receive the bookseller’s stocklist and a list of categories. Your task is to find the total number of books in the bookseller’s stocklist, with the category codes in the list of categories. Note: the codes are in the same order in both lists.

Return the result as a string described in the example below, or as a list of pairs (Haskell/Clojure/Racket/Prolog).

If any of the input lists is empty, return an empty string, or an empty array/list (Clojure/Racket/Prolog).

# the bookseller's stocklist:
"ABART 20", "CDXEF 50", "BKWRK 25", "BTSQZ 89", "DRTYM 60"

# list of categories: 
"A", "B", "C", "W"

# result:
"(A : 20) - (B : 114) - (C : 50) - (W : 0)"

My solution

function stockList($listOfArt, $listOfCat){
  
  $glossary = [];
  
  foreach($listOfArt as $code) {
    $first_letter = substr($code, 0, 1);
    $quantity = (int) explode(" ", $code)[1];
    
    if (isset($glossary[$first_letter])) {
      $glossary[$first_letter] +=$quantity;
    } else {
      $glossary[$first_letter] = $quantity;
    }
    
  }
  
  if (array_sum(array_values($glossary)) == 0) return '';
  
  $categoriesQuantity = count($listOfCat);
  
  $result = '';
  
  for ($i = 0; $i < $categoriesQuantity; $i++) {
    $letter = $listOfCat[$i];
    $last = $i == $categoriesQuantity - 1;
    
    if (isset($glossary[$letter])) {
      if ($last) {
    	 $result .= '(' . $letter . ' : ' . $glossary[$letter] .')';
      } else {
      	 $result .= '(' . $letter . ' : ' . $glossary[$letter] .') - ';
      }
    } else {
        if ($last) {
          $result .= '(' . $letter . ' : 0)';
        } else {
        	$result .= '(' . $letter . ' : 0) - ';
        } 
    }
  }
  
  return $result; 
}

Best solution

function stockList($listOfArt, $listOfCat){
   $arr = [];
   $empty = true;
   foreach ($listOfCat as $cat) {
       $sum = 0;
       foreach ($listOfArt as $art) {
           if (substr($art, 0, 1) == $cat) {
               $sumCat = preg_replace('#\D+#','',$art);  
               $sum += $sumCat;
           }
           
           if ($sum) { $empty = false; }
       }
       
       $arr[]= "({$cat} : {$sum})";
   }
   
   return $empty ? '' : implode(' - ', $arr);
   }

Advise

It’s better to use implode(‘ – ‘, $arr) to put “0” between the strings. First, make array. Second, implode into string and separate with “-“.

<?php

function stockList($listOfArt, $listOfCat){
  
  $glossary = [];
  
  foreach($listOfArt as $code) {
    $first_letter = substr($code, 0, 1);
    $quantity = (int) explode(" ", $code)[1];
    
    if (isset($glossary[$first_letter])) {
      $glossary[$first_letter] +=$quantity;
    } else {
      $glossary[$first_letter] = $quantity;
    }
    
  }
  
  if (array_sum(array_values($glossary)) == 0) return '';
  
  foreach ($glossary as $key => $value) {
  	 $glossary[$key] = "({$key} : {$value})";
  }
  
  $result = [];
  $categoriesQuantity = count($listOfCat);
  
  for ($i = 0; $i < $categoriesQuantity; $i++) {
    $letter = $listOfCat[$i];
    
    if (isset($glossary[$letter])) {
     $result[$letter] = $glossary[$letter];
    } else {
       $result[$letter] = "({$letter} : 0)";
    }
  }
  
  $result = implode(' - ', $result);
  return $result; 
}

$b = ["BBAR 150", "CDXE 515", "BKWR 250", "BTSQ 890", "DRTY 600"];
$c = ["A", "B", "C", "D"];

        
var_dump(stockList($b, $c));


// Output
string(44) "(A : 0) - (B : 1290) - (C : 515) - (D : 600)"

А вот еще чище:

<?php

function stockList($listOfArt, $listOfCat) {
    if (empty($listOfArt) || empty($listOfCat)) return '';

    $glossary = [];

    foreach ($listOfArt as $code) {
        [$ref, $qty] = explode(' ', $code);
        $letter = $ref[0];
        $glossary[$letter] = ($glossary[$letter] ?? 0) + (int)$qty;
    }

    $parts = [];
    foreach ($listOfCat as $letter) {
        $parts[] = "($letter : " . ($glossary[$letter] ?? 0) . ")";
    }

    return implode(' - ', $parts);
}


$b = ["BBAR 150", "CDXE 515", "BKWR 250", "BTSQ 890", "DRTY 600"];
$c = ["A", "B", "C", "D"];

        
var_dump(stockList($b, $c));