[SOLVED] CS /*

$25

File Name: CS_/*.zip
File Size: 47.1 KB

5/5 - (1 vote)

/*
* Copyright (c) 2018. Phasmid Software
*/

package edu.neu.coe.csye7200.asstll

import scala.annotation.tailrec

/**
* Case class representing a non-empty ListLike.
*
* @param xthe head of the stream.
* @param lazyTail a function which, when invoked, yields the tail of this stream.
* @tparam X the underlying type of the stream, and of the value x.
*/
case class MyLazyList[X](x: X, lazyTail: () => ListLike[X]) extends LazyListLike[X] {

/**
* Concatenate this ListLike with ys.
*
* @param ys the stream to be used if/when this stream is exhausted.
* @tparam Y the underlying type of ys and the result.
* @return a ListLike[Y] which contains all the elements of this followed by all the elements of ys.
*/
def ++[Y >: X](ys: ListLike[Y]): ListLike[Y] = MyLazyList[Y](x, () => lazyTail() ++ ys)

def head: X = x

def tail: ListLike[X] = lazyTail()

/**
* The “flatMap” function.
*
* @param f a function which converts an X ListLike[Y] .
* @tparam Y the underlying type of the result.
* @return a ListLike[Y] where each element is the result of applying f this and then "flattening" the result
* by concatenating all streams together.
*/
def flatMap[Y](f: X => Monadic[Y]): ListLike[Y] = {
val y = f(x).asInstanceOf[ListLike[Y]]
MyLazyList(y.head, () => y.tail ++ lazyTail().flatMap(f))
}

/**
* Method to determine if this ListLike object is empty.
*
* @return true if the list is empty.
*/
def isEmpty: Boolean = false

/**
* Method to form a new list-like object by pre-pending y
*
* @param y the value to serve as the new head
* @tparam Y the type of y
* @return a new ListLike[Y] object with y as its head and this as its tail
*/
def +:[Y >: X](y: Y): ListLike[Y] = MyLazyList(y, () => this)

/**
* The “filter” function.
*
* @param p a predicate which takes an X and yields a Boolean .
* @return a Monadic[X] where every element satisfies the predicate p .
*/
def filter(p: X => Boolean): ListLike[X] = {
val tailFunc = () => lazyTail().filter(p)
if (p(x)) MyLazyList(x, tailFunc) else tailFunc()
}

/**
* Method to “zip” to ListLike objects together
*
* @param ys the stream of Ys
* @tparam Y the underlying type of ys
* @return a ListLike[(X,Y)] where each element is a tuple of the corresponding elements from this
* and ys respectively.
*/
def zip[Y](ys: ListLike[Y]): ListLike[(X, Y)] = ys match {
case MyLazyList(y, g) => MyLazyList((x, y), () => lazyTail() zip g())
case _ => EmptyList
}

/**
* Take the first n elements from this ListLike as a ListLike.
* NOTE: that this is not tail-recursive so may fail on large lists.
*
* @param n the number of elements to take (must not be negative).
* @return a sequence of length n.
*/
def take(n: Int): ListLike[X] =
if (n == 0)
EmptyList
else if (n > 0)
this match {
case MyLazyList(h, f) => MyLazyList(h, () => f() take n - 1)
case _ => EmptyList
}
else
throw LazyListException("cannot take negative number of elements")

/**
* Drop the first n elements of this ListLike object and return the remainder as a ListLike object.
*
* @param n the number of elements to drop (must not be negative).
* @return a ListLike[(X,Y)] which is shorter than this by n.
*/
def drop(n: Int): ListLike[X] = n match {
case 0 => this
case _ =>
if (n > 0)
this match {
case MyLazyList(_, f) => f().drop(n - 1)
case _ => EmptyList
}
else
throw LazyListException("cannot drop negative number of elements")
}

/**
* Convert this ListLike[X]into a Seq[X], element for element.
*
* @return a Seq[X]
*/
def toSeq: Seq[X] = {
@tailrec
def inner(rs: Seq[X], xs: ListLike[X]): Seq[X] = xs match {
case MyLazyList(h, f) => inner(rs :+ h, f())
case _ => rs
}

inner(Nil, this)
}

/**
* Method to yield the size of this list-like object.
*
* @return Some(n) where n is size if it’s definite; if size is not known (lazy) then return None
*/
def size(): Option[Int] = None

/**
* The “filterNot” function.
* Overrides the definition form Monadic by making the result type more specific.
*
* @param p a predicate which takes an Xand yields a Boolean.
* @return a ListLike[X]where every element satisfies the predicate p.
*/
def filterNot(p: X => Boolean): ListLike[X] = filter(FunctionalUtility.invert(p))

/**
* Construct a ListLike[X]with the elements of ys.
*
* Note that this is an instance method.
*
* @param ys the sequence of elements with which to construct the list-like object.
* @tparam Y the underlying type of ysand the underlying type of the resulting ListLike object
* @return a ListLike[Y]with exactly one element (whose value is y).
*/
def build[Y](ys: Seq[Y]): ListLike[Y] = ys match {
case h :: t => MyLazyList(h, t)
case _ => MyLazyList(ys)
}

override def iterator: Iterator[X] = Iterator.unfold[X, ListLike[X]](this) {
case EmptyList => None
case MyLazyList(x, f) => Some(x -> f())
}
}

