List Commands Library for 50g
|
07-14-2017, 07:22 PM
Post: #41
|
|||
|
|||
RE: List Commands Library for 50g
I went ahead and implemented the I→NL command. It seemed silly not to, especially since it could be made to be a good performer via the use of a custom Saturn routine to populate the result list.
DOCOMB and DOPERM now have a local variable available for obtaining the "discards" from the source list after a combination has been selected. I'm not sure if there's a formal name for those elements, but I've been thinking of them as the "combination remnant", so the local is currently named CRMNT. Better naming suggestions are welcome! The user program can simply include CRMNT in its code at any point where those elements are needed. They are returned as a list. In searching for a good example problem to show the use of CRMNT with DOPERM, I decided that the "Vietnamese Snake Puzzle" from Gerald's post was a good match. It may also be easier to understand for the folks that already participated in that thread. If you're not familiar with it, I'd advise taking a look at the original source first to get an idea what it's about. Like many permutation problems, there is great benefit in recognizing the constraints that are built into the problem itself that may keep you from having to use a "brute-force" approach that simply checks every possible permutation. For this example, I'm focusing on one of those constraints: ((13BI)+(CGH))/CI must be an integer in all of the final solutions. With that in mind, I've constructed the following program using commands from the library where appropriate. It essentially permutes the list of 9 digits, choosing 5 at a time for the initial test. For each of those permutations, it checks the above expression to see if it is an integer, and if so, continues to check the remaining digits as a potential solution to the final expression: Code: \<< I've commented this code copiously in an effort to make it clear what it does. On my 50g, it finds all 136 solutions in about 23.5 minutes. Further constraint checking would likely speed this up a bit, but I wanted to keep this as simple as possible while still showing a meaningful use of the CRMNT local. These latest changes (and a couple others) will be in the next update, which will hopefully be one of the last ones before finalizing the command set. I'll give it a couple more days as I continue to hammer out some more tests with it. |
|||
07-14-2017, 08:20 PM
(This post was last modified: 07-14-2017 08:22 PM by Gilles59.)
Post: #42
|
|||
|
|||
RE: List Commands Library for 50g
Hi David,
I notice that, with DOPERM, on the contrary of DOLIST and DOSUBS, there is no possibilty to access to the stack in the inner program... Code:
I think it would be more powerfull to do as DOLIST and DOSUBS does. This can avoid in many cases to create a variable where there no necessity to do. |
|||
07-14-2017, 09:37 PM
(This post was last modified: 07-14-2017 10:38 PM by Gilles59.)
Post: #43
|
|||
|
|||
RE: List Commands Library for 50g
Here is a generic program to solve "cryptarithms" :
Code:
Enter the cryptarithm like this, for example : "neuf+un+un==onze" "li+li==cii" (roman numbers ![]() "sin^2+cos^2==unite" "3*twenty+2*ten==eighty" "jupiter+saturne+uranus==neptune" Note that: - It uses DOPERM, LDDUP, LSUM, S->SL of the Library of DavidM - use lowercase, it's better to avoid conflicts with names of a function, - buy a pack of beers, it's sloooow even with an emulator - The program searches all the solutions and return a list, but the solutions are displayed on the screen. Note that a beautiful cryptarithm has only one solution. You can change the program to stop at the first one - the program dont check that a number begin with a 'zero'. No comment for the program, but if you run it step by step you will see that its very simple. |
|||
07-14-2017, 10:41 PM
Post: #44
|
|||
|
|||
RE: List Commands Library for 50g
(07-14-2017 08:20 PM)Gilles59 Wrote: Hi David, This was actually intentional, and now that I'm checking on it I see that I was mistakenly assuming that I was mimicking the inherent behavior of the built-in commands by protecting the stack. This is clearly not the case. Where did I get the impression that the list commands worked this way? I'm not sure. Thanks for pointing this out! The only consequence I can think of by not protecting the stack in this way is that it means that the user-supplied program should never delete any of the pre-existing stack elements. I've checked DOLIST/DOSUBS, and they apparently just notate the stack depth at the beginning of the command and assume that anything greater goes into the final result list. If the user-program deletes pre-existing stack objects, the grouped result doesn't include the same number of initial objects placed on the stack by the user program. In other words, if the user program deletes 3 pre-existing stack objects, then the first 3 objects in the result will be on the stack but not in the result list when DOLIST/DOSUBS completes. I could easily replicate that behavior with DOPERM and DOCOMB. An example of what I'm referring to: Code: \<< |
|||
07-16-2017, 02:40 PM
Post: #45
|
|||
|
|||
RE: List Commands Library for 50g
Seeking opinions about the implementation of NL→I
NL→I (Number List to Integer) is intended as an easy/fast way to convert a list of numbers into an integer. I'd guess that 99% of the time it will be used to convert a list of single decimal digits to an integer made up of those digits, something like this: Code: { 1 2 3 4 5 6 7 8 9 0 } NL→I => 1234567890 At present, the input list must contain only numbers (specifically integers or reals) or an error will result. This seems reasonable to me, as I would think that raising an error makes more sense than simply ignoring non-numeric objects embedded in the list, and trying to come up with something reasonable to do for non-numeric object types would erode the performance benefit. Limiting the valid input in this way still leaves room for some ambiguous input, however. Reals with a fractional part seem fairly straightforward -- I just ignore the fractional part. But I'm pondering the best way to handle negative and |x|>=10 numbers. A potential list of numbers could be something like the following, and NL→I needs to be able to handle it appropriately: Code: { 1.8 -3 15 10000.003 123456789 } My inclination is to simply ignore the sign of any digits, thus implying that every result for NL→I will be positive. That forces the user to design their own way of tracking and applying the sign of final results, which seems like a reasonable approach given the possibility of having a mixture of signed/unsigned numbers in the input. |x|>=10 numbers are less clear to me, though. I can think of several possibilities for those:
|
|||
07-16-2017, 06:47 PM
(This post was last modified: 07-16-2017 11:29 PM by Gilles59.)
Post: #46
|
|||
|
|||
RE: List Commands Library for 50g
Hi David, I suggest for NL→I (Number List to Integer) :
Code: { 1 2 3 4 5 6 7 8 9 0 } NL→I => 1234567890 Code: { 1 22 37 4 } NL→I => 122374 I agree about ignoring sign. About real, just take the interger part, or perhaps the best way is just "bad argument type". If need, its easy to do Code: { 123.456 7 8.01 9 } IP R→I NL→I |
|||
07-17-2017, 04:21 PM
Post: #47
|
|||
|
|||
RE: List Commands Library for 50g
(07-16-2017 06:47 PM)Gilles59 Wrote: Hi David, I suggest for NL→I (Number List to Integer) : I'd rather the command take the IP instead of generating an error for reals with fractional parts -- it's easy enough to do and performance would likely be better as well. And I don't think it would be good to force the user to have to use exact integers for this kind of thing (especially since I usually have my calculator set to approx. mode ![]() I guess the issue in my mind about using all of the pre-radix digits in the final integer is this: isn't there value in the user being able to assume that the final integer will have no more digits than the list has elements? Less wouldn't be a surprise due to the possibility of leading 0s, but more seems like it breaks a fundamental relationship between the list and integer. Part of that may be because I'm sensing a correlation between NL→I and NL→S, which out of necessity has to restrict the range of the numbers to 0-255. Please don't take this to mean that I'm already convinced of one particular path to follow here -- I'm not. I'm really just trying to anticipate what types of situations NL→I is most useful for and what the expected behavior would be in those situations. I'm sure that part of my indecision results from my having a hard time coming up with appropriate use cases where the list elements are >=10. |
|||
07-22-2017, 10:49 PM
Post: #48
|
|||
|
|||
RE: List Commands Library for 50g
NL→I
Due to the clear consensus of feedback (100% ![]() Convert 12345 to 11112222333344445555 Code: 12345 I→NL 1111 * NL→I Combine 13579 and 24680 to make 1234567890 Code: 13579 I→NL 24680 I→NL 2 →LIST LCLLT NL→I I'm sure there's much better uses than the above, though. The most common use of the command, however, is still likely to be translating a list of single-digit numbers into an exact integer: Code: { 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 } NL→I => 123456789012345 It also became clear that it wasn't really necessary to have a separate LV→I command, so I simply added a section to NL→I so that any identifiers in the list would be RCL'd before attempting to proceed with building the result. If the identifier doesn't already exist in the current search path and isn't a defined local, NL→I will throw a bad argument error. Another use for DOCOMB Karl-Ludwig Butte recently posted an interesting article discussing the history of the "power set". It appeared to me that there was a close correlation with his demonstration of creating a power set for { 1 2 3 } and the output of the DOCOMB command run with increasing combination choices. I'm not sure if the ordering ends up being exactly the same for larger lists (I haven't tried to input his program to run a comparison), but the following should at least generate the same group of combinations for a given input list: Code: \<< I'll post a follow-up message with the latest version of the library shortly. |
|||
07-22-2017, 11:24 PM
(This post was last modified: 09-10-2017 02:20 PM by DavidM.)
Post: #49
|
|||
|
|||
RE: List Commands Library for 50g
Although I'm still calling this a "development" release, it's really more like a beta. It feels like the command set has stabilized, and as far as I'm aware everything is fully functional in this release. Please beat on it as much as you like and let me know if anything misbehaves or doesn't work as expected.
Thanks to everyone who has participated with this! Hopefully the result is a useful collection of tools to extend the list processing functionality of the 49-50 systems. Edit: The attachment has been deleted; see the first post in this thread for the latest version. ListExt Release Notes Version 0.11.0d 2017-07-22 - Added new command: I→NL - Updated DOCOMB and DOPERM to make non-selected elements for the current combination available in local variable CRMNT. - Changed behavior of DOCOMB and DOPERM so that the standard user stack is available to the user program. - Fixed bug in LRCL to correctly handle local variables. - Dropped the LV→I command and incorporated its functionality into NL→I. - NL→I now includes all pre-radix digits when building the final integer result. - Updated command description for NL→I to include information about sign treatment. - Updated and fixed a several typos in the command descriptions. COMMAND SUMMARY DOCOMB - feeds indicated combinations of a list to a user-supplied program DOPERM - feeds indicated permutations of a list to a user-supplied program LCLLT - collates a list of sublists LCNT - counts objects in a list LDDUP - removes duplicates from a list LDST - distributes list items into sublists (reciprocal of LCLLT) LEQ - checks list items to see if any do not match LGRP - replaces repeated elements with a single instance LHDTL - retrieves the first element in a list while leaving the rest on the stack LMRPT - repeats list contents as indicated by count LNDUP - creates a list by repeating an object as indicated by count LPOS - returns a list of all positions of an object in a list LPOSL - returns a list of all positions of an object in a list or its sublists LPROD - ΠLIST that also accepts lists with 0 or 1 element LRCL - recalls objects identified by variables in a list LREPL - replaces list elements with a substitute object as indicated LRLL - rolls the list (equivalent to 1 LROT) LRLLD - "roll down" the list (equivalent to -1 LROT) LROT - rotates list elements left or right as indicated by count LRPCT - list with LGRP elements and another list of the count of each element LSDIV - subdivides a list into <count> sublists LSEQ - creates a list of <count> integers as a sequence from 1..<count> LSEQR - creates a list of integers for the range specified LSHF - shuffles the contents of a list LSPLT - splits a list as indicated into two sublists LSUM - ΣLIST that also accepts lists with 0 or 1 element LSWP - swaps the positions of two list elements LXIL - explodes inner sublists into individual elements (non-recursive) LXILR - recursive version of LXIL RPTCHR - creates a string of repeated characters I→NL - converts an integer to a list of numbers NL→I - converts a list of numbers to an integer S→NL - converts a string to a list of numbers NL→S - converts a list of numbers to a string S→SL - converts a string to a list of characters SL→S - converts a list of characters to a string |
|||
07-23-2017, 02:03 PM
Post: #50
|
|||
|
|||
RE: List Commands Library for 50g
(07-22-2017 10:49 PM)DavidM Wrote: Karl-Ludwig Butte recently posted an interesting article discussing the history of the "power set". It appeared to me that there was a close correlation with his demonstration of creating a power set for { 1 2 3 } and the output of the DOCOMB command run with increasing combination choices. I'm not sure if the ordering ends up being exactly the same for larger lists (I haven't tried to input his program to run a comparison), but the following should at least generate the same group of combinations for a given input list: Unless I'm mistaken, the Goferlists function Subs also does this. It remains to compare the three programs as to the order of the permutations in the output list. John |
|||
07-23-2017, 03:35 PM
(This post was last modified: 07-23-2017 03:56 PM by John Keith.)
Post: #51
|
|||
|
|||
RE: List Commands Library for 50g
(07-22-2017 10:49 PM)DavidM Wrote: NL→I This is a welcome change. However, the execution time has increased compared to the previous version (4.8s vs. 2.4s for a list of 1000 single-digit integers) As a further example, the following simple program produces the digits of Champernowne's constant ending with the supplied integer: Code: \<< 1 SWAP 1 Seq NL\->I \>> John |
|||
07-23-2017, 06:07 PM
Post: #52
|
|||
|
|||
RE: List Commands Library for 50g
Nice david! I long for a bit of quiet times to go back solving problems with the 50g.
Wikis are great, Contribute :) |
|||
07-23-2017, 09:25 PM
Post: #53
|
|||
|
|||
RE: List Commands Library for 50g
(07-23-2017 02:03 PM)John Keith Wrote: Unless I'm mistaken, the Goferlists function Subs also does this. It remains to compare the three programs as to the order of the permutations in the output list. You aren't mistaken, John. Subs not only creates all of the sublists, but it does it very quickly as well. A sample test using a nine-element list as the input shows Subs creating the list in about 1.8 seconds. The sample UserRPL code I showed in the previous note completes the same task in about 8.9 seconds. (07-23-2017 03:35 PM)John Keith Wrote: This is a welcome change. However, the execution time has increased compared to the previous version (4.8s vs. 2.4s for a list of 1000 single-digit integers) The amazing thing about this is that the time only doubled. ![]() Is the time savings worth having a separate command that uses the previous method? (07-23-2017 03:35 PM)John Keith Wrote: As a further example, the following simple program produces the digits of Champernowne's constant ending with the supplied integer: Or even simpler: Code: \<< LSEQ NL\->I \>> |
|||
07-23-2017, 10:44 PM
Post: #54
|
|||
|
|||
RE: List Commands Library for 50g | |||
08-07-2017, 05:54 PM
(This post was last modified: 09-10-2017 02:21 PM by DavidM.)
Post: #55
|
|||
|
|||
RE: List Commands Library for 50g
After working on Joe's Odd-digit mini-challenge and becoming reacquainted with SREPL, it inspired me to create one final command for the List Extensions library: CHR+.
It processes a string by adding an offset to every character's ordinal value. An alternate form of the command allows you to limit the range of characters that are valid targets for applying the offset. Like SREPL, it is very fast. Here's the description from the library documentation: CHR+ (Offset String Character Values) Input 2: String of 0 or more characters 1: number (Offset) or list { LowerBound UpperBound Offset } Output 1: String with offset added to appropriate characters Alters the string in stack level 2 by adding the given offset to each character in the string. The integer part of the offset must be between -255 and 255 (inclusive). If the parameter in stack level 1 is a list, the offset will only be added if the original character is within the bounds specified by the first two elements (inclusive). The final character value will always be in the range 0-255. If the given offset would move the new character value out of that range, the final value is normalized via a MOD 256 operation. Note: CHR+ will allow the creation of null characters (CHR value 0) in a string. If this happens, you may not be able to edit the string with the calculator's built-in commands. If you wish to convert all null characters in a string to some other character, simply execute "{ 0 0 <CHR> } CHR+" with whatever replacement character code for <CHR> you wish to use. Examples: "0000000000" 1 CHR+ => "1111111111" "99999" -5 CHR+ => "44444" "99999" 251 CHR+ => "44444" "THIS IS THE TENTH (10TH) TEST!" { 65 90 32 } CHR+ => "this is the tenth (10th) test!" "Convert to UPPER case???" { 97 122 -32 } CHR+ => "CONVERT TO UPPER CASE???" As I was creating the above description, I couldn't help but think how easy it would be to add commands for remapping the 50g's characters between lower and upper case. So LCASE and UCASE were added as well. See the command descriptions for a detailed listing of the character mappings used (diacritics are included where appropriate). I appreciate everyone's patience with this. I've probably already worn out my welcome with these posts, and in an effort to draw this to a close I'm promoting this version to "Release Candidate" status. If you have any interest at all in the list/string processing features the library includes, please give it a try! Edit: The attachment has been deleted; see the first post in this thread for the latest version. ______________________________________________________________________________ Version 1.0.0 RC1 2017-08-07 - DOCOMB and DOPERM now accept a "choices" parameter of 0. - DOCOMB and DOPERM now accept an empty list, but only if the choices parameter is 0. - Added new commands: CHR+, LCASE, UCASE - Status change to 1.0.0 Release Candidate 1 ______________________________________________________________________________ COMMAND SUMMARY DOCOMB - feeds indicated combinations of a list to a user-supplied program DOPERM - feeds indicated permutations of a list to a user-supplied program LCLLT - collates a list of sublists LCNT - counts objects in a list LDDUP - removes duplicates from a list LDST - distributes list items into sublists (reciprocal of LCLLT) LEQ - checks list items to see if any do not match LGRP - replaces repeated elements with a single instance LHDTL - retrieves the first element in a list while leaving the rest on the stack LMRPT - repeats list contents as indicated by count LNDUP - creates a list by repeating an object as indicated by count LPOS - returns a list of all positions of an object in a list LPOSL - returns a list of all positions of an object in a list or its sublists LPROD - ΠLIST that also accepts lists with 0 or 1 element LRCL - recalls objects identified by variables in a list LREPL - replaces list elements with a substitute object as indicated LRLL - rolls the list (equivalent to 1 LROT) LRLLD - "roll down" the list (equivalent to -1 LROT) LROT - rotates list elements left or right as indicated by count LRPCT - list with LGRP elements and another list of the count of each element LSDIV - subdivides a list into <count> sublists LSEQ - creates a list of <count> integers as a sequence from 1..<count> LSEQR - creates a list of integers for the range specified LSHF - shuffles the contents of a list LSPLT - splits a list as indicated into two sublists LSUM - ΣLIST that also accepts lists with 0 or 1 element LSWP - swaps the positions of two list elements LXIL - explodes inner sublists into individual elements (non-recursive) LXILR - recursive version of LXIL CHR+ - Adds an offset to the CHR value of each character of a string LCASE - Converts upper case characters in a string to lower case UCASE - Converts lower case characters in a string to upper case RPTCHR - creates a string of repeated characters I→NL - converts an integer to a list of numbers NL→I - converts a list of numbers to an integer S→NL - converts a string to a list of numbers NL→S - converts a list of numbers to a string S→SL - converts a string to a list of characters SL→S - converts a list of characters to a string |
|||
08-08-2017, 11:43 AM
Post: #56
|
|||
|
|||
RE: List Commands Library for 50g
Thank you David ! I will test all this ;D
|
|||
08-10-2017, 10:07 PM
(This post was last modified: 08-11-2017 09:13 AM by pier4r.)
Post: #57
|
|||
|
|||
RE: List Commands Library for 50g
David, since you are doing a very neat work to work with lists (in complement with goferlist, I do not know any other library with list commands, aside from the built in commands) may I ask you to consider also vectors and/or matrices ?
Because for the little that I know, there are only the built in commands and no real library, and the built in commands are not even that much. For example would be pretty neat to have the possibility to iterate on a vector, like DOSUBS, without converting it to a list. Same for a matrix. Just ideas though, I do not know how hard it will be. Wikis are great, Contribute :) |
|||
08-10-2017, 11:14 PM
(This post was last modified: 08-10-2017 11:21 PM by Gilles59.)
Post: #58
|
|||
|
|||
RE: List Commands Library for 50g
(08-10-2017 10:07 PM)pier4r Wrote: David, since you are doing a very neat work to work with lists (in complement with goferlist, I do not know any other library with list commands, aside from the built in commands) may I ask you to consider also vectors and/or matrices ? Hi Pier4 You can use the MAP command for the Matrices. And the AXL command is very fast. So imho you can easily create your own commands in User RPL, with things like <<AXL .... AXL >>. There are many commands about matrices in the 50G. |
|||
08-11-2017, 09:14 AM
(This post was last modified: 08-11-2017 09:58 AM by pier4r.)
Post: #59
|
|||
|
|||
RE: List Commands Library for 50g
(08-10-2017 11:14 PM)Gilles59 Wrote: Hi Pier4 Then it may be that I never explored that part of commands. The built in library is vast but I normally refer to commands often mentioned in the 50g user guide (that are not many for matrices). I'll have a look! update: - map works, but the flag requirements are somehow strict (why radiants?) - AXL is great! And it shows how much still I do not know of the default builtin functions! I even wrote userRPL routines to convert lists in arrays and viceversa and in all the time I searched in the AUR I never stumbled upon the AXL command. This happens when I read the user guide (that gives me the first directions, then I check the AUR) and I skip the parts that I deem not so crucial. I wonder when I will master all the built in commands that I may need, I need to use the 50g more. Wikis are great, Contribute :) |
|||
08-11-2017, 02:15 PM
Post: #60
|
|||
|
|||
RE: List Commands Library for 50g
(08-11-2017 09:14 AM)pier4r Wrote: update: I had already started typing a response that prominently featured the AXL command last night (it would have been very similar to Gilles', actually). But then I decided to sleep on it before responding. After more consideration, I'm still coming to the same conclusion: the conversion of vectors/matrices to lists is simple enough, and best handled at the user's discretion. Adding this functionality to the library would probably add complexity to the code (and therefore size) that isn't offset by the value received. When you consider that arrays/matrices are much more limited in the object types they can contain, it would put a bit more burden on the library's commands to check embedded object types. This could impact performance in ways that just don't seem to be a good trade-off to me. (08-11-2017 09:14 AM)pier4r Wrote: I wonder when I will master all the built in commands that I may need, I need to use the 50g more. One of the amazing things about all of these devices is that, no matter how much I learn about what they can do, there's always more to discover. Even the commands that I think I already understand are sometimes used in novel ways at the hands of the creative people that share their insights here. I'm not sure what it would be like to actually "master" all the built-in commands of something like the 50g, but if one were to achieve that status, there's plenty of other tools to learn about. Just take a couple of minutes looking through any of the other threads here... ![]() |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 1 Guest(s)