Notifications
Clear all

[Closed] Middle Middle Middle

I’m working on a better submission tool for my farm rendering and in nearly ever scenario I want to submit the frames to the render farm in a order like this…

Here is the frame range: 01…09

What i need to do is return an array that does the first and last frame, then gets the middle frame for each part until all frames are in the new array. This is what the final output should be and in this order.

01, 02, 03, 04, 05, 06, 07, 08, 09 –original

01, 09, 05, 03, 07, 02, 04, 06, 08 –ordered by middle

to further break it down step by step

01 , 09 -first and last frame
05 –middle frame of 01 – 09
03 –middle frame of 01 – 05
07 –middle frame of 05 – 09
02 –middle frame of 01 – 03
04 –middle frame of 03 – 05
06 –middle frame of 05 – 07
08 –middle frame of 07 – 09

34 Replies

I think this code can do it.

(
	clearlistener()
	prevArray = #("01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17")
	orderedArray = #()
	leftOrRight = true
	
	
	function getStepCount = 
	(
		local steps = 0
		local middle = prevArray.count
		do
		(
			steps += 1
			middle = ceil (middle / 2.0)
		)
		while (middle > 1)
		steps
	)
	
	function addValues n =
	(
		div = (pow 2 n)
		for i=1 to (div-1) do
		(
			appendifunique orderedArray prevArray[(ceil ((prevArray.count / div) * i))]
		)
	)
	
	local stepCount = getStepCount()
	appendifunique orderedArray prevArray[1]
	appendifunique orderedArray prevArray[prevArray.count]
	for i=1 to (stepCount-1) do
	(
		addValues i
	)
	print orderedArray
)
 lo1

That’s quite a lot of code

fn sortByMiddle arr =
(
	local sorted = #()
	local stepSize = amax 1 (arr.count - 1)
	while (stepSize > 0) do
	(
		local index = 1
		for index = 1 to arr.count by stepSize do
		(
			appendIfUnique sorted arr[index]
		)
		stepSize /= 2
	)
	sorted
)

sortByMiddle (for i = 1 to 9 collect i)

Yes it was dirty but did the job.
Yours is what I would have wanted to get ;).

Not as tidy, but this one’s a slightly faster function (1-50000 range took 200ms instead of 9000ms and 17705ms). And it only requires start and end range values, also easily accepts negative values.

fn RTMA_mid  dp = floor((dp.v2-dp.v1)/2.0)+dp.v1

fn RangeToMiddlesArr a b = 
(
	if a<b then
		(
		dpArr = #()
		dpArr[1] = datapair a b
		
		arr = #()
		arr[1] = a
		arr[2] = b
		
		while dpArr.count > 0 do
		(
			newdpArr =#()
			for dp in dpArr do
			(
				local dpMid = (RTMA_mid  dp)
				if dp.v2-dp.v1 == 2 then append arr dpMid
				else
				(
					if dpMid != dp.v1 AND dpMid != dp.v2 then append arr dpMid
					if dpMid-dp.v1 > 1 then append newdpArr (datapair dp.v1 dpMid)
					if dp.v2-dpMid > 1 then append newdpArr (datapair dpMid dp.v2)
				)
			)
			dparr = #()
			dpArr = newdpArr
		)
		arr
		)
	else false
)

I’m sure it can be done better, but my poor recursion-challenged brain can’t figure it out in a short amount of time.

Results for 13 items:

#2 #(1, 13, 7, 4, 10, 2, 5, 9, 12)
#3 #(1, 13, 7, 4, 10, 2, 3, 5, 6, 8, 9, 11, 12)
#5 #(1, 13, 7.0, 4.0, 10.0, 2.0, 5.0, 8.0, 11.0, 3.0, 6.0, 9.0, 12.0)

i don’t sure that you function works right. try this array:

seed 0
a = (for i = 1 to 40 by (random 1 4) collect i)
sortByMiddle a

… deleted as doubled

only LO’s algorithm meets the rule. two other are doing something their own.

Well, if the requirement is getting the middle parts, arguably my algorithm proves closer to the goal.

Was wondering what the distribution looked like, so I made a comparison graph (attached) of a sorted 1…100 array.

Y curve is lo: #(1, 100, 50, 99, 25, 49, 73, 97, 13, 37, 61, 85, 7, 19, 31, 43, 55, 67, 79, 91, …)
Z curve is mine: #(1.0, 100.0, 50.0, 25.0, 75.0, 13.0, 37.0, 62.0, 87.0, 7.0, 19.0, 31.0, 43.0, 56.0, 68.0, 81.0, 93.0, 4.0, 10.0, 16.0, …)

Page 1 / 3