Substring a text using MOVEL function in RPG - rpgle

Question:
Is it save to get substring n characters from a text in RPG using MOVEL function which take a text with length x and store it to a variable with capacity n?
Or the only save way to get the first n character is using SUBST?
The background of the question is one of my colleague getting the first 3 characters from a database with 30 char in length is using MOVEL to a variable with length only 3 char (like truncating the rest of it). The strange way, sometimes the receive variable is showing minus character ('-'), sometimes doesn't. So I assume using MOVEL is not a safe way. I am thinking like string in C which always terminated by '\0', you need to use strcpy function to get the copy save, not assigning using = operator.
Anybody who knows RPG familiar with this issue?

MOVEL should work. RPG allows several character data types. Generally speaking, someone using MOVEL will not be dealing with null terminated strings because MOVEL is an old technique and null terminated strings are a newer data type. You can read up on the MOVEx operations and the string operations in the RPG manual. To get a better answer, please post your code, including the definitions of the variables involved.
EDIT: Example of how MOVEL handles signs.
dcl-s long char(20) inz('CORPORATION');
dcl-s short char(3) inz('COR');
dcl-s numb packed(3: 0);
// 369
c movel long numb
dsply numb;
// -369
c movel short numb
dsply numb;
*inlr = *on;

With signed numeric fields in RPG the sign is held in the zone of the last byte of the field. So 123 is X'F1F2F3' but -123 is X'F1F2D3'. If you look at those fields as character strings they will have 123 and 12L in them.
In your program you are transferring something like "123 AAAAAL" to a 3 digit numeric field so you get X'F1F2F3' but because the final character is X'D3' that changes the result to have a zone of D i.e. X'F1F2D3'
You anomaly is dependent on what the 30th character contains. If it is } or any capital letter J to R then you get a negative result. [It doesn't matter whether the first 3 characters are numbers or letters because it is only the second half of the byte, the digit, that matters in your example.]
The IBM manuals say:
If factor 2 is character and the result field is numeric, a minus zone is moved into the rightmost position of the result field if the zone from the rightmost position of factor 2 is a hexadecimal D (minus zone). However, if the zone from the rightmost position of factor 2 is not a hexadecimal D, a positive zone is moved into the rightmost position of the result field. Other result field positions contain only numeric characters.
Don

Related

How to convert a string to number in scheme without removing the leading zero?

I want to convert a string to a number in Scheme, but when I use the function string->number it removes the leading zero
For example
(string->number "01") gives me 1
Is there a way to convert the string so that it doesnt remove the leading zero and gives me 01 instead?
You can't: leading zeros are just part of the written representation of numbers, not part of the number itself. In particular 01, 1 and 00000001 are all the same number.
If you want to print numbers with leading zeros, for instance to line things up, then there are utilities which do that. For instance in Racket, while the format / printf family of procedures cannot do this, the procedures provided by racket/format can:
> (require racket/format)
> (~a 1 #:width 2 #:align 'right #:pad-string "0")
"01"
However you will still need to deal with negative numbers yourself, which is rather annoying.

What is the Algorithm for this Programming Question?

This is a question I encountered in a Test and I am not able to solve it. Every time I think of an algorithm, a new corner case comes that fails it. Can someone please explain me, how to move through the problem ?
Problem Statement
The Cytes Lottery is the biggest lottery in the world. On each ticket, there is a string of a-z letters. The company produces a draw string S. A person wins if his/her ticket string is a special substring of the draw string. A special substring is a substring which can be formed by ignoring at most K characters from drawString. For example, if draw string = "xyzabc" and tickets are [ac zb yhja] with K=1 then the winning tickets will be 2 i.e ac (won by ignoring "b" in drawstring) and zb (won by ignoring "a" in drawstring).
Now some people change their ticket strings in order to win the lottery. To avoid any kind of suspicion, they can make the following changes in their strings.
They can change character 'o' to character 'a' and vice versa
They can change character 't' to character 'l' and vice versa
They can erase a character from anywhere in the string
Note that they can ignore at most 'K' characters from the draw string to get a match with the ticket string.
Write an algorithm to find the number of people who win the lottery (either honestly or by cheating).
Input:
The first line of the input consists of an integer - numTickets, representing the number of tickets (N).
The second line consists of a string - drawString, representing the draw string (S).
The third line consists of N space-seperated strings - tickets1, tickets2,........., ticketsN representing the tickets.
The last line consists of an integer-tolerance, representing the maximum number of characters that can be deleted from the drawString(K).
Output:
An integer representing the number of winning tickets (either fairly or by cheating).
Constraints:
0 <= numTickets <= 1000
0 <= length of drawString <= 200
0 <= length of tickets[i] <= 200
0 <= tolerance <= 1000
Note:
The drawString contains lowercase English alphabets
Example:
Input:
3
aabacd
abcde aoc actld
1
Output:
2

Space-efficient way to encode numbers as sortable strings

Starting with a list of integers the task is to convert each integer into a string such that the resulting list of strings will be in numeric order when sorted lexicographically.
This is needed so that a particular system that is only capable of sorting strings will produce an output that is in numeric order.
Example:
Given the integers
1, 23, 3
we could convert the to strings like this:
"01", "23", "03"
so that when sorted they become:
"01", "03", "23"
which is correct. A wrong result would be:
"1", "23", "3"
because that list is sorted in "string order", not in numeric order.
I'm looking for something more efficient than the simple zero-padding scheme. In order to cover all possible 32 bit integers we'd need to pad to 10 digits which is inefficient.
For integers, prefix each number with the length. To make it more readable, use 'a' for length 1, and 'b' for length 2. Example:
non-encoded encoded
1 "a1"
3 "a3"
23 "b23"
This scheme is a bit simpler than prefixing each digit, but only works with numbers, not numbers mixed with text. It can be made to work for negative numbers as well, and even BigDecimal numbers, using some tricks. I wrote an implementation in Apache Jackrabbit 2.x, to make BigDecimal indexable (sortable) as text. For that, I used a format that only uses the characters '0' to '9' and consists of:
one character for: signum(value) + 2
one character for: signum(exponent) + 2
one character for: length(exponent) - 1
multiple characters for: exponent
multiple characters for: value (-1 if inverted)
Only the signum is encoded if the value is zero. The exponent is not encoded if zero. Negative values are "inverted" character by character (0 => 9, 1 => 8, and so on). The same applies to the exponent.
Examples:
non-encoded encoded
0 "2"
2 "322" (signum 1; exponent 0; value 2)
120 "330212" (signum 1; exponent signum 1, length 1, value 2; value 12)
-1 "179" (signum -1, rest inverted; exponent 0; value 1 (-1, inverted))
Values between BigDecimal(BigInteger.ONE, Integer.MIN_VALUE) and BigDecimal(BigInteger.ONE, Integer.MAX_VALUE) are supported.
TL;DR
Encode digits according to their order of magnitude (OM) and other characters so they sort as desired, relative to numbers: jj-a123 would be encoded zjzjz-zaC1B2A3
Longer explanation
This would depend somewhat upon the sorting algorithm that will finally be used to sort and how one would want any given punctuation characters to be sorted in relation to letters and numbers, but if it's "ascii-betical" or similar, you could encode each digit of a number to represent its order of magnitude (OM) in the number, while encoding other characters such that they would sort according to your desired sort order.
For simplicity, I would suggest beginning with encoding every non-numeric character with a "high" value (e.g. lower case z or even ~ if final value is ASCII), so that it sorts after encoded digits. Then cache each digit encountered until another non-numeric is encountered, then encode each cached digit with a value representing its OM. If the number 12945 was encountered in between non-numerics, you would output an E to encode an OM of 5, then the digit that is that order of magnitude, 1, followed by the next OM of 4 (D) and its associated digit, 2. Continue until all numeric digits have been flushed, then continue with non-numerics.
Non-numerics would be treated individually and ranked relative to the OM of digits. If it is desired for them to sort "above" numbers (perhaps the space character or certain others deemed special) they would be encoded by prepending a low-value character (like the space character, if final value will be treated and sorted as ASCII). When/if another numeric is encountered, begin caching and encode according to OM once all consecutive numerics are cached.
Alternately, processing the string in reverse order would preclude the need to cache numbers except for a single "is it a digit?" test and "is the last character a digit?" test. If the first is not true, then use (one of?) the "non-digit" OM character(s). If the first test is true then use the lowest-OM "digit" character (A in my examples). If both tests are true, then increment your OM character (A -> B or E -> F) before use.
Certain levels of additional filtering - or even translation - could be applied. If one wanted to allow accurate sorting based upon Roman numerals, one could encode them as decimal (or even hexadecimal) numbers with an appropriate OM.
Treating decimal points (either periods or commas, depending) as actual decimal separators, and distinct from other punctuation would probably be beyond the true utility of this encoding scheme, as alphanumeric fields seldom use a period or comma as a decimal separator. If it is desired to use them that way, the algorithm would simply detect a decimal separator (either period or comma as appropriate, in between digits) and not encode the numeric portion after that separator as anything but normal text. Fractional portions are actually sorted correctly during a normal ASCII based sort, because more digits represents greater precision - not greater magnitude.
Examples
non-encoded encoded
----------- -------
12345 E1D2C3B4A5
a100 zaC1B0A0
a20 zaB2A0
a2000 zaD2C0B0A0
x100.5 zxC1B0A0z.A5
x100.23 zxC1B0A0z.B2A3
1, 23, 3 A1z,z B2A1z,z A3
1, 2, 3 A1z,z A2z,z A3
1,2,3 A1z,A2z,A3
Potential advantages
Going somewhat beyond simple numeric sorting, some advantages to this encoding method would be several aspects of flexibility with final effective sort order - you are essentially encoding a category for each character - digits get a category based upon their position within the greater string of digits known as a number, while other characters are simply told to sort in their normal way (e.g. ASCII), but after numbers. Any exceptions that should sort before numbers or in other orders would be in one or more additional categories. ASCII can effectively be re-encoded to sort in a non-ASCII way:
You could encode lower case letters to sort before or along with upper case letters. To switch the lower and upper cases, you encode lower case letters with a y and upper case letters with a z. For a pseudo-case-insensitive sort, categorizing both A and a with the same encoding character would sort both of them before B and b, though A would nonetheless always sort before a
If you want Extended ASCII characters (e.g. with diacritics) to sort along with their ASCII cousins, you encode À, Á, Â, Ã, Ä, Å, and Æ along with A by using an a as the OM character, encode B, C, and Ç with a b, and E, È, É, Ê, and Ë with a c, etc. The same intra-category sort order caveat still applies, and some decisions need to be made on characters like capital Eth, and to a certain extent others like Thorn, and Sharp S (Ð, Þ, and ß respectively) as to whether they will sort based on similarities in appearance or pronunciation, or instead more properly perhaps, alphabetical order.
Small advantage of being basically human-readable, with effort
Caveats
Though this allows many 'categories' of characters to be defined, be sure to remember that each order of magnitude for digits is its own category - you need to know that the data will not contain numbers that are greater in OM than approximately 250, depending upon how many other categories you wish to define (ASCII 0 is reserved for storing strings, and there needs to be at least one other character to indicate "not a digit" - at least for alphanumeric data - making the maximum perhaps 254 orders of magnitude), but that should be plenty for any situation I can imagine. I'm not sure what other issues quantum computing will bring about, but there's probably a quantum solution to it, whatever it is.
Finally, if the hyphen is encoded as a non-numeric character, and all non-numerics are encoded with a higher OM than digits, negative numbers would be encoded as greater than any positive number. The hyphen should be encoded as a lower-than-digit-OM (perhaps only when preceding a digit) if negative numbers need to be sorted correctly according to magnitude.
Since the ASCII code of A is greater than 9, you could encode them as hexadecimal strings.
The integers
1, 23, 3
can be encoded as
00000001, 00000017, 00000003
and 32-bit integers can always be encoded as 8-character strings. (assume unsigned)

Convert text to numbers while preserving ordering?

I've got a strange requirements, which I can't seem to get my head around. I need to come up with a function that would take a text string and return a number corresponding to that string - in such a way that, when sorted, these numbers would go in the same order as the original strings. For example, if I the function produces this mapping:
"abcd" -> x
"abdef" -> y
"xyz" -> z
then the numbers must be such that x < y < z. The strings can be arbitrary length, but always non-empty and the string comparison should be case-insensitive (i.e. "ABC" and "abc" should result in the same numerical value).
My first though was to map each letter to a corresponding number 1 through 26 and then just get the resulting number, e.g. a = 1, b = 2, c = 3, ..., z = 26, then "abc" would become 1*26^2 + 2*26 + 3, however then I realised that the text string can contain any text in any language (i.e. full unicode), so this isn't going to work. At this point I'm stuck. Any other ideas before I tell the client to sod off?
P.S. This strange requirement is due to a limitation in a proprietary system that can only do sorting by a numeric field. If the sorting is required by any other field type, it must be converted to some numerical representation - and then sorted. Don't ask.
You can make this work if you allow for arbitrary-precision real numbers, though that kinda feels like cheating. Unicode strings are sequences of characters drawn from 1,114,112 options. You can therefore think of them as decimal base-1,114,113 numbers: write 0., then write out your Unicode string, and you have a real number in base-1,114,113 (shift each character's numeric value up by one so that missing characters have the value 0). Comparing two of these numbers in base-1,114,113 compares the numbers lexicographically: if you scan the digits from left-to-right, the first digit that they disagree on tiebreaks between the two. This approach is completely infeasible unless you have an arbitrary-precision real number library.
If you just have IEEE-734 doubles, this approach won't work. One way to see this is that there are at most 264 possible doubles (or 280 of them if you allow for long doubles) because there are only 64 (80) bits in a double, but there are infinitely many different strings. That eliminates the possibility simply because there are too many strings to go around.
Unfortunately, you can't make this work if you have arbitrary-precision integers. The natural ordering on strings has the fun property that you can find pairs of strings that have infinitely many strings lexicographically between them. For example, notice that
a < ab < aab < aaab < aaaab < ... < b
Now imagine that you have a function that maps each string to an integer that obeys the rules you'd like. That would mean that
f(a) < f(ab) < f(aab) < f(aaab) < f(aaaab) < ... < f(b)
But that's not possible in the integers - you can't have two integers f(a) and f(b) with infinitely many integers between them. (The number of integers between f(a) and f(b) is at most f(b) - f(a) - 1).
So it seems like the answer is "this is possible if you have arbitrary-precision real numbers, it's not possible with doubles, and it's not possible with arbitrary-precision integers." I'd basically label that "not going to happen in practice" even though it's theoretically possible. :-)

What does $ with a numeric value mean in Delphi

What does it means, in Delphi, when I see a command like this:
char($23)
What does the dollar symbol mean in this context?
The dollar symbol represents that the following is a hex value.
ShowMessage(Char($23)); shows #.
The $ symbol is used to prefix a hexadecimal literal. The documentation says:
Numerals
Integer and real constants can be represented in decimal notation as
sequences of digits without commas or spaces, and prefixed with the +
or - operator to indicate sign. Values default to positive (so that,
for example, 67258 is equivalent to +67258) and must be within the
range of the largest predefined real or integer type.
Numerals with decimal points or exponents denote reals, while other
numerals denote integers. When the character E or e occurs within a
real, it means "times ten to the power of". For example, 7E2 means 7 *
10^2, and 12.25e+6 and 12.25e6 both mean 12.25 * 10^6.
The dollar-sign prefix indicates a hexadecimal numeral, for example,
$8F. Hexadecimal numbers without a preceding - unary operator are
taken to be positive values. During an assignment, if a hexadecimal
value lies outside the range of the receiving type an error is raised,
except in the case of the Integer (32-bit integer) where a warning
is raised. In this case, values exceeding the positive range for
Integer are taken to be negative numbers in a manner consistent with two's complement integer representation.
So, in your example, $23 is the number whose hexadecimal representation is 23. That number has decimal representation 35, so you can write:
Assert($23 = 35);
It represents a character. For example char(13) is end of line.

Resources