RPGLE code to RPG - Count number of Digits - rpgle

I am having an issue with coding this, I need some similar code with this but written in RPG to count the digits in a number.
NumField (15, 0) packed decimal
EVAL numDig = %len(%trim(%char(NumField)))

the %editc built in function dates back to the begin of time. So does %len, %trim and varying fields.
** ---------------------- test0003r ---------------------------
dtest0003r pi
d errmsg s 256a
d packNum s 15p 0
d lx s 10i 0
d v20 s 20a varying
d ch50 s 50a
/free
packNum = 32553;
v20 = %trim(%editc(packNum:'Z')) ;
lx = %len(v20) ;
ch50 = %trim(%editc(lx:'Z')) + ' ' + v20 ;
dsply ch50 ;
*inlr = '1' ;
return ;
/end-free

A fun challenge.
#zen, I agree with others. I would not try to code this in RPG III. I would either convert the RPG III program to RPG IV, or I would call an RPG IV program to do this calculation.
But here is some RPG III code that gets the number of digits. It is horrible code, and almost completely untested. I would never use this code or recommend that anyone else use this code.
C Z-ADD1.2 NUM 52
C EXSR SUB1
C Z-ADD-123.45 NUM 52
C EXSR SUB1
C Z-ADD0 NUM 52
C EXSR SUB1
C RETRN
C SUB1 BEGSR
C MOVELNUM STR 30 P
C '0':' ' XLATESTR STR2 30 P
C ' ' CHECKSTR2 P 50
C P IFGT 0
C SUBSTSTR2:P STR3 30 P
C ' ' CHEKRSTR3 P 50
C ENDIF
C P DSPLY
C ENDSR
It displays 2, 5, 0.

Related

Get If (condition), then (assign value), else (assign other value) statement in Linear Programming

I'm looking for a linear programming equation that satisfied the conditions;
Given that all variables here are binary variables
if A+B = 2; then C = 1; else C = 0
Also,
if A+B+D = 3; then E = 1; else E = 0
How would one phrase this and satisfy these conditions as well as linearity conditions?
I've tried
A + B - 2 <= M(1-y) and 1 - C <= My
for the first constraint but it doesn't seem to work
For the first equation, you can use:
C + 1 >= A + B
2C <= A + B
If there is a natural sense (max/min) for C in the problem, one of those is sufficient.
Similarly for the second:
E + 2 >= A + B + D
3E <= A + B + D

How to calculate the number of neighbors of a string with exact and at most d mismatches?

