Skip to content

Instantly share code, notes, and snippets.

@eschen42
Last active September 24, 2021 13:50
Show Gist options
  • Save eschen42/a4764fd8c1e0e498ad44d7359469dedf to your computer and use it in GitHub Desktop.
Save eschen42/a4764fd8c1e0e498ad44d7359469dedf to your computer and use it in GitHub Desktop.
Produce lists combining memoized infinte sequences
############################################################################
#
# 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{ "[ ", |*&current
, ", ", |*&current
, ", ", |*&current
, " ]"
} \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