Scala foldRight giving different results than reverse.foldLeft - scala

I am writing a function to convert a byte array to an integer. It detects the endianness of the system to determine which direction it should read the 4 byte array from. I am using a foldLeft with bitshifting and bitwise or. Ideally, if it is little endian, you just fold right instead
However, this is returning the wrong value.
scala> val bytes = Array[Byte](0xAA.toByte, 0xBB.toByte, 0xCC.toByte, 0xDD.toByte)
val bytes: Array[Byte] = Array(-86, -69, -52, -35)
scala> bytes.foldLeft(0)((accum, num) => {
| (num & 0x000000FF) | (accum << 8)
| }).toHexString
val res38: String = aabbccdd <- correct
scala> bytes.foldRight(0)((accum, num) => {
| (num & 0x000000FF) | (accum << 8)
| }).toHexString
val res36: String = ffffaa00 <- wat
scala> bytes.reverse.foldLeft(0)((accum, num) => {
| (num & 0x000000FF) | (accum << 8)
| }).toHexString
val res37: String = ddccbbaa <- correct
I'm a bit of a scala noob, would someone mind pointing out why this is producing different values?

Related

using scala Find four elements from list that sum to a given value

I am new to scala programming language and want to implement the code having below scenerio.
given a list sampleone of n integer and an integer samplethree, there are elements a,b,c and d in sampleone such that a+b+c+d = samplethree. Find all unique quadruplet in the list which gives the sum of samplethree
Example:
sampleone =[1,0,-1,0,-2,2] and samplethree = 0
a solution set is
[-1,0,0,1]
[-2,-1,1,2]
[-2,0,0,2]
the code that I have used is
scala> def findFourElements(A: List[Int], n: Int, x: Int) = {
| {
| for(a <- 0 to A.length-3)
| {
| for(b <- a+1 to A.length-2)
| {
| for(c <- b+1 to A.length-1)
| {
| for(d <- c+1 to A.length)
| {
| if(A(a) + A(b) + A(c) + A(d) == x)
| {
| print(A(a)+A(b)+A(c)+A(d))
| }}}}}}
| }
findFourElements: (A: List[Int], n: Int, x: Int)Unit
scala> val sampleone = List(1,0,-1,0,-2,2)
sampleone: List[Int] = List(1, 0, -1, 0, -2, 2)
scala> val sampletwo = sampleone.length
sampletwo: Int = 6
scala> val samplethree = 0
samplethree: Int = 0
scala> findFourElements(sampleone,sampletwo,samplethree)
0java.lang.IndexOutOfBoundsException: 6
at scala.collection.LinearSeqOptimized$class.apply(LinearSeqOptimized.scala:65)
at scala.collection.immutable.List.apply(List.scala:84)
at $anonfun$findFourElements$1$$anonfun$apply$mcVI$sp$1$$anonfun$apply$mcVI$sp$2$$anonfun$apply$mcVI$sp$3.apply$mcVI$sp(<console>:33)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
at $anonfun$findFourElements$1$$anonfun$apply$mcVI$sp$1$$anonfun$apply$mcVI$sp$2.apply$mcVI$sp(<console>:31)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
at $anonfun$findFourElements$1$$anonfun$apply$mcVI$sp$1.apply$mcVI$sp(<console>:29)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
at $anonfun$findFourElements$1.apply$mcVI$sp(<console>:27)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
at findFourElements(<console>:25)
... 48 elided
But I am getting error of index out of bound exception.
Also is there a way to have a more optimized code in scala.
Thanks for help.
This may do what you want:
sampleone.combinations(4).filter(_.sum == samplethree)
The combinations method gives an iterator that delivers each possible combination of values in turn. If there is more than one way to construct the same sequence, only one will be returned.
The filter call removes any sequences that do not sum to the samplethree value.

Reverse bit positions without toBinaryString

