I am writing a recursive function to check if a non-negative Integer is Prime in SCALA. My function takes two inputs to do so. Here is my code:
import io.StdIn._
def isPrime (x:Int, i:Int): Boolean = {
if (i < 3) {
true
}else if (x % i == 0) {
false
}else{
isPrime(x,i-1)
}
}
print("Enter a number to check if it is a prime number: " )
val num1 = readInt()
println(isPrime(num1,num1-1))
My question is that is there a way for me to take one input as the parameter for the function? The code has to use a recursive function. I know that there are more effective ways to check if a number is prime (using iteration perhaps), but I'm just doing this as a practice problem.
It is perfectly fine, I'd say even standard practice, to wrap recursive functions with a calling function. For example:
def isPrime( x:Int ) = {
def recIsP( n:Int, i:Int ) : Boolean = i == n || n % i != 0 && recIsP(n, i + 1)
recIsP(x,2)
}
isPrime(3301)
One option is to make an inner method
def isPrime(x:Int): Boolean = {
def loop(i: Int): Boolean =
if (i<3 ) {
true
} else if (x % i==0) {
false
} else {
isPrime(x,i-1)
}
loop(x, x - 1)
}
another option is to make a default parameter. Those can't refer back to the previous parameter, so you'll have to use a workaround. Here I pass some j, and make i = x - j, so I can just increment j starting from 1
def isPrime(x: Int, j: Int = 1): Boolean = {
val i = x - j
if (i < 3) {
true
} else if (x % i==0) {
false
} else {
isPrime(x, j + 1)
}
}
Unrelatedly, there is a bug in your code: 4 should not be prime.
Could you please run println(func("ctnkh"))? I got 4, but isn't it supposed to be 5?
def func(s: String): Int = {
if(s == "")
return 0
val len = s.length
var max = Int.MinValue
for(i <- 0 until len)
for(j <- i+1 to len) {
val ss = s.substring(i, j)
if(ss.mkString == ss.toSet.mkString) {
if(ss.length > max)
max = ss.length
}
}
max
}
I'll appreciate any of your hints
because ss.toSet.mkString will be in a different order than ss.mkString
for ex. try the following:
val str = "ctnkh"
println(str.mkString)
println(str.toSet.mkString)
output is:
ctnkh
ntchk
so the result will never be 5
edit: as mentioned in the comments you can't rely on the order of the characters in the Set as this order is not predictable.
You probably meant: ss.distinct. It drops all duplicate characters from the string, and preserves the order of the remaining characters.
def func(s: String): Int = {
val len = s.length
var max = 0
for(i <- 0 until len) {
for(j <- i+1 to len) {
val ss = s.substring(i, j)
if(ss == ss.distinct) {
max = max.max(ss.length)
}
}
}
max
}
println(func("ctnkh"))
gives 5, as you expected.
For your test, it's sufficient to check size:
if (ss.length == ss.toSet.size) max = max.max(ss.length)
since iteration order is extraneous.
Recently, I've started learning Scala for school project. The assignment says that we have to delete elements of an unsorted array, without leaving "holes" in the array. I've made the following code:
private var _list = new Array[NAW](20)
private var _highestIndex = 0;
def removeAllbyName(name : String): Unit = {
for(i <- 0 until _highestIndex){
if(_list(i).name == name)
deleteByIndex(i)
}
}
def deleteByIndex(i : Int) : Unit = {
if(i != -1){
for(x <- i until _highestIndex){
_list(x) = _list(x + 1)
}
_highestIndex -= 1
}
}
I filled the array with 10 instances, the highestIndex will be 10 and after the first removal 9. But the for-loop still keeps counting to 9, which results in a null-pointer exception, even though we use "until". The debugger does recognise that _highestIndex is 9. Can somebody please explain why this is happening?
Thanks in advance!
0 until _highestIndex only gets evaluated once.
for (i <- 0 until _highestIndex) {
if (_list(i).name == name)
deleteByIndex(i)
}
Is equivalent to:
val range = 0 until _highestIndex
for (i <- range) {
if (_list(i).name == name)
deleteByIndex(i)
}
You can see that the range is determined only once.
You could try using a while loop instead, or a guard in your if statement.
Change your for-loop inside deleteByIndex like this to avoid exception
for(
x <- i until highestIndex
if (x + 1) < highestIndex
)
list(x) = list(x + 1)
I've got the following Scala code(ported from a Java one):
import scala.util.control.Breaks._
object Main {
def pascal(col: Int, row: Int): Int = {
if(col > row) throw new Exception("Coloumn out of bound");
else if (col == 0 || col == row) 1;
else pascal(col - 1, row - 1) + pascal(col, row - 1);
}
def balance(chars: List[Char]): Boolean = {
val string: String = chars.toString()
if (string.length() == 0) true;
else if(stringContains(")", string) == false && stringContains("(", string) == false) true;
else if(stringContains(")", string) ^ stringContains("(", string)) false;
else if(getFirstPosition("(", string) > getFirstPosition(")", string)) false;
else if(getLastPosition("(", string) > getLastPosition(")", string)) false;
else if(getCount("(", string) != getCount(")", string)) false;
var positionOfFirstOpeningBracket = getFirstPosition("(", string);
var openingBracketOccurences = 1; //we already know that at the first position there is an opening bracket so we are incrementing it right away with 1 and skipping the firstPosition variable in the loop
var closingBracketOccurrences = 0;
var positionOfClosingBracket = 0;
breakable {
for(i <- positionOfFirstOpeningBracket + 1 until string.length()) {
if (string.charAt(i) == ("(".toCharArray())(0)) {
openingBracketOccurences += 1;
}
else if(string.charAt(i) == (")".toCharArray())(0) ) {
closingBracketOccurrences += 1;
}
if(openingBracketOccurences - closingBracketOccurrences == 0) { //this is an important part of the algorithm. if the string is balanced and at the current iteration opening=closing that means we know the bounds of our current brackets.
positionOfClosingBracket = i; // this is the position of the closing bracket
break;
}
}
}
val insideBrackets: String = string.substring(positionOfFirstOpeningBracket + 1, positionOfClosingBracket)
balance(insideBrackets.toList) && balance( string.substring(positionOfClosingBracket + 1, string.length()).toList)
def getFirstPosition(character: String, pool: String): Int =
{
for(i <- 0 until pool.length()) {
if (pool.charAt(i) == (character.toCharArray())(0)) {
i;
}
}
-1;
}
def getLastPosition(character: String, pool: String): Int =
{
for(i <- pool.length() - 1 to 0 by -1) {
if (pool.charAt(i) == (character.toCharArray())(0)) {
i;
}
}
-1;
}
//checks if a string contains a specific character
def stringContains(needle: String, pool: String): Boolean = {
for(i <- 0 until pool.length()) {
if(pool.charAt(i) == (needle.toCharArray())(0)) true;
}
false;
}
//gets the count of occurrences of a character in a string
def getCount(character: String, pool: String) = {
var count = 0;
for ( i <- 0 until pool.length()) {
if(pool.charAt(i) == (character.toCharArray())(0)) count += 1;
}
count;
}
}
}
The problem is that the Scala IDE(lates version for Scaal 2.10.1) gives the following error at line 78(on which there is a closin brace): "Type mismatch; Found Unit, expected Boolean". I really can't understand what the actual problem is. The warning doesn't give any information where the error might be.
In Scala (and most other functional languages) the result of a function is the value of the last expression in the block. The last expression of your balance function is the definition of function getCount, which is of type Unit (the Scala equivalent of void), and your function is declared as returning a Boolean, thus the error.
In practice, you've just screwed up your brackets, which would be obvious if you used proper indentation (Ctrl+A, Ctrl+Shift+F in scala-ide).
To make it compile, you can put the following two lines at the end of the balance method instead of in the middle:
val insideBrackets: String = string.substring(positionOfFirstOpeningBracket + 1, positionOfClosingBracket)
balance(insideBrackets.toList) && balance(string.substring(positionOfClosingBracket + 1, string.length()).toList)
You would also have to put the inner functions at the top of balance I think -- such as getCount.
I came across this problem from CodeChef. The problem states the following:
A positive integer is called a palindrome if its representation in the
decimal system is the same when read from left to right and from right
to left. For a given positive integer K of not more than 1000000
digits, write the value of the smallest palindrome larger than K to
output.
I can define a isPalindrome method as follows:
def isPalindrome(someNumber:String):Boolean = someNumber.reverse.mkString == someNumber
The problem that I am facing is how do I loop from the initial given number and break and return the first palindrome when the integer satisfies the isPalindrome method? Also, is there a better(efficient) way to write the isPalindrome method?
It will be great to get some guidance here
If you have a number like 123xxx you know, that either xxx has to be below 321 - then the next palindrom is 123321.
Or xxx is above, then the 3 can't be kept, and 124421 has to be the next one.
Here is some code without guarantees, not very elegant, but the case of (multiple) Nines in the middle is a bit hairy (19992):
object Palindrome extends App {
def nextPalindrome (inNumber: String): String = {
val len = inNumber.length ()
if (len == 1 && inNumber (0) != '9')
"" + (inNumber.toInt + 1) else {
val head = inNumber.substring (0, len/2)
val tail = inNumber.reverse.substring (0, len/2)
val h = if (head.length > 0) BigInt (head) else BigInt (0)
val t = if (tail.length > 0) BigInt (tail) else BigInt (0)
if (t < h) {
if (len % 2 == 0) head + (head.reverse)
else inNumber.substring (0, len/2 + 1) + (head.reverse)
} else {
if (len % 2 == 1) {
val s2 = inNumber.substring (0, len/2 + 1) // 4=> 4
val h2 = BigInt (s2) + 1 // 5
nextPalindrome (h2 + (List.fill (len/2) ('0').mkString)) // 5 + ""
} else {
val h = BigInt (head) + 1
h.toString + (h.toString.reverse)
}
}
}
}
def check (in: String, expected: String) = {
if (nextPalindrome (in) == expected)
println ("ok: " + in) else
println (" - fail: " + nextPalindrome (in) + " != " + expected + " for: " + in)
}
//
val nums = List (("12345", "12421"), // f
("123456", "124421"),
("54321", "54345"),
("654321", "654456"),
("19992", "20002"),
("29991", "29992"),
("999", "1001"),
("31", "33"),
("13", "22"),
("9", "11"),
("99", "101"),
("131", "141"),
("3", "4")
)
nums.foreach (n => check (n._1, n._2))
println (nextPalindrome ("123456678901234564579898989891254392051039410809512345667890123456457989898989125439205103941080951234566789012345645798989898912543920510394108095"))
}
I guess it will handle the case of a one-million-digit-Int too.
Doing reverse is not the greatest idea. It's better to start at the beginning and end of the string and iterate and compare element by element. You're wasting time copying the entire String and reversing it even in cases where the first and last element don't match. On something with a million digits, that's going to be a huge waste.
This is a few orders of magnitude faster than reverse for bigger numbers:
def isPalindrome2(someNumber:String):Boolean = {
val len = someNumber.length;
for(i <- 0 until len/2) {
if(someNumber(i) != someNumber(len-i-1)) return false;
}
return true;
}
There's probably even a faster method, based on mirroring the first half of the string. I'll see if I can get that now...
update So this should find the next palindrome in almost constant time. No loops. I just sort of scratched it out, so I'm sure it can be cleaned up.
def nextPalindrome(someNumber:String):String = {
val len = someNumber.length;
if(len==1) return "11";
val half = scala.math.floor(len/2).toInt;
var firstHalf = someNumber.substring(0,half);
var secondHalf = if(len % 2 == 1) {
someNumber.substring(half+1,len);
} else {
someNumber.substring(half,len);
}
if(BigInt(secondHalf) > BigInt(firstHalf.reverse)) {
if(len % 2 == 1) {
firstHalf += someNumber.substring(half, half+1);
firstHalf = (BigInt(firstHalf)+1).toString;
firstHalf + firstHalf.substring(0,firstHalf.length-1).reverse
} else {
firstHalf = (BigInt(firstHalf)+1).toString;
firstHalf + firstHalf.reverse;
}
} else {
if(len % 2 == 1) {
firstHalf + someNumber.substring(half,half+1) + firstHalf.reverse;
} else {
firstHalf + firstHalf.reverse;
}
}
}
This is most general and clear solution that I can achieve:
Edit: got rid of BigInt's, now it takes less than a second to calculate million digits number.
def incStr(num: String) = { // helper method to increment number as String
val idx = num.lastIndexWhere('9'!=, num.length-1)
num.take(idx) + (num.charAt(idx)+1).toChar + "0"*(num.length-idx-1)
}
def palindromeAfter(num: String) = {
val lengthIsOdd = num.length % 2
val halfLength = num.length / 2 + lengthIsOdd
val leftHalf = num.take(halfLength) // first half of number (including central digit)
val rightHalf = num.drop(halfLength - lengthIsOdd) // second half of number (also including central digit)
val (newLeftHalf, newLengthIsOdd) = // we need to calculate first half of new palindrome and whether it's length is odd or even
if (rightHalf.compareTo(leftHalf.reverse) < 0) // simplest case - input number is like 123xxx and xxx < 321
(leftHalf, lengthIsOdd)
else if (leftHalf forall ('9'==)) // special case - if number is like '999...', then next palindrome will be like '10...01' and one digit longer
("1" + "0" * (halfLength - lengthIsOdd), 1 - lengthIsOdd)
else // other cases - increment first half of input number before making palindrome
(incStr(leftHalf), lengthIsOdd)
// now we can create palindrome itself
newLeftHalf + newLeftHalf.dropRight(newLengthIsOdd).reverse
}
According to your range-less proposal: the same thing but using Stream:
def isPalindrome(n:Int):Boolean = n.toString.reverse == n.toString
def ints(n: Int): Stream[Int] = Stream.cons(n, ints(n+1))
val result = ints(100).find(isPalindrome)
And with iterator (and different call method, the same thing you can do with Stream, actually):
val result = Iterator.from(100).find(isPalindrome)
But as #user unknown stated, it is direct bruteforce and not practical with large numbers.
To check if List of Any Type is palindrome using slice, without any Loops
def palindrome[T](list: List[T]): Boolean = {
if(list.length==1 || list.length==0 ){
false
}else {
val leftSlice: List[T] = list.slice(0, list.length / 2)
var rightSlice :List[T]=Nil
if (list.length % 2 != 0) {
rightSlice = list.slice(list.length / 2 + 1, list.length).reverse
} else {
rightSlice = list.slice(list.length / 2, list.length).reverse
}
leftSlice ==rightSlice
}
}
Though the simplest solution would be
def palindrome[T](list: List[T]): Boolean = {
list == list.reverse
}
You can simply use the find method on collections to find the first element matching a given predicate:
def isPalindrome(n:Int):Boolean = n.toString.reverse == n.toString
val (start, end) = (100, 1000)
val result: Option[Int] = (start to end).find(isPalindrome)
result foreach println
>Some(101)
Solution to verify if a String is a palindrome
This solution doesn't reverse the String. However I am not sure that it will be faster.
def isPalindrome(s:String):Boolean = {
s.isEmpty ||
((s.last == s.head) && isPalindrome(s.tail.dropRight(1)))
}
Solution to find next palindrome given a String
This solution is not the best for scala (pretty the same as Java solution) but it only deals with Strings and is suitable for large numbers
You just have to mirror the first half of the number you want, check if it is higher than the begin number, otherwise, increase by one the last digit of the first half and mirror it again.
First, a function to increment the string representation of an int by 1:
def incrementString(s:String):String = {
if(s.nonEmpty){
if (s.last == '9')
incrementString(s.dropRight(1))+'0'
else
s.dropRight(1) + (s.last.toInt +1).toChar
}else
"1"
}
Then, a function to compare to string representation of ints: (the function 'compare' doesn't work for that case)
/* is less that 0 if x<y, is more than 0 if x<y, is equal to 0 if x==y */
def compareInts(x:String, y:String):Int = {
if (x.length !=y.length)
(x.length).compare(y.length)
else
x.compare(y)
}
Now the function to compute the next palindrome:
def nextPalindrome(origin_ :String):String = {
/*Comment if you want to have a strictly bigger number, even if you already have a palindrome as input */
val origin = origin_
/* Uncomment if you want to have a strictly bigger number, even if you already have a palindrome as input */
//val origin = incrementString(origin_)
val length = origin.length
if(length % 2 == 0){
val (first, last) = origin.splitAt(length/2);
val reversed = first.reverse
if (compareInts(reversed,last) > -1)
first ++ reversed
else{
val firstIncr = incrementString(first)
firstIncr ++ firstIncr.reverse
}
} else {
val (first,last) = origin.splitAt((length+1)/2)
val reversed = first.dropRight(1).reverse
if (compareInts(reversed,last) != -1)
first ++ reversed
else{
val firstIncr = incrementString(first)
firstIncr ++ firstIncr.dropRight(1).reverse
}
}
}
You could try something like this, I'm using basic recursive:
object Palindromo {
def main(args: Array[String]): Unit = {
var s: String = "arara"
println(verificaPalindromo(s))
}
def verificaPalindromo(s: String): String = {
if (s.length == 0 || s.length == 1)
"true"
else
if (s.charAt(0).toLower == s.charAt(s.length - 1).toLower)
verificaPalindromo(s.substring(1, s.length - 1))
else
"false"
}
}
#tailrec
def palindrome(str: String, start: Int, end: Int): Boolean = {
if (start == end)
true
else if (str(start) != str(end))
false
else
pali(str, start + 1, end - 1)
}
println(palindrome("arora", 0, str.length - 1))