I recently started to learn scala ad try to familiarize myself with a simple demo program.
I want to check if a cell has all neighbours. In java this could be accomplished via:
public boolean hasFullNeighbourhood() {
if (top != null && bottom != null && left != null && right != null &&
top.getLeft() != null && top.getRight()
!= null && bottom.getLeft() != null
&& bottom.getRight() != null)
return true;
else
return false;
}
Cell is defined as:
class Cell(
val x: Int,
val y: Int,
val left: Option[Cell],
val right: Option[Cell],
val top: Option[Cell],
val bottom: Option[Cell],
var isPainted: Boolean)
How can I define a full neighbourhood in scala?
I started like:
def hasFullNeighbourhood(r:Int): Boolean={
if(r ==0)
return true
if (List(top, bottom, left, right).forall(_.isDefined))
return true
else
return false
}
But how accessing the rest (x.top, x.bottom, x.left, x.right) and checking if these are not null/ optional is unclear for me.
I think something like top.foreach() would be possible - but if added to the list of optionals it would not fail if this returned none.
edit
I redefined my class as a case class:
case class Cell(
val x: Int,
val y: Int,
val left: Option[Cell],
val right: Option[Cell],
val top: Option[Cell],
val bottom: Option[Cell],
var isPainted: Boolean)
Does this mean that
def isMiddleCell()={
if(List(top, bottom, left, right).forall(_.isDefined))
true
else
false
}
can be rewritten as:
def isMiddleCell(c: Cell) = c match {
case Cell(_, _, Some(top), Some(bottom), Some(left), Some(right), _) => true
case _ => false
}
Which still seems a bit strange as I would rather like to check for a given cell if this one is a middle cell an does not specify Cell.isMiddleCell(givenCell) but rather givenCell.isMiddleCell()
However to implement the
def hasFullNeughbourhood(radius:Int) correctly wouldn't I need some more statements as I do not only want to check for immediate neighbours. For me, it is still unclear how to access these. In java I would use x.getLeft()and recursively x.getLeft().hasFullNeighbourhood(r - 1).
def hasFullNeighbourhood(c: Cell) = c match {
case Cell(_, _, Some(top), Some(bottom), Some(left), Some(right), _) => true
case _ => false
}
edit2
do I understand correctly that isMiddleCell should be implemented as:
def isMiddleCell() = {
this match {
case Cell(_, _, Some(top), Some(bottom), Some(left), Some(right), _) => true
case _ => false
}
There are typically to good ways to perform an action on the contents of a container in Scala: mapping or decomposition via pattern matching. Pattern matching is the more intuitive one in case of Option if you are not used to functional programming.
To make pattern matching easier, you should define your cell-class as a case class. This gives you pattern matching without having to implement anything yourself and will make the next example nicer. Case-classes are always a good idea for simple data model classes.
def hasFullNeighbourhood(c: Cell) = c match {
case Cell(_,_,Some(top),Some(bottom),Some(left),Some(right),_) => true
case _ => false
I left in the variable names top bottom and so on because you could use those to do something with those values. But as you do not need them for this method I could have just written _ as well. If you do not know pattern matching yet, read up on it. Scala without it isn't fun.
The other way is using map. This is only interesting if you want to do some computation of the stuff in a "container" and put it back into the same kind of container:
val possiblyANumber1 = Some(5)
val possiblyANumber2 = Some(5)
val possiblyANumber3 = possiblyANumber1.flatMap(x => possiblyANumber2.map(y => x + y))
In this example this allows you to do an addition on two numbers without knowing, whether they actually exist.
Related
This question already has answers here:
Use tail recursion to find maxDepth of Binary Tree
(4 answers)
Closed 3 months ago.
Please advice is there a way to have a tailrec implementation of "classical" tree depth algo.
import scala.annotation.tailrec
object Tree extends App {
sealed trait Tree[+A]
case class Node[A](value: A,
left: Option[Tree[A]] = None,
right: Option[Tree[A]] = None) extends Tree[A]
object Node:
def apply[A](value: A) =
new Node[A](value = value, left = None, right = None)
def apply[A](value: A, node: Tree[A]) =
new Node[A](value = value, left = Some(node), right = None)
def apply[A](value: A, left: Tree[A], right: Tree[A]) =
new Node[A](value = value, left = Some(left), right = Some(right))
def unapply[A](node: Node[A]): (A, Option[Tree[A]], Option[Tree[A]]) =
(node.value, node.left, node.right)
def go[A](node: Option[Tree[A]]): Int =
node match
case None => 0
case Some(Node(_, left, right)) => Math.max(go(left), go(right)) + 1
val tree = Node(value = "root",
left = Node(value = "a"),
right = Node(value = "b",
left = Node(value = "c"),
right = Node(value = "d")))
println(go(Some(tree)))
}
I've found some pointers to use CPS (continuation passing style) way - but it still fails for me.
Thanks.
There probably wouldn't be a solution for this question which is both tail recursive, efficient and that would work for all possible kind of tree (this is not 100% true, this is probable as far as I could reason about). Let me explain what I mean. In a tail recursive action, returning expression must be either a calculated value or a call to the function itself, with no extra computation on the returning expression/value, right? Think about factorial calculation, you either return the accumulated value, or just call the function itself. Now in your case your tree might look something like this:
R
/ \
A B
/ \ /
C D E
/
F
Lets start on R, both children nodes are fulfilled, how do you want to calculate the maximum depth of nodes? You HAVE to traverse the whole depth of both sub trees (A and B) and return the maximum right? so your adding an extra operation on the return value of A and B depths (Math.max). Now there fortunately is an approach to somehow turn the expression to tail recursive, but it is not efficient at all.
...
// in your else expression where you know that the node is not empty itself
(node.left.isEmpty, node.right.isEmpty) match {
case (true, true) => currentDepth + 1
case (true, false) => go(node.right, currentDepth)
case (false, true) => go(node.left, currentDepth)
case _ =>
val leftLDepth = go(node.left, currentDepth)
val rightDepth = go(node.right, currentDepth)
// this is were everything gets dirty
if (leftDepth > rightDepth) {
go(node.left, currentDepth)
} else if (rightDepth > leftDepth) {
go(node.right, currentDepth)
} else { leftLength }
}
This actually is terrible, time complexity of this touches the 7th sky. So you can actually do it with tail recursion , but tail recursion is not suitable for this case. And pay attention that this is not actually tailrec, it just might be accepted by the compiler as tailrec (maybe, not sure!). because when you're calculating the children nodes depth and comparing, you're using 2 stackframes for each of the calculations (each of them can also have 2 childrens, so...).
Dynamic programming seems a better fit.
Update
I actually tried to implement the approach, and the compiler does not accept it, since the call to the function, is not only in the tail position :D
If I wanted to pattern match on a basic option type in Scala, I would run something along the lines of
val opt = Option(5)
val lessThanTen = opt match {
case Some(e) => if (e < 10) true else false
case None => None
}
But suppose that opt comes as a result of one of Slick's Queries, and therefore has the Lifted Embedding Type of Rep[Option[Int]]
How can I carry out the same pattern matching in a way that allows us the to see inside of the the lifted type? I.e. something along the lines of
val opt = Rep(Option(5))
val lessThanTen = opt match {
case Rep[Some(e)] => Rep[if (e < 10) true else false]
case Rep[None] => Rep[None]
}
But of course, one that compiles ;)
You can use the map method to apply some operation on the content of a Rep.
val rep: Rep[Option[Int]] = ???
val boolRep = rep.map {
case Some(i) => Some(i < 10)
case None => None
}
Even better: Option, like many other collection types in Scala, also has a similar map method, so you can write
val boolRep = rep.map(_.map(_ < 10))
In that expression, the first _ is the Option[Int], and the second one is the Int itself. In cases where the Option[Int] is None, the map method has nothing to apply the given function to, so it returns None by definition.
In ScalaTest, I have the following check:
"abc".r shouldBe "abc".r
But it is not equal. I don't understand.
abc was not equal to abc
ScalaTestFailureLocation: com.ing.cybrct.flink.clickstream.ConfigsTest$$anonfun$6 at (ConfigsTest.scala:97)
Expected :abc
Actual :abc
While it's possible to decide whether two regular expressions accept the same language, it seems to be rather complicated and not all that terribly useful for everyday regex usage. Therefore, equality on compiled regex patterns is just referential equality:
val x = "abc".r
val y = "abc".r
x == y
// res0: Boolean = false
The method shouldBe in Scalatest 3.0.5 delegates the equality check to the areEqualComparingArraysStructurally method:
def shouldBe(right: Any): Assertion = {
if (!areEqualComparingArraysStructurally(leftSideValue, right)) {
val (leftee, rightee) = Suite.getObjectsForFailureMessage(leftSideValue, right)
val localPrettifier = prettifier // Grabbing a local copy so we don't attempt to serialize AnyShouldWrapper (since first param to indicateFailure is a by-name)
indicateFailure(FailureMessages.wasNotEqualTo(localPrettifier, leftee, rightee), None, pos)
}
else indicateSuccess(FailureMessages.wasEqualTo(prettifier, leftSideValue, right))
}
which in turn simply delegates the equality check (as you can expect) to the == operator:
private[scalatest] def areEqualComparingArraysStructurally(left: Any, right: Any): Boolean = {
// Prior to 2.0 this only called .deep if both sides were arrays. Loosened it
// when nearing 2.0.M6 to call .deep if either left or right side is an array.
// TODO: this is the same algo as in scalactic.DefaultEquality. Put that one in
// a singleton and use it in both places.
left match {
case leftArray: Array[_] =>
right match {
case rightArray: Array[_] => leftArray.deep == rightArray.deep
case _ => leftArray.deep == right
}
case _ => {
right match {
case rightArray: Array[_] => left == rightArray.deep
case _ => left == right
}
}
}
}
In Scala, at least on the JVM, == simply calls equals, which, if not overridden, checks whether the compared variables point to the same object. case classes are peculiar in that the compiler overrides equals for you to compare the constructor arguments.
You can test it very easily with the following (but as you can imagine, the same applies to simply using == on your own):
package org.example
import org.scalatest.{FlatSpec, Matchers}
final class MyClass(val a: Int)
final case class MyCaseClass(a: Int)
final class TestSpec extends FlatSpec with Matchers {
"equality on case classes" should "succeed" in {
new MyCaseClass(1) shouldBe new MyCaseClass(1)
}
"equality on non-case classes" should "fail" in {
new MyClass(1) shouldNot be(new MyClass(1))
}
"equality between Regex objects" should "fail" in {
"abc".r shouldNot be("abc".r)
}
}
What the r method does is instantiating a new Regex object, which is not a case class and does not override the equality definition, thus yielding the result you see.
Yes, they are not equal. Both "abc".r are different references to two different memory locations. shouldbe is to check equality but not identity.
I wish to find a match within a List and return values dependant on the match. The CollectFirst works well for matching on the elements of the collection but in this case I want to match on the member swEl of the element rather than on the element itself.
abstract class CanvNode (var swElI: Either[CSplit, VistaT])
{
private[this] var _swEl: Either[CSplit, VistaT] = swElI
def member = _swEl
def member_= (value: Either[CSplit, VistaT] ){ _swEl = value; attach}
def attach: Unit
attach
def findVista(origV: VistaIn): Option[Tuple2[CanvNode,VistaT]] = member match
{
case Right(v) if (v == origV) => Option(this, v)
case _ => None
}
}
def nodes(): List[CanvNode] = topNode :: splits.map(i => List(i.n1, i.n2)).flatten
//Is there a better way of implementing this?
val temp: Option[Tuple2[CanvNode, VistaT]] =
nodes.map(i => i.findVista(origV)).collectFirst{case Some (r) => r}
Do I need a View on that, or will the collectFirst method ensure the collection is only created as needed?
It strikes me that this must be a fairly general pattern. Another example could be if one had a List member of the main List's elements and wanted to return the fourth element if it had one. Is there a standard method I can call? Failing that I can create the following:
implicit class TraversableOnceRichClass[A](n: TraversableOnce[A])
{
def findSome[T](f: (A) => Option[T]) = n.map(f(_)).collectFirst{case Some (r) => r}
}
And then I can replace the above with:
val temp: Option[Tuple2[CanvNode, VistaT]] =
nodes.findSome(i => i.findVista(origV))
This uses implicit classes from 2.10, for pre 2.10 use:
class TraversableOnceRichClass[A](n: TraversableOnce[A])
{
def findSome[T](f: (A) => Option[T]) = n.map(f(_)).collectFirst{case Some (r) => r}
}
implicit final def TraversableOnceRichClass[A](n: List[A]):
TraversableOnceRichClass[A] = new TraversableOnceRichClass(n)
As an introductory side node: The operation you're describing (return the first Some if one exists, and None otherwise) is the sum of a collection of Options under the "first" monoid instance for Option. So for example, with Scalaz 6:
scala> Stream(None, None, Some("a"), None, Some("b")).map(_.fst).asMA.sum
res0: scalaz.FirstOption[java.lang.String] = Some(a)
Alternatively you could put something like this in scope:
implicit def optionFirstMonoid[A] = new Monoid[Option[A]] {
val zero = None
def append(a: Option[A], b: => Option[A]) = a orElse b
}
And skip the .map(_.fst) part. Unfortunately neither of these approaches is appropriately lazy in Scalaz, so the entire stream will be evaluated (unlike Haskell, where mconcat . map (First . Just) $ [1..] is just fine, for example).
Edit: As a side note to this side note: apparently Scalaz does provide a sumr that's appropriately lazy (for streams—none of these approaches will work on a view). So for example you can write this:
Stream.from(1).map(Some(_).fst).sumr
And not wait forever for your answer, just like in the Haskell version.
But assuming that we're sticking with the standard library, instead of this:
n.map(f(_)).collectFirst{ case Some(r) => r }
I'd write the following, which is more or less equivalent, and arguably more idiomatic:
n.flatMap(f(_)).headOption
For example, suppose we have a list of integers.
val xs = List(1, 2, 3, 4, 5)
We can make this lazy and map a function with a side effect over it to show us when its elements are accessed:
val ys = xs.view.map { i => println(i); i }
Now we can flatMap an Option-returning function over the resulting collection and use headOption to (safely) return the first element, if it exists:
scala> ys.flatMap(i => if (i > 2) Some(i.toString) else None).headOption
1
2
3
res0: Option[java.lang.String] = Some(3)
So clearly this stops when we hit a non-empty value, as desired. And yes, you'll definitely need a view if your original collection is strict, since otherwise headOption (or collectFirst) can't reach back and stop the flatMap (or map) that precedes it.
In your case you can skip findVista and get even more concise with something like this:
val temp = nodes.view.flatMap(
node => node.right.toOption.filter(_ == origV).map(node -> _)
).headOption
Whether you find this clearer or just a mess is a matter of taste, of course.
For those who don't know what a 5-card Poker Straight is: http://en.wikipedia.org/wiki/List_of_poker_hands#Straight
I'm writing a small Poker simulator in Scala to help me learn the language, and I've created a Hand class with 5 ordered Cards in it. Each Card has a Rank and Suit, both defined as Enumerations. The Hand class has methods to evaluate the hand rank, and one of them checks whether the hand contains a Straight (we can ignore Straight Flushes for the moment). I know there are a few nice algorithms for determining a Straight, but I wanted to see whether I could design something with Scala's pattern matching, so I came up with the following:
def isStraight() = {
def matchesStraight(ranks: List[Rank.Value]): Boolean = ranks match {
case head :: Nil => true
case head :: tail if (Rank(head.id + 1) == tail.head) => matchesStraight(tail)
case _ => false
}
matchesStraight(cards.map(_.rank).toList)
}
That works fine and is fairly readable, but I was wondering if there is any way to get rid of that if. I'd imagine something like the following, though I can't get it to work:
private def isStraight() = {
def matchesStraight(ranks: List[Rank.Value]): Boolean = ranks match {
case head :: Nil => true
case head :: next(head.id + 1) :: tail => matchesStraight(next :: tail)
case _ => false
}
matchesStraight(cards.map(_.rank).toList)
}
Any ideas? Also, as a side question, what is the general opinion on the inner matchesStraight definition? Should this rather be private or perhaps done in a different way?
You can't pass information to an extractor, and you can't use information from one value returned in another, except on the if statement -- which is there to cover all these cases.
What you can do is create your own extractors to test these things, but it won't gain you much if there isn't any reuse.
For example:
class SeqExtractor[A, B](f: A => B) {
def unapplySeq(s: Seq[A]): Option[Seq[A]] =
if (s map f sliding 2 forall { case Seq(a, b) => a == b } ) Some(s)
else None
}
val Straight = new SeqExtractor((_: Card).rank)
Then you can use it like this:
listOfCards match {
case Straight(cards) => true
case _ => false
}
But, of course, all that you really want is that if statement in SeqExtractor. So, don't get too much in love with a solution, as you may miss simpler ways of doing stuff.
You could do something like:
val ids = ranks.map(_.id)
ids.max - ids.min == 4 && ids.distinct.length == 5
Handling aces correctly requires a bit of work, though.
Update: Here's a much better solution:
(ids zip ids.tail).forall{case (p,q) => q%13==(p+1)%13}
The % 13 in the comparison handles aces being both rank 1 and rank 14.
How about something like:
def isStraight(cards:List[Card]) = (cards zip cards.tail) forall { case (c1,c2) => c1.rank+1 == c2.rank}
val cards = List(Card(1),Card(2),Card(3),Card(4))
scala> isStraight(cards)
res2: Boolean = true
This is a completely different approache, but it does use pattern matching. It produces warnings in the match clause which seem to indicate that it shouldn't work. But it actually produces the correct results:
Straight !!! 34567
Straight !!! 34567
Sorry no straight this time
I ignored the Suites for now and I also ignored the possibility of an ace under a 2.
abstract class Rank {
def value : Int
}
case class Next[A <: Rank](a : A) extends Rank {
def value = a.value + 1
}
case class Two() extends Rank {
def value = 2
}
class Hand(a : Rank, b : Rank, c : Rank, d : Rank, e : Rank) {
val cards = List(a, b, c, d, e).sortWith(_.value < _.value)
}
object Hand{
def unapply(h : Hand) : Option[(Rank, Rank, Rank, Rank, Rank)] = Some((h.cards(0), h.cards(1), h.cards(2), h.cards(3), h.cards(4)))
}
object Poker {
val two = Two()
val three = Next(two)
val four = Next(three)
val five = Next(four)
val six = Next(five)
val seven = Next(six)
val eight = Next(seven)
val nine = Next(eight)
val ten = Next(nine)
val jack = Next(ten)
val queen = Next(jack)
val king = Next(queen)
val ace = Next(king)
def main(args : Array[String]) {
val simpleStraight = new Hand(three, four, five, six, seven)
val unsortedStraight = new Hand(four, seven, three, six, five)
val notStraight = new Hand (two, two, five, five, ace)
printIfStraight(simpleStraight)
printIfStraight(unsortedStraight)
printIfStraight(notStraight)
}
def printIfStraight[A](h : Hand) {
h match {
case Hand(a: A , b : Next[A], c : Next[Next[A]], d : Next[Next[Next[A]]], e : Next[Next[Next[Next[A]]]]) => println("Straight !!! " + a.value + b.value + c.value + d.value + e.value)
case Hand(a,b,c,d,e) => println("Sorry no straight this time")
}
}
}
If you are interested in more stuff like this google 'church numerals scala type system'
How about something like this?
def isStraight = {
cards.map(_.rank).toList match {
case first :: second :: third :: fourth :: fifth :: Nil if
first.id == second.id - 1 &&
second.id == third.id - 1 &&
third.id == fourth.id - 1 &&
fourth.id == fifth.id - 1 => true
case _ => false
}
}
You're still stuck with the if (which is in fact larger) but there's no recursion or custom extractors (which I believe you're using incorrectly with next and so is why your second attempt doesn't work).
If you're writing a poker program, you are already check for n-of-a-kind. A hand is a straight when it has no n-of-a-kinds (n > 1) and the different between the minimum denomination and the maximum is exactly four.
I was doing something like this a few days ago, for Project Euler problem 54. Like you, I had Rank and Suit as enumerations.
My Card class looks like this:
case class Card(rank: Rank.Value, suit: Suit.Value) extends Ordered[Card] {
def compare(that: Card) = that.rank compare this.rank
}
Note I gave it the Ordered trait so that we can easily compare cards later. Also, when parsing the hands, I sorted them from high to low using sorted, which makes assessing values much easier.
Here is my straight test which returns an Option value depending on whether it's a straight or not. The actual return value (a list of Ints) is used to determine the strength of the hand, the first representing the hand type from 0 (no pair) to 9 (straight flush), and the others being the ranks of any other cards in the hand that count towards its value. For straights, we're only worried about the highest ranking card.
Also, note that you can make a straight with Ace as low, the "wheel", or A2345.
case class Hand(cards: Array[Card]) {
...
def straight: Option[List[Int]] = {
if( cards.sliding(2).forall { case Array(x, y) => (y compare x) == 1 } )
Some(5 :: cards(0).rank.id :: 0 :: 0 :: 0 :: 0 :: Nil)
else if ( cards.map(_.rank.id).toList == List(12, 3, 2, 1, 0) )
Some(5 :: cards(1).rank.id :: 0 :: 0 :: 0 :: 0 :: Nil)
else None
}
}
Here is a complete idiomatic Scala hand classifier for all hands (handles 5-high straights):
case class Card(rank: Int, suit: Int) { override def toString = s"${"23456789TJQKA" rank}${"♣♠♦♥" suit}" }
object HandType extends Enumeration {
val HighCard, OnePair, TwoPair, ThreeOfAKind, Straight, Flush, FullHouse, FourOfAKind, StraightFlush = Value
}
case class Hand(hand: Set[Card]) {
val (handType, sorted) = {
def rankMatches(card: Card) = hand count (_.rank == card.rank)
val groups = hand groupBy rankMatches mapValues {_.toList.sorted}
val isFlush = (hand groupBy {_.suit}).size == 1
val isWheel = "A2345" forall {r => hand exists (_.rank == Card.ranks.indexOf(r))} // A,2,3,4,5 straight
val isStraight = groups.size == 1 && (hand.max.rank - hand.min.rank) == 4 || isWheel
val (isThreeOfAKind, isOnePair) = (groups contains 3, groups contains 2)
val handType = if (isStraight && isFlush) HandType.StraightFlush
else if (groups contains 4) HandType.FourOfAKind
else if (isThreeOfAKind && isOnePair) HandType.FullHouse
else if (isFlush) HandType.Flush
else if (isStraight) HandType.Straight
else if (isThreeOfAKind) HandType.ThreeOfAKind
else if (isOnePair && groups(2).size == 4) HandType.TwoPair
else if (isOnePair) HandType.OnePair
else HandType.HighCard
val kickers = ((1 until 5) flatMap groups.get).flatten.reverse
require(hand.size == 5 && kickers.size == 5)
(handType, if (isWheel) (kickers takeRight 4) :+ kickers.head else kickers)
}
}
object Hand {
import scala.math.Ordering.Implicits._
implicit val rankOrdering = Ordering by {hand: Hand => (hand.handType, hand.sorted)}
}