Shift list elements to left by 3: Difference between revisions

Content added Content deleted
(Add an example in Common Lisp utilizing the rotate function from the alexandria library)
m (→‎AppleScript: →‎Two in-place alternatives: Added range parameters to both scripts.)
Line 206: Line 206:
===Two in-place alternatives===
===Two in-place alternatives===
Fewest moves:
Fewest moves:
<lang applescript>(* List rotation, in-place with temporary external storage. Negative 'amount' = left rotation, positive = right.
<lang applescript>(* List range rotation, in-place with temporary external storage. Negative 'amount' = left rotation, positive = right.
Method:
Method:
Adjust the specified amount to get a positive, < list length, left-rotation figure.
Adjust the specified amount to get a positive, < list length, left-rotation figure.
Store the leftmost 'amount' items.
Store the range's leftmost 'amount' items.
Move the other items 'amount' places to the left.
Move the range's other items 'amount' places to the left.
Move the stored items into the rightmost slots.
Move the stored items into the range's rightmost slots.
*)
*)
on rotate(lst, amount)
on rotate(theList, l, r, amount)
set listLength to (count theList)
if (listLength < 2) then return
if (l < 0) then set l to listLength + l + 1
if (r < 0) then set r to listLength + r + 1
if (l > r) then set {l, r} to {r, l}
script o
script o
property l : lst
property lst : theList
property storage : missing value
property storage : missing value
end script
end script
set len to (count o's l)
set rangeLength to r - l + 1
set amount to (rangeLength + rangeLength - amount) mod rangeLength
if (len is 0) then return
set amount to ((len - amount) mod len + len) mod len
if (amount is 0) then return
if (amount is 0) then return
set o's storage to items 1 thru amount of o's l
set o's storage to o's lst's items l thru (l + amount - 1)
repeat with i from (amount + 1) to len
repeat with i from (l + amount) to r
set item (i - amount) of o's l to item i of o's l
set o's lst's item (i - amount) to o's lst's item i
end repeat
end repeat
repeat with i from -amount to -1
set j to r - amount
set item i of o's l to item i of o's storage
repeat with i from 1 to amount
set o's lst's item (j + i) to o's storage's item i
end repeat
end repeat
end rotate
end rotate
Line 235: Line 241:
local lst
local lst
set lst to {1, 2, 3, 4, 5, 6, 7, 8, 9}
set lst to {1, 2, 3, 4, 5, 6, 7, 8, 9}
-- Left-rotate all items (1 thru -1) by three places.
rotate(lst, -3)
rotate(lst, 1, -1, -3)
return lst</lang>
return lst</lang>


Wholly in-place:
Wholly in-place:
<lang applescript>(* List rotation, wholly in-place. Negative 'amount' = left rotation, positive = right.
<lang applescript>(* List range rotation, wholly in-place. Negative 'amount' = left rotation, positive = right.
Method:
Method:
Adjust the specified rotation amount to get a positive, < list length, left-rotation figure.
Adjust the specified rotation amount to get a positive, < list length, left-rotation figure.
If rotating by only 1 in either direction, do it in the obvious way.
If rotating by only 1 in either direction, do it in the obvious way.
Otherwise reverse the leftmost 'amount' items, reverse the others, then reverse the entire list.
Otherwise reverse the range's leftmost 'amount' items, reverse the others, then reverse the lot.
*)
*)
on rotate(lst, amount)
on rotate(theList, l, r, amount)
set len to (count lst)
set listLength to (count theList)
if (len is 0) then return
if (listLength < 2) then return
if (l < 0) then set l to listLength + l + 1
if (r < 0) then set r to listLength + r + 1
if (l > r) then set {l, r} to {r, l}
script o
script o
property l : lst
property lst : theList
on rotate1(a, z, step)
on rotate1(a, z, step)
set v to item a of my l
set v to my lst's item a
repeat with i from (a + step) to z by step
repeat with i from (a + step) to z by step
set item (i - step) of my l to item i of my l
set my lst's item (i - step) to my lst's item i
end repeat
end repeat
set item z of my l to v
set my lst's item z to v
end rotate
end rotate1
on |reverse|(i, j)
on |reverse|(i, j)
repeat with i from i to ((i + j - 1) div 2)
repeat with i from i to ((i + j - 1) div 2)
set v to item i of my l
set v to my lst's item i
set item i of my l to item j of my l
set my lst's item i to my lst's item j
set item j of my l to v
set my lst's item j to v
set j to j - 1
set j to j - 1
end repeat
end repeat
Line 270: Line 280:
end script
end script
set amount to ((len - amount) mod len + len) mod len
set rangeLength to r - l + 1
set amount to (rangeLength + rangeLength - amount) mod rangeLength
if (amount is 1) then
if (amount is 1) then
tell o to rotate1(1, len, 1) -- Rotate left by 1.
tell o to rotate1(l, r, 1) -- Rotate left by 1.
else if (amount is len - 1) then
else if (amount = rangeLength - 1) then
tell o to rotate1(len, 1, -1) -- Rotate right by 1.
tell o to rotate1(r, l, -1) -- Rotate right by 1.
else if (amount > 0) then
else if (amount > 0) then
tell o to |reverse|(1, amount)
tell o to |reverse|(l, l + amount - 1)
tell o to |reverse|(amount + 1, len)
tell o to |reverse|(l + amount, r)
tell o to |reverse|(1, len)
tell o to |reverse|(l, r)
end if
end if
end rotate
end rotate
Line 285: Line 296:
local lst
local lst
set lst to {1, 2, 3, 4, 5, 6, 7, 8, 9}
set lst to {1, 2, 3, 4, 5, 6, 7, 8, 9}
-- Left-rotate all items (1 thru -1) by three places.
rotate(lst, -3)
rotate(lst, 1, -1, -3)
return lst</lang>
return lst</lang>