Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
variable loop depth
#1
in a program i am now working on i need to run a stack of loops and this is a variable number that is itself variable. the current value of each loop must add up to a number in a range between two given variables. this begs for a recursive implementation (have done that before). but before i do that i am wondering if Python has anything that can make this better. many decades ago i did this in assembler using an escaped loop (the loop would restart itself after the escape with an incremented position in an index array to avoid recursion).
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
Keep track of the recursion yourself. Have a stack (list) of iterators. Use __next__ to advance the last (deepest) iterator. When that one is done, pop it off. When a new one is needed, append it on.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
if i use recursion, i can make it just not recurse when it no longer needs to (when the sum of the indexes reaches a certain value). when i did this in C i basically did the same as my 360 assembler version and used a goto to escape the loop to effect the same as recursion (without pushing the stack) and another to re-enter the loop (without pulling the stack). but it looks like recursion is the way to go in Python. i'm wondering if i can do this as a generator.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#4
With my suggestion you can completely skip out any time you want to, and restart where you left off. I'm not saying use recursion, I'm saying fake the recursion.

def silly(n, x):
    m = n
    stack = [iter(range(m))]
    total = 0
    while stack:
        try:
            i = stack[-1].__next__()
        except StopIteration:
            stack.pop()
            continue
        total += i
        if total >= x:
            break
        if i == 5:
            m -= 1
            stack.append(iter(range(m)))
    return total
By keeping the stack of iterators yourself, you have complete control over it. You could pass the stack around between different functions doing different things.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
it still looks bigger and more complex than doing recursion. what i am worried about next is whether or not i can do a yield in the recursive function. during the many loops in the recursion there is a point where the total equals or exceeds a limit. if it exceeds the limit, that last loop is broken out of and the recursion returns to the previous loop for it next try. but if it equals the limit, i want to yield the list of all the iterated values before doing that recursion descent. i just want to be sure that yield mechanism can resume the recursive stack. i supposed i can just try it and see. the alternative would be to print the list and have the code that needs to process these values just read them from a pipe. each loop in one recursion has the same range. there will be many such recursions being run to look for specific results each with different ranges. this may involve a lot of CPU time. hopefully, your code ideas overcome that extra code by avoiding the extra overhead. but i may have to still go back and redo this in C. but there are somE ideas i have for changes that could be hard to do in C.

here is code i am currently thinking around
def nestloop(xlist,abc,sum,limit):
    xlist.append(0)
    for num in range(*abc):
        xlist[-1] = num
        u = sum+num
        if u==limit:
            print(' '.join([repr(x) for x in xlist]))
            # or do a yield of xlist here
            break
        if u>limit:
            break
        nestloop(xlist,abc,u,limit)
    xlist.pop(-1)
    return
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#6
here is the recursive code working:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import division, generators, print_function, with_statement
r"""Generate signal codings for the multiple interval signal system.

file          signalcoding.py
purpose       generate signal codings for the multiple interval signal
              system
email         10054452614123394844460370234029112340408691
"""
#-------#-------#-------#-------#-------#-------#-------#-------#-------#-------#
__license__ = r"""
Copyright © 2018, by Phil D. Howard - all other rights reserved

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

The author may be contacted by decoding the number
10054452614123394844460370234029112340408691
(provu igi la numeron al duuma)
"""
#-------#-------#-------#-------#-------#-------#-------#-------#-------#-------#
try:
    from d import sl, pr, pv
except:
    def sl(*a,**o): return
    def pr(*a,**o): return
    def pv(*a,**o): return

try:
    from printobject import print_object
except:
    def print_object(*a,**o):
        return 0

try:
    from intx import intx
except:
    intx = int

#-------#-------#-------#-------#-------#-------#-------#-------#-------#-------#
def depth():
    from inspect import currentframe
    d = -2
    f = currentframe()
    while 'f_back' in dir(f):
        d += 1
        f = f.f_back
    return d


def eprint(*a,**o):
    if 'file' not in o:
        o['file']=stderr
    f=o['file']
    r=print(*a,**o) if o else print(*a)
    f.flush()
    return r


# sum   is the accumulated sum of all previous loops, starts with 0
# xlist is the indexed list keeping each loop value, starts with []
# limit is the limit of sum of loop indexes, length of the code sum
# sss   is a 3-tuple (start,stop,step) passed as args to range() to
#       control each loop at each recursive depth

def nestloop(sum,xlist,limit,sss):
    deep = depth()-1
    xlist.append(0)
    for num in range(*sss):
        xlist[-1] = num
        sn = sum+num
        if sn==limit:
            print('{:>4d}:'.format(deep),' '.join([repr(x) for x in xlist]))
            stdout.flush()
            break
        if sn>limit:
            break
        nestloop(sn,xlist,limit,sss)
    xlist.pop(-1)
    return


#-------#-------#-------#-------#-------#-------#-------#-------#-------#-------#
def main(args):
    errors = 0
    cname = args.pop(0)
    if len(args) > 4: return 'too many arguments - max 4 - '\
    'need: [ limit (8) [ start (1) [ last (start+1) [ step (1) ] ] ] ]'
    names = ('limit','start','last','step')
    nums = []
    for x,arg in enumerate(args):
        if x > 3:
            eprint('argument',repr(1+x),'['+names[x]+']','is an extra argument')
            errors += 1
            continue
        try:
            n = intx(arg)
        except:
            eprint('argument',repr(1+x),'['+names[x]+']','is','('+repr(arg)+')',
                   'not a valid number')
            errors += 1
        nums.append(n)
    if len(nums) == 0: nums += [15,3,5,1]
    if len(nums) == 1: nums += [3,5,1]
    if len(nums) == 2: nums += [nums[1]+1,1]
    if len(nums) == 3: nums += [1]
    limit, start, last, step = nums
    print('limit =',repr(limit))
    print('start =',repr(start))
    print(' last =',repr(last))
    print(' step =',repr(step))
    stdout.flush()
    
    if errors: return 'aborting due to '+repr(errors)+' errors'
    nestloop(0,[],limit,(start,last+1,step))

    return 0

#-------#-------#-------#-------#-------#-------#-------#-------#-------#-------#
if __name__ == '__main__':
    from sys import argv, stderr, stdout
    if bytes == str:
        BrokenPipeError, FileNotFoundError = IOError, OSError
    try:
        result=main(argv)
    except BrokenPipeError:
        result = 99
    except KeyboardInterrupt:
        stderr.flush()
        print()
        result = 98
    stderr.flush()
    stdout.flush()
    if result is 0 or result is None or result is True:
        exit(0)
    if result is 1 or result is False:
        exit(1)
    if isinstance(result, str):
        print(result, file=stderr)
        exit(2)
    try:
        exit(int(result))
    except ValueError:
        print(str(result), file=stderr)
        exit(3)
    except TypeError:
        exit(4)
# EOF
the 4 command arguments default to 15 3 5 1 if none are given. this means to generate all the groups of numbers in the range(3,6,1) that add up to a fixed total of 15. this represents a single coding scheme to modulate data over an analog medium such as as a keyed radio carrier. this design works by having varying lengths of time between on/off transitions. there are 18 such codes as the output of this program shows. 2 of them would be used for idling (3 3 3 3 3) and (5 5 5) and the other 16 used to encode 4 bits of data. the coding scheme with lengths 4 through 7 for a total of 28 has 277 possible combinations which has plenty of code combinations to use 2 for idling (4 4 4 4 4 4 4) and (7 7 7 7) and 256 of the remaining 275 for 8 bits of data. many more schemes can be made, all with a fixed total over all of the codes for each scheme. by limiting the inter-transition length to numbers where the longest is no longer than twice the shortest, it is possible to reconstruct the original data level waveform from a smoothed level analog waveform that can be had through a narrow bandwidth frequency filter. the information part of the waveform is maintained in that narrow range as defined by the shortest and longest intervals. the up/down positive/negative state of the signal does not matter. all the information is in the timing between transitions, eliminating concern for the DC bias of the signal, which will average out to zero with scrambled or encrypted data.

back when i first made this program in assembler (for both IBM 360/370 mainframes and 6502 in an Apple II) i realized by watching the data (codes) fly by real fast, that they was a better way to generate all the codes for a given scheme. i did implement that and generated a lot of schemes. from that i found an even more optimal way to select good schemes without generating codes that was based on Pascal's Triangle and some variations of that (adding more than just 2 numbers from the line above). but really the 28 4 7 1 scheme is all we need (the 15 3 5 1 scheme for 4-bit streams).

the above embedded source code is also available at http://ipal.net/free/signalcoding.py
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Variable definitions inside loop / could be better? gugarciap 2 375 Jan-09-2024, 11:11 PM
Last Post: deanhystad
  How to create a variable only for use inside the scope of a while loop? Radical 10 1,526 Nov-07-2023, 09:49 AM
Last Post: buran
  Nested for loops - help with iterating a variable outside of the main loop dm222 4 1,532 Aug-17-2022, 10:17 PM
Last Post: deanhystad
  loop (create variable where name is dependent on another variable) brianhclo 1 1,103 Aug-05-2022, 07:46 AM
Last Post: bowlofred
  Multiple Loop Statements in a Variable Dexty 1 1,175 May-23-2022, 08:53 AM
Last Post: bowlofred
Big Grin Variable flag vs code outside of for loop?(Disregard) cubangt 2 1,131 Mar-16-2022, 08:54 PM
Last Post: cubangt
  How to save specific variable in for loop in to the database? ilknurg 1 1,110 Mar-09-2022, 10:32 PM
Last Post: cubangt
  How to add for loop values in variable paulo79 1 1,411 Mar-09-2022, 07:20 PM
Last Post: deanhystad
  Max recursion depth.... Error MeloB 2 1,838 Feb-16-2022, 05:21 PM
Last Post: MeloB
  Using Excel Cell As A Variable In A Loop knight2000 7 4,015 Aug-25-2021, 12:43 PM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020