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)
Related
My requirement is to drop every Nth element from a Scala Array (pls note every Nth element). I wrote the below method which does the job. Since, I am new to Scala, I couldn't avoid the Java hangover. Is there a simpler or more efficient alternative?
def DropNthItem(a: Array[String], n: Int): Array[String] = {
val in = a.indices.filter(_ % n != 0)
val ab: ArrayBuffer[String] = ArrayBuffer()
for ( i <- in)
ab += a(i-1)
return ab.toArray
}
You made a good start. Consider this simplification.
def DropNthItem(a: Array[String], n: Int): Array[String] =
a.indices.filter(x => (x+1) % n != 0).map(a).toArray
How about something like this?
arr.grouped(n).flatMap(_.take(n-1)).toArray
You can do this in two steps functionally using zipWithIndex to get an array of elements tupled with their indices, and then collect to build a new array consisting of only elements that have indices that aren't 0 = i % n.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] =
arr.zipWithIndex.collect { case (a, i) if (i + 1) % n != 0 => a }
This will make it
def DropNthItem(a: Array[String], n: Int): Array[String] =
a.zipWithIndex.filter(_._2 % n != 0).map(_._1)
If you're looking for performance (since you're using an ArrayBuffer), you might as well track the index with a var, manually increment it, and check it with an if to filter out n-multiple-indexed values.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] = {
val buf = new scala.collection.mutable.ArrayBuffer[A]
var i = 0
for(a <- arr) {
if((i + 1) % n != 0) buf += a
i += 1
}
buf.toArray
}
It's faster still if we traverse the original array as an iterator using a while loop.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] = {
val buf = new scala.collection.mutable.ArrayBuffer[A]
val it = arr.iterator
var i = 0
while(it.hasNext) {
val a = it.next
if((i + 1) % n != 0) buf += a
i += 1
}
buf.toArray
}
I'd go with something like this;
def dropEvery[A](arr: Seq[A], n: Int) = arr.foldLeft((Seq.empty[A], 0)) {
case ((acc, idx), _) if idx == n - 1 => (acc, 0)
case ((acc, idx), el) => (acc :+ el, idx + 1)
}._1
// example: dropEvery(1 to 100, 3)
// res0: Seq[Int] = List(1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 100)
This is efficient since it requires a single pass over the array and removes every nth element from it – I believe that is easy to see.
The first case matches when idx == n - 1 and ignores the element at that index, and passes over the acc and resets the count to 0 for the next element.
If the first case doesn't match, it adds the element to the end of the acc and increments the count by 1.
Since you're willing to get rid of the Java hangover, you might want to use implicit classes to use this in a very nice way:
implicit class MoreFuncs[A](arr: Seq[A]) {
def dropEvery(n: Int) = arr.foldLeft((Seq.empty[A], 0)) {
case ((acc, idx), _) if idx == n - 1 => (acc, 0)
case ((acc, idx), el) => (acc :+ el, idx + 1)
}._1
}
// example: (1 to 100 dropEvery 1) == Nil (: true)
I want to generate sequance of all fibonacci numbers, that less then 10000
For example, this will generate 40 fibonacci numbers. But i want to stop generate them with some condition. How can i do this?
def main(args: Array[String]) {
val fibonacciSequence = for(i <- 1 to 40) yield fibonacci(i)
println(fibonacciSequence)
}
def fibonacci(i: Int) : Int = i match {
case 0 => 0
case 1 => 1
case _ => fibonacci(i - 1) + fibonacci(i - 2);
}
I want something like this: for(i <- 1 to ?; stop if fibonacci(i) > 100000)
This method, involving lazy infinite collection calculation, could produce suitable result:
import scala.Numeric.Implicits._
def fibonacci[N: Numeric](a: N, b: N): Stream[N] = a #:: fibonacci(b, a + b)
so
fibonacci(0L,1L).takeWhile(_ < 1000L).toList
yields
List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987)
If you don't want to use intermediate value to cache collection of proper type and init, you could just declare a val like this:
val fib: Stream[Long] = 0 #:: 1 #:: (fib zip fib.tail map { case (a, b) => a + b })
Using iterators and memoization (computing the current result based in the latest ones, not recomputing what has already been done), (method from Rosetta, similar to Odomontois's streams),
def fib() = Iterator.iterate((0,1)){ case (a,b) => (b,a+b)}.map(_._1)
To get the first nth values consider for instance,
def nfib(n: Int) = fib().zipWithIndex.takeWhile(_._2 < n).map(_._1).toArray
To get consecutive values up to a given condition or predicate,
def pfib(p: Int => Boolean) = fib().takeWhile(p).toArray
Thus, for example
nfib(10)
Array(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
pfib( _ < 55)
Array(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
Assuming there the list of numbers and a range value, I want to group them into groups, in which the item in each group is within the range from the lowest number, and sort them.
For example, I have a list val l = List(1,2,3,4,5,6,7,8,9,10) and the range val range = 2. Then, I'm looking for a way to output the following result: result = List(List(1,2,3), List(4,5,6), List(7,8,9), List(10)). Which means if range = 0 then only identical numbers are in the same group.
At the moment, I use the following method
val minVal = l.min
val range1 = (minVal + range).toDouble
val groups = l.foldLeft(Map[Int, List[Int]]())((result, num) => {
val numRange = math.ceil(num / range1).toInt
if (result.contains(numRange)) {
result.updated(numRange, num :: result(numRange))
} else {
result.updated(numRange, List(num))
}
})
groups.keys.toList.sortBy(k => k).map(groups(_))
It works in most cases except when range = 0 and slowestNum != 1. E.g. for the list val l = List(2,3,4,5,6,7,8,9,10) and the range val range = 2, the result is List(List(2), List(4, 3), List(6, 5), List(8, 7), List(10, 9)).
So, I wonder if there is any other way to solve this problem.
Why complicate?
def coll(l: List[Int], range: Int): List[List[Int]] =
if (l.isEmpty) Nil else {
val (b, a) = l.span((l.head - range to l.head + range).contains)
b :: coll(a, range)
}
So, this algorithm collects numbers into a group until the number are in the plus/minus range.
val list = List(7,4,1,9,10,20,50,52,30)
coll(list, 3)
res6: List[List[Int]] = List(List(7, 4), List(1), List(9, 10), List(20), List(50, 52), List(30))
If you want each group by itself sorted, then call res6.map(_.sorted).
I would personally do something like this:
val l = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val range = 2
val result = l.sorted.foldLeft(List[List[Int]]()) {
(cur, x) =>
if ((cur nonEmpty) && x - cur.head.last <= range) (x :: cur.head) :: cur.tail
else List(x) :: cur
}
although there may be some clever and neat ways. Of course, you can always do if you want the result ordered:
val ret = result.reverse.map(_.reverse)
Hope it helped!
Try something like this
val groupedList = l.map(i => l.filter(s => s >= i && s - i <= range))
groupedList.foldLeft(List(groupedList.head)) {
case (r, c) => if (r.last.last < c.head) r ++ List(c) else r
}
For range 2
val l = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val range = 2
val groupedList = l.map(i => l.filter(s => s >= i && s - i <= range))
groupedList.foldLeft(List(groupedList.head)) {
case (r, c) => if (r.last.last < c.head) r ++ List(c) else r
}
//> res0: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9), List(10))
For range 0
val l = List(1,1,1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val range = 0
val groupedList = l.map(i => l.filter(s => s >= i && s - i <= range))
groupedList.foldLeft(List(groupedList.head)) {
case (r, c) => if (r.last.last < c.head) r ++ List(c) else r
}
//> res0: List[List[Int]] = List(List(1, 1, 1), List(2), List(3), List(4), List(5), List(6), List(7), List(8), List(9), List(10))
I'm trying to write a function which takes an Int and returns all of the prime numbers up to and including that Int.
for example "list of primes for 8" = List(3,5,7)
This is what I have so far :
def isPrime(i: Int): Boolean = {
if (i <= 1)
false
else if (i == 2)
true
else
!(2 to (i - 1)).exists(x => i % x == 0)
} //> isPrime: (i: Int)Boolean
def getListOfPrimesToN(n : Int) = {
}
for the function getListOfPrimesToN I plan to
1. create a List "l" of size n and populate it with elements ranging from 0 to n.
2. call map function of "l" and call isPrime for each element in List.
How to create the List of element 1 to N ?
Any alternative solutions for returning all of the prime numbers up to and including an Int N welcome.
You can solve this with infinite streams. If you had a stream primes of all the primes, you could just say primes.takeWhile(_ <= n) to get the primes up to and including n.
To get all the primes, you start with a stream of all the numbers starting from 2, the first prime. You can then skip all the even numbers since those are definitely not prime. Then you can skip all the other numbers that are not prime.
val primes = 2 #:: Stream.from(3,2).filter(isPrime)
Now you just need isPrime to check if a given number is prime. A number is prime if it is not divisible by any smaller prime. We actually need only consider primes whose square is not greater than the number (since, logically, a composite number's smallest prime factor can't be larger than its square root).
def isPrime(n: Int): Boolean =
primes.takeWhile(p => p*p <= n).forall(n % _ != 0)
Check this in the REPL:
scala> primes.takeWhile(_ <= 8).toList
res0: List[Int] = List(2, 3, 5, 7)
Caveat: This only works for positive numbers smaller than Integer.MAX_VALUE.
An implementation of the Sieve of Eratosthenes algorithm for efficiently finding prime numbers up to a given value N includes the following, (fixed and improved on this SO answer),
implicit class Sieve(val N: Int) extends AnyVal {
def primesUpTo() = {
val isPrime = collection.mutable.BitSet(2 to N: _*) -- (4 to N by 2)
for (p <- 2 +: (3 to Math.sqrt(N).toInt by 2) if isPrime(p)) {
isPrime --= p*p to N by p
}
isPrime.toImmutable
}
}
Hence
10.primesUpTo.toList
res: List(2, 3, 5, 7)
11.primesUpTo.toList
res: List(2, 3, 5, 7, 11)
Note Find prime numbers using Scala. Help me to improve for additional ideas and discussion.
Here is the code based on your:
scala> def isPrime(n: Int): Boolean =
| n >= 2 && (2 to math.sqrt(n).toInt).forall(n%_ != 0)
isPrime: (n: Int)Boolean
scala> def getListOfPrimesToN(n: Int): List[Int] =
| List.range(2, n+1) filter isPrime
getListOfPrimesTON: (n: Int)List[Int]
scala> getListOfPrimesToN(97)
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)
Here is another solution using Stream:
scala> def getListOfPrimesToN(n: Int): List[Int] = {
| lazy val ps: Stream[Int] = 2 #:: Stream.from(3)
.filter(x => ps.takeWhile(p => p*p <= x).forall(x%_ != 0))
| ps.takeWhile(_ <= n).toList
| }
getListOfPrimesToN: (n: Int)List[Int]
scala> getListOfPrimesToN(97)
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)
How about this.
def getPrimeUnder(n: Int) = {
require(n >= 2)
val ol = 3 to n by 2 toList // oddList
def pn(ol: List[Int], pl: List[Int]): List[Int] = ol match {
case Nil => pl
case _ if pl.exists(ol.head % _ == 0) => pn(ol.tail, pl)
case _ => pn(ol.tail, ol.head :: pl)
}
pn(ol, List(2)).reverse
}
In one invocation to map we construct a collection of tuples, for instance like this,
val a = (1 to 5).map { x => (x, x*10) }
a: Vector((1,10), (2,20), (3,30), (4,40), (5,50))
and then we extract the first and second elements into two separate, immutable collections
val b1 = a.map {_._1}
b1: Vector(1, 2, 3, 4, 5)
val b2 = a.map {_._2}
b2: Vector(10, 20, 30, 40, 50)
How to obtain b1 and b2 by iterating over the initial collection once only,
val (b1,b2) = (1 to 5).map { x => /* ??? */ }
Use unzip:
scala> (1 to 5).unzip { x => x -> x * 3 }
res0: (Vector(1, 2, 3, 4, 5),Vector(3, 6, 9, 12, 15))
Note that Ionuț G. Stan's answer is the same as:
(1 to 5).unzip{ x => (x, x * 3)}
which makes how to get triples of collections back even clearer:
(1 to 5).unzip3{ x => (x, x * 3, x * 10)}