/**
* Case object representing an empty ListLike.
*/
case object EmptyList extends LazyListLike[Nothing] {

/**
* Method to indicate whether it’s possible to cheaply calculate the length of this object.
*
* @return -1
*/
override def knownSize: Int = -1

def head = throw LazyListException(“empty”)

def tail: ListLike[Nothing] = EmptyList

/**
* The “flatMap” function.
*
* @param f a function which converts an X ListLike[Y] .
* @tparam Y the underlying type of the result.
* @return a ListLike[Y] where each element is the result of applying f this and then "flattening" the result
* by concatenating all streams together.
*/
def flatMap[Y](f: Nothing => Monadic[Y]): ListLike[Y] = EmptyList

/**
* Method to determine if this ListLike object is empty.
*
* @return true if the list is empty.
*/
def isEmpty: Boolean = true

/**
* Method to form a new list-like object by pre-pending y
*
* @param y the value to serve as the new head
* @tparam Y the type of y
* @return a new ListLike[Y] object with y as its head and this as its tail
*/
def +:[Y >: Nothing](y: Y): ListLike[Y] = unit(y)

/**
* Concatenate this ListLike with ys.
*
* CONSIDER renaming as ++
* CONSIDER moving to LazyListLike
*
* @param ys the stream to be used if/when this stream is exhausted.
* @tparam Y the underlying type of ys and the result.
* @return a ListLike[Y] which contains all the elements of this followed by all the elements of ys.
*/
def ++[Y >: Nothing](ys: ListLike[Y]): ListLike[Y] = ys

/**
* Method to “zip” to ListLike objects together
*
* @param ys the stream of Ys
* @tparam Y the underlying type of ys
* @return a ListLike[(X,Y)] where each element is a tuple of the corresponding elements from this
* and ys respectively.
*/
def zip[Y](ys: ListLike[Y]): ListLike[(Nothing, Y)] = EmptyList

/**
* Convert this ListLike into a Seq[X]by evaluating the first n X and yields a Boolean .
* @return a Monadic[X] where every element satisfies the predicate p .
*/
def filter(p: Nothing => Boolean): ListLike[Nothing] = EmptyList

/**
* Drop the first n elements of this ListLike object and return the remainder as a ListLike object.
*
* @param n the number of elements to drop (must not be negative).
* @return a ListLike[(X,Y)] which is shorter than this by n.
*/
def drop(n: Int): ListLike[Nothing] = EmptyList

/**
* Convert this ListLike[X]into a Seq[X], element for element.
*
* @return a Seq[X]
*/
def toSeq: Seq[Nothing] = Nil

/**
* Method to yield the size of this list-like object.
*
* @return Some(n) where n is size if it’s definite; if size is not known (lazy) then return None
*/
def size(): Option[Int] = Some(0)

/**
* The “filterNot” function.
* Overrides the definition form Monadic by making the result type more specific.
*
* @param p a predicate which takes an Xand yields a Boolean.
* @return a ListLike[X]where every element satisfies the predicate p.
*/
def filterNot(p: Nothing => Boolean): ListLike[Nothing] = EmptyList

/**
* Construct a ListLike[X]with the elements of ys.
*
* Note that this is an instance method.
*
* @param ys the sequence of elements with which to construct the list-like object.
* @tparam Y the underlying type of ysand the underlying type of the resulting ListLike object
* @return a ListLike[Y]with exactly one element (whose value is y).
*/
def build[Y](ys: Seq[Y]): ListLike[Y] = ys match {
case h :: t => MyLazyList(h, t)
case _ => MyLazyList(ys)
}

override def iterator: Iterator[Nothing] = Iterator.empty
}