Given a string, and a set of four alphabets (A, B, C, D) for generating strings of length n. I need a generalized mathematical formula to calculate the number of neighbors for any string of length n with at most d mismatches, and the number of neighbors with exactly d mismatches.
For example: Given a string=”AAA” and d=3
We have 9 Strings with exactly d=1
BAA
CAA
DAA
ABA
ACA
ADA
AAB
AAC
AAD
We have 27 Strings with exactly d=2
BBA BCA BDA
BAB BAC BAD
CBA CCA CDA
CAB CAC CAD
DBA DCA DDA
DAB DAC DAD
ABB ABC ABD
ACB ACC ACD
ADB ADC ADD
We have 27 Strings with exactly d=3
BBB CBB DBB
BCB CCB DCB
BDB CDB DDB
BBC CBC DBC
BCC CCC DCC
BDC CDC DDC
BBD CBD DBD
BCD CCD DCD
BDD CDD DDD
Number of Strings with at most d=3 are 9+27+27=63 strings
Let's consider a string of size n.
We want to know how many 'neighbors' this string has, with a distance d. The first thing we remark, with your definition of 'distance', is that it means that we must choose d characters among the n of the string and modify them. So there are n choose d possible combinations of charactersto modify.
Each of these can be modified in 3 different manners (since the size of the alphabet is 4.
So ultimately, we have:
n choose d possible combinations of characters that will be modified
d characters will be modified, and each of them can be modified in 3different manners.
So the formula is ultimately (s - 1) ^ d * (n choose d), where s is the size of the alphabet (here 4). I let you verify that it fits the first examples you provided.
If you want to try it out:
#include <iostream>
#include <string>
using namespace std;
int n = 3; int d = 2;
string s = "AAA";
int counter(string curr, int index, int currd){
if(currd == 0 || index == n){
cout<<curr<<s.substr(index, n - index)<<endl;
return 1;
}
int ans = 0;
for(char c = 'A'; c < 'E'; c++){
if(c != s[index]){
ans += counter(curr + c, index + 1, currd - 1);
}
else{
ans += counter(curr + c, index + 1, currd);
}
}
return ans;
}
int main(){
cout<<"answer = "<<counter("", 0, d) - 1;
}

Use regexprep with cell array for colons to format

I have a cell array formatted as:
t = {'23:34:22.959511';
'22:34:11.885113';
'12:34:08.995146';
'11:34:02.383092'}
I am trying to format the output as 4 column vectors as:
a = 23
22
12
11
b = 34
34
34
34
c = 22
11
08
02
d = 959511
885113
995146
383092
I am using regexprep to operate on the data:
a = regexprep(t,':34:22.959511', '')
However this only pertains to only one string in the data set and not all strings.
How do I divide the string into 4 column vectors -- using regexprep for colon: and display the output below?
If you're willing to use other solutions that regexp: strplit can split on any desired character:
a = zeros(numel(t),1);
b = zeros(numel(t),1);
c = zeros(numel(t),1);
d = zeros(numel(t),1);
for ii = 1:numel(t)
C = strsplit(t{ii}, ':');
a(ii) = str2double(C{1});
b(ii) = str2double(C{2});
tmp = strsplit(C{3},'.'); % Additional split for dot
c(ii) = str2double(tmp{1});
d(ii) = str2double(tmp{2});
end
Of course this only works when your data always has this structure (two colons, then one dot)
Here's a way:
r = cell2mat(cellfun(#str2double, regexp(t, ':|\.', 'split'), 'uniformoutput', false));
This gives
r =
23 34 22 959511
22 34 11 885113
12 34 8 995146
11 34 2 383092
If you really need four separate variables, you can use:
r = num2cell(r,1);
[a, b, c, d] = r{:};
I would recommend using split instead of strsplit. split will operate on vectors and if you use the string datatype you can just call double on the string to get the numeric value
>> profFunc
Adriaan's Solution: 5.299892
Luis Mendo's Solution: 3.449811
My Solution: 0.094535
function profFunc()
n = 1e4; % Loop to get measurable timings
t = ["23:34:22.959511";
"22:34:11.885113";
"12:34:08.995146";
"11:34:02.383092"];
tic
for i = 1:n
a = zeros(numel(t),1);
b = zeros(numel(t),1);
c = zeros(numel(t),1);
d = zeros(numel(t),1);
for ii = 1:numel(t)
C = strsplit(t{ii}, ':');
a(ii) = str2double(C{1});
b(ii) = str2double(C{2});
tmp = strsplit(C{3},'.'); % Additional split for dot
c(ii) = str2double(tmp{1});
d(ii) = str2double(tmp{2});
end
end
fprintf('Adriaan''s Solution: %f\n',toc);
tic
for i = 1:n
r = cell2mat(cellfun(#str2double, regexp(t, ':|\.', 'split'), 'uniformoutput', false));
r = num2cell(r,1);
[a, b, c, d] = r{:};
end
fprintf('Luis Mendo''s Solution: %f\n',toc);
tic
for i = 1:n
x = split(t,[":" "."]);
x = double(x);
a = x(:,1);
b = x(:,2);
c = x(:,3);
d = x(:,4);
end
fprintf('My Solution: %f\n',toc);

Problem with GCC compiler

I am using Arch Linux and when I am compiling and running the following C code,
#include <stdio.h>
#include<string.h>
int main(void) {
char s1[]="Hello";
char s2[]="World";
strcat(s1,s2);
int s2_len=strlen(s2);
printf("s1 = %s, s2 = %s and length of s2 = %d.\n", s1, s2, s2_len);
return 0;
}
I am getting the output:
s1 = HelloWorld, s2 = orld and length of s2 = 4.
Although the output shoud be s1 = HelloWorld, s2 = World and length of s2 = 5. and it is the output when I am using some online IDE.
Can somebody explain me why is this happening?
char s1[]="Hello";
char s2[]="World";
strcat(s1,s2);
The variable declarations allocate memory for 5 characters each, plus the terminating NUL byte. Your strcat call writes past that space, which produces undefined results.
In this case, the memory layout is probably something like this
0 1 2 3 4 5 6 7 8 9 10 11
H e l l o \0 W o r l d \0
^ ^
s1 s2
After the strcat, the result is:
0 1 2 3 4 5 6 7 8 9 10 11
H e l l o W o r l d \0 \0
^ ^
s1 s2
Which gives the result you see. Note that there could be other possible results, the program could e.g. crash at the strcat call.

Definition not found for symbol 'QMHSNDPM'

I am following Scott Klement's tutorials on IFS programming with RPGLE. I am facing the below issues. I have added the code snippets as well. Please assist.
Ownership of object WITHERRH in QTEMP type *MODULE changed.
*SRVPGM object QZDMMDTA in library QSOC not found.
Definition not found for symbol 'QMHSNDPM'.
Definition not found for symbol 'QMHSNDPM'.
Program WITHERRH in library ABCLIBL not created.
The PR were defined inside this copy source.
/if not defined(ERRNO_H)
D strerror PR * extproc('strerror')
D errnum 10I 0 value
/define ERRNO_H
/endif
/if defined(ERRNO_LOAD_PROCEDURE)
P die B
D die PI N
D msg 256A const
D QMHSNDPM PR extproc('QMHSNDPM')
D messageId 7A const
D qualMsgF 20A const
D msgData 256A const
D msgDataLen 10I 0 const
D msgType 10A const
D callSktEnt 10A const
D callSktCnt 10I 0 const
D messageKey 4A
D errorCode 256A
D dsEC DS
D dsECBytesP 1 4I 0 inz(%size(dsEC))
D dsECBytesA 5 8I 0 inz(0)
D dsECMsgId 9 15
D dsECReserv 16 16
D dsECMsgData 17 256
D msgLen S 10I 0
D theKey S 4A
msgLen = %checkr(msg:' ');
if msgLen < 1;
return *off;
endif;
callP QMHSNDPM('CPF9897':'QCPFMSG *LIBL':msg:msgLen:
'*ESCAPE':'*':3:theKey:dsEC);
return *off;
P E
The main program has QC2LE binding directory added; the 'die' procedure is invoked as below,
H dftactgrp(*no) actgrp(*new) bnddir('QC2LE')
D/copy ABCLIBL/QIFSSRC,IFSIO_H
D/copy ABCLIBL/QIFSSRC,ERRNO_H
.....
if write(fd:%addr(wrdata):%size(wrdata)) < 1;
errMsg = %str(strerror(errno));
callP close(fd);
callP die('open(): ' + errMsg);
endif;
As #user2338816 said QMHSNDPM is a external program not a procedure:
D QMHSNDPM PR extpgm('QMHSNDPM')
Most APIs are external programs and not procedures. And when they aren't external programs it's easy to see from the documentation.
For example: Dump Module Variables
With this API you would bind your program to the QTEDMPV service program and then use extproc to reference the procedure.
D DumpVariables PR extproc('QteDumpModuleVariables')

Resources