How to convert Mac address as String format to Long in scala? - scala

my question is converting string to long in scala.
where string is format as Mac Address.
for eg:
"fe:1a:90:20:00:00" and "a0:b4:ac:c0:00:01"
How to convert in long type using scala.

This may help:
mac.split(":").map(Integer.parseInt(_,16)).foldLeft(0L) {case (acc,item) => acc*256+item}
First operation
mac.split(":")
gives Array of strings, like Array("fe","1a","90","20","00","00"). Each item of this array is base-16 encoded integer, so we can convert it to array of integers with:
val arrayOfInts = mac.split(":").map(Integer.parseInt(_,16))
which gives for first example Array(254, 26, 144, 32, 0, 0).
The last thing to do is to convert array of integers to long. Each item of array is in range [0,255], so multiplication on 256 is exactly enough to hold the value, last operation
arrayOfInts.foldLeft(0L) {case (acc,item) => acc*256+item}
does the conversion. It starts from 0L and for each item multiplies result on 256 and adds item:
(((((((0L*256 + 254)*256 + 26)*256) + 144)*256 + 32)*256 + 0)*256) + 0

I found the answer in github:
https://github.com/ppurang/flocke/blob/master/core/src/main/scala/org/purang/net/flocke/MacAddress.scala

You could use java library
def hex2Long(hex: String, removeDelimiter: String = ""): Long = {
java.lang.Long.valueOf(hex.replaceAll(removeDelimiter, ""), 16)
}
scala> hex2Long("00:00:00:00:2f:59")
res2: Long = 12121

Related

How to generate 15 digit random number using Scala

I am new to Scala programming, I want to generate random number with 15 digits, So can you please let share some example. I have tried the below code to get the alpha number string with 10 digits.
var ranstr = s"${(Random.alphanumeric take 10).mkString}"
print("ranstr", ranstr)
You need to pay attention to the return type. You cannot have a 15-digit Int because that type is a 32-bit signed integer, meaning that it's maximum value is a little over 2B. Even getting a 10-digit number means you're at best getting a number between 1B and the maximum value of Int.
Other answers go in the detail of how to get a 15-digits number using Long. In your comment you mentioned between, but because of the limitation I mentioned before, using Ints will not allow you to go beyond the 9 digits in your example. You can, however, explicitly annotate your numeric literals with a trailing L to make them Long and achieve what you want as follows:
Random.between(100000000000000L, 1000000000000000L)
Notice that the documentation for between says that the last number is exclusive.
If you're interested in generating arbitrarily large numbers, a String might get the job done, as in the following example:
import scala.util.Random
import scala.collection.View
def nonZeroDigit: Char = Random.between(49, 58).toChar
def digit: Char = Random.between(48, 58).toChar
def randomNumber(length: Int): String = {
require(length > 0, "length must be strictly positive")
val digits = View(nonZeroDigit) ++ View.fill(length - 1)(digit)
digits.mkString
}
randomNumber(length = 1)
randomNumber(length = 10)
randomNumber(length = 15)
randomNumber(length = 40)
Notice that when converting an Int to a Char what you get is the character encoded by that number, which isn't necessarily the same as the digit represented by the Int itself. The numbers you see in the functions from the ASCII table (odds are it's good enough for what you want to do).
If you really need a numeric type, for arbitrarily large integers you will need to use BigInt. One of its constructors allows you to parse a number from a string, so you can re-use the code above as follows:
import scala.math.BigInt
BigInt(randomNumber(length = 15))
BigInt(randomNumber(length = 40))
You can play around with this code here on Scastie.
Notice that in my example, in order to keep it simple, I'm forcing the first digit of the random number to not be zero. This means that the number 0 itself will never be a possible output. If you want that to be the case if one asks for a 1-digit long number, you're advised to tailor the example to your needs.
A similar approach to that by Alin's foldLeft, based here in scanLeft, where the intermediate random digits are first collected into a Vector and then concatenated as a BigInt, while ensuring the first random digit (see initialization value in scanLeft) is greater than zero,
import scala.util.Random
import scala.math.BigInt
def randGen(n: Int): BigInt = {
val xs = (1 to n-1).scanLeft(Random.nextInt(9)+1) {
case (_,_) => Random.nextInt(10)
}
BigInt(xs.mkString)
}
To notice that Random.nextInt(9) will deliver a random value between 0 and 8, thus we add 1 to shift the possibble values from 1 to 9. Thus,
scala> (1 to 15).map(randGen(_)).foreach(println)
8
34
623
1597
28474
932674
5620336
66758916
186155185
2537294343
55233611616
338190692165
3290592067643
93234908948070
871337364826813
There a lot of ways to do this.
The most common way is to use Random.nextInt(10) to generate a digit between 0-9.
When building a number of a fixed size of digits, you have to make sure the first digit is never 0.
For that I'll use Random.nextInt(9) + 1 which guarantees generating a number between 1-9, a sequence with the other 14 generated digits, and a foldleft operation with the first digit as accumulator to generate the number:
val number =
Range(1, 15).map(_ => Random.nextInt(10)).foldLeft[Long](Random.nextInt(9) + 1) {
(acc, cur_digit) => acc * 10 + cur_digit
}
Normally for such big numbers it's better to represent them as sequence of characters instead of numbers because numbers can easily overflow. But since a 15 digit number fits in a Long and you asked for a number, I used one instead.
In scala we have scala.util.Random to get a random value (not only numeric), for a numeric value random have nextInt(n: Int) what return a random num < n. Read more about random
First example:
val random = new Random()
val digits = "0123456789".split("")
var result = ""
for (_ <- 0 until 15) {
val randomIndex = random.nextInt(digits.length)
result += digits(randomIndex)
}
println(result)
Here I create an instance of random and use a number from 0 to 9 to generate a random number of length 15
Second example:
val result2 = for (_ <- 0 until 15) yield random.nextInt(10)
println(result2.mkString)
Here I use the yield keyword to get an array of random integers from 0 to 9 and use mkString to combine the array into a string. Read more about yield