abstract class LazyListLike[+X] extends ListLike[X] {

/**
* The “map” function.
* NOTE: that we have defined the mapfunction in terms of flatMapand the
* applyfunction (sometimes known as the “unit” function).
*
* @param f a function which converts an X Y .
* @tparam Y the underlying type of the result.
* @return a LazyList[Y] where each element is the result of applying f this .
*/
def map[Y](f: X => Y): ListLike[Y] = flatMap(x => unit[Y](f(x)))

/**
* Construct a (finite) LazyList[X]with exactly one element.
*
* @param y the value of the element.
* @tparam Y the underlying type of the resulting ListLike object
* @return a ListLike[Y]with exactly one element (whose value is y).
*/
def unit[Y](y: Y): ListLike[Y] = MyLazyList(y)

/**
* ToString method.
*
* @return a String which shows the head but leaves the tail as question marks.
*/
override def toString = s”$head, ???”

}

object FunctionalUtility {
def invert[X](p: X => Boolean): X => Boolean = !p(_)
}

object MyLazyList {

/**
* Construct a (finite) LazyList[X]with exactly one element.
*
* @param x the value of the element.
* @tparam X the underlying type of the result.
* @return a ListLike[X]with exactly one element (whose value is x).
*/
def apply[X](x: X): ListLike[X] = MyLazyList(x, () => EmptyList)

/**
* Construct a (finite) ListLike[X]corresponding to a sequence.
*
* @param xs the sequence.
* @tparam X the underlying type of the result.
* @return a ListLike[X]with the same number of elements as xs.
*/
def apply[X](xs: Seq[X]): ListLike[X] = xs match {
case Nil => EmptyList
case h :: t => MyLazyList(h, () => apply(t))
}

/**
* Construct a LazyList from a head element and a tail of a Stream
*
* @param xthe head of the new list-like object
* @param xs the sequence.
* @tparam X the underlying type of the result.
* @return a ListLike[X]with the same number of elements as xs.
*/
def apply[X](x: X, xs: Seq[X]): ListLike[X] = MyLazyList(x, () => apply(xs))

/**
* Construct a stream of xs.
*
* CONSIDER should we use call-by-value here instead of call-by-name?
*
* @param x the call-by-name value to be repeated
* @tparam X the type of X
* @return a ListLike[X]with an infinite number of element (whose values are x).
*/
def continually[X](x: => X): ListLike[X] = MyLazyList(x, () => continually(x))

/**
* A lazy val definition of a stream of 1s.
*/
lazy val ones: ListLike[Int] = MyLazyList(1, () => ones)

/**
* Method to yield a singleton LazyList
*
* @param x the single value.
* @tparam X the underlying type of x.
* @return a MyLazyList with just x as a value.
*/
def singleton[X](x: => X): ListLike[X] = MyLazyList(x, () => EmptyList)

/**
* Construct a stream of Integers starting with startand with successive elements being
* greater than their predecessors by step.
*
* @param start the value of the first element.
* @param stepthe difference between successive elements.
* @return a ListLike[X]with an infinite number of element (whose values are x,
* x+step, etc.).
*/
def from(start: Int, step: Int): ListLike[Int] = MyLazyList(start, () => from(start + step, step)) // TO BE IMPLEMENTED

/**
* Construct a stream of Integers starting with startand with successive elements being
* the next greater Int.
*
* @param start the value of the first element.
* @return a ListLike[X]with an infinite number of element (whose values are x,
* x+1, etc.).
*/
def from(start: Int): ListLike[Int] = from(start, 1)
}

case class LazyListException(w: String) extends Exception(s”LazyList exception: $w”)

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] CS /*
$25