Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth
Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Boost your online presence with premium web hosting and servers

Disclosure: My content contains affiliate links.

42,641 questions

55,376 answers

573 users

How to perform high‑performance reversible text compression using a word dictionary in Scala

1 Answer

0 votes
/*
    =====================================================================
    High‑Performance Reversible Text Compression Using a Word Dictionary
    ---------------------------------------------------------------------
    This program compresses text by replacing repeated words with tokens
    like @0, @1, @2... and stores each unique word in a dictionary.

    The compressed text is fully reversible.

    WHY THIS VERSION IS FAST (Scala):
    ---------------------------------
    • Uses mutable.HashMap[String, Int] for O(1) average lookup.
    • Uses ArrayBuffer[String] for compact dictionary storage.
    • Manual scanning avoids regex overhead.
    • Uses StringBuilder for efficient string construction.
    • Clean, idiomatic, modern Scala design.
    =====================================================================
*/

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

// ---------------------------------------------------------------------
// Dictionary structure: ArrayBuffer + HashMap
// ---------------------------------------------------------------------
final class WordDictionary {
  val words: ArrayBuffer[String] = ArrayBuffer.empty[String]          // index → word
  val indexMap: mutable.HashMap[String, Int] = mutable.HashMap.empty  // word → index
}

// ---------------------------------------------------------------------
// Find or add a word to the dictionary (O(1) average)
// ---------------------------------------------------------------------
def findOrAdd(dict: WordDictionary, word: String): Int = {
  dict.indexMap.get(word) match {
    case Some(idx) => idx
    case None =>
      val newIndex = dict.words.length
      dict.words += word
      dict.indexMap.put(word, newIndex)
      newIndex
  }
}

// ---------------------------------------------------------------------
// Compress text into @ID tokens
// ---------------------------------------------------------------------
def compress(input: String, dict: WordDictionary): String = {
  val out = new StringBuilder(input.length * 2)
  var i   = 0
  val n   = input.length

  while (i < n) {
    val c = input.charAt(i)

    // Pass punctuation/spaces directly
    if (!c.isLetterOrDigit) {
      out.append(c)
      i += 1
    } else {
      // Extract word
      val start = i
      while (i < n && input.charAt(i).isLetterOrDigit) {
        i += 1
      }
      val word = input.substring(start, i)

      // Get dictionary index
      val id = findOrAdd(dict, word)

      // Write token
      out.append('@').append(id)
    }
  }

  out.toString()
}

// ---------------------------------------------------------------------
// Decompress @ID tokens back into original text
// ---------------------------------------------------------------------
def decompress(compressed: String, dict: WordDictionary): String = {
  val out = new StringBuilder(compressed.length * 2)
  var i   = 0
  val n   = compressed.length

  while (i < n) {
    val c = compressed.charAt(i)

    // Token?
    if (c == '@') {
      i += 1
      var id = 0

      // Parse digits
      while (i < n && compressed.charAt(i).isDigit) {
        id = id * 10 + (compressed.charAt(i) - '0')
        i += 1
      }

      if (id >= 0 && id < dict.words.length)
        out.append(dict.words(id))
    } else {
      // Pass punctuation/spaces
      out.append(c)
      i += 1
    }
  }

  out.toString()
}

// ---------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------
object WordDictionaryCompression {
  def main(args: Array[String]): Unit = {
    val original =
      "this is is a test test compression string string test " +
      "this is a test compression"

    val dict       = new WordDictionary
    val compressed = compress(original, dict)
    val decompressed = decompress(compressed, dict)

    println(s"""Original:      "$original"""")
    println(s"""Compressed:    "$compressed"""")
    println(s"""Decompressed:  "$decompressed"""")
    println()

    println("Dictionary:")
    dict.words.zipWithIndex.foreach { case (w, i) =>
      println(s"  @$i => $w")
    }
  }
}


/*
run:

Original:      "this is is a test test compression string string test this is a test compression"
Compressed:    "@0 @1 @1 @2 @3 @3 @4 @5 @5 @3 @0 @1 @2 @3 @4"
Decompressed:  "this is is a test test compression string string test this is a test compression"

Dictionary:
  @0 => this
  @1 => is
  @2 => a
  @3 => test
  @4 => compression
  @5 => string

*/

 



answered Aug 1 by avibootz

Related questions

...