I have been trying to use scala to reverse bit positions by only using shifting, forcing and toggling. I was wondering if somebody could find my error, I have been staring my code too long now :)
Examples:
1010 1010 -> 0101 0101
1100 1001 -> 1001 0011
Here is my code atm:
def reverse(word: Byte): Byte = {
var r = 0x00 // Reversed bitstring
for (i <- 0 to 7) {
if ((word >> (7 - i) & 1) == 1) r = r & 1
r >> 1
}
r
}
Old:
def reverse(word: Byte) = {
var reversed = 0xFF.toByte
for (i <- 0 to 7) {
if ((word >> i & 1) == 1) {
reversed = reversed >> 1
}
else reversed = reversed >>> 1
}
reversed
}
Just take any answer for a Java implementation and do it simpler in Scala. (I added an explicit bit-size). Like:
import annotation.tailrec
#tailrec
def reverse(in: Int, n: Int = 8, out: Int = 0): Int =
if (n == 0) out
else reverse(in >>> 1, n - 1, (out << 1) | (in & 1))
For the number of bits, copy lowest bit from input to output and shift in opposite directions. Verify:
assert(reverse(0xAA) == 0x55)
assert(reverse(0xC9) == 0x93)
for (x <- 0x00 to 0xFF) assert(reverse(reverse(x)) == x)
This is a weird problem to spend time solving ... Homework?
#tailrec
def reverse(in: Int, out: Int = 0, n: Int = 0): Int =
if(in == 0) out else reverse(in >> 1, out | (in & 1) << (7-n), n+1)
java.lang.Integer and Long have methods for reversing of bits (and bytes), but for some silly reason, java.lang.Byte doesnt, so if you were to just use this method, remember to shift over the bytes properly:
Eg: (Integer.reverse(x) >>> 24) & 0xFF
This may be easier than writing all the bitwise operations yourself if not quite up to that, and Oracle implements it with a well optimized version for 32&64 bit integers

Easiest way to flip the endianness of a byte in Scala

The title says it all, what is the easiest way to flip the endianness of a byte in Scala?
Edit: Here is an example of a hex string that can be converted to a List[Byte] for what I am talking about
"44[5e405f7b46d912b50ea59d0f0962ed9e251042a4b31208315c406a4aa962]ff" was not equal to "44[e504f5b7649d215be05ad9f09026dee95201244a3b218013c504a6a49a26]ff"
If you mean flipping low with high half-bits of a Byte:
(b: Byte) => (b >>> 4) + (b << 4)
If you want to flip every half-byte on a hex string I would grouped by 2 characters then flip the pairs before creating the string back again:
val input = "44[5e405f...".replaceAll("[^0-9a-f]","")
val expected = "44[e504f5...".replaceAll("[^0-9a-f]","")
// as suggested by #PaulDraper in the comments
input.grouped(2).map(_.reverse).mkString == expected
// or the verbose
val ab = "(.)(.)".r
input.grouped(2).map { case ab(a, b) => b ++ a }.mkString == expected
If your input is a List[Byte]:
val inputBytes = input.grouped(2).map(Integer.parseInt(_, 16).toByte)
val expectedBytes = expected.grouped(2).map(Integer.parseInt(_, 16).toByte)
inputBytes.map((b: Byte) => (b >>> 4) + (b << 4)).map(_.toByte).toSeq == expectedBytes.toSeq

scala - serialize Int to ArrayBuffer[Byte]. Bit twiddle goes wrong

I want to serialize an into into a Byte array or array buffer.
I realise that I can use 'java.nio.ByteBuffer' but I am experimenting for fun and trying to do it myself.
The following code works for positive Int but goes wrong when I serialize a negative Int.
Can anyone explain why or show me a correction?
import scala.collection.mutable.ArrayBuffer
object b {
val INTBYTES:Int = 4 // int is 4 bytes
def toArrayBuf(x:Int): ArrayBuffer[Byte] = {
val buf = new ArrayBuffer[Byte](INTBYTES)
for(i <- 0 until INTBYTES) {
buf += ((x >>> (INTBYTES - i - 1 << 3)) & 0xFF).toByte
}
buf
}
}
the following test works as expected:-
int the REPL it prints:-
scala> val test:Int = 0x4f0f0f0f
test: Int = 1326386959
scala> println(test.toBinaryString)
1001111000011110000111100001111
scala> val t1 = b.toArrayBuf(test)
t1: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(79, 15, 15, 15)
scala> t1.foreach( it => printf("%s ",it.toInt.toBinaryString))
1001111 1111 1111 1111
but this with a negative int does something wierd:-
scala> val test2:Int = 0x8f0f0f0f
test2: Int = -1894838513
scala> println(test2.toBinaryString)
10001111000011110000111100001111
scala> val t2 = b.toArrayBuf(test2)
t2: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(-113, 15, 15, 15)
scala> t2.foreach( it => printf("%s ",it.toInt.toBinaryString))
11111111111111111111111110001111 1111 1111 1111
notice that the first byte has been 1 filled for the whole int it shoild be '10001111'
Any ideas?
FYI
Im using :-
scala -version
Scala code runner version 2.10.1 -- Copyright 2002-2013, LAMP/EPFL
java -fullversion
java full version "1.7.0_40-b31"
with OpenJDK
Thanks
Scala's toBinaryString method defers to the Java one on Integer. From those documents:
public static String toBinaryString(int i)
Returns a string representation of the integer argument as an unsigned
integer in base 2. The unsigned integer value is the argument plus
2^32 if the argument is negative; otherwise it is equal to the
argument. This value is converted to a string of ASCII digits in
binary (base 2) with no extra leading 0s.
In other words it's working as specified. Your bit-twiddling seems to be OK, but when you're printing the numbers out, you need to realise that the number of characters is dependent on the length of the data type. (E.g. -1: Int in binary is 11111111111111111111111111111111 while -1: Byte is 11111111.) You get away with it for positive numbers only because the leading zeros are not displayed, as specified above.
Solution: make your own toBinaryString for bytes, or just taking the rightmost 8 digits from the Int version should work (though less efficient) i.e.
it.toInt.toBinaryString.takeRight(8)
Taking Luigi's advice I hacked up a pimp for Byte that provides a toBinaryString that works properly, in case anyone else is struggling with similar problems here is what I did.
object b {
val INTBYTES:Int = 4 // int is 4 bytes
val SIZEBYTE:Short = 8
def toArrayBuf(x:Int): ArrayBuffer[Byte] = {
val buf = new ArrayBuffer[Byte](INTBYTES)
for(i <- 0 until INTBYTES) {
buf += ((x >>> (INTBYTES - i - 1 << 3)) & 0xFF).toByte
}
buf
}
def toBinaryString(x: Byte): String = {
val buf = new StringBuilder(SIZEBYTE)
for(i <- 0 until SIZEBYTE) {
buf.append((x >>> (SIZEBYTE - i - 1)) & 0x01)
}
buf.toString()
}
}
//pimp Byte
implicit def fooBar(byte: Byte) = new {def toBinaryString = b.toBinaryString(byte)}
Now when I run the previous experiment it works properly
scala> val test:Int = 0x4f0f0f0f
test: Int = 1326386959
scala> println(test.toBinaryString)
1001111000011110000111100001111
scala> val t1 = toArrayBuf(test)
t1: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(79, 15, 15, 15)
scala> t1.foreach( it => printf("%s ",it.toBinaryString))
01001111 00001111 00001111 00001111
and
scala> val test2:Int = 0x8f0f0f0f
test2: Int = -1894838513
scala> println(test2.toBinaryString)
10001111000011110000111100001111
scala> val t2 = toArrayBuf(test2)
t2: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(-113, 15, 15, 15)
scala> t2.foreach( it => printf("%s ",it.toBinaryString))
10001111 00001111 00001111 00001111
Thanks Luigi

Why converting '1' char to int using toInt method results to 49?

I want to convert a char to an int value.
I am a bit puzzled by the way toInt works.
println(("123").toList) //List(1, 2, 3)
("123").toList.head // res0: Char = 1
("123").toList.head.toInt // res1: Int = 49 WTF??????
49 pops up randomly for no reason.
How do you convert a char to int the right way?
For simple digit to int conversions there is asDigit:
scala> "123" map (_.asDigit)
res5: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3)
Use Integer.parseInt("1", 10). Note that the 10 here is the radix.
val x = "1234"
val y = x.slice(0,1)
val z = Integer.parseInt(y)
val z2 = y.toInt //equivalent to the line above, see #Rogach answer
val z3 = Integer.parseInt(y, 8) //This would give you the representation in base 8 (radix of 8)
49 does not pop up randomly. It's the ascii representation of "1". See http://www.asciitable.com/
.toInt will give you the ascii value. It's probably easiest to write
"123".head - '0'
If you want to handle non-numeric characters, you can do
c match {
case c if '0' <= c && c <= '9' => Some(c - '0')
case _ => None
}
You can also use
"123".head.toString.toInt