In this session we will learn about the XML Parsing in IBM i.For detailed description and explanation refer the E-Book.EBook Link: https://programmers.io/ibmi-ebook/Programmers.io is a registered IBM business partner and a global IT services and consulting firm, providing on-demand software development Read More
Subfile – Single Page Programmers IO
In this session we will learn about the Single Page Subfile in IBM i.For detailed description and explanation refer the E-Book.EBook Link: https://programmers.io/ibmi-ebook/Programmers.io is a registered IBM business partner and a global IT services and consulting firm, providing on-demand software development Read More
Subfile – Load All Programmers IO
In this session we will learn about Load All Subfile in IBM i.For detailed description and explanation refer the E-Book.EBook Link: https://programmers.io/ibmi-ebook/Programmers.io is a registered IBM business partner and a global IT services and consulting firm, providing on-demand software development Read More
2024: An IBM i Year In Review Alex Woodie
[[{“value”:”It’s hard to believe that yet another year is coming to a close. As 2024 rolls to its merciful end, it’s time for us to take stock of the major events and announcements that impacted the IBM i community.
January
News broke in late January that revenue in IBM’s Power Systems business grew for the second year in a row in 2023. TPM’s model showed $1.53 billion in external Power Systems sales for the year, which was a hair above the 2022 figure, which was a hair above the 2021 figure. It’s not 2010-era numbers, when the figure was north …
The post 2024: An IBM i Year In Review appeared first on IT Jungle.”}]] Read More
Advent of Code 2024 day 3, RPG edition
[[{“value”:”This is the third day of Advent of Code, let’s solve today’s puzzles with RPG.
The puzzle as well as the input data are available here.
The code is available here.
Part 1
We are provided with a (stream) file containing a corrupted program. We need to find valid instructions in the form mul(X,Y) where X and Y are 1 to 3 digit numbers.
We need to find all valid instructions, calculate X*Y and sum the results.
The IFS file can easily be read using QSYS2.IFS_READ_UTF8 table function.
Finding valid instructions can easily be done using regular expressions which can be used in RPG programs via SQL.
The regular expression to identify valid instructions is mul((d{1,3}),(d{1,3})). See here for an explenation of this regular expression.
Each report can be devided into levels with the %SPLIT RPG built-in function. We can iterate over the levels extracted by %SPLIT with the for-each instruction.
We use the REGEXP_COUNT SQL function to check how many matches are found.
We then do a for loop to process each match. For each match, we use REGEXP_SUBSTR twice to extract the parameters of the mul() function. We the multiply those two values and add it to the result.
Here is the RPG code for part 1:
**free
ctl-opt dftactgrp(*no); // We’re using procedure so we can’t be in the default activation group
dcl-pi *n;
input char(50);
end-pi;
dcl-pr processLine;
line varchar(32000);
end-pr;
dcl-s fileName varchar(50);
dcl-s line varchar(32000);
dcl-s result int(10) inz(0);
fileName = %trim(input);
// Read the input data from the IFS one line at a time
exec sql declare c1 cursor for select cast(line as varchar(32000)) from table(qsys2.ifs_read_utf8(path_name => :fileName));
exec sql open c1;
// Read first line
exec sql fetch from c1 into :line;
// Loop until the end of the file
dow sqlcode = 0;
processLine(line);
// Read next line
exec sql fetch from c1 into :line;
enddo;
exec sql close c1;
snd-msg *info ‘Result: ‘ + %char(result) %target(*pgmbdy:1); // Send message with answer
*inlr = *on;
return;
dcl-proc processLine;
dcl-pi *n;
line varchar(32000);
end-pi;
dcl-s count int(10); // Number of correct instructions found
dcl-s val1 int(10); // First operand
dcl-s val2 int(10); // Second operand
dcl-s index int(10); // Index of the occurence
exec sql select regexp_count(:line, ‘mul((d{1,3}),(d{1,3}))’) into :count from sysibm.sysdummy1;
for index = 1 to count;
exec sql select int(regexp_substr(:line, ‘mul((d{1,3}),(d{1,3}))’, 1, :index, ‘c’, 1)) into :val1 from sysibm.sysdummy1;
exec sql select int(regexp_substr(:line, ‘mul((d{1,3}),(d{1,3}))’, 1, :index, ‘c’, 2)) into :val2 from sysibm.sysdummy1;
result += val1 * val2;
endfor;
end-proc;
Part 2
In part 2, we’ll use the same input as in part 1.
We still need to calculate the sum of the mul() instructions but 2 new instructions must be handled:
do() that enables future mul instructions
don’t() that disables future mul instructions
Only the lastest do() or don’t() instruction applies. We consider that mul instructions are enabled at the begining of the program.
We introduce a global indicator variable inDo that contains *on if mul instructions are enabled and *off otherwise.
We use a slightly more complex regular expression to find the next valid instruction: mul((d{1,3}),(d{1,3}))|do()|don’t() see here for an explanation of this regular expression.
We use the REGEXP_INSTR SQL to return the position of the first valid instruction in the string. If no valid instruction is found, it returns 0.
We analyse the 3 characters at the returned position to determine which instruction was found with RPG select/when-is structure:
if we have ‘do(‘, it means it’s a do() instruction, so we set inDo to *on
if we have ‘don’, it means it’s a don’t() instruction, so we set inDo to *off
if we have ‘mul’, it means it’s a mul() instruction. If inDo is *off, we do nothing. If inDo is *on, we use the same regular expression as in part 1 to extract the parameters and multiply the values.
**free
ctl-opt dftactgrp(*no); // We’re using procedure so we can’t be in the default activation group
dcl-pi *n;
input char(50);
end-pi;
dcl-pr processLine;
line varchar(32000);
end-pr;
dcl-s fileName varchar(50);
dcl-s line varchar(32000);
dcl-s result int(10) inz(0);
dcl-s inDo ind inz(*on);
fileName = %trim(input);
// Read the input data from the IFS one line at a time
exec sql declare c1 cursor for select cast(line as varchar(32000)) from table(qsys2.ifs_read_utf8(path_name => :fileName));
exec sql open c1;
// Read first line
exec sql fetch from c1 into :line;
// Loop until the end of the file
dow sqlcode = 0;
processLine(line);
// Read next line
exec sql fetch from c1 into :line;
enddo;
exec sql close c1;
snd-msg *info ‘Result: ‘ + %char(result) %target(*pgmbdy:1); // Send message with answer
*inlr = *on;
return;
dcl-proc processLine;
dcl-pi *n;
line varchar(32000);
end-pi;
dcl-s val1 int(10); // First operand
dcl-s val2 int(10); // Second operand
dcl-s pos int(10) inz(1); // currentPosition
dcl-s nextPosition int(10); // next position
// search for the first do(), don’t() or mul(xxx,xxx)
exec sql select regexp_instr(:line, ‘mul((d{1,3}),(d{1,3}))|do()|don”t()’, :pos) into :nextPosition from sysibm.sysdummy1;
dow nextPosition > 0;
select %subst(line: nextPosition: 3);
when-is ‘do(‘; // If we found a do(), we set inDo to *on
inDo = *on;
when-is ‘don’; // If we found a don’t(), we set inDo to *off
inDo = *off;
when-is ‘mul’; // If we found a mul() we process the multiplication only if inDo is set to *on
if inDo;
exec sql select int(regexp_substr(:line, ‘mul((d{1,3}),(d{1,3}))’, :nextPosition, 1, ‘c’, 1)) into :val1 from sysibm.sysdummy1;
exec sql select int(regexp_substr(:line, ‘mul((d{1,3}),(d{1,3}))’, :nextPosition, 1, ‘c’, 2)) into :val2 from sysibm.sysdummy1;
result += val1 * val2;
endif;
endsl;
pos = nextPosition + 1;
// search for the next do(), don’t() or mul(xxx,xxx)
exec sql select regexp_instr(:line, ‘mul((d{1,3}),(d{1,3}))|do()|don”t()’, :pos) into :nextPosition from sysibm.sysdummy1;
enddo;
end-proc;”}]] Read More