Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I have finally figured this out after much messing about:</p> <pre><code>scala&gt; def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)] = { | (divs.traverse[({type l[a] = State[List[Int], a]})#l, Option[(Int, Int)]]( div =&gt; | state { (rem: List[Int]) =&gt; | rem.find(_ % div == 0).map(n =&gt; rem.filterNot(_ == n) -&gt; Some(div -&gt; n)).getOrElse(rem -&gt; none[(Int, Int)]) | } | ) ! nums).flatten | } findMatches: (divs: List[Int], nums: List[Int])List[(Int, Int)] </code></pre> <p>I think I'll be looking at Eric's answer for more insight into what is actually going on, though.</p> <hr/> <h3>Iteration #2</h3> <p>Exploring Eric's answer using scalaz6</p> <pre><code>scala&gt; def findMatches2(divs: List[Int], nums: List[Int]): List[(Int, Int)] = { | case class S(matches: List[(Int, Int)], remaining: List[Int]) | val initialState = S(nil[(Int, Int)], nums) | def find(div: Int, s: S) = { | val newState = s.remaining.find(_ % div == 0).map { (n: Int) =&gt; | S(s.matches :+ div -&gt; n, s.remaining filterNot (_ == n)) | }.getOrElse(s) | newState -&gt; newState.matches | } | val findDivs = (div: Int) =&gt; state((s: S) =&gt; find(div, s)) | (divs.traverse[({type l[a]=State[S, a]})#l, List[(Int, Int)]](findDivs) ! initialState).join | } findMatches2: (divs: List[Int], nums: List[Int])List[(Int, Int)] scala&gt; findMatches2(List(2, 3, 4), List(1, 6, 7, 8, 9)) res11: List[(Int, Int)] = List((2,6), (2,6), (3,9), (2,6), (3,9), (4,8)) </code></pre> <p>The <code>join</code> on the <code>List[List[(Int, Int)]]</code> at the end is causing grief. Instead we can replace the last line with:</p> <pre><code>(divs.traverse[({type l[a]=State[S, a]})#l, List[(Int, Int)]](findDivs) ~&gt; initialState).matches </code></pre> <hr/> <h3>Iteration #3</h3> <p>In fact, you can do away with the extra output of a state computation altogether and simplify even further:</p> <pre><code>scala&gt; def findMatches2(divs: List[Int], nums: List[Int]): List[(Int, Int)] = { | case class S(matches: List[(Int, Int)], remaining: List[Int]) | def find(div: Int, s: S) = | s.remaining.find(_ % div == 0).map( n =&gt; S(s.matches :+ div -&gt; n, s.remaining filterNot (_ == n)) ).getOrElse(s) -&gt; () | (divs.traverse[({type l[a]=State[S, a]})#l, Unit](div =&gt; state((s: S) =&gt; find(div, s))) ~&gt; S(nil[(Int, Int)], nums)).matches | } findMatches2: (divs: List[Int], nums: List[Int])List[(Int, Int)] </code></pre> <h3>Iteration #4</h3> <p><code>modify</code> described above by <em>Apocalisp</em> is also available in scalaz6 and removes the need to explicitly supply the <code>(S, ())</code> pair (although you do need <code>Unit</code> in the type lambda):</p> <pre><code>scala&gt; def findMatches2(divs: List[Int], nums: List[Int]): List[(Int, Int)] = { | case class S(matches: List[(Int, Int)], remaining: List[Int]) | def find(div: Int) = modify( (s: S) =&gt; | s.remaining.find(_ % div == 0).map( n =&gt; S(s.matches :+ div -&gt; n, s.remaining filterNot (_ == n)) ).getOrElse(s)) | (divs.traverse[({type l[a]=State[S, a]})#l, Unit](div =&gt; state(s =&gt; find(div)(s))) ~&gt; S(nil, nums)).matches | } findMatches2: (divs: List[Int], nums: List[Int])List[(Int, Int)] scala&gt; findMatches2(List(2, 3, 4), List(1, 6, 7, 8, 9)) res0: List[(Int, Int)] = List((2,6), (3,9), (4,8)) </code></pre>
    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. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    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