0
votes
  def checkPeq[A,B](list1: List[(A, List[B])])( P: (A,B) => Boolean): List[Boolean] = {
    def helper[A,B](list2: List[(A, List[B])], list3: List[B], acc1: Boolean, acc2: List[Boolean])(leq:(A,B) => Boolean): List[Boolean] = {
      list2 match {
        case h1::t1 => {
              list3 match {
                case Nil if t1!=Nil => helper(t1, t1.head._2, true, acc1::acc2)(leq)
                case Nil => (acc1::acc2).reverse
                case h2::t2 if(leq(h1._1, h2)) => helper(list2, t2, acc1, acc2)(leq)
                case h2::t2 => helper(list2, t2, false, acc2)(leq)
              }
        }
      }
    }
    helper(list1, list1.head._2, true, List())(P)
  }
  val list1 = List((1,List(1,2,3)), (2, List(2,3)), (3, List(3,2)), (4, List(4,5,6,3)))
  println(checkPeq(list1)(_<=_))

I have a tail recursive function which returns List[Boolean], in this case List(true, true, false, false). It's working, but the problem is I need to do it without ._ or .head and preferably without indexes(bcz I can easily replace .head in this function with (0)). I need to do it with pattern matching and I don't have an idea how to start. I also got a tip from my teacher replacing it should be pretty fast. I'd appreciate any tips on how to deal with the problem.

2
Seeking improvements for working code is better suited to CodeReview. - Adrian Mole
I suppose that recursion and pattern matching is a requirement for this assignment, because it can be done much simpler: list1.map{case (a,lst) => lst.forall(pred(a,_))} - jwvh

2 Answers

1
votes

One solution is to simply pattern match both the outer A list and the inner B list at the same time, i.e. as part of a single pattern.

def checkPeq[A,B](in: List[(A,List[B])])(pred: (A,B) => Boolean): List[Boolean] = {
  @annotation.tailrec
  def loop(aLst :List[(A,List[B])], acc :List[Boolean]) :List[Boolean] =
    aLst match {
      case Nil               => acc.reverse          //A list done
      case (_,Nil)    :: aTl => loop(aTl, true::acc) //B list done
      case (a,b::bTl) :: aTl =>                      //test a and b
        if (pred(a,b)) loop((a,bTl) :: aTl, acc)
        else           loop(aTl, false::acc)
    }
  loop(in, List.empty[Boolean])
}
1
votes

Here are missing pieces that should help you solve the rest of the problem:

Pattern matching a list

val l = List(2,3)

l match {
  case Nil          => "the list is empty"
  case head :: Nil  => "the least has one element"
  case head :: tail => "thie list has a head element and a tail of at least one element"
}

Pattern matching a tuple

val t = (75, "picard")

t match {
  case (age, name) => s"$name is $age years old"
}

Pattern matching a list of tuples

val lt = List((75, "picard"))

lt match {
  case Nil                 => "the list is empty"
  case (name, age) :: Nil  => "the list has one tuple"
  case (name, age) :: tail => "the list has head tuple and a tail of at least another tuple"
}

Pattern matching a tuple of list of tuples

val lt = List((75, "picard"))
val ct = List((150, "Data"))

(lt, ct) match {
  case (Nil, Nil)                 => "tuple of two empty lists"
  case ((name, age) :: Nil, Nil)  => "tuple of a list with one tuple and another empty list"
  case (Nil, (name, age) :: Nil)  => "tuple of an empty list and another list with one tuple"
  case ((name, age) :: tail, Nil) => "tuple of list with head tuple and a tail of at least another tuple, and another empty list"
  case _ => "and so on"
}

Note how patterns can be composed.