def reverse(w: Short): Short = { w.toBinaryString.reverse.toShort }
This should be work like this:
reverse(0x0000.toShort)
0x0000.toShort
reverse(0xFFFF.toShort)
0xFFFF.toShort
reverse(0xAAAA.toShort)
0x5555.toShort
reverse(0x1234.toShort)
0x2C48.toShort
I'd forgo the String translations for a more mathematical approach.
def reverse(w :Short) :Short =
Stream.iterate(w.toInt, 16)(_ >> 1)
.foldLeft(0:Short){case (s,i) => ((s<<1)+(i&1)).toShort}
testing:
reverse(0) == 0 //res0: Boolean = true
reverse(-1) == -1 //res1: Boolean = true
reverse(0xAAAA.toShort) == 0x5555 //res2: Boolean = true
reverse(0x1234.toShort) == 0x2C48 //res3: Boolean = true
Related
I have a list of String where the String element could start with prefix of AA, BB or CC. How can I check if the list must and only contains String startWith both AA and BB but not CC. This is what I have now which is working, is that a better way to do it? Thanks.
private final val ValidPatternA: String = "^AA.*"
private final val ValidPatternB: String = "^BB.*"
private final val InvalidPatternC: String = "^CC.*"
def main(args: Array[String]): Unit = {
println(isValid(Seq())) // false
println(isValid(Seq("AA0"))) // false
println(isValid(Seq("BB1"))) // false
println(isValid(Seq("CC2"))) // false
println(isValid(Seq("AA0", "BB1", "CC2"))) // false
println(isValid(Seq("AA0", "CC2"))) // false
println(isValid(Seq("BB1", "CC2"))) // false
println(isValid(Seq("AA0", "BB1"))) // true
}
private def isValid(listOfString: Seq[String]) =
!listOfString.exists(_.matches(InvalidPatternC)) &&
listOfString.exists(_.matches(ValidPatternA)) &&
listOfString.exists(_.matches(ValidPatternB))
The code you have is clear and expressive, so the only concern can be performance. A recursive function can do one pass efficiently:
def isValid(listOfString: Seq[String]) = {
#annotation.tailrec
def loop(rem: List[String], foundA: Boolean, foundB: Boolean): Boolean =
rem match {
case Nil => foundA && foundB
case s"CC$_" :: _ => false
case s"AA$_" :: tail => loop(tail, true, foundB)
case s"BB$_" :: tail => loop(tail, foundA, true)
case hd :: tail => loop(tail, foundA, foundB)
}
loop(listOfString.toList, false, false)
}
The #annotation.tailrec indicates that this will be compiled into a fast loop with rem, foundA and foundB stored in local variables, and loop being a goto back to the start of the function.
You can optimize it by using bit mask to save on number of collection traversals.
private def isValid(listOfString: Seq[String]) =
listOfString.foldLeft(0) { (mask, str) =>
mask | str.matches(ValidPatternA).compare(false) | str.matches(ValidPatternB).compare(false) << 1 | str.matches(InvalidPatternC).compare(false) << 2
} == 3 // 1 & 2 & ^4
I implemented two versions of the algorithm in Scala (without using sets, by the way). A first one :
def isContained(letter: Char, word: String): Boolean =
if (word == "") false
else if (letter == word.head) true
else isContained(letter, word.tail)
def hasUniqueChars(stringToCheck: String): Boolean =
if (stringToCheck == "") true
else if (isContained(stringToCheck.head, stringToCheck.tail)) false
else hasUniqueChars(stringToCheck.tail)
which is in O(N2).
And a second one :
def hasUniqueChars2Acc(str: String, asciiTable: List[Boolean]): Boolean = {
if (str.length == 0) true
else if (asciiTable(str.head.toByte)) false
else hasUniqueChars2Acc(str.tail, asciiTable.updated(str.head.toByte, true))
}
def hasUniqueChars2(str: String): Boolean = {
val virginAsciiTable = List.fill(128)(false)
if (str.length > 128) false
else hasUniqueChars2Acc(str, virginAsciiTable)
}
which is in O(N).
But when testing, the second version takes as much as 20 times the duration of the first one. Why? Is it related to the .updated method ?
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
val aggFilters = Array["IR*","IR_"]
val aggCodeVal = "IR_CS_BPV"
val flag = compareFilters(aggFilters,aggCodeVal)
As per my requirement I want to compare the patterns given in the aggFilters with aggCodeVal. The first pattern "IR*" is a match with "IR_CS_BPV" but not the second one, hence I want to break out of the for loop after the match is found so that I don't go for the second one "IR_". I don't want to use break statement like java.
def compareFilters(aggFilters: Array[String], aggCodeVal: String): Boolean = {
var flag: Boolean = false
for (aggFilter <- aggFilters) {
if (aggFilter.endsWith("*")
&& aggCodeVal.startsWith(aggFilter.substring(0, aggFilter.length() - 1))) {
flag = true
}
else if (aggFilter.startsWith("*")
&& aggCodeVal.startsWith(aggFilter.substring(1, aggFilter.length()))) {
flag = true
}
else if (((aggFilter startsWith "*")
&& aggFilter.endsWith("*"))
&& aggCodeVal.startsWith(aggFilter.substring(1, aggFilter.length() - 1))) {
flag = true
}
else if (aggFilter.equals(aggCodeVal)) {
flag = true
}
else {
flag = false
}
}
flag
}
If * is your only wild-card character, you should be able to leverage Regex to do your match testing.
def compareFilters(aggFilters: Array[String], aggCodeVal: String): Boolean =
aggFilters.exists(f => s"$f$$".replace("*",".*").r.findAllIn(aggCodeVal).hasNext)
You can use the built-in exists method to do it for you.
Extract a function that compares a single filter, with this signature:
def compareFilter(aggFilter: String, aggCodeVal: String): Boolean
And then:
def compareFilters(aggFilters: Array[String], aggCodeVal: String): Boolean = {
aggFilters.exists(filter => compareFilter(filter, aggCodeVal))
}
The implementation of compareFilter, BTW, can be shortened to something like:
def compareFilter(aggFilter: String, aggCodeVal: String): Boolean = {
(aggFilter.startsWith("*") && aggFilter.endsWith("*") && aggCodeVal.startsWith(aggFilter.drop(1).dropRight(1))) ||
(aggFilter.endsWith("*") && aggCodeVal.startsWith(aggFilter.dropRight(1))) ||
(aggFilter.startsWith("*") && aggCodeVal.startsWith(aggFilter.drop(1))) ||
aggFilter.equals(aggCodeVal)
}
But - double check me on that one, not sure I followed your logic perfectly.
Is there a better way to convert a sequence of Bytes into an Seq[Boolean] where each element represents a bit from the Byte sequence?
I'm currently doing this, but byte2Bools seems a little too heavy...
object Main extends App {
private def byte2Bools(b: Byte) =
(0 to 7).foldLeft(ArrayBuffer[Boolean]())((bs, i) => bs += isBitSet(b, i))
private def isBitSet(byte: Byte, bit: Int) =
((byte >> bit) & 1) == 1
val bytes = List[Byte](1, 2, 3)
val bools = bytes.flatMap(b => byte2Bools(b))
println(bools)
}
Perhaps the real question is: what's a better implementation of byte2Bools?
First, accumulator in foldLeft is not necessary need to be a mutable collection.
def byte2Bools(b: Byte): Seq[Boolean] =
(0 to 7).foldLeft(Vector[Boolean]()) { (bs, i) => bs :+ isBitSet(b)(i) }
Second, you can just map initial sequence with isBitSet.
def byte2Bools(b: Byte): Seq[Boolean] =
0 to 7 map isBitSet(b)
def isBitSet(byte: Byte)(bit: Int): Boolean =
((byte >> bit) & 1) == 1
For whatever it's worth, you can convert a Byte to a BinaryString and then to sequence of Booleans with:
val b1 : Byte = 7
(0x100 + b1).toBinaryString.tail.map{ case '1' => true; case _ => false }
Results in: Vector(false, false, false, false, false, true, true, true)
And, you would go back (Booleans to Byte) with:
val s1 = Vector(false, false, false, false, false, true, true, true)
Integer.parseInt( s1.map{ case true => '1'; case false => '0' }.mkString, 2 ).toByte