DEV Community

Discussion on: Daily Challenge #137 - Help the Bookseller

Collapse
 
avalander profile image
Avalander

Scala

object Bookstore {
  case class Book(code: String, val quantity: Int) {
    val category = code.head
  }

  case class Category(code: Char, quantity: Int) {
    override def toString(): String =
      s"( $code : $quantity )"
  }

  type Stocklist = Seq[Book]

  def categorise (cat: Seq[String], stock: Stocklist): Seq[Category] = {
    def sorted = stock
      .groupBy(_.category)
      .map {
        case (code, books) => code -> countBooks(code, books)
      }
    cat map (_.head) map (x => sorted.getOrElse(x, Category(x, 0)))
  }

  private def countBooks (code: Char, books: Stocklist): Category =
    Category(code, books.map(_.quantity).sum)

  def of (raw: Seq[String]): Stocklist =
    raw map (_ split ' ') map {
      case Array(c, q) => Book(c, q.toInt)
    }

  def pretty (stock: Seq[Category]): String =
    stock map {
      case Category(c, q) => s"($c : $q)"
    } mkString " - "


  def solve (cat: Seq[String], stock: Seq[String]): String = {
    val stocklist = of(stock)
    val sorted = categorise(cat, stocklist)
    pretty(sorted)
  }
}
Collapse
 
avalander profile image
Avalander

I was under a strong sleep deprivation when I wrote that solution, I think it can be done in a simpler way:

object Bookstore2 {
  type Book = (Char, Int)

  def parseBook (s: String): Book = {
    val Array(c, q) = s.split(' ')
    (c.head, q.toInt)
  }

  def countBooks (books: Seq[Book]): Int = {
    (books map (_._2)).sum
  }

  def solve (cat: Seq[String], stock: Seq[String]): String = {
    val stocklist = stock map parseBook groupBy (_._1) mapValues countBooks
    val cats = for {
      c <- cat
      q = stocklist.getOrElse(c.head, 0)
    } yield s"($c : $q)"
    cats mkString " - "
  }
}