How to remove' identifier expected but integer literal found error' in Scala? - scala

I am trying to build a function to identify if a an expresson has balanced parenthesis or not.
My problem is that I am getting this error on my functions for the variables opening_index and closing_index :
Error:(3, 30) identifier expected but integer literal found.
var opening_index: Int =-1
Error:(6, 30) identifier expected but integer literal found.
var closing_index: Int =-1
Error:(34, 30) identifier expected but integer literal found.
var opening_index: Int =-1
Error:(37, 30) identifier expected but integer literal found.
var closing_index: Int =-1
I have been googling my error for the last hour without finding any valuable cluses.
Here is my code:
object Test
{
def balance(chars: List[Char]): Boolean=
{
var opening_index: Int =-1
var closing_index: Int =-1
opening_index=chars.indexOf('(')
closing_index=chars.indexOf(')')
if (opening_index ==-1 && closing_index==-1)
{
true
}
if (closing_index>-1 && opening_index>-1)
{
if (closing_index<=opening_index) return(false)
else
{
balance(chars.drop(closing_index).drop(opening_index))
}
}
else
return (false)
}
}

The tokenizer doesn't know, where a token ends or starts. Use some delimiters, which makes the code more readable for humans too:
object Test {
def balance(chars: List[Char]): Boolean =
{
var opening_index: Int = -1
var closing_index: Int = -1
opening_index=chars.indexOf ('(')
closing_index=chars.indexOf (')')
if (opening_index == -1 && closing_index == -1)
{
true
}
if (closing_index > -1 && opening_index > -1)
{
if (closing_index <= opening_index)
return false
else
balance (chars.drop (closing_index).drop (opening_index))
}
else
return false
}
}
Since you only initialize your vars to reinitialize them directly again, you can easily earn some functional points by declaring them as vals:
def balance (chars: List[Char]): Boolean =
{
val opening_index: Int = chars.indexOf ('(')
val closing_index: Int = chars.indexOf (')')
For recursive calls, you don't have to bother - those generate a new pair of values which don't interfere with those of the calling context.
You might also note, that return statements dont need a function-call-look with parens return (false) but can be written as return false, and even the return keyword is most of the time superflous.
object Test {
def balance (chars: List[Char]): Boolean =
{
val opening_index: Int = chars.indexOf ('(')
val closing_index: Int = chars.indexOf (')')
if (opening_index == -1 && closing_index == -1)
{
true // but note the else in the 2nd next line
}
else if (closing_index > -1 && opening_index > -1)
{
if (closing_index <= opening_index)
false
else
balance (chars.drop (closing_index).drop (opening_index))
}
else
false
}
}

When Scala sees =-1, it gets tokenized (split) not as = -1 (as in other languages you may be familiar with), but as =- 1, since =- is a perfectly fine identifier in Scala.
Since = hasn't been seen, the entire Int =- 1 must be a type. By infix notation for types, it's equivalent to =-[Int, 1]. Except 1 here must be a type. To be a type it should start with an identifier, and that's what the error message is saying. If you fixed that, it would complain about unknown =- type next.

This can be simplified by just counting how many of each there are and seeing if the numbers match up:
def balance (chars: List[Char]): Boolean = {
val opening = chars.count(_ == '(')
val closing = chars.count(_ == ')')
opening == closing
}
balance(List('(', ')', '(', ')', '(')) //false
balance(List('(', ')', '(', ')')) //true
If you want the balanced parentheses to be in order, you can do it recursively:
def balance(chars: List[Char], open: Int = 0): Boolean = {
if (chars.isEmpty)
open == 0
else if (chars.head == '(')
balance(chars.tail, open + 1)
else if (chars.head == ')' && open > 0)
balance(chars.tail, open - 1)
else
balance(chars.tail, open)
}
val x = "(apple + pear + (banana)))".toList
balance(x) //true
val y = "(()(".toList
balance(y) //false
This goes through every element of the list and adds/subtracts to/from a variable called open until the list is empty, at which point if open is 0 it returns true otherwise it returns false.

Related

Scala seems to require 'return' keyword for recursive functions

I'm new to Scala and know that the 'return' keyword is redundant. However, when writing a recursive function, the control doesn't return from a call stack when the desired condition is met if the 'return' keyword is missing.
Below is a code to check for balanced parentheses -
Using 'return' (works fine):
def balance(chars: List[Char]): Boolean = {
def parenBalance(char : List[Char]) :Boolean = {
parenBalanceRecur(char, 0 , 0)
}
def parenBalanceRecur(charSequence: List[Char], itr : Int, imbalance : Int) : Boolean = {
if (imbalance < 0) then return false
if (itr == charSequence.length ) {
if (imbalance == 0) then return true else return false
}
if (charSequence(itr) == '(') {
parenBalanceRecur(charSequence, (itr + 1), (imbalance + 1))
}
else if (charSequence(itr) == ')') {
parenBalanceRecur(charSequence, itr + 1, imbalance -1)
}
else {
parenBalanceRecur (charSequence, itr +1, imbalance)
}
}
parenBalance(chars)
}
Without return (Successfully computes #1, but doesn't return, fails at #2 with IndexOutOfBoundsException):
def balance(chars: List[Char]): Boolean = {
def parenBalance(char : List[Char]) :Boolean = {
parenBalanceRecur(char, 0 , 0)
}
def parenBalanceRecur(charSequence: List[Char], itr : Int, imbalance : Int) : Boolean = {
if (imbalance < 0) then false
if (itr == charSequence.length ) {
if (imbalance == 0) then true else false // #1
}
if (charSequence(itr) == '(') { // # 2
parenBalanceRecur(charSequence, (itr + 1), (imbalance + 1))
}
else if (charSequence(itr) == ')') {
parenBalanceRecur(charSequence, itr + 1, imbalance -1)
}
else {
parenBalanceRecur (charSequence, itr +1, imbalance)
}
}
parenBalance(chars)
}
Is this specific to tail recursion? Please help me understand this.
As mentioned in some comments, you can not just short circuit the path and return a value without the return keyword. return is not needed only at the last value of the method. In any case, usually, it's a good practice to avoid short circuits with multiple returns in a method.
In your example, adding two else you can construct the path down to the last value of each possible output without using the return keyword:
def balance(chars: List[Char]): Boolean = {
def parenBalance(char : List[Char]) :Boolean = {
parenBalanceRecur(char, 0 , 0)
}
#tailrec
def parenBalanceRecur(charSequence: List[Char], itr : Int, imbalance : Int) : Boolean = {
if (imbalance < 0) then false
else if (itr == charSequence.length ) {
if (imbalance == 0) then true else false // #1
}
else if (charSequence(itr) == '(') { // # 2
parenBalanceRecur(charSequence, (itr + 1), (imbalance + 1))
}
else if (charSequence(itr) == ')') {
parenBalanceRecur(charSequence, itr + 1, imbalance -1)
}
else {
parenBalanceRecur (charSequence, itr +1, imbalance)
}
}
parenBalance(chars)
}
As currently implemented, parenBalanceRecur() has 3 top-level if expressions, they each evaluate to a boolean value, but the rule in scala is that only the last expression of the function is the return value of the function => the first two are simply ignored.
=> in your second implementation:
def parenBalanceRecur(charSequence: List[Char], itr : Int, imbalance : Int) : Boolean = {
if (imbalance < 0) then false
if (itr == charSequence.length ) {
if (imbalance == 0) then true else false // #1
}
if (charSequence(itr) == '(') { // # 2
parenBalanceRecur(charSequence, (itr + 1), (imbalance + 1))
}
else if (charSequence(itr) == ')') {
parenBalanceRecur(charSequence, itr + 1, imbalance -1)
}
else {
parenBalanceRecur (charSequence, itr +1, imbalance)
}
}
parenBalance(chars)
}
The first expression if (imbalance < 0) then false will evaluate to either true or false, but this expression is disconnected from the rest of the code => the function is not doing anything with that boolean. We could as well write val thisAchievesNothing = if (imbalance < 0) then false. Our thisAchievesNothing will hold some value, which is valid syntax, but is not very useful.
Likewise, this:
if (itr == charSequence.length ) {
if (imbalance == 0) then true else false // #1
}
will evaluate to another boolean that is equally ignored.
Finally, the last if... else if... else will also evaluate to yet another boolean, and since this one is the last expression of the function, that and that only will be the returned value.
Try to re-writing parenBalanceRecur as one single if.. else if... else if ... expression instead of 3, and then the behavior will be the same as the implementation that uses return.
(we tend to avoid return since it's a statement that does something, whereas the habit is to write functions/expression that are some value)
Besides the accepted answer, some things worth considering:
use #tailrec, so your recursive method gets tail-call optimized by the compiler. Otherwise it can produce stack overflow for very large lists. (Although this might not be the case here, always consider using this annotation when implementing tail-recursive methods).
List in Scala is a singly-linked list, so it's not indexed. Using cs(iter) on each recursive call makes your method get the element in linear time for every index. That means you'll get O(n^2) complexity. As an alternative, either use chars: Array[Char] which is indexed-based and gives you each element in O(1) or continue using list but switch to pattern match instead.
minor things: redundant curly braces from if expressions with only a single statement inside; parenBalance can be removed and call directly parenBalanceRecur(char, 0 , 0) as the last statement in balance; use default values for parenBalanceRecur.
My suggestions in code:
def isBalanced(chars: List[Char]): Boolean = {
#tailrec
def balance(cs: List[Char], imbalances: Int = 0): Boolean =
if (imbalances < 0) false
else cs match {
case Nil => imbalances == 0
case x :: xs =>
if (x == '(') balance(xs, imbalances + 1)
else if (x == ')') balance(xs, imbalances - 1)
else balance(xs, imbalances)
}
balance(chars)
}
println(isBalanced("()".toList)) // true
println(isBalanced("()(())".toList)) // true
println(isBalanced(")(".toList)) // false
println(isBalanced("(()))".toList)) // false
println(isBalanced("((((()))))".toList)) // true

How to extend binary with Scala?

I am trying to complete the below exercise:
I have attempted it below, but my code is not acting as expected.
def extend(p: Long): Long = {
var e = p.toBinaryString
if ( e.count(_== '1') % 2 == 0) {
e="0"+e
}else {
e="1"+e
}
e.toLong
}
What am I doing wrong here? I don't understand how I'm supposed to change binary right Hex.
#Test def testExtend() {
assertEquals("extend(0x0000000000000000L)", 0x0000000000000000L, extend(0x0000000000000000L))
assertEquals("extend(0x0000000000000001L)", 0x8000000000000001L, extend(0x0000000000000001L))
assertEquals("extend(0x0000000000000011L)", 0x0000000000000011L, extend(0x0000000000000011L))
assertEquals("extend(0x8000000000000000L)", 0x0000000000000000L, extend(0x8000000000000000L))
assertEquals("extend(0x8000000000F00000L)", 0x0000000000F00000L, extend(0x8000000000F00000L))
assertEquals("extend(0x0000001000300000L)", 0x8000001000300000L, extend(0x0000001000300000L))
}
The first problem is that .toLong assumes that what's being converted is the String representation of a decimal value. So "10" is assumed to represent ten (decimal), not two (binary).
The next problem is that Long has a fixed length. You can't add an extra bit to it. You have to flip an existing bit.
def extend(p: Long): Long =
if (p.toBinaryString.count(_ == '1') % 2 == 0) p
else p ^ Long.MinValue
testing:
0x0000000000000000L == extend(0x0000000000000000L) //res0: Boolean = true
0x8000000000000001L == extend(0x0000000000000001L) //res1: Boolean = true
0x0000000000000011L == extend(0x0000000000000011L) //res2: Boolean = true
0x0000000000000000L == extend(0x8000000000000000L) //res3: Boolean = true
0x0000000000F00000L == extend(0x8000000000F00000L) //res4: Boolean = true
0x8000001000300000L == extend(0x0000001000300000L) //res5: Boolean = true

Ternary Operators in Scala

I would like to simplify this:
var countA: Int = 0
var countB: Int = 0
if (validItem) {
if (region.equalsIgnoreCase( "US" )) {
if (itemList > 0) {
countB = 1
} else {
countA = 1
}
} else {
countB = 1
}
} else {
countA = 1
}
How do I use ternary operator in scala.
You should not need to use a ternary operator in Scala. In Scala, if is an expression not a statement, you can say val x = if (b) 1 else 2.
The usage of var in your example also points to a problem, because you can usually avoid this when you use the if as an expression.
Let's try to break down the code to avoid the var, i.e. first remove all if statements that are not expressions with a corresponding else and always provide both values:
var countA: Int = ???
var countB: Int = ???
if (validItem) {
if (region.equalsIgnoreCase("US")) {
if (itemList > 0) {
countA = 0
countB = 1
} else {
countA = 1
countB = 0
}
} else {
countA = 0
countB = 1
}
} else {
countA = 1
countB = 0
}
Now we can define the condition for which either of countA and countB is one:
val isUS = region.equalsIgnoreCase("US")
val hasItems = itemList > 0
val isA = !validItem || (isUS && !hasItems)
val isB = !isA
// or: val isB = validItem && (!isUS || hasItems)
and then:
val countA = if (isA) 1 else 0
val countB = if (isB) 1 else 0
I think the short answer is that in Scala there is no ?: ternary operator. Although you can imitate the syntax using implicits (see #jwvh's answer), I think it doesn't really simplify anything.
There are a couple of important properties of the conventional ?:
it always has two branches
following from the previous property, the ternary operator always returns a value (this is mostly the point of using ?:)
val result: Int = if (true) 1 else 2
// result is 1
branches are evaluated lazily
if (true) 1 else (0/0) // returns 1
if (false) 0/0 else 2 // returns 2
// i.e. 0/0 is not evaluated
As you see, in Scala if-else (with else) construction satisfies these properties. This is not the case for if-else construction in some other languages, like C or Java, because it doesn't return a value.
So the bottom line is that in Scala you don't need a ternary operator, because you can just use if-else.
UPDATE
As Alexey Romanov mentions in the comments, if statement without else actually satisfies the first condition as well. When you write
val result = if (true) 1
it actually means if (true) 1 else (), so result will have type AnyVal instead of Int, because the return type of the if expression is the lowest common bound of the both branches (Int and Unit in this case).
This might be a bit confusing for a "newbie", but you could attach a ternary method to the Boolean class like so.
implicit class Ternary[T](condition: Boolean) {
def ??(a: => T, b: => T): T = if (condition) a else b
}
Usage:
(4 == 4)??("yes","no") // res0: String = yes
("abc".length < 2).??(1,0) // res1: Int = 0
List('c').isEmpty.??('X','+') // res2: Char = +
To expand on #0__'s answer (if that is his/her real name), you can also use tuples to assign to two variables at once.
val (countA, countB) =
if (validItem) {
if (region.equalsIgnoreCase("US")) {
if (itemList > 0) (0,1) else (1,0)
} else {
(0,1)
}
} else {
(1,0)
}
This is an old question and I'm taking a break from a current problem, so I thought I'd leave a basic pattern match solution.
val (countA, countB) =
(validItem, region.equalsIgnoreCase("US"), itemList > 0) match {
case (true, true, false) | (false, _, _) => (1, 0)
case _ => (0, 1)
}

Why do I have "Type mismatch; Found Unit, expected Boolean" in Scala-IDE?

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.

Palindromes using Scala

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))