Scala nested loops yield - scala

I wonder if there is a simple way to do something like this in scala:
case class Pot(width: Int, height: Int, flowers: Seq[FlowerInPot])
case class FlowerInPot(x: Int, y: Int, flower: String)
val flowers = Seq("tulip", "rose")
val height = 3
val width = 3
val res =
for (flower <- flowers;
h <- 0 to height;
w <- 0 to width) yield {
// ??
}
and at an output I'd like to have a Seq of Pots with all possible combinations of flowers placed in it. So in following example, the output should be:
Seq(
Pot(3, 3, Seq(FlowerInPot(0, 0, "tulip"), FlowerInPot(0, 1, "rose"))),
Pot(3, 3, Seq(FlowerInPot(0, 0, "tulip"), FlowerInPot(0, 2, "rose"))),
Pot(3, 3, Seq(FlowerInPot(0, 0, "tulip"), FlowerInPot(1, 0, "rose"))),
Pot(3, 3, Seq(FlowerInPot(0, 0, "tulip"), FlowerInPot(1, 1, "rose"))),
...
Pot(3, 3, Seq(FlowerInPot(2, 2, "tulip"), FlowerInPot(2, 1, "rose")))
)
any ideas?

Is this what you want?
case class FlowerInPot(x: Int, y: Int, flower: String)
case class Pot(width: Int, height: Int, flowers: Seq[FlowerInPot])
val x, y = 0
val flowers = Seq("tulip", "rose")
val height = 3
val width = 3
val res = for {
h <- 0 to height
w <- 0 to width
} yield Pot(height, width, flowers.map(flower => FlowerInPot(w, h, flower)))

I figured it out, for now this solution seems to work:
val res = for {
h <- 0 to height;
w <- 0 to width;
flower <- flowers
} yield (h, w, flower)
val pots: Seq[Pot] = res.sliding(flowers.size).map(l => Pot(width, height, l.map(f => FlowerInPot(f._1, f._2, f._3)))).toList

Related

scala how to reduce while n > 0

I am wondering if there's a way to deal with a while (n > 0) loop in a more functional way, I have a small Scala app that counts the number of digits equal to K from a range from 1 to N:
for example 30 and 3 would return 4 [3, 13, 23, 30]
object NumKCount {
def main(args: Array[String]): Unit = {
println(countK(30,3))
}
def countKDigit(n:Int, k:Int):Int = {
var num = n
var count = 0
while (num > 10) {
val digit = num % 10
if (digit == k) {count += 1}
num = num / 10
}
if (num == k) {count += 1}
count
}
def countK(n:Int, k:Int):Int = {
1.to(n).foldLeft(0)((acc, x) => acc + countKDigit(x, k))
}
}
I'm looking for a way to define the function countKDigit using a purely functional approach
First expand number n into a sequence of digits
def digits(n: Int): Seq[Int] = {
if (n < 10) Seq(n)
else digits(n / 10) :+ n % 10
}
Then reduce the sequence by counting occurrences of k
def countKDigit(n:Int, k:Int):Int = {
digits(n).count(_ == k)
}
Or you can avoid countKDigit entirely by using flatMap
def countK(n:Int, k:Int):Int = {
1.to(n).flatMap(digits).count(_ == k)
}
Assuming that K is always 1 digit, you can convert n to String and use collect or filter, like below (there's not much functional stuff you can do with Integer):
def countKDigit(n: Int, k: Int): Int = {
n.toString.collect({ case c if c.asDigit == k => true }).size
}
or
def countKDigit(n: Int, k: Int): Int = {
n.toString.filter(c => c.asDigit == 3).length
}
E.g.
scala> 343.toString.collect({ case c if c.asDigit == 3 => true }).size
res18: Int = 2
scala> 343.toString.filter(c => c.asDigit == 3).length
res22: Int = 2
What about the following approach:
scala> val myInt = 346763
myInt: Int = 346763
scala> val target = 3
target: Int = 3
scala> val temp = List.tabulate(math.log10(myInt).toInt + 1)(x => math.pow(10, x).toInt)
temp: List[Int] = List(1, 10, 100, 1000, 10000, 100000)
scala> temp.map(x => myInt / x % 10)
res17: List[Int] = List(3, 6, 7, 6, 4, 3)
scala> temp.count(x => myInt / x % 10 == target)
res18: Int = 2
Counting the occurrences of a single digit in a number sequence.
def countK(n:Int, k:Int):Int = {
assert(k >= 0 && k <= 9)
1.to(n).mkString.count(_ == '0' + k)
}
If you really only want to modify countKDigit() to a more functional design, there's always recursion.
def countKDigit(n:Int, k:Int, acc: Int = 0):Int =
if (n == 0) acc
else countKDigit(n/10, k, if (n%10 == k) acc+1 else acc)

MaxSubArray using dynamic style

I have been trying to create code that counts the max substring from array and returns sum and starting and ending point. I have some error in there however that I cannot spot because for example when I use Array(-2, 1, -3, 4, -1, 2, 1, -5, 4) as source I get return (7, 5,8). However, the correct answer should be (6, 3, 6). Code below.
def solve(a: Array[Int]): (Int, Int, Int) = {
require(a.nonEmpty)
val n = a.length
val temp = Array.fill(n)(0, 0, 0)
var max = (0,0,0) // sum, start, end
for (i <- 0 to n-1) {
temp(i) = (a(i), i, i)
}
for (i <- 0 to n-1) {
for (j <- 0 to i) {
if (a(i) > a(j) && temp(i)._1 < temp (j)._1 + a(i)) {
temp(i) = (temp(j)._1 + a(i), j, i)
}
}
}
for (i <- 0 to n-1){
if (max._1 < temp(i)._1){
max = temp(i)
}
}
return max
}
How about a more Scala/functional approach?
def solve(a: Array[Int]): (Int, Int, Int) = {
a.tails.zipWithIndex.flatMap{
case (arr, ti) =>
arr.inits.map{
tail => (tail.sum, ti, ti + tail.length -1)
}
}.maxBy(_._1)
}
solve (Array(-2, 1, -3, 4, -1, 2, 1, -5, 4)) => res7: (Int, Int, Int) = (6,3,6)

how to compare to previous values in Seq[Double]

I am new to functional programming, I have a Seq[Double] and I'd like to check for each value if it is higher (1), lower (-1) or equal (0) to previous value, like:
val g = Seq(0.1, 0.3, 0.5, 0.5, 0.5, 0.3)
and I'd like to have a result like:
val result = Seq(1, 1, 0, 0, 0, -1)
is there a more concise way than:
val g = Seq(0.1, 0.3, 0.5, 0.5, 0.5, 0.3)
g.sliding(2).toList.map(xs =>
if (xs(0)==xs(1)){
0
} else if(xs(0)>xs(1)){
-1
} else {
1
}
)
Use compare:
g.sliding(2).map{ case Seq(x, y) => y compare x }.toList
compare is added by an enrichment trait called OrderedProxy
That's rather concise in my opinion but I'd make it a function and pass it into map to make it more readable. I used pattern matching and guards.
//High, low, equal
scala> def hlo(x: Double, y: Double): Int = y - x match {
| case 0.0 => 0
| case x if x < 0.0 => -1
| case x if x > 0.0 => 1
| }
hlo: (x: Double, y: Double)Int
scala> g.sliding(2).map(xs => hlo(xs(0), xs(1))).toList
res9: List[Int] = List(1, 1, 0, 0, -1)
I agree with Travis Brown's comment from above so am proposing it as an answer.
Reversing the order of the values in the zip, just to match the order of g. This has the added benefit of using tuples instead of a sequence so no pattern matching is needed.
(g, g.tail).zipped.toList.map(t => t._2 compare t._1)
res0: List[Int] = List(1, 1, 0, 0, -1)

Ugly number implementation in scala

I am trying to implement ugly number sequence generation in Scala.
Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15...
I have implemented using var keyword like java implementation and it is working fine. Here is the ideone link of complete code: http://ideone.com/qxMEBw
Can someone suggest better of implementing it using Scala idioms and without using mutable values.
Pasting code here for reference :
/**
* Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence
* 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15,
* shows the first 11 ugly numbers. By convention, 1 is included.
* Write a program to find and print the 150th ugly number.
*
*/
object UglyNumbers extends App {
var uglyNumbers = List(1)
val n = 11
var i2 = 0;
var i3 = 0;
var i5 = 0;
// initialize three choices for the next ugly numbers
var next_multiple_2 = uglyNumbers(i2) * 2;
var next_multiple_3 = uglyNumbers(i3) * 3;
var next_multiple_5 = uglyNumbers(i5) * 5;
for (i <- 0 to n) {
val nextUglyNumber = min(next_multiple_2, next_multiple_3, next_multiple_5)
uglyNumbers = uglyNumbers :+ nextUglyNumber
if (nextUglyNumber == next_multiple_2) {
i2 = i2 + 1
next_multiple_2 = uglyNumbers(i2) * 2
}
if (nextUglyNumber == next_multiple_3) {
i3 = i3 + 1
next_multiple_3 = uglyNumbers(i3) * 3
}
if (nextUglyNumber == next_multiple_5) {
i5 = i5 + 1
next_multiple_5 = uglyNumbers(i5) * 5
}
}
for (uglyNumber <- uglyNumbers)
print(uglyNumber + " ")
def min(a: Int, b: Int, c: Int): Int = (a, b, c) match {
case _ if (a <= b && a <= c) => a
case _ if (b <= a && b <= c) => b
case _ => c
}
}
could take a look at following codes, using stream & recursion:
object App extends App {
val ys = Array(2, 3, 5)
def uglynumber(n: Int): Boolean =
n match {
case x if x == 1 => true
case x if x % 5 == 0 => uglynumber(x / 5)
case x if x % 3 == 0 => uglynumber(x / 3)
case x if x % 2 == 0 => uglynumber(x / 2)
case _ => false
}
def uglynumbers: Stream[Int] = {
def go(x: Int): Stream[Int] =
if (uglynumber(x)) x #:: go(x + 1)
else go(x + 1)
go(1)
}
println(uglynumbers.take(30).toList.sorted)
}
The output for the first 30 ugly numbers:
List(1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80)
revise it to use your way
def nums: Stream[Int] = {
def go(a: Int, b: Int, c: Int): Stream[Int] = {
val xs = nums.take(a.max(b.max(c))).toArray
val a2 = 2 * xs(a - 1)
val b3 = 3 * xs(b - 1)
val c5 = 5 * xs(c - 1)
if (a2 <= b3 && a2 <= c5) a2 #:: go(a + 1, b, c)
else if (b3 <= a2 && b3 <= c5) b3 #:: go(a, b + 1, c)
else c5 #:: go(a, b, c + 1)
}
(1 #:: go(1, 1, 1)).distinct
}
println(nums.take(30).toList)
So, how about this one:
scala> lazy val ugly: Stream[Int] = 1 #:: Stream.from(2).filter{ n =>
| ugly.takeWhile(n/2>=).flatten(x => Seq(2, 3, 5).map(x*)).contains(n)
| }
warning: there were 2 feature warning(s); re-run with -feature for details
ugly: Stream[Int] = <lazy>
scala> ugly.take(30).toList
res5: List[Int] = List(1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18,
20, 24, 25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80)

In Scala, how do I keep track of running totals without using var?

For example, suppose I wish to read in fat, carbs and protein and wish to print the running total of each variable. An imperative style would look like the following:
var totalFat = 0.0
var totalCarbs = 0.0
var totalProtein = 0.0
var lineNumber = 0
for (lineData <- allData) {
totalFat += lineData...
totalCarbs += lineData...
totalProtein += lineData...
lineNumber += 1
printCSV(lineNumber, totalFat, totalCarbs, totalProtein)
}
How would I write the above using only vals?
Use scanLeft.
val zs = allData.scanLeft((0, 0.0, 0.0, 0.0)) { case(r, c) =>
val lineNr = r._1 + 1
val fat = r._2 + c...
val carbs = r._3 + c...
val protein = r._4 + c...
(lineNr, fat, carbs, protein)
}
zs foreach Function.tupled(printCSV)
Recursion. Pass the sums from previous row to a function that will add them to values from current row, print them to CSV and pass them to itself...
You can transform your data with map and get the total result with sum:
val total = allData map { ... } sum
With scanLeft you get the particular sums of each step:
val steps = allData.scanLeft(0) { case (sum,lineData) => sum+lineData}
val result = steps.last
If you want to create several new values in one iteration step I would prefer a class which hold the values:
case class X(i: Int, str: String)
object X {
def empty = X(0, "")
}
(1 to 10).scanLeft(X.empty) { case (sum, data) => X(sum.i+data, sum.str+data) }
It's just a jump to the left,
and then a fold to the right /:
class Data (val a: Int, val b: Int, val c: Int)
val list = List (new Data (3, 4, 5), new Data (4, 2, 3),
new Data (0, 6, 2), new Data (2, 4, 8))
val res = (new Data (0, 0, 0) /: list)
((acc, x) => new Data (acc.a + x.a, acc.b + x.b, acc.c + x.c))