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( |
on rotate(theList, l, r, amount) |
||
set listLength to (count theList) |
|||
⚫ | |||
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 |
property lst : theList |
||
property storage : missing value |
property storage : missing value |
||
end script |
end script |
||
set |
set rangeLength to r - l + 1 |
||
⚫ | |||
⚫ | |||
⚫ | |||
if (amount is 0) then return |
if (amount is 0) then return |
||
set o's storage to items |
set o's storage to o's lst's items l thru (l + amount - 1) |
||
repeat with i from ( |
repeat with i from (l + amount) to r |
||
set item (i - amount) |
set o's lst's item (i - amount) to o's lst's item i |
||
end repeat |
end repeat |
||
set j to r - amount |
|||
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 |
Otherwise reverse the range's leftmost 'amount' items, reverse the others, then reverse the lot. |
||
*) |
*) |
||
on rotate( |
on rotate(theList, l, r, amount) |
||
set |
set listLength to (count theList) |
||
if ( |
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 |
property lst : theList |
||
on rotate1(a, z, step) |
on rotate1(a, z, step) |
||
set v to item a |
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) |
set my lst's item (i - step) to my lst's item i |
||
end repeat |
end repeat |
||
set item z |
set my lst's item z to v |
||
end |
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 |
set v to my lst's item i |
||
set item i |
set my lst's item i to my lst's item j |
||
set item j |
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 |
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( |
tell o to rotate1(l, r, 1) -- Rotate left by 1. |
||
else if (amount |
else if (amount = rangeLength - 1) then |
||
tell o to rotate1( |
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|( |
tell o to |reverse|(l, l + amount - 1) |
||
tell o to |reverse|( |
tell o to |reverse|(l + amount, r) |
||
tell o to |reverse|( |
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> |
||