I have a checksum that I need to add to a ruby string in hex. I have been unable to convert the checksum successfully. I am relatively new to ruby, so I'm not sure if I'm missing something. Here is what I am doing:
def get_checksum message
# get the checksum
cnt = 0
lrc = 0
while (cnt < message.length - 1)
lrc = lrc ^ message[cnt].to_i
cnt += 1
end
# return as hex
lrc.to_s.each_byte.map { |b| b.to_s(16) + " " }.join
end
I have some c# reference code as well, but have never used C# being a long time mac C/C++/Obj-C coder. Here is the C# code I am trying to convert:
// calculate LRC
private string GetChecksum(string inputstring)
{
int checksum = 0;
foreach (char c in inputstring)
{
checksum ^= Convert.ToByte(c);
}
return checksum.ToString("X2");
}
Any help would be appreciated.
.to_i will return 0 when called on a character.
def get_checksum message
# get the checksum
lrc = 0
message.each_byte do |b|
lrc = lrc ^ b
end
# return as hex
lrc.to_s(16)
end
Related
How do i make a random to an int to use it afterwards?
Error i get:
CS0029 Cannot implicitly convert type 'System.Random' to 'int'
Console.Write("How old am i? Guess!");
string randomguess = Console.ReadLine();
Console.WriteLine("My age is " + (random.Next(1, 101)));
int newrandomguess = Convert.ToInt32(randomguess);
if(newrandomguess == random)
{
Console.WriteLine("Oh you guessed my age correctly! Im surprised.");
}
else
{
Console.WriteLine("As i expected, u guessed wrong..");
}
To make a new random value:
int randomValue = random.Next(1, 101);
To use that random value to write out to the console:
Console.WriteLine("My age is " + randomValue);
To compare the guess against the value:
if (randomGuess == randomValue)
{
...
}
I'm making a JSON parser and I am looking for an algorithm that can find all of the matching brackets ([]) and braces ({}) and put them into a table with the positions of the pair.
Examples of returned values:
table[x][firstPos][secondPos] = type
table[x] = {firstPos, secondPos, bracketType}
EDIT: Let parse() be the function that returns the bracket pairs. Let table be the value returned by the parse() function. Let codeString be the string containing the brackets that I want to detect. Let firstPos be the position of the first bracket in the Nth pair of brackets. Let secondPos be the position of the second bracket in the Nth pair of brackets. Let bracketType be the type of the bracket pair ("bracket" or "brace").
Example:
If you called:
table = parse(codeString)
table[N][firstPos][secondPos] would be equal to type.
Well, In plain Lua, you could do something like this, also taking into account nested brackets:
function bm(s)
local res ={}
if not s:match('%[') then
return s
end
for k in s:gmatch('%b[]') do
res[#res+1] = bm(k:sub(2,-2))
end
return res
end
Of course you can generalize this easy enough to braces, parentheses, whatever (do keep in mind the necessary escaping of [] in patterns , except behind the %b pattern).
If you're not restricted to plain Lua, you could use LPeg for more flexibility
If you are not looking for the contents of the brackets, but the locations, the recursive approach is harder to implement, since you should keep track of where you are. Easier is just walking through the string and match them while going:
function bm(s,i)
local res={}
res.par=res -- Root
local lev = 0
for loc=1,#s do
if s:sub(loc,loc) == '[' then
lev = lev+1
local t={par=res,start=loc,lev=lev} -- keep track of the parent
res[#res+1] = t -- Add to the parent
res = t -- make this the current working table
print('[',lev,loc)
elseif s:sub(loc,loc) == ']' then
lev = lev-1
if lev<0 then error('too many ]') end -- more closing than opening.
print(']',lev,loc)
res.stop=loc -- save bracket closing position
res = res.par -- revert to the parent.
end
end
return res
end
Now that you have all matched brackets, you can loop through the table, extracting all locations.
I figured out my own algorithm.
function string:findAll(query)
local firstSub = 1
local lastSub = #query
local result = {}
while lastSub <= #self do
if self:sub(firstSub, lastSub) == query then
result[#result + 1] = firstSub
end
firstSub = firstSub + 1
lastSub = lastSub + 1
end
return result
end
function string:findPair(openPos, openChar, closeChar)
local counter = 1
local closePos = openPos
while closePos <= #self do
closePos = closePos + 1
if self:sub(closePos, closePos) == openChar then
counter = counter + 1
elseif self:sub(closePos, closePos) == closeChar then
counter = counter - 1
end
if counter == 0 then
return closePos
end
end
return -1
end
function string:findBrackets(bracketType)
local openBracket = ""
local closeBracket = ""
local openBrackets = {}
local result = {}
if bracketType == "[]" then
openBracket = "["
closeBracket = "]"
elseif bracketType == "{}" then
openBracket = "{"
closeBracket = "}"
elseif bracketType == "()" then
openBracket = "("
closeBracket = ")"
elseif bracketType == "<>" then
openBracket = "<"
closeBracket = ">"
else
error("IllegalArgumentException: Invalid or unrecognized bracket type "..bracketType.."\nFunction: findBrackets()")
end
local openBrackets = self:findAll(openBracket)
if not openBrackets[1] then
return {}
end
for i, j in pairs(openBrackets) do
result[#result + 1] = {j, self:findPair(j, openBracket, closeBracket)}
end
return result
end
Will output:
5 14
6 13
7 12
8 11
9 10
How do I convert a hex strign to its 32 bit signed int equivalent in ruby?
for example
a = "fb6d8cf1" #hex string
[a].pack('H*').unpack('l') #from the documentation it unpacks to its 32 bit signed int
It converts to
-242455045
But the actual answer is
-76706575
Could you point me to what I am doing wrong?
Seems like you had an endian problem. This gives the desired result:
[a].pack("H*").unpack("l>")
# => [-76706575]
["038a67f90"].pack("H*").unpack("l>")
#=> [59402233]
You could flip the bytes yourself to get around the endian and sign issues:
>> ['fb6d8cf1'.scan(/[0-9a-f]{2}/i).reverse.join].pack('H*').unpack('l')
=> [-76706575]
Use:
class String
def to_si(base, lenght = 32)
mid = 2**(length-1)
max_unsigned = 2**length
n = self.to_i base
(n>=mid) ? n - max_unsigned : n
end
end
"fb6d8cf1".to_si 16, 32
I'm trying to send an integer over the serial port to my Ardunio. The chip is then going to display the number in binary on the LED's. However I'm having lots of trouble trying to send the data as a byte over the serial port, as far as I can debug the following code sends it as the ASC char values.
Can anyone point me in the right direction or spot the mistake? I'd really appreciate it. I've been pulling my hair out over this for a long time.
Ruby
require 'rubygems'
require 'serialport' # use Kernel::require on windows, works better.
#params for serial port
port_str = "/dev/tty.usbserial-A700dZt3" #may be different for you
baud_rate = 9600
data_bits = 8
stop_bits = 1
parity = SerialPort::NONE
sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)
i = 15
#just write forever
while true do
sp.write(i.to_s(2))
sleep 10
end
Arduino
int ledPin = 10;
int ledPin1 = 11;
int ledPin2 = 12;
int ledPin3 = 13;
byte incomingByte; // for incoming serial data
void setup() {
pinMode(ledPin, OUTPUT); // initialize the LED pin as an output:
pinMode(ledPin1, OUTPUT); // initialize the LED pin as an output:
pinMode(ledPin2, OUTPUT); // initialize the LED pin as an output:
pinMode(ledPin3, OUTPUT); // initialize the LED pin as an output:
Serial.begin(9600);
Serial.println("I am online");
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
incomingByte = Serial.read();
Serial.println(incomingByte, DEC);
int value = (incomingByte, DEC) % 16;
digitalWrite(ledPin, (value >> 0) % 2);
digitalWrite(ledPin1, (value >> 1) % 2);
digitalWrite(ledPin2, (value >> 2) % 2);
digitalWrite(ledPin3, (value >> 3) % 2); // MSB
}
}
I'm guessing you are trying to write the value 15 in order to light all the LEDs at once. However, 15.to_s(2) is "1111". The ASCII value of the character '1' is 49, so instead of writing 15 once you are writing 49 four times in rapid succession.
The write command you are looking for is therefore probably sp.putc(i). This writes only one character with the given binary value (= machine-readable for Arduino) instead of an ASCII string representation of the value expressed in binary (= human-readable for you).
So keeping everything else the same, replace the while loop in your Ruby code with:
loop do
sp.putc(i)
puts 'Wrote: %d = %bb' % [ i, i ]
i = (i == 15) ? 0 : (i + 1)
sleep(10)
end
If you wish to read the responses from Arduino, you can use e.g. sp.gets to get one line of text, e.g. try placing puts 'Arduino replied: ' + sp.gets in the loop before sleep (and one puts sp.gets before the loop to read the "I am online" sent when the connection is first established).
Edit: I just spotted another problem in your code, on the Arduino side: value = (incomingByte, DEC) % 16; always results in the value 10 because (incomingByte, DEC) has the value DEC (which is 10). You should use value = incomingByte % 16; instead. Or do away with value altogether and modify incomingByte itself, e.g. incomingByte %= 16;.
Your problems may be caused by buffering. To disable buffering, you can do one of the following:
Set sp to unbuffered after creating it (before writing): sp.sync = true
Call flush after the write
Use the unbuffered syswrite instead of write
It's been so long since I did anything with serial ports that I can't help there, but I do see one thing.
>> 15.to_s #=> "15"
and
>> 15.to_s(2) #=> "1111"
I think if you want the binary value to be sent you'll want "\xf" or "\u000F".
Change your code from:
while true do
sp.write(i.to_s(2)) # <-- this sends a multi-character ASCII representation of the "i" value, NOT the binary.
sleep 10
end
to:
while true do
sp.write(i.chr) # <-- this sends a single byte binary representation of the "i" value, NOT the ASCII.
sleep 10
end
To show the difference, here's the length of the strings being output:
>> 15.to_s(2).size #=> 4
>> 15.chr.size #=> 1
And the decimal values of the bytes comprising the strings:
>> 15.to_s(2).bytes.to_a #=> [49, 49, 49, 49]
>> 15.chr.bytes.to_a #=> [15]
I've had this Ruby code work before
while true do
printf("%c", sp.getc)
end
rather than using sp.write(i.to_s). It looks like you are explicitly converting it to a string, which may be the cause of your problems.
I found the original blog post I used:
http://www.arduino.cc/playground/Interfacing/Ruby
I would like to convert a raw string to an array of big-endian words.
As example, here is a JavaScript function that do it well (by Paul Johnston):
/*
* Convert a raw string to an array of big-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binb(input)
{
var output = Array(input.length >> 2);
for(var i = 0; i < output.length; i++)
output[i] = 0;
for(var i = 0; i < input.length * 8; i += 8)
output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
return output;
}
I believe the Ruby equivalent can be String#unpack(format).
However, I don't know what should be the correct format parameter.
Thank you for any help.
Regards
I think you should have posted few examples of the input/output pairs. Here's code that gives me the same output as your JS code in Chrome:
/* JS in Chrome: */
rstr2binb('hello world!')
[1751477356, 1864398703, 1919706145]
# irb, Ruby 1.9.1:
'hello world!'.unpack('N*')
#=> [1751477356, 1864398703, 1919706145]
However, I am not sure it will give the same results if you try it on some multibyte characters, unpack shouldn't be ignoring anything.