Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First, let's denote the types by names for clarity:</p> <pre><code>type Estimates = Map[Int, List[Int]] type Entry = (Int, List[Int]) </code></pre> <p>Since we'll need to compare entries by their list size, it's useful to have an explicitly named comparator:</p> <pre><code>val byNumsSize: Ordering[Entry] = Ordering.by(_._2.size); </code></pre> <p>Later, we'll need to find a minimum of a list entries according to <code>byNumsSize</code>, or <code>None</code> if the list is empty. This can be accomplished using <code>reduceOption(byNumsSize.min)</code>, see <a href="https://stackoverflow.com/a/10922659/1333025">this answer</a>.</p> <p>Let's focus on the inner loop. The idea is to find the first element for which the inner call to <code>eliminate</code> succeeds. This can be accomplished by <a href="https://stackoverflow.com/q/3361478/1333025">lazy views</a>, mapping over the collection and <code>collect</code>ing the first acceptable result. It's always useful to split a piece of code to several smaller functions so let's express it as</p> <pre><code>def eliminate(estimates : Estimates, entry: Entry) : Option[Estimates] = { val pos = entry._1; entry._2 .view // process the sequence lazily to run each step only when needed .map(n =&gt; search(eliminate(estimates.updated(pos, List(n)), pos, n))) .collectFirst({ case es if !es.isEmpty =&gt; es }) // better/safer than != Map.empty } </code></pre> <p>Now we have building blocks for the <code>search</code> function. Instead of sorting the list and picking the minimum (which is <em>O(n log n)</em>), we can rather find the least one by traversing it. First, we filter out all entries with list size 1 and then look at the minimum by size. If the minimum has a nonempty list, we try process it with the previous function. If the minimum has an empty list, we failed. In such a case we return the empty map.</p> <p><strong>Edit:</strong> I made a mistake when comparing the size (<code>_._2.size</code> vs <code>_._2</code>). To prevent such a mistake, I'll better define a separate function for it:</p> <pre><code>def entrySize(e: Entry): Int = e._2.size </code></pre> <p>If all entries have a list of size 1, we skip the processing and return the original map immediately:</p> <pre><code>def search(estimates : Estimates) : Estimates = estimates .toSeq .filter(entrySize(_) != 1) // Find the minimum by size not equal to 1, if there is one: // see https://stackoverflow.com/a/10922659/1333025 .reduceOption[Entry](byNumsSize.min) .map(entry =&gt; { if (entrySize(entry) &gt; 1) eliminate(estimates, entry) else None }.getOrElse(Map.empty)) .getOrElse(estimates); // all sizes are equal to 1 </code></pre> <p>I'm not sure if this solution will be more comprehensible for you. But it uses neither any mutable state nor <code>return</code>s from methods, it only operates on collections and <code>Option</code>s.</p> <p>(Note that I haven't checked that my code works exactly as yours, I only tried to compile it.)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload