List Processing

To begin:

·       In Eclipse create a Scala project called ListLab.

·       Add a worksheet to this project called session

·       Add a Scala interpreter to this project

In the session worksheet define and test the following functions.

For each function implement four versions:

·       Iterative version

·       Recursive version

·       Tail-recursive version (this should be different from the previous version)

·       map-filter-reduce version

All of your implementations should be as generic as possible.

 To end:

·       Export session.sc to your file system and send it to the grader by the deadline.

1.     Problem

Write a function that computes the sum of cubes of all odd numbers occurring in a list of integers.

2.     Problem

Write a function that computes the sum of numbers in a list of lists of numbers:

sumOfSums(List(List 1, 2, 3), List(4, 5, 6)) = 21

3.     Problem

Write a function that returns the depth of a list of nested lists:

depth(List(List(List 1, 2, List(3)))) = 4

4.     Problem

Write a function that computes the average of a list of doubles

5.     Problem

Write a function that returns the largest element of a list of comparables.

6.     Problem

Write a function that returns the number of elements in a list that satisfy a given predicate. (The predicate is a parameter of type T=>Boolean.)

7.     Problem

Write a function that returns true if all elements in a list satisfy a given predicate.

8.     Problem

Write a function that returns true if any element in a list satisfies a given predicate.

9.     Problem

Write a function that reverses the elements in a list.

10.  Problem

Write a function that returns true if a given list of comparables is sorted.

11.  Problem: My Map

If the List.map function didn't exist, how would you define it?

12.  Problem: Take, Drop and Zip

If take, drop, and zip didn't exist for lists, how would you define them?

13.  Problem: Streams

A stream is like a list except that it is constructed using the lazy version of cons:

scala>  val s1 = 1 #:: 2 #:: 3 #:: Stream.Empty
s1: scala.collection.immutable.Stream[Int] = Stream(1, ?)

scala> s1.head
res0: Int = 1

scala> s1.tail.head
res1: Int = 2

Create the following streams

·       An infinitely long stream of 1's

·       The stream of all non-negative integers

·       The stream of all non-negative even integers

·       The stream of all squares of integers

14.  Problem: Proplog and Logic Programming

A logic program consists of a set of rules and facts:

Conclusion if Condition1 and Condition2 and ...

A fact is simply a conclusion without conditions.

For example:

Bart is the son of Homer if Bart is male and Homer is the parent of Bart

Bart is male

Homer is male

Homer is the parent of Lisa

Lisa is the daughter of Homer if Lisa is female and Homer is the parent of Lisa

Homer is the parent of Bart if Homer is the parent of Lisa and Lisa is the sister of Bart

Lisa is the sister of Bart if Lisa is female and Bart is the sibling of Lisa

Bart is the sibling of Lisa if Lisa is the sibling of Bart

Lisa is the sibling of Bart

etc.

Conclusions, goals, conditions, and facts are Boolean-valued predicates.

The three main logic programming languages are:

·       Proplog- predicates are strings

·       Datalog- predicates may also contain variables: X is the sibling of Y if Y is the sibling of X

·       Prolog- predicates may also contain structures: Person(Name1, Age1) is the sibling of Person(Name2, Age2) if (Person(Name2, Age2) is the sibling of Person(Name1, Age1)

We can represent a logic program as a list of lists of statements:

val simpsons: List[List[String]] = List(
   List("Bart is the son of Homer", "Bart is male", "Homer is the parent of Bart")
   List("Bart is male")
   etc.
)

Given a list of goal statements and a logic program as input, a solver attempts to prove that each goal statement can be proved from the program:

def solve(goals: List[Statement], program: List[List[Statement]]): Boolean = if (program proves goals) true else false

In some cases solve may not terminate.

The main inference rule used is resolution:

Assume we have proved A1 and A2, then from the rule A if A1 and A2, we can infer A

In Prolog and Datalog solve also needs to find bindings for variables that will make a conclusion match with a goal, this is called unification:

Bart is the Sibling of Lisa

X is the sibling of Y if Y is the sibling of X

Lisa is the Sibling of Bart (assuming unifier = {X = Lisa, Y = Bart})

Implement and test solve for Proplog.

Hints:

·       Add a new Scala application object called proplog to a Scala project called proplog.

package proplog
object proplog extends App {   }

·       Add an integer parameter, pos, to solve. Pos - 1 indicates the position in the program of the last rule or fact that matched the current goal:

package proplog
object proplog extends App {
   def solve(goals: List[String], program: List[List[String]], pos: Int = 0): Boolean = {...}
}

·       If the goal list is empty, then return true, solve has satisfied all of the goals.

·       If program length <= pos, return false, we're out of rules and facts to resolve with our goals.

·       Assume A is the head of goals. Let (A, A1, A2, A3) be the first rule (or fact) in the program with index >= pos. (Use program.indexWhere(unifier _, pos).)

·       If none exists, then return false, otherwise recursively call solve. The new list of goals is the old list with A replaced by A1, A2, A3. You can experiment with placing these conditions at the front or rear of goals. If A matches a fact, then A is simply removed from the goal list. It has been satisfied. Set pos = 0, we're starting over.

·       If the above recursive call returns false, recursively call solve again. No changes to goals or program this time, but pos = index + 1. In other words, we look for the next fact or rule that might match A.

·       Print out the goals and pos at the start of solve. This is the (attempted) proof.

·       Add some test code to the app object and run it:

package proplog
object proplog extends App {
   def solve(goals: List[String], program: List[List[String]], pos: Int = 0): Boolean = {...}
   var program1 = List(...)
   var goals1 = List(...)
   println("result = " + solve(goals1, program1))
   // etc.
}

15.  Problem

Find an iterative implementation of solve

16.  Problem

Find a non-recursive, non-iterative implementation of solve that uses map. filter, and reduce.