indexOf second argument in Scala

I want to understand what does second argument in indexOf in Scala mean for Strings?
object Playground extends App {
val g: String = "Check out the big brains on Brad!"
println(g.indexOf("o",7));
}
The above program returns: 25 which is something I am not able to understand why?
It is actually the index of last o but how is it related to 7? Is it like the second argument n returns the index of the occurence of nth character and if n exceeds with the number of occurences then it returns the index of last present element?
But if that's the case then this doesn't make sense:
object Playground extends App {
val g: String = "Check out the big brains on Brad!"
(1 to 7).foreach(i => println(s"$i th Occurence = ${g.indexOf("o",i)} "))
}
which outputs:
1 th Occurence = 6
2 th Occurence = 6
3 th Occurence = 6
4 th Occurence = 6
5 th Occurence = 6
6 th Occurence = 6
7 th Occurence = 25
Source: https://www.scala-exercises.org/std_lib/infix_prefix_and_postfix_operators
According to Scala String documentation, the second parameter is the index to start searching from:
def indexOf(elem: Char, from: Int): Int
Finds index of first occurrence of some value in this string after or at some start index.
elem : the element value to search for.
from : the start index
returns : the index >= from of the first element of this string that is equal (as determined by ==) to elem, or -1, if none exists.
Thus, in your case, when you specify 7, it means that you will look for the index of the first character "o" which is located at index 7 or after . And indeed, in your String you have two "o", one at index 6, one at index 25.
indexOf(int ch, int fromIndex) looks for the character in the string from the specified index (fromIndex). This means it starts looking at 7th position.
Going forward you need to learn to read the official docs: indexOf:
def indexOf(elem: A, from: Int): Int
[use case] Finds index of first occurrence of some value in this general sequence after or at some start index.
Note: may not terminate for infinite-sized collections.
elem
the element value to search for.
from
the start index
returns
the index >= from of the first element of this general sequence that is equal (as determined by ==) to elem, or -1, if none exists.
I personally like to use Intellij to jump into the source code with CMD + B.
No matter how you take it: in your development flow you'll frequently access the manual\docs of the lib or lang you're using.

Can you convert an array of Bytes to an array of Strings and then back to an array of Bytes?

Let's say I have an array of Bytes
val base = [-2, 50, 48]
and I converted this array of Bytes to an array of Strings
val baseConverted = ["-2","50","48"]
Is there a way to convert 'baseConverted' back to 'base'?
You just need to use toByte from a String on every element:
List("-2","50","48").map(_.toByte)
Here is how one can do it using Array:
val baseConverted = Array("-2", "50", "48")
val backToBase = baseConverted.map(_.toByte)
// Prints
// backToBase: Array[Byte] = Array(-2, 50, 48)

Absolute function

In my program I am using Bigdecimal to truncate numbers and storing them in a variable. Eg. 123.456789 is getting displayed as 123.45.Further I am trying to find the absolute of the numbers.The problem arises here i.e - 123.45 should appear as 123.45 but it's appearing as 123.4589Egh.Can someone please help as to how can I find absolute of numbers.
var diff1=BigDecimal(diff).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble
var bigdec=abs(diff1)
Try taking inputs for 10-15 numbers in an array (in diff variable)
Uhm, I'm not sure what your problem is, but for me this works fine:
val diff = -123.456789
var diff1 = BigDecimal(diff).setScale(2, BigDecimal.RoundingMode.DOWN).toDouble
var bigdec = Math.abs(diff1)
println(bigdec) // 123.45
Note that if you want 123.45 instead of 123.46 you have to change your rounding mode.
Taking in an array doesn't change anything, although you need to make a def and map over the array now when rounding - as you cannot call the BigDecimal apply function on an Array:
// generates an Array of 20 elements with random doubles from 0 to 200
val diff = Array.fill(20)(math.random).map(_ * 200)
.map { num => // using this map function to make some negatives
if (num < 100) num * -1
else num
}
def round(double: Double) = BigDecimal(double)
.setScale(2, BigDecimal.RoundingMode.HALF_UP)
.toDouble
var absolute = diff.map(num => Math.abs(round(num)))
Does the above code reflect what you are doing? If so, for var absolute I am getting an Array[Double] with positive numbers and only 2 decimal places.

Parse signed number from hex using BigInt

I'm trying to parse a signed number using a BigInt. Here have been my attempts
scala> -1.toHexString
res7: String = ffffffff
scala> val bigInt = BigInt(res7,16)
bigInt: scala.math.BigInt = 4294967295
Is there any way to easily parse a signed number from a hex using BigInt?
If your hex string began life as an Integer or a Long—before converting it to a BigInt—parse it as an unsigned number with
java.lang.Integer.parseUnsignedInt("ffffffff",16) // Results in -1
or
java.lang.Long.parseUnsignedLong("ffffffffffffffff",16) // Results in -1
You have to tell it how long your number is one way or another. Without it, just saying "ffffffff" is ambiguous: as an Int it is -1, but as a long it is a large positive value:
bigInt.toLong
res48: Long = 4294967295
bigInt.toInt
res49: Int = -1