Avoiding a rebuild if none of the dependencies have changed, but the output file has - incremental-build

I have a complicated setup where I generate a Vivado project file, and then run Vivado's synthesis tool to consume said project file and produce a bitfile. During this last step, Vivado updates some fields in the project file.
Below is a self-contained model of the situation:
import Development.Shake
import Development.Shake.FilePath
import Data.Time.Clock
import Control.Concurrent
outDir = "_build"
vivadoXPR :: IO ()
vivadoXPR = do
putStrLn "vivadoXPR"
threadDelay $ 1 * 1000 * 1000
writeFile (outDir </> "xpr") "xpr"
vivadoBitfile :: IO ()
vivadoBitfile = do
putStrLn "vivadoBitfile"
threadDelay $ 1 * 1000 * 1000
time <- getCurrentTime
writeFile (outDir </> "bitfile") (show time)
writeFile (outDir </> "xpr") (show time)
main = shakeArgs shakeOptions{ shakeFiles = outDir {-, shakeChange = ChangeModtimeAndDigestInput -} } $ do
outDir </> "manifest" %> \out -> do
alwaysRerun
writeFileChanged out "manifest"
outDir </> "tcl" %> \out -> do
need [outDir </> "manifest"]
writeFileChanged out "tcl"
outDir </> "xpr" %> \out -> do
need [outDir </> "tcl"]
liftIO vivadoXPR
outDir </> "bitfile" %> \out -> do
need [outDir </> "xpr"]
liftIO vivadoBitfile
What I would like to avoid is re-building xpr after a full build, since doing that invalidates all of Vivado's internal state, triggering a full re-synthesis. Note that none of xpr's dependencies change.
Building _build/bitfile twice with --trace shows the following:
$ rm -rf _build && \
stack exec -- shake --trace --trace _build/bitfile && \
stack exec -- shake --trace --trace _build/bitfile
% Starting run
% Number of actions = 1
% Number of builtin rules = 9 [FilesQ,DoesDirectoryExistQ,GetDirectoryContentsQ,AlwaysRerunQ,GetDirectoryDirsQ,DoesFileExistQ,GetDirectoryFilesQ,GetEnvQ,FileQ]
% Number of user rule types = 1
% Number of user rules = 4
% Before usingLockFile on _build/.shake.lock
% After usingLockFile
% Missing -> Running, _build/bitfile
# _build/bitfile
% Missing -> Running, _build/xpr
# _build/xpr
% Missing -> Running, _build/tcl
# _build/tcl
% Missing -> Running, _build/manifest
# _build/manifest
% Missing -> Running, alwaysRerun
% Running -> Ready, alwaysRerun
= ((),"") (changed)
% Running -> Ready, _build/manifest
= ((Just File {mod=0x540BBC70,size=0x8,digest=NEQ},"")) (changed)
% Running -> Ready, _build/tcl
= ((Just File {mod=0x540BBC70,size=0x3,digest=NEQ},"")) (changed)
vivadoXPR
% Running -> Ready, _build/xpr
= ((Just File {mod=0x178FA5A0,size=0x3,digest=NEQ},"")) (changed)
vivadoBitfile
% Running -> Ready, _build/bitfile
= ((Just File {mod=0xECA7F588,size=0x21,digest=NEQ},"")) (changed)
Build completed in 2.01s
% Starting run
% Number of actions = 1
% Number of builtin rules = 9 [FilesQ,DoesDirectoryExistQ,GetDirectoryContentsQ,AlwaysRerunQ,GetDirectoryDirsQ,DoesFileExistQ,GetDirectoryFilesQ,GetEnvQ,FileQ]
% Number of user rule types = 1
% Number of user rules = 4
% Before usingLockFile on _build/.shake.lock
% After usingLockFile
% Chunk 0 [len 34] 01000100000000000000040000000100000001000000010000000000000000000000 Id 1 = (StepKey (),Loaded (Result {result = "\SOH\NUL\NUL\NUL", built = Step 1, changed = Step 1, depends = [], execution = 0.0, traces = []}))
% Chunk 1 [len 30] 0a000600000000000000000000000100000001000000cd02cc3700000000 Id 6 = (alwaysRerun,Loaded (Result {result = "", built = Step 1, changed = Step 1, depends = [], execution = 2.432e-5, traces = []}))
% Chunk 2 [len 73] 0800050000000f0000005f6275696c642f6d616e696665737414000000000000000000000072bc0b540a000000010000000100000001000000d6ea4439080000000400000006000000 Id 5 = (_build/manifest,Loaded (Result {result = "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NULr\188\vT\n\NUL\NUL\NUL\SOH\NUL\NUL\NUL", built = Step 1, changed = Step 1, depends = [[Id 6]], execution = 1.87795e-4, traces = []}))
% Chunk 3 [len 68] 0800040000000a0000005f6275696c642f74636c14000000000000000000000072bc0b5405000000010000000100000001000000b1ef8d39080000000400000005000000 Id 4 = (_build/tcl,Loaded (Result {result = "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NULr\188\vT\ENQ\NUL\NUL\NUL\SOH\NUL\NUL\NUL", built = Step 1, changed = Step 1, depends = [[Id 5]], execution = 2.70722e-4, traces = []}))
% Chunk 4 [len 68] 0800030000000a0000005f6275696c642f787072140000000000000000000000a2a58f17050000000100000001000000010000002c32803f080000000400000004000000 Id 3 = (_build/xpr,Loaded (Result {result = "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\162\165\143\ETB\ENQ\NUL\NUL\NUL\SOH\NUL\NUL\NUL", built = Step 1, changed = Step 1, depends = [[Id 4]], execution = 1.0015311, traces = []}))
% Chunk 5 [len 72] 0800020000000e0000005f6275696c642f62697466696c651400000000000000000000008af5a7ec23000000010000000100000001000000263a803f080000000400000003000000 Id 2 = (_build/bitfile,Loaded (Result {result = "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL\138\245\167\236#\NUL\NUL\NUL\SOH\NUL\NUL\NUL", built = Step 1, changed = Step 1, depends = [[Id 3]], execution = 1.0017745, traces = []}))
% Chunk 6 [len 50] 0000070000000000000000000000010000000100000000000000080000000400000002000000080000001e4500401e450040 Id 7 = (Root,Loaded (Result {result = "", built = Step 1, changed = Step 1, depends = [[Id 2]], execution = 0.0, traces = [Trace {traceMessage = "", traceStart = 2.0042186, traceEnd = 2.0042186}]}))
% Read 7 chunks, plus 0 slop
% Found at most 8 distinct entries out of 7
% Loaded -> Running, _build/bitfile
% Loaded -> Running, _build/xpr
% Loaded -> Running, _build/tcl
% Loaded -> Running, _build/manifest
% Loaded -> Running, alwaysRerun
% Running -> Ready, alwaysRerun
= ((),"") (changed)
# _build/manifest
% Running -> Ready, _build/manifest
= ((Just File {mod=0x540BBC70,size=0x8,digest=NEQ},"")) (unchanged)
% Running -> Ready, _build/tcl
= ((Just File {mod=0x540BBC70,size=0x3,digest=NEQ},"")) (changed)
# _build/xpr
vivadoXPR
% Running -> Ready, _build/xpr
= ((Just File {mod=0xDC183BD8,size=0x3,digest=NEQ},"")) (changed)
# _build/bitfile
vivadoBitfile
% Running -> Ready, _build/bitfile
= ((Just File {mod=0x9F9C2120,size=0x21,digest=NEQ},"")) (changed)
Build completed in 2.01s
How can avoid vivadoXPR running on the second shake run?

