How can do a tuple comparison in coffeescript similar to that in python? - coffeescript

This is a my function
st3 = (x, y) ->
console.log "#{x?}, #{y?}"
if [x?, y?] is [true, true] # <- this is the line
'good'
'bad'
This is the output
true, true
bad
I want to be able to do a tuple comparison like it is in python.
In python, the if can be written roughly as
if (x, y) == (True, False):
return 'good'
The coffescript if loop is translated into javascript as such
if ([x != null, y != null] === [true, true]) {
'good';
}
That's why this will not evaluated to true.
Is there any alternative way to express it in coffeescript?

If you want to check to see if all of your arguments are not None, then I would do this:
def check_all(*args):
return all(arg is not None for arg in args)
If you wanted to check if they're all True (like literally True) then you could use
def check_all(*args):
return all(arg is True for arg in args)
If you wanted to take in a list (instead of variable number of parameters, remove the asterisk.

Related

Apply function to all elements of a WrappedArray elegantly

This:
val checkValue = udf { (array: WrappedArray[String], value: String) => array.contains(value) }
works if you do not worry about case of words.
I can apply .toLowerCase() to value easily enough to get this ...(value.toLowerCase() )
But how to apply to the incoming array being WrappedArray and not externally?
array.contains(value)
is the same as
array.exists(_ == value)
The _ == value can be replaced by an arbitrary predicate.
In your case, it would be something like
array.exists(value.equalsIgnoreCase)
Also, note that "ß".toUpperCase == "SS" is true, whereas "ß" == "SS".toLowerCase and "ß".compareIgnoreCase("SS") are both false, see for example this answer.

Anagram Recursion Scala

This is the question that I tried to write a code for.
Consider a recursive algorithm that takes two strings s1 and s2 as input and checks if these strings are the anagram of each other, hence if all the letters contained in the former appear in the latter the same number of times, and vice versa (i.e. s2 is a permutation of s1).
Example:
if s1 = ”elevenplustwo” and s2 = ”twelveplusone” the output is true
if s1 = ”amina” and s2 = ”minia” the output is false
Hint: consider the first character c = s1(0) of s1 and the rest of r =s1.substring(1, s1.size) of s1. What are the conditions that s2 must (recursively) satisfy with respect to c and r?
And this is the piece of code I wrote to solve this problem. The problem is that the code works perfectly when there is no repetition of characters in the strings. For example, it works just fine for amin and mina. However, when there is repetition, for example, amina and maina, then it does not work properly.
How can I solve this issue?
import scala.collection.mutable.ArrayBuffer
object Q32019 extends App {
def anagram(s1:String, s2:String, indexAr:ArrayBuffer[Int]):ArrayBuffer[Int]={
if(s1==""){
return indexAr
}
else {
val c=s1(0)
val s=s1.substring(1,s1.length)
val ss=s2
var count=0
for (i<-0 to s2.length-1) {
if(s2(i)==c && !indexAr.contains(s2.indexOf(c))) {
indexAr+=i
}
}
anagram(s,s2,indexAr)
}
indexAr
}
var a="amin"
var b="mina"
var c=ArrayBuffer[Int]()
var d=anagram(a,b,c)
println(d)
var check=true
var i=0
while (i<a.length && check){
if (d.contains(i) && a.length==b.length) check=true
else check=false
i+=1
}
if (check) println("yes they are anagram")
else println("no, they are not anagram")
}
The easiest way is probably to sort both strings and just compare them:
def areAnagram(str1: String, str2: String): Boolean =
str1.sorted == str2.sorted
println(areAnagram("amina", "anima")) // true
println(areAnagram("abc", "bcc")) // false
Other one is more "natural". Two strings are anagrams if they have the same count of each character.
So you make two Map[Char, Int] and compare them:
import scala.collection.mutable
def areAnagram(str1: String, str2: String): Boolean = {
val map1 = mutable.Map.empty[Char, Int].withDefaultValue(0)
val map2 = mutable.Map.empty[Char, Int].withDefaultValue(0)
for (c <- str1) map1(c) += 1
for (c <- str2) map2(c) += 1
map1 == map2
}
There is also another version of second solution with Arrays probably, if you know the chars are only ASCII ones.
Or some other clever algorithm, IDK.
EDIT: One recursive solution could be to remove the first char of str1 from str2. The rests of both strings must be anagrams also.
E.g. for ("amina", "niama") first you throw out an a from both, and you get ("mina", "nima"). Those 2 strings must also be anagrams, by definition.
def areAnagram(str1: String, str2: String): Boolean = {
if (str1.length != str2.length) false
else if (str1.isEmpty) true // end recursion
else {
val (c, r1) = str1.splitAt(1)
val r2 = str2.replaceFirst(c, "") // remove c
areAnagram(r1, r2)
}
}
When you calculate anagrams you can take advantage of property of XOR operation, which says, that if you xor two same numbers you'd get 0.
Since characters in strings are essentially just numbers, you could run xor over all characters of both strings and if result is 0, then these strings are anagrams.
You could iterate over both strings using loop, but if you want to use recursion, I would suggest, that you convert your string to lists of chars.
Lists allow efficient splitting between first element (head of list) and rest (tail of list). So solution would go like this:
Split list to head and tail for both lists of chars.
Run xor over characters extracted from heads of lists and previous result.
Pass tails of list and result of xoring to the next recursive call.
When we get to the end of lists, we just return true is case result of xoring is 0.
Last optimalization we can do is short-curcuiting with false whenever strings with different lengths are passed (since they never could be anagrams anyway).
Final solution:
def anagram(a: String, b: String): Boolean = {
//inner function doing recursion, annotation #tailrec makes sure function is tail-recursive
#tailrec
def go(a: List[Char], b: List[Char], acc: Int): Boolean = { //using additional parameter acc, allows us to use tail-recursion, which is safe for stack
(a, b) match {
case (x :: xs, y :: ys) => //operator :: splits list to head and tail
go(xs, ys, acc ^ x ^ y) //because we changed string to lists of chars, we can now efficiently access heads (first elements) of lists
//we get first characters of both lists, then call recursively go passing tails of lists and result of xoring accumulator with both characters
case _ => acc == 0 //if result of xoring whole strings is 0, then both strings are anagrams
}
}
if (a.length != b.length) { //we already know strings can't be anagrams, because they've got different size
false
} else {
go(a.toList, b.toList, 0)
}
}
anagram("twelveplusone", "elevenplustwo") //true
anagram("amina", "minia") //false
My suggestion: Don't over-think it.
def anagram(a: String, b: String): Boolean =
if (a.isEmpty) b.isEmpty
else b.contains(a(0)) && anagram(a.tail, b diff a(0).toString)

Scala - Find duplicates in list using pattern matching and recursion

I am trying to solve a beginner problem but can't reach the solution:
If any duplicates in list, return true, else false. Empty lists considered.
def duplicates(a: List[Int]): Boolean = {
case Nil => false
case x :: xs =>
if(xs.contains(x)) true else false
}
But this doesn't work. And it's not recursive. It's just something where I wanted to start but I'm stuck. Please kindly help and try to avoid non-beginner solutions if reasonable.
You need to call your function recursively. So if xs doesn't contain x, then call the function but with the remaining list.
def duplicates(a: List[Int]): Boolean = a match {
case Nil => false
case x :: xs =>
if(xs.contains(x)) true else duplicates(xs)
}

Condition as function in for comprehension loop

I would like to use a custom condition function in my for-comprehension loop for slick query:
def findNewsletterUsers(f: (NewsletterUsers, NewsletterStatuses) => Boolean) = {
for {
u <- NewsletterUsers
s <- NewsletterStatuses if (u.statusId === s.id)
d <- NewsletterDelays if (u.delayId === d.id)
if f(u, s)
} yield (u, d, s)
}
I would like to invoke this method with actual custom condition filled in a layer above. Something like:
findNewsletterUsers((nu, ns) => ns.name == 'C')
This invocation returns no rows though (while it should). Is there any way to make it work that way?
Best regards
An easy mistake to make in slick is to use the == operator instead of the === operator.
In your case you use the function (nu, ns) => ns.name == 'C'). This function always returns false because ns.name is not a Char but a Rep[Char].
To solve this issue, you simply need to replace == by ===, slick will automatically lift the literal char 'C' to a Rep[Char].

