Storing bit flags and BCD lookup data in Ruby - ruby

I'm writing a CLI that interacts with an external USB device. The device's status is discovered by reading the Status registers, 24x 8 bits wide. The register values are read from a serial port and arrive as an array of Strings:
=> ["000", "000", "000", "000", "086", "003", "000", "000", "255", "255", ...]
The registers are in 2 formats, bit flags and BCD (I'm not sure of Correct terminology here). They can be mix also.
Bit flags
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
Bit 1
Bit 0
Error 10
Error 11
Error 12
Error 13
Error 14
Error 15
Error 16
Error 17
A value of 34 (0b00100010) means 'Error 16' and 'Error 12' are present.
BCD
Bit 2
Bit 1
Bit 0
result
0
0
0
State A
0
0
1
State B
0
1
0
State C
0
1
1
State D
1
1
1
State E
A value of 3 (0b00000011) means 'State D'
Is there an elegant Ruby way (or conventions) for storing and looking up this type of String data?

Although I don't quite understand what's the relation between the 24*8 Status registers and Bit flags and BCD, but I think it's just about the number base conversion.
You can use to_s if you want to change the number base from 2 to 36.
5.to_s(2)
# => '101'
255.to_s(2)
# => '11111111'
36.to_s(36)
# => '10'
After you convert the number to binary, you can use rjust to supplement with the leading zeros.
5.to_s(2).rjust(8, '0')
# => '00000101'
Then you can use the index of the string to decide what is the status now.
For Bit flags, you can make a array of errors:
errors = ['Error 10', 'Error 11', 'Error 12', 'Error 13', 'Error 14', 'Error 15', 'Error 16', 'Error 17']
'034'.to_i.to_s(2).rjust(8, '0').chars.each_with_index.map do |bit, index|
bit == '1' ? errors[index] : nil
end.compact
# => ["Error 12", "Error 16"]
For BCD you can make a Hash variable for the states:
states = {
'000' => 'A',
'001' => 'B',
'010' => 'C',
'011' => 'D',
'111' => 'E',
}
bits = '003'.to_i.to_s(2).rjust(8, '0')[-3..-1]
states[bits]
# => 'D'
btw, your markdown tables don't display well...

Related

Trying to get daykey for Array but not getting output as required

I am trying to get the daykey from dates which i need to use in Array to fill "0" if data is not available .
My dates start from "2022-02-08" and end with "2022-03-10".
Trying to get daykey using code
$rahul = Buffalomilkrecord::select(DB::raw('date'), DB::raw('sum(totalmilk) as totalmilk, DATE_FORMAT(date,"%d") as "daykey"'))
->whereBetween('date', [$olddate, $todaydate] )
->groupBy(DB::raw('date'))
->orderBy('date','asc')
->get();
the out put i am getting
array:31 [▼
0 => "2022-03-01"
1 => 0
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => "2022-02-08"
8 => 0
9 => 0
10 => 0
11 => 0
12 => 0
13 => 0
14 => 0
15 => "2022-02-16"
16 => "2022-02-17"
17 => "2022-02-18"
18 => "2022-02-19"
19 => "2022-02-20"
20 => "2022-02-21"
21 => "2022-02-22"
22 => "2022-02-23"
23 => 0
24 => "2022-02-25"
25 => "2022-02-26"
26 => 0
27 => 0
28 => 0
29 => 0
30 => 0
]
$ddtest = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
foreach($rahul as $order)
{
$ddtest[$order->daykey-1] = $order->date;
}
Here i am expecting to start array with
0 => "2022-02-08" and so on.... as date start in Month and end with March
I feel i am doing some error in query but can not find where i am doing mistake..
Thanks in advance for help
The SQL will only return exiting data, so if there is no data for this specific day, you wont get a row for this day. This is something you have to take care outside of the query.
You need to build the date range by yourself. for example like this:
I have 2 dates in PHP, how can I run a foreach loop to go through all of those days?
Build one array with "default" entries per day with 0 values and than merge them with the sql result.

High & Low Numbers From A String (Ruby)

Good evening,
I'm trying to solve a problem on Codewars:
In this little assignment you are given a string of space separated numbers, and have to return the highest and lowest number.
Example:
high_and_low("1 2 3 4 5") # return "5 1"
high_and_low("1 2 -3 4 5") # return "5 -3"
high_and_low("1 9 3 4 -5") # return "9 -5"
Notes:
All numbers are valid Int32, no need to validate them.
There will always be at least one number in the input string.
Output string must be two numbers separated by a single space, and highest number is first.
I came up with the following solution however I cannot figure out why the method is only returning "542" and not "-214 542". I also tried using #at, #shift and #pop, with the same result.
Is there something I am missing? I hope someone can point me in the right direction. I would like to understand why this is happening.
def high_and_low(numbers)
numberArray = numbers.split(/\s/).map(&:to_i).sort
numberArray[-1]
numberArray[0]
end
high_and_low("4 5 29 54 4 0 -214 542 -64 1 -3 6 -6")
EDIT
I also tried this and receive a failed test "Nil":
def high_and_low(numbers)
numberArray = numbers.split(/\s/).map(&:to_i).sort
puts "#{numberArray[-1]}" + " " + "#{numberArray[0]}"
end
When omitting the return statement, a function will only return the result of the last expression within its body. To return both as an Array write:
def high_and_low(numbers)
numberArray = numbers.split(/\s/).map(&:to_i).sort
return numberArray[0], numberArray[-1]
end
puts high_and_low("4 5 29 54 4 0 -214 542 -64 1 -3 6 -6")
# => [-214, 542]
Using sort would be inefficient for big arrays. Instead, use Enumerable#minmax:
numbers.split.map(&:to_i).minmax
# => [-214, 542]
Or use Enumerable#minmax_by if you like result to remain strings:
numbers.split.minmax_by(&:to_i)
# => ["-214", "542"]

Suggestions for data extraction Data in fortran

I use F95/90 and IBM compiler. I am trying to extract the numerical values from block and write in a file. I am facing a strange error in the output which I cannot understand. Every time I execute the program it skips the loop between 'Beta' and 'END'. I am trying to read and store the values.
The number of lines inside the Alpha- and Beta loops are not fixed. So a simple 'do loop' is of no use to me. I tried the 'do while' loop and also 'if-else' but it still skips the 'Beta' part.
Alpha Singles Amplitudes
15 3 23 4 -0.186952
15 3 26 4 0.599918
15 3 31 4 0.105048
15 3 23 4 0.186952
Beta Singles Amplitudes
15 3 23 4 0.186952
15 3 26 4 -0.599918
15 3 31 4 -0.105048
15 3 23 4 -0.186952
END `
The simple short code is :
program test_read
implicit none
integer::nop,a,b,c,d,e,i,j,k,l,m,ios
double precision::r,t,rr
character::dummy*300
character*15::du1,du2,du3
open (unit=10, file="1.txt", status='old',form='formatted')
100 read(10,'(a100)')dummy
if (dummy(1:3)=='END') goto 200
if(dummy(2:14)=='Alpha Singles') then
i=0
160 read(10,'(a4,i2,a6,i1,a4,i2,a6,i1,f12.6)')du1,b,du2,c,du3,d,du4,e,r
do while(du1.ne.' Bet')
write(*,'(a2,a4,i2,a6,i1,a4,i2,a6,i1,f12.6)')'AS',du1,b,du2,c,du3,d,du4,e,r
goto 160
end do
elseif (dummy(2:14)=='Beta Singles') then
170 read(10,'(a4,i2,a6,i1,a4,i2,a6,i1,f12.6)')du1,b,du2,c,du3,d,du4,e,r
if((du1=='END'))then
stop
else
write(*,'(a2,a4,i2,a6,i1,a4,i2,a6,i1,f12.6)')'BS',du1,b,du2,c,du3,d,du4,e,r
goto 170
end if
end if
goto 100
200 print*,'This is the end'
end program test_read
Your program never gets out of the loop which checks for Beta because when your while loop exits, it has already read the line with Beta. It then goes to 100 which reads the next line after Beta, so you never actually see Beta Singles. Try the following
character(len=2):: tag
read(10,'(a100)')dummy
do while (dummy(1:3).ne.'END')
if (dummy(2:14)=='Alpha Singles') then
tag = 'AS'
else if (dummy(2:14)=='Beta Singles') then
tag = 'BS'
else
read(dummy,'(a4,i2,a6,i1,a4,i2,a6,i1,f12.6)')du1,b,du2,c,du3,d,du4,e,r
write(*,'(a2,a4,i2,a6,i1,a4,i2,a6,i1,f12.6)')tag,du1,b,du2,c,du3,d,du4,e,r
end if
read(10, '(a100)') dummy
end do
print*,'This is the end'

ruby YAML parse bug with number

I have encountered what appears to be a bug with the YAML parser. Take this simple yaml file for example:
new account:
- FLEETBOSTON
- 011001742
If you parse it using this ruby line of code:
INPUT_DATA = YAML.load_file("test.yml")
Then I get this back:
{"new account"=>["FLEETBOSTON", 2360290]}
Am I doing something wrong? Because I'm pretty sure this is never supposed to happen.
It is supposed to happen. Numbers starting with 0 are in octal notation. Unless the next character is x, in which case they're hexadecimal.
07 == 7
010 == 8
011 == 9
0x9 == 9
0xA == 10
0xF == 15
0x10 == 16
0x11 == 17
Go into irb and just type in 011001742.
1.9.2-p290 :001 > 011001742
=> 2360290
PEBKAC. :)
Your number is a number, so it's treated as a number. If you want to make it explictly a string, enclose it into quotes, so YAML will not try to make it a number.
new account:
- FLEETBOSTON
- '011001742'

Btrieve GetNextExtended Status 62

I'm having trouble getting the GetNextExtended(36) operation working
in Btrieve. Here is the call which returns the status code 62 :
intStatus = BTRCALL(B_GETNEXTEXTENDED, _
m_byteFilePosBlk, _
m_byteRecordBuffer(0), _
lngDataBufferLen, _
ByVal strKeyBuffer, _
intKeyBufferLen, _
m_intKeyNum)
After doing a search for the code I found numerous site stating that the
code indicates an error in the databuffer, stored in m_byteRecordBuffer.
Here are the values stored in that variable :
m_byteRecordBuffer(0) 16 'These two bytes indicate the total size of'
m_byteRecordBuffer(1) 0 'data buffer'
m_byteRecordBuffer(2) 67 'These two bytes indicate the characters 'UC''
m_byteRecordBuffer(3) 85
m_byteRecordBuffer(4) 0 'These two bytes indicate the maximum reject'
m_byteRecordBuffer(5) 0 'count, which if set to 0 defaults to 4,095'
m_byteRecordBuffer(6) 0 'These two bytes indicate the number of terms'
m_byteRecordBuffer(7) 0 'which has been set to zero'
m_byteRecordBuffer(8) 1 'These two bytes indicate the number of'
m_byteRecordBuffer(9) 0 'records to return'
m_byteRecordBuffer(10) 1 'These two bytes indicate the number of fields'
m_byteRecordBuffer(11) 0 'to extract'
m_byteRecordBuffer(12) 2 'These two bytes indicate the length of the'
m_byteRecordBuffer(13) 0 'field to extract'
m_byteRecordBuffer(14) 1 'These two bytes indicate the field offset'
m_byteRecordBuffer(15) 0
I hope I am just missing something simple. Any help would be greatly appreciated.
In the record buffer, try swapping the position of the UC characters.
Put 'U' (85) in position 2 and 'C' (67) in position 3.

Resources