Related

Run the celery tasks automatically every day at a particular time in python

Here i am using python 3.7 and django 3.0
I want to run a celery task every day at 11:30
Here is my settings.py
CELERYBEAT_SCHEDULE = {
'create_auto_capacity': {
'task': 'crm.tasks.create_auto_capacity',
'schedule': crontab(minute='30', hour='11')
},
}
Here is my crm/tasks.py
#celery_app.task()
def create_auto_capacity():
production_settings = ProductionSettings.objects.all()
client_id = []
for i in production_settings:
client_id.append(i.client.id)
client = ''
for id in client_id:
client = Client.objects.get(id=id)
process = ProductionProcess.objects.filter(is_deleted=False,client=client)
capacity = ProductionCapacity.objects.filter(client=client).last()
capacity_last_date = capacity.date
for i in production_settings:
c_time = []
work_time = WorkTime.objects.filter(client=client,day_type='Weekdays').values_list('total_time',flat=True)
for j in work_time:
try:
t = datetime.datetime.combine(capacity_last_date.min, j) - datetime.datetime.min
except:
t = datetime.combine(capacity_last_date.min, j) - datetime.min
x = isinstance(t, timedelta)
y = t.total_seconds() / 60
c_time.append(y)
g = sum(c_time)
capacity = g * i.num_of_people
remaning_time = g * i.num_of_people
ProductionCapacity.objects.create(client=client,date=capacity_last_date,
production_process=i.production_process,number_of_people=i.num_of_people,
capacity=capacity,remaning_time=remaning_time,manual_add=False)
I want to run this code(crm/tasks) daily at 11:30 but this is not working