Curried function evaluates all arguements

I'm trying to figure out why my curried function operates in the following way. I built the function ensure to take a more function approach instead of multiple if-then statements that would accomplish the same thing.
I discovered a bug today will running some tests where if the condition in the first ensure function e.g. ensure(contents.hasNext && acc != null) is true, the false condition or second arguement still gets evaluated and becomes the overriding function.
I can fix the problem if I simple change this: ensure(contents.hasNext) to this: ensure(contents.hasNext && acc == null) but i'm struggling with WHY this is happening.
Is there a more obvious (or just better) solution to this?
def ensure[T](f: => Boolean)(truth: => T, lie: T) = if (f) truth else lie
def lines(): Stream[String] = {
def matchLine(text: String, acc: String): Stream[String] = text match {
...
case NewLine(string) =>
ensure(contents.hasNext && acc != null)(acc +: matchLine(contents.next, string),
ensure(contents.hasNext)(matchLine(contents.next, string), acc +: string +: empty))
...
}
ensure(contents.hasNext)(matchLine(contents.next, null), empty)
}
(truth: => T, lie: T)
This means that the expression given for the truth parameter, will be evaluated each time that truth is used within your function (and only then), while lie will be executed exactly once before your function starts executing. In other words: truth is passed by name and lie isn't. To achieve the behaviour you want, you'd need to pass both by name (on the other passing the condition by name is not really necessary since it will be evaluated exactly once at the beginning of the function in all cases):
ensure[T](f: Boolean)(truth: => T, lie: => T) = if (f) truth else lie
That said, I wouldn't agree that replacing if-then-else expressions with a function that's basically a wrapper around if-then-else, makes your code more functional.