Mapping binary data in perl - perl

I have the following predefined codes that represent an index in a binary bitmap:
0 = standard
1 = special
2 = regular
3 = late
4 = early
5 = on time
6 = generic
7 = rfu
An example value I would take as an input would be 213, which becomes 11010101 in binary. Index 0, 2, 4, 6, and 7 have their bit flipped indicating that this record is:
standard + regular + early + generic + rfu.
I am trying to figure out in perl how to take that binary data and build a string, like mentioned above with code + code + code, etc.
Any help would be greatly appreciated. Thanks.
Edit: My thoughts on how I might approach this are:
Convert decimal to binary
Find length of binary string
Using substr get the value (0 or 1) index by index
If index value = 1 then add relevant code to string
Is there a better way to go about this?

You can test bits on input from 0 to 7, and take only these that are set,
my $in = 213;
my #r = ("standard","special","regular","late","early","on time","generic","rfu");
print join " + ", #r[ grep { $in & (1 << $_) } 0 .. $#r ];
# or
# print join " + ", map { $in & (1<<$_) ? $r[$_] : () } 0 .. $#r;
output
standard + regular + early + generic + rfu

Related

Incrementing numbers in REXX

I have a requirement where I take a SUBSTR (e.g st_detail = "%BOM0007992739871P", st_digit = SUBSTR(st_detail, 8, 10) ). I have to do some validations on the st_digit and if it is valid change "%BOM0002562186P" to "%BOM0002562186C". My code works fine upto this. But I was asked to increment st_digit (I used st_digit = st_digit + 1 ) and print 100 valid st_digits and append it with C. so I put the code in a loop and display st_detail. But when i ran it i got "%BOM0007.99273987E+9C" after first increment. Please help on how to display "%BOM0007992739872C"? (NOTE: this is a reference only and I can't display the validation logic here and my code works fine. The extra code i added was the code I used here)
out_ctr = 1
DO while out_ctr < 101
/* validations */
IF valid THEN
say st_digit " is valid"
ELSE
say st_digit " is invalid"
st_digit = st_digit + 1
out_ctr = out_ctr + 1
END
It seems the NUMERIC setting was " 9 0 SCIENTIFIC ". I changed it to NUMERIC DIGITS 12, So, now it works.
parse numeric my_numeric_settings
say my_numeric_settings /* 9 0 SCIENTIFIC */
NUMERIC DIGITS 16
parse numeric my_numeric_settings
say my_numeric_settings /* 16 0 SCIENTIFIC */
It's because I used SUBSTR(st_detail, 8, 10),So, st_digit is of length 10, which is greater than the DEFAULT setting of "9 0 SCIENTIFIC", So by changing it to either "NUMERIC DIGITS 10" or "NUMERIC DIGITS 12" the code worked.

How to convert MongoDB UUID to string in MongoDB query? [duplicate]

I currently have some ids stored in Mongo as UUIDs (necessary for processing). They get returned like this:
"_id" : new BinData(3, "JliB6gIMRuSphAD2KmhzgQ==")
What would be an easy way to turn this value into a string for debugging?
Just to be clear - the application can handle the data fine. I just need a way to get the actual UUID from Mongo quickly.
The answer to your question is more complicated that you would expect! The main reason it's complicated is that for historical reasons (unfortunately) different drivers have written UUIDs to the database using different byte orders. You don't mention which driver you are using, but I'll use the C# driver as an example.
Suppose I use the following code to insert a document:
var guid = new Guid("00112233-4455-6677-8899-aabbccddeeff");
collection.Insert(new BsonDocument {
{ "_id", guid },
{ "x", 1 }
});
If I then examine the document using the Mongo shell, it looks like this:
> db.test.findOne()
{ "_id" : BinData(3,"MyIRAFVEd2aImaq7zN3u/w=="), "x" : 1 }
>
The Mongo shell has a built-in function called hex that you can use to display the binary value as a hex string:
> var doc = db.test.findOne()
> doc._id.hex()
33221100554477668899aabbccddeeff
>
Look carefully: the byte order of the hex string doesn't match the original UUID value used in the C# program. That's because the C# driver uses the byte order returned by Microsoft's ToByteArray method of the Guid class (which sadly returns the bytes in a bizarre order, which fact was not discovered for many months). Other drivers have their own idiosyncracies.
To help out with this we have some helper functions written in Javascript that can be loaded into the Mongo shell. They are defined in this file:
https://github.com/mongodb/mongo-csharp-driver/blob/master/uuidhelpers.js
The Mongo shell can be told to process a file as it starts up by providing the name of the file on the command line (along with the --shell argument). Having loaded this file we have access to a number of helper functions to create and display BinData values that are UUIDs. For example:
C:\mongodb\mongodb-win32-x86_64-2.0.1\bin>mongo --shell uuidhelpers.js
MongoDB shell version: 2.0.1
connecting to: test
type "help" for help
> var doc = db.test.findOne()
> doc._id.toCSUUID()
CSUUID("00112233-4455-6677-8899-aabbccddeeff")
> db.test.find({_id : CSUUID("00112233-4455-6677-8899-aabbccddeeff")})
{ "_id" : BinData(3,"MyIRAFVEd2aImaq7zN3u/w=="), "x" : 1 }
>
In this example the toCSUUID function is used to display a BinData value as a CSUUID and the CSUUID function is used to create a BinData value for a UUID using the C# driver's byte ordering conventions so that we can query on a UUID. There are similar functions for the other drivers (toJUUID, toPYUUID, JUUID, PYUUID).
Some day in the future all drivers will standardize on a new binary subtype 4 with a standard byte order. In the meantime you have to use the appropriate helper function that matches whatever driver you are using.
Use this function before your query:
function ToGUID(hex) {
var a = hex.substr(6, 2) + hex.substr(4, 2) + hex.substr(2, 2) + hex.substr(0, 2);
var b = hex.substr(10, 2) + hex.substr(8, 2);
var c = hex.substr(14, 2) + hex.substr(12, 2);
var d = hex.substr(16, 16);
hex = a + b + c + d;
var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
return '"' + uuid + '"';
}
var id = new BinData(3, "JliB6gIMRuSphAD2KmhzgQ==");
ToGUID(id.hex());
Result:
"ea815826-0c02-e446-a984-00f62a687381"
If you are using Java spring-data, you can use this algorithm:
function ToUUID(hex) {
var msb = hex.substr(0, 16);
var lsb = hex.substr(16, 16);
msb = msb.substr(14, 2) + msb.substr(12, 2) + msb.substr(10, 2) + msb.substr(8, 2) + msb.substr(6, 2) + msb.substr(4, 2) + msb.substr(2, 2) + msb.substr(0, 2);
lsb = lsb.substr(14, 2) + lsb.substr(12, 2) + lsb.substr(10, 2) + lsb.substr(8, 2) + lsb.substr(6, 2) + lsb.substr(4, 2) + lsb.substr(2, 2) + lsb.substr(0, 2);
hex = msb + lsb;
var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
return uuid;
}
def binaryToUUID(byte: Array[Byte]): String = {
if (byte == null) null
else {
val bb = ByteBuffer.wrap(byte)
new UUID(bb.getLong, bb.getLong()).toString
}
}
If your mongodb driver uses javascript, then you could try this to get hex:
BinData(3,"ABEiM0RVZneImaq7zN3u/w==").toString('hex');

Split an array based on value

This is my first question here, so sorry if I make any mistakes posting this.
I'm trying to split an array based on its values. Basically I want to create two arrays whose values are as close to the average as possible. I managed to do this with this code:
function Sum($v) {
[Linq.Enumerable]::Sum([int64[]]$v)
}
$arr = 0..9 | % {get-random -min 1 -max 10}
"ARRAY:" + $arr
"SUM: " + (sum $arr)
"AVG: " + (sum $arr)/2
# start of the code that matters
$wavg = (sum $arr)/2
foreach ($i in (0..($arr.Count-1))) {
$wavg -= $arr[$i]
if ($wavg -le 0) {
$i-=(-$wavg -gt $arr[$i]/2);break
}
}
"SPLIT INDEX: " + $i
"ARR1: " + $arr[0..$i] + " (" + $(sum $arr[0..$i]) + ")"
"ARR2: " + $arr[($i+1)..$arr.Count] + " (" + $(sum $arr[($i+1)..$arr.Count]) + ")"
The reason my foreach is structured this way is because in my actual code the values are in an index hash and are accessed as $index[$arr[$i]].
This means that the resulting two arrays could be of unequal size (it would be easy if I could just split the array in half). Sample output of my code to demonstrate this:
ARRAY: 5 3 6 3 2 3 6 3 1 3
SUM: 35
AVG: 17.5
SPLIT INDEX: 3
ARR1: 5 3 6 3 (17)
ARR2: 2 3 6 3 1 3 (18)
The code works as is, but I feel it could be done in a more elegant and speedier way. Because I need to execute this code a few thousand times in my script I want it to be as fast as possible.

Finding notes sounding at the same time in a different voice in a midi file

I have a midi file consisting of two parts. Now I need to print out, for each note in part 0 (including rests), which note sounds at the same time in part 1 (and the note that proceeds this).
I can go through all of the notes in part 0 with music21, but how do I find the note at that time in part 1. Will I need to use end times? Or is there a function for this?
for thisNote in s.parts[0].notes:
print thisNote.ps
Here is a very interesting function that let me solve this:
secondPart = s.parts[1]
for thisNote in s.parts[0].notes:
sys.stdout.write('at ' + str(thisNote.offset) + ' toppitch: ' + str(thisNote.ps))
soundingNotes = secondPart.getElementsByOffset(thisNote.offset, mustFinishInSpan=False, mustBeginInSpan=False)
try:
if soundingNotes > 0:
basslength = len(soundingNotes)
except:
basslength = 0
if basslength > 1:
print "oh ow, more then one note sounding in the bass."
if basslength > 0:
if soundingNotes[0].isRest:
sys.stdout.write(' bottompitch: R')
else:
sys.stdout.write(' bottompitch: ' + str(soundingNotes[0].ps)) # + ' from ' + str(soundingNotes[0].offset))
# print the previous note
soundingNotes2 = secondPart.getElementsByOffset(thisNote.offset-1, mustFinishInSpan=False, mustBeginInSpan=False)

Get BinData UUID from Mongo as string

I currently have some ids stored in Mongo as UUIDs (necessary for processing). They get returned like this:
"_id" : new BinData(3, "JliB6gIMRuSphAD2KmhzgQ==")
What would be an easy way to turn this value into a string for debugging?
Just to be clear - the application can handle the data fine. I just need a way to get the actual UUID from Mongo quickly.
The answer to your question is more complicated that you would expect! The main reason it's complicated is that for historical reasons (unfortunately) different drivers have written UUIDs to the database using different byte orders. You don't mention which driver you are using, but I'll use the C# driver as an example.
Suppose I use the following code to insert a document:
var guid = new Guid("00112233-4455-6677-8899-aabbccddeeff");
collection.Insert(new BsonDocument {
{ "_id", guid },
{ "x", 1 }
});
If I then examine the document using the Mongo shell, it looks like this:
> db.test.findOne()
{ "_id" : BinData(3,"MyIRAFVEd2aImaq7zN3u/w=="), "x" : 1 }
>
The Mongo shell has a built-in function called hex that you can use to display the binary value as a hex string:
> var doc = db.test.findOne()
> doc._id.hex()
33221100554477668899aabbccddeeff
>
Look carefully: the byte order of the hex string doesn't match the original UUID value used in the C# program. That's because the C# driver uses the byte order returned by Microsoft's ToByteArray method of the Guid class (which sadly returns the bytes in a bizarre order, which fact was not discovered for many months). Other drivers have their own idiosyncracies.
To help out with this we have some helper functions written in Javascript that can be loaded into the Mongo shell. They are defined in this file:
https://github.com/mongodb/mongo-csharp-driver/blob/master/uuidhelpers.js
The Mongo shell can be told to process a file as it starts up by providing the name of the file on the command line (along with the --shell argument). Having loaded this file we have access to a number of helper functions to create and display BinData values that are UUIDs. For example:
C:\mongodb\mongodb-win32-x86_64-2.0.1\bin>mongo --shell uuidhelpers.js
MongoDB shell version: 2.0.1
connecting to: test
type "help" for help
> var doc = db.test.findOne()
> doc._id.toCSUUID()
CSUUID("00112233-4455-6677-8899-aabbccddeeff")
> db.test.find({_id : CSUUID("00112233-4455-6677-8899-aabbccddeeff")})
{ "_id" : BinData(3,"MyIRAFVEd2aImaq7zN3u/w=="), "x" : 1 }
>
In this example the toCSUUID function is used to display a BinData value as a CSUUID and the CSUUID function is used to create a BinData value for a UUID using the C# driver's byte ordering conventions so that we can query on a UUID. There are similar functions for the other drivers (toJUUID, toPYUUID, JUUID, PYUUID).
Some day in the future all drivers will standardize on a new binary subtype 4 with a standard byte order. In the meantime you have to use the appropriate helper function that matches whatever driver you are using.
Use this function before your query:
function ToGUID(hex) {
var a = hex.substr(6, 2) + hex.substr(4, 2) + hex.substr(2, 2) + hex.substr(0, 2);
var b = hex.substr(10, 2) + hex.substr(8, 2);
var c = hex.substr(14, 2) + hex.substr(12, 2);
var d = hex.substr(16, 16);
hex = a + b + c + d;
var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
return '"' + uuid + '"';
}
var id = new BinData(3, "JliB6gIMRuSphAD2KmhzgQ==");
ToGUID(id.hex());
Result:
"ea815826-0c02-e446-a984-00f62a687381"
If you are using Java spring-data, you can use this algorithm:
function ToUUID(hex) {
var msb = hex.substr(0, 16);
var lsb = hex.substr(16, 16);
msb = msb.substr(14, 2) + msb.substr(12, 2) + msb.substr(10, 2) + msb.substr(8, 2) + msb.substr(6, 2) + msb.substr(4, 2) + msb.substr(2, 2) + msb.substr(0, 2);
lsb = lsb.substr(14, 2) + lsb.substr(12, 2) + lsb.substr(10, 2) + lsb.substr(8, 2) + lsb.substr(6, 2) + lsb.substr(4, 2) + lsb.substr(2, 2) + lsb.substr(0, 2);
hex = msb + lsb;
var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
return uuid;
}
def binaryToUUID(byte: Array[Byte]): String = {
if (byte == null) null
else {
val bb = ByteBuffer.wrap(byte)
new UUID(bb.getLong, bb.getLong()).toString
}
}
If your mongodb driver uses javascript, then you could try this to get hex:
BinData(3,"ABEiM0RVZneImaq7zN3u/w==").toString('hex');