[REBOL] Re: REBOL Enhancement Proposals (REPs)
From: greggirwin:starband at: 27-Sep-2001 10:18
Hi Joel,
I love a puzzle, plus I need more console time with REBOL, being a newbie.
<< Given a block of numbers, what's the simplest way in REBOL to write a
smoothing
operation that averages each interior value (i.e.,
all but the first and last) with the two values on either
side of it? >>
My first whack is a direct translation of what you posted:
smooth-interior: func [blk /local i] [
for i 2 (length? blk) - 1 1 [
change at blk i divide ((pick blk i - 1) + (pick blk i) + (pick
blk i + 1)) 3
]
]
The "pick" and "change at" stuff is more verbose than direct element access
by index.
To try and simplify things, I broke out a sub-function and tried using next
and back:
avg-fore-back: func [blk] [
divide ((first back blk) + (first blk) + (first next blk)) 3
]
smooth-interior: func [blk /local i] [
for i 2 (length? blk) - 1 1 [
change at blk i avg-fore-back at blk i
]
]
Next I moved the change at bit to the sub-function to see how I liked that:
avg-fore-back: func [blk] [
change blk divide ((first back blk) + (first blk) + (first next
blk)) 3
]
smooth-interior: func [blk /local i] [
for i 2 (length? blk) - 1 1 [
avg-fore-back at blk i
]
]
Finally, I added other generic functions to see what that did for me:
sum: func [values[any-block!]] [
either tail? values [0][add (first values) (sum next values)]
]
avg: func [values[any-block!]] [
divide (sum values) (length? values)
]
smooth-interior: func [blk /local i] [
for i 2 (length? blk) - 1 1 [
change at blk i avg copy/part at blk (i - 1) 3
]
]
At first I didn't like this because the call to avg virtually disappears,
becoming indistinct as a separate function. BUT, if I read it as a sentence
as if it were pseudo-code it "reads" very clearly.
I think the first version would be the most familiar for people coming
from other mainstream languages, but I think I like the last one the best.
I'll have to spend some more time with it to be sure. One other advantage
to it, is that it's easy to extend for more than 3 point averaging.
smooth-interior: func [blk width[integer!] /local i wd-offset] [
wd-offset: to-integer ((width - 1) / 2)
; TBD Ensure width is odd
for i (1 + wd-offset) ((length? blk) - wd-offset) 1 [
change at blk i avg copy/part at blk (i - wd-offset) width
]
return head blk
]
I know flexibility wasn't part of your puzzle, and I'm not a numerical
analyst, or number theory kinda' guy, so I don't know how valuable that
is but common sense tells me it could be useful.
Thanks for the prompt to learn a little more!
--Gregg