Last active
September 24, 2021 13:50
-
-
Save eschen42/a4764fd8c1e0e498ad44d7359469dedf to your computer and use it in GitHub Desktop.
Produce lists combining memoized infinte sequences
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################ | |
# | |
# File: LcomboP.icn | |
# | |
# Subject: Produce lists combining memoized infinte sequences | |
# | |
# Author: Art Eschenlauer (@eschen42 on GitHub, | |
# - https://orcid.org/0000-0002-2882-0508 | |
# - https://github.com/eschen42 | |
# | |
# Date: September 23, 2021 | |
# | |
############################################################################ | |
# | |
# This file is in the public domain. | |
# - http://creativecommons.org/publicdomain/zero/1.0/ | |
# - CC0 | |
# | |
# "To the extent possible under law, Arthur Eschenlauer has waived all | |
# copyright and related or neighboring rights to LcomboP.icn." | |
# | |
############################################################################ | |
# | |
# These procedures use produce lists each of which comprises one | |
# combination of the results produced by the co-expressions in the list | |
# that they are passed as an argument. | |
# | |
# LiFiniteP{e} produces [ every |@e(1), every |@e(2), ... ] | |
# for finite e(i) | |
# | |
# LiP{e} produces [ every |@e(1), every |@e(2), ... ] | |
# for infinite e(i), by a breadth-first path | |
# | |
# Usage example: | |
# | |
# every "write"!LiP{"[", 1 to 2, ", ", 4 to 7, ", ", 8 to 9, "]"} | |
# | |
# which writes: | |
# | |
# [1, 4, 8] | |
# [2, 4, 8] | |
# [1, 5, 8] | |
# [2, 5, 8] | |
# [1, 4, 9] | |
# [1, 5, 9] | |
# [2, 4, 9] | |
# [2, 5, 9] | |
# [1, 6, 8] | |
# [1, 6, 9] | |
# [2, 6, 8] | |
# [2, 6, 9] | |
# [1, 7, 8] | |
# [1, 7, 9] | |
# [2, 7, 8] | |
# [2, 7, 9] | |
# | |
############################################################################ | |
# | |
# Requires: co-expressions | |
# | |
############################################################################ | |
# | |
# Links: none | |
# | |
############################################################################ | |
$ifndef LIST_COMBINED_RESULTS | |
$define LIST_COMBINED_RESULTS | |
procedure LiFiniteP(LofC) #: produce lists combining finite sequences | |
# For a list of co-expressions that produce a finite sequence | |
# of results; produce a list of each combination of results. | |
# This "recursive suspension" technique was adapted from | |
# Bob Alexander's regexp.icn from the IPL. | |
# For example, LiFiniteP{1 to 2, 5 to 6} produces: | |
# [1,5], then [1,6], then [2,5], and then [2,6]. | |
local C, v | |
# For the first C to be activated more than once, | |
# all but the first C must be finite. | |
C := ^LofC[1] | |
while v := @C | |
do if *LofC > 1 | |
then suspend [v] ||| LiFiniteP(LofC[2:0]) | |
else suspend [v] | |
end | |
procedure LiP(A) #: produce lists combining infinite sequences | |
# Generate combinations of argument results for list-invocation, | |
# not requiring that the arguments yield finite sequences: | |
# - For each co-expression, create an empty memoization list to hold | |
# the results that it will produce. | |
# - Activate each co-expression, putting the result onto its list. | |
# - Next produce the combination of the (one-member) memoization lists. | |
# - Next, in round-robin fashion: | |
# - activate each co-expression; | |
# - if activation succeeded: | |
# - add the result to its memoization list | |
# - and then produce the combinations of that result with the | |
# previous results of the other co-expressions, i.e., with | |
# all of the members of their memoization lists. | |
local done # set to not &null when all C are exhausted | |
local i # current C index, element of 1 to nA | |
local j # reusable index, element of 1 to nA | |
local lcpCL # list of C to be passed to LiFiniteP | |
local memoLL # list of memoization lists | |
local nA # size of A | |
local saveL # temporary holder to save memoLL[i] | |
nA := *A; memoLL := [] | |
every i := 1 to nA # Collect first result from each C, | |
do put( memoLL, [@A[i]] ) | fail # which is strictly required. | |
until \done # Repeat until every C is exhausted | |
do { | |
done := 1 # Revert to &null when @C succeeds | |
every i := 1 to nA # For any @(!A) that succeeds, | |
do { # memoize the result and suspend L | |
saveL := ( # If @A[i] fails, advance to i + 1 | |
(/saveL, memoLL[1]) | # - first activation, special case | |
put( memoLL[i], @A[i] ) | # - otherwise, require activation | |
next # - or next i | |
)[-1:0] # saveL slice has only last value | |
done := &null # C produces a value | |
saveL :=: memoLL[i] # Save memoization list for i | |
lcpCL := [] # Build list of C, each produ- | |
every j := 1 to nA # cing the memoized values | |
do put(lcpCL, create !memoLL[j]) # but with only latest @A[i] | |
suspend LiFiniteP(lcpCL) # Generate the combinations | |
memoLL[i] :=: saveL # Revert memoization list for i | |
} # next i | |
} # until \done | |
end | |
$ifndef MAIN | |
$define MAIN | |
# Generate (and display) lists combining co-expression results | |
procedure main() | |
write("\n# Produce all combinations of three finite sequences") | |
every "write"!LiP{"[ ", 1 to 2, ", ", 4 to 7, ", ", 8 to 9, " ]"} | |
write("\n# Produce first 30 combinations of three infinte finite sequences") | |
# Demonstrate infinite result-sequences | |
every "write"!LiP{ "[ ", |*¤t | |
, ", ", |*¤t | |
, ", ", |*¤t | |
, " ]" | |
} \30 | |
end | |
$endif # MAIN | |
$endif # LIST_COMBINED_RESULTS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment