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

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

Related

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

How can I pad a Vector of Strings in Scala?

I'd like to pad a vector of strings with a given value on all sides (i.e., top, bottom, right, left). For example, the following vector of strings:
1122
1122
3344
3344
should look like this:
000000
011220
011220
033440
033440
000000
Of course, this representation is purely for visual purposes and it is actually a Vector of strings.
I found I can accomplish this with the following code.
val v = Vector("1122", "1122", "3344", "3344")
Vector("000000") ++ (for { r <- v } yield "0" + r + "0") ++ Vector("000000")
However, I am fairly new to Scala and I feel I might be missing a better way to accomplish this. Is there a better way to pad a Vector of Strings in Scala with a given value?
Using jwvh's map approach with the * operator on String:
def repeat(len: Int, c: Char) = c.toString * len
def padLeftRight(s: String, len: Int, c: Char) = {
repeat(len - 1 - s.size, c) + s + c
}
def padSeq[S <: Seq[String]](xs: S, c: Char) = {
val len = xs.map(_.size).max + 2
val padded = repeat(len, c)
padded +: xs.map(padLeftRight(_, len, c)) :+ padded
}
Using padSeq with your example:
val v = Vector("1122", "1122", "3344", "3344")
val result = padSeq(v, '0')
gives:
Vector("000000", "011220", "011220", "033440", "033440", "000000")

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

call a def within a block

If there is any way to call a def from a block
def factor (n: Int) : Int = if (n == 0 ) 1 else n * factor(n-1)
val i = 1000
i.toString.foreach ( x => sum += factor(x.toInt) )
at the end I want to get the sum of factorial of every digit
But it seems like def doesn't return a value, everytime is 0
How to fix it?
Thanks!
The problem actually has nothing to do with Scala per se; your code and your def are fine. The issue is with toInt:
scala> '3'.toInt
res7: Int = 51
toInt doesn't actually convert it as a decimal digit, but as a unicode (ish?) character value. These are producing very large numbers which go beyond what factor can handle:
scala> factor(6)
res8: Int = 720
scala> factor(20)
res9: Int = -2102132736
scala> factor(100)
res10: Int = 0
So instead use (thanks to Luigi)
x.asDigit