How to Sort a table of strings according to the order defined by another table of strings (Lua)

I have 2 lua tables:
OrderTbl = {'Hello', 'Question', 'Answer', 'Bye'}
UnsortedTbl = {'Question', 'Bye, 'Bye', 'Question', 'Hello', 'Something'}
How to sort UnsortedTbl in order given by OrderTbl? (Fields not found in OrderTbl are placed in the end of result table, unsorted)
I have translated a sample of code from Java, and it works with numbers. Here it is:
function first(arr, low, high, x, n)
if high >= low then
-- (low + high)/2
local mid = low + math.floor((high - low) / 2)
if (mid == 1 or x > arr[mid - 1]) and arr[mid] == x then
return mid
end
if x > arr[mid] then return first(arr, (mid + 1), high, x, n) end
return first(arr, low, (mid - 1), x, n)
end
return nil
end
-- Sort A1 according to the order
-- defined by A2
function sortAccording(A1, A2)
local m=#A1
local n=#A2
-- The temp array is used to store a copy
-- of A1{} and visited{} is used to mark the
-- visited elements in temp{}.
local temp = {}
local visited = {}
for i = 1, m do
temp[i] = A1[i]
visited[i] = 0
end
-- Sort elements in temp
table.sort(temp)
-- for index of output which is sorted A1{}
local ind = 0
-- Consider all elements of A2{}, find them
-- in temp{} and copy to A1{} in order.
for i = 1, n do
-- Find index of the first occurrence
-- of A2[i] in temp
local f = first(temp, 1, m, A2[i], m+1)
-- If not present, no need to proceed
if not f then
-- continue
else
-- Copy all occurrences of A2[i] to A1{}
j = f
while j < m and temp[j] == A2[i] do
A1[ind] = temp[j]
ind = ind + 1
visited[j] = 1
j = j + 1
end
end
end
-- Now copy all items of temp{} which are
-- not present in A2{}
for i = 1, m do
if visited[i] == 0 then
ind = ind + 1
A1[ind] = temp[i]
end
end
end
function printArray(arr)
for i = 1, #arr do
print(arr[i] .. " ")
end
end
-- Driver program to test above function.
local A1 = {2, 1, 2, 5, 7, 1, 9, 3, 6, 8, 8}
local A2 = {2, 1, 4, 3, 6, 5, 8, 7}
sortAccording(A1, A2)
printArray(A1)
I don't quite understand how to make it work with strings. Could you help me?
You can use the form of table.sort that accepts a custom comparator:
local OrderTbl = {'Hello', 'Question', 'Answer', 'Bye'}
local UnsortedTbl = {'Question', 'Bye', 'Bye', 'Question', 'Hello', 'Something', 'Else'}
-- convert the order to hash that can be easily queried
for idx, val in ipairs(OrderTbl) do OrderTbl[val] = idx end
local maxIdx = #OrderTbl + 1 -- this will mark "missing" elements
-- pass a custom comparator that will check OrderTbl
table.sort(UnsortedTbl, function(a, b)
local pa = OrderTbl[a] or maxIdx -- desired index of a
local pb = OrderTbl[b] or maxIdx -- desired index of b
if pa == pb then return a < b end -- sort by name
return pa < pb -- sort by index
end)

I have some code that take under 2 seconds to run 100 iterations, under 8 seconds to run 1000, and over 11 minutes to run 10,000

I'm a hobbyist programmer, and this is just a little project I set for myself. I know I very likely have something in this code that is inefficient enough to not matter for small loops but is compounding when I scale it up. Any suggestions would be appreciated.
def RndSelection(ProjMatrix):
percentiles = [0,10,20,25,30,40,50,60,70,75,80,90,99]
results = []
for row in ProjMatrix.itertuples():
x = npr.randint(1,100)
for p in range(3,16):
if p < 15:
a = percentiles[p-3]
b = percentiles[p-2]
if x in range (a,b):
factor = (b-x)/(b-a)
r = round((row[p]*factor)+((row[p+1])*(1-factor)),2)
break
else:
r = row[p]
results.append(r)
thisrun = pd.DataFrame(results)
return(thisrun)
def main():
ts = datetime.datetime.now()
print ('Run Started: ', ts)
Matrix = SetMatrix()
Outcome = Matrix['player_id']
with concurrent.futures.ProcessPoolExecutor() as executor:
results = [executor.submit(RndSelection,Matrix) for _ in range(10000)]
for f in concurrent.futures.as_completed(results):
thisrun = f.result()
Outcome = pd.concat([Outcome,thisrun],axis=1)
print(Outcome)
ts = datetime.datetime.now()
print('Run Completed: ', ts)
if __name__ == '__main__':
main()
So the answer, as Jérôme pointed out, was the iteration of the concat.
Moving the output to a list of lists and then concat just once improved the runtime of 10,000 interactions to 8 seconds and 100,000 iterations to 2 mins, 34 seconds.
def RndSelection(ProjMatrix):
percentiles = [0,10,20,25,30,40,50,60,70,75,80,90,99]
results = []
r = ""
for row in ProjMatrix.itertuples():
x = npr.randint(1,100)
for p in range(3,16):
if p < 15:
a = percentiles[p-3]
b = percentiles[p-2]
if x in range (a,b):
factor = (b-x)/(b-a)
r = round((row[p]*factor)+((row[p+1])*(1-factor)),2)
break
else:
r = row[p]
results.append(r)
return results
def main():
ts = datetime.datetime.now()
print ('Run Started: ', ts)
Matrix = SetMatrix()
runs = 100000
s = 0
Outcome = pd.DataFrame(Matrix['player_id'])
thisrun = np.empty((runs,0)).tolist()
with concurrent.futures.ProcessPoolExecutor() as executor:
results = [executor.submit(RndSelection,Matrix) for _ in range(runs)]
for f in concurrent.futures.as_completed(results):
thisrun[s]=f.result()
s += 1
allruns = pd.DataFrame(thisrun).transpose()
Outcome = pd.concat([Outcome,allruns],axis=1)
ts = datetime.datetime.now()
print('Run Completed: ', ts)
if __name__ == '__main__':
main()

Why this Fuction cannot be called

I have this list that I want to sort based on bubble sort, and there is a function in code (Swap()) is refusing to work. I don't know why. there is the code
score = [92,95,7,5,85,55,789,47,125,3265,88,965,655,3,15,448,0,255,455]
size = len(score)
x = 0
COMPS = size - 1
def swap():
temp = score[x + 1]
score[x + 1] = score[x]
score[x] = temp
# The Sort Array Function
def SortArray():
y = 0
while y < COMPS:
x = 0
while x < COMPS:
if score[x] > score[x + 1]:
#This function not working.
swap()
x += 1
y += 1
#Display Array Function
def displayArray():
x = 0
while x < size:
print(score[x])
x += 1
SortArray()
displayArray()
but inserting the swap() code, thus the code under the swap() and replacing it underneath the SortArray(), below the if condition; just like this:
def SortArray():
y = 0
while y < COMPS:
x = 0
while x < COMPS:
if score[x] > score[x + 1]:
#This Works
temp = score[x + 1]
score[x + 1] = score[x]
score[x] = temp
x += 1
y += 1
then it works, so I want to know why the swap() function doesn't get called under the SortArray()
I want to know why the swap() function doesn't get called under the SortArray()
Actually, it IS called - which you can check by yourself adding a couple print() calls within or using the step debugger - but it doesn't do what you think it should do, because you're confusing local and global variables.
In SortArray() you define a local variable named x (it's defined as local because you assign it in the function), and this is obviously the one you expect swap() to use. But in your swap function, you use a variable x which is neither an argument of the function nor assigned within the function (both of which would make it a local variable), so it's resolved as the global x declared above.
IOW, swap uses the global x why you'd expect it to use the one which is local to SortArray(). This is also why the second version works, since this time it uses the proper variable.
The solution is to remove the global x and explicitely pass the correct value to swap(), ie:
def swap(x):
temp = score[x + 1]
score[x + 1] = score[x]
score[x] = temp
def SortArray():
y = 0
while y < COMPS:
x = 0
while x < COMPS:
if score[x] > score[x + 1]:
swap(x)
x += 1
y += 1
And while you're at it, you should also to the same with score - actually, you should avoid globals as much as possible (and believe me, you can write a lot of code without using globals):
def swap(score, x):
temp = score[x + 1]
score[x + 1] = score[x]
score[x] = temp
def SortArray(score):
comps = len(score) - 1
y = 0
while y < comps:
x = 0
while x < comps:
if score[x] > score[x + 1]:
swap(score, x)
x += 1
y += 1
def displayArray(score):
x = 0
while x < len(score):
print(score[x])
x += 1
if __name__ == "__main__":
score = [92,95,7,5,85,55,789,47,125,3265,88,965,655,3,15,448,0,255,455]
SortArray(score)
displayArray(score)
And now your functions can be used with any list or sequence. They are still totally unpythonic but that's obviously not the point here (python has one of the most optimized sort algorithm builtin anyway).

How can I count the recursive calls of a function in Python?

I was playing with the recursive Ackermanns function. For certain values my prompt whould not show every calculated output 'cause Python whould exceed its recursive limit so fast that whould freeze the prompt before the "easy" parts whould catch up with it.
So I thought I could add a recursive counter and a quick pause after a full execution of the function. I was getting the anticipated outputs until it reached the values (1,0). After that I got a TypeError: can only concatenate tuple (not "int") to tuple.
My code is as follows:
import time
import sys
sys.setrecursionlimit(3000)
def ackermann(i,j,rec):
output = None
if i==0:
output = j+1
elif j==0:
output = ackermann(i-1,1,rec)
rec=rec+1
else:
output = ackermann(i-1,ackermann(i,j-1,rec),rec)
rec=rec+1
return output,rec
rec=0
for i in range(5):
for j in range(5):
print("(",i,",",j,")= ",ackermann(i,j,rec))
time.sleep(2)
Notice that removing all instances of rec (my recurence counter), the program runs fine. (You can see all outputs for values i,j = 3)
Can someone point out how to correct my code or propose a different method of finding how many times the Ackermann function has calls itself ?
Also, I've noticed that putting a limit of 5000 whould crash my python kernel very fast. Is there an upper limit ?
I use the latest Anaconda.
EDIT
I tried to implement the same function using a list as a parameter with the following data [i,j,output,#recursion]
import time
import sys
sys.setrecursionlimit(3000)
def ackermann(*rec):
rec=list(rec)
print(rec) # see the data as they initialize the function
if rec[0][0]==0:
rec[0][1]=rec[0][1]+1
rec[0][2] = rec[0][1]+1
elif rec[0][1]==0:
rec[0][0]=rec[0][0]-1
rec[0][1]=1
rec = ackermann()
rec[0][3]=rec[0][3]+1
else:
rec[0][0]=rec[0][0]-1
rec[0][1] = ackermann()
rec = ackermann()
rec[0][3]=rec[0][3]+1
return rec
for i in range(5):
for j in range(5):
rec=[i,j,0,0]
print(ackermann(rec))
time.sleep(1)
But this time I get a IndexError: list index out of rangebecause for some unknown reason my list gets emptied
OUTPUT:
[[0, 0, 0, 0]]
[[0, 1, 2, 0]]
[[0, 1, 0, 0]]
[[0, 2, 3, 0]]
[[0, 2, 0, 0]]
[[0, 3, 4, 0]]
[[0, 3, 0, 0]]
[[0, 4, 5, 0]]
[[0, 4, 0, 0]]
[[0, 5, 6, 0]]
[[1, 0, 0, 0]]
[]
The problem with the original implementation is that
return output, rec
will happily create a tuple when output and rec are both numbers, which is true whenever i=0. But once you get to i=1, j=0 the function calls Ackerman on (0,1,rec), which returns a tuple, to which it then cannot add the integer rec, hence the error message. I believe I have worked with that idea, though, almost unchanged, except rather than trying to pass and return rec, I made it global (ugly, I know). I also reformatted the output so I could read it better. Thus:
import time
import sys
sys.setrecursionlimit(3000)
def ackermann(i,j):
global rec
output = None
if i==0:
output = j+1
elif j==0:
output = ackermann(i-1,1)
rec=rec+1
else:
output = ackermann(i-1,ackermann(i,j-1))
rec=rec+1
return output
for i in range(5):
for j in range(5):
rec = 0
print
print("ack("+str(i)+","+str(j)+") = "+str(ackermann(i,j)))
print("rec = "+str(rec))
print
time.sleep(1)
and the output, before erroring out, is,
ack(0,0) = 1
rec = 0
ack(0,1) = 2
rec = 0
ack(0,2) = 3
rec = 0
ack(0,3) = 4
rec = 0
ack(0,4) = 5
rec = 0
ack(1,0) = 2
rec = 1
ack(1,1) = 3
rec = 2
ack(1,2) = 4
rec = 3
ack(1,3) = 5
rec = 4
ack(1,4) = 6
rec = 5
ack(2,0) = 3
rec = 3
ack(2,1) = 5
rec = 8
ack(2,2) = 7
rec = 15
ack(2,3) = 9
rec = 24
ack(2,4) = 11
rec = 35
ack(3,0) = 5
rec = 9
ack(3,1) = 13
rec = 58
ack(3,2) = 29
rec = 283
ack(3,3) = 61
rec = 1244
ack(3,4) = 125
rec = 5213
ack(4,0) = 13
rec = 59
It seems to me there are only one or two other values (it will choke on 4,2 I believe, no matter what, so you would need to get 5, 0 first) you could hope to get out this way, no matter how much you tinker.
I am a little troubled that rec appears to exceed the recursion limit, but I think Python must be interpreting along the way somehow, so that it gets deeper than one might think, or that I don't fully understand sys.recursionlimit (I looked at rec a few times, and at the very least I followed your lead on calculating it; also, as a sanity check I switched the order of incrementing it and the function call and got the same results).
EDIT: I added another parameter to track how deeply any particular call ever recurses. That turns out to be typically less than (and at most one more than) "rec." rec represents (actually 1 less than) how many times the function is called to make the particular calculation, but not all of these need be on the Python interpreter stack simultaneously.
Revised code:
import time
import sys
sys.setrecursionlimit(3000)
def ackermann(i,j,d):
global rec
global maxDepth
if ( d > maxDepth ) : maxDepth = d
output = None
if i==0:
output = j+1
elif j==0:
rec=rec+1
output = ackermann(i-1,1, d+1)
else:
rec=rec+1
output = ackermann(i-1,ackermann(i,j-1, d+1),d+1)
return output
for i in range(5):
for j in range(5):
rec = 0
maxDepth=0
print
print("ack("+str(i)+","+str(j)+") = "+str(ackermann(i,j,1)))
print("rec = "+str(rec))
print("maxDepth = "+str(maxDepth))
print
time.sleep(1)
revised output (before it gives up)
ack(0,0) = 1
rec = 0
maxDepth = 1
ack(0,1) = 2
rec = 0
maxDepth = 1
ack(0,2) = 3
rec = 0
maxDepth = 1
ack(0,3) = 4
rec = 0
maxDepth = 1
ack(0,4) = 5
rec = 0
maxDepth = 1
ack(1,0) = 2
rec = 1
maxDepth = 2
ack(1,1) = 3
rec = 2
maxDepth = 3
ack(1,2) = 4
rec = 3
maxDepth = 4
ack(1,3) = 5
rec = 4
maxDepth = 5
ack(1,4) = 6
rec = 5
maxDepth = 6
ack(2,0) = 3
rec = 3
maxDepth = 4
ack(2,1) = 5
rec = 8
maxDepth = 6
ack(2,2) = 7
rec = 15
maxDepth = 8
ack(2,3) = 9
rec = 24
maxDepth = 10
ack(2,4) = 11
rec = 35
maxDepth = 12
ack(3,0) = 5
rec = 9
maxDepth = 7
ack(3,1) = 13
rec = 58
maxDepth = 15
ack(3,2) = 29
rec = 283
maxDepth = 31
ack(3,3) = 61
rec = 1244
maxDepth = 63
ack(3,4) = 125
rec = 5213
maxDepth = 127
ack(4,0) = 13
rec = 59
maxDepth = 16
In your edited version of the code, you used a *arg in your def for ackerman and made it explicitly a list, and you get eleven output lists containing a four-element list in each until on the twelfth recursion you get an empty list. So, did the first eleven lists contain the expected elements according to the ackermann constraints? Also, on the twelfth recursion, you say the list was "emptied." I wonder for analytical purposes if it might make sense to say instead it wasn't filled in the first place. That is, not that something emptied it but that something didn't fill it as expected on the twelfth time through.

Resources