AutoHotkey Community

It is currently May 26th, 2012, 4:59 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: AHK Stacks
PostPosted: March 29th, 2008, 12:40 am 
Offline

Joined: February 8th, 2008, 9:17 pm
Posts: 31
Location: VA
AHK Stacks by no1readsthese

Description:

Stacks or Last In First Out (LIFO) data structures based on strings with delimiter instead of arrays
mostly proof of concept



Usage:

Set And Change Delimiter:

Code:
  AHKStack_Delimiter := "Delimiter"
  ;Sets Delimiter For Future Stacks
  ;Default Delimiter Is "`n"
  ;Do Not Use After A Stack Has Been Created

  AHKStack_ChangeDelimiter(Stack, NewDelimiter="")
  ;Changes Delimiter For Current And Future Stacks
  ;If No Delimiter Is Defined, "`n" Is Used


IsEmpty:

Code:
  Var := AHKStack_IsEmpty(Stack)
  ;Returns 1 If Stack Is Empty
  ;Returns 0 If Stack Is Not Empty


Size:

Code:
  Var := AHKStack_Size(Stack)
  ;Returns The Size Of The Stack To Var


Push:

Code:
  AHKStack_Push(Stack, Element)
  ;Pushes The Element Into The Stack


Pop:

Code:
  Var := AHKStack_Pop(Stack)
  ;Removes The Last Element From The Stack And
  ;Returns Said Element
  ;If Stack Is Empty, The ERRORLEVEL Var Is Set To 1 And The Function Returns An Empty String
  ;ERRORLEVEL Is Otherwise Set To 0


Poop (The Counterpart Of Pop. Thanks [VxE]):

Code:
  Var := AHKStack_Poop(Stack)
  ;Removes The First Element From The Stack And
  ;Returns Said Element
  ;If Stack Is Empty, The ERRORLEVEL Var Is Set To 1 And The Function Returns An Empty String
  ;ERRORLEVEL Is Otherwise Set To 0


Peek:

Code:
  Var := AHKStack_Peek(Stack, Index="")
  ;Returns The Element At The Index, Where The First Element Is At Index 1
  ;Returns The Last Element If No Index Is Defined
  ;If Stack Is Empty, The ERRORLEVEL Var Is Set To 1 And The Function Returns An Empty String
  ;ERRORLEVEL Is Otherwise Set To 0


Clear:

Code:
  AHKStack_Clear(Stack)
          OR
  Stack := ""
  ;Clears Stack Of All Elements


Copy Stack:

Code:
  NewStack := AHKStack_Copy(Stack)
          OR
  NewStack := Stack
  ;Copies Stack To NewStack




Script:
Code:
;=================================================
;==         AHK Stacks by no1readsthese         ==
;=================================================

/*
;=================================================
;=======================Use=======================
;=================================================

Set And Change Delimiter:

  AHKStack_Delimiter := "Delimiter"
  ;Sets Delimiter For Future Stacks
  ;Default Delimiter Is "`n"
  ;Do Not Use After A Stack Has Been Created

  AHKStack_ChangeDelimiter(Stack, NewDelimiter="")
  ;Changes Delimiter For Current And Future Stacks
  ;If No Delimiter Is Defined, "`n" Is Used

IsEmpty:

  Var := AHKStack_IsEmpty(Stack)
  ;Returns 1 If Stack Is Empty
  ;Returns 0 If Stack Is Not Empty

Size:

  Var := AHKStack_Size(Stack)
  ;Returns The Size Of The Stack To Var

Push:

  AHKStack_Push(Stack, Element)
  ;Pushes The Element Into The Stack

Pop:

  Var := AHKStack_Pop(Stack)
  ;Removes The Last Element From The Stack And
  ;Returns Said Element
  ;If Stack Is Empty, The ERRORLEVEL Var Is Set To 1 And The Function Returns An Empty String
  ;ERRORLEVEL Is Otherwise Set To 0

Poop (The Counterpart Of Pop. Thanks [VxE]):

  Var := AHKStack_Poop(Stack)
  ;Removes The First Element From The Stack And
  ;Returns Said Element
  ;If Stack Is Empty, The ERRORLEVEL Var Is Set To 1 And The Function Returns An Empty String
  ;ERRORLEVEL Is Otherwise Set To 0

Peek:

  Var := AHKStack_Peek(Stack, Index="")
  ;Returns The Element At The Index, Where The First Element Is At Index 1
  ;Returns The Last Element If No Index Is Defined
  ;If Stack Is Empty, The ERRORLEVEL Var Is Set To 1 And The Function Returns An Empty String
  ;ERRORLEVEL Is Otherwise Set To 0

Clear:

  AHKStack_Clear(Stack)
          OR
  Stack := ""
  ;Clears Stack Of All Elements

Copy Stack:

  NewStack := AHKStack_Copy(Stack)
          OR
  NewStack := Stack
  ;Copies Stack To NewStack

*/


;=================================================
;====================Functions====================
;=================================================

AHKStack_Delimiter := "`n"

AHKStack_ChangeDelimiter(ByRef Stack, NewDelimiter="")
  {
    Global AHKStack_Delimiter
    If Not NewDelimiter
      NewDelimiter := "`n"
    StringReplace, Stack, Stack, %AHKStack_Delimiter%, %NewDelimiter%, All
    AHKStack_Delimiter := NewDelimiter
    Return Stack
  }

AHKStack_IsEmpty(ByRef Stack)
  {
    If Stack
      Return 0
    Return 1
  }

AHKStack_Size(ByRef Stack)
  {
    Global AHKStack_Delimiter
    If Not Stack
      Return 0
    StringReplace, Stack, Stack, %AHKStack_Delimiter%, %AHKStack_Delimiter%, UseErrorLevel
    Return ErrorLevel + 1
  }

AHKStack_Push(ByRef Stack, Element)
  {
    Global AHKStack_Delimiter
    StringReplace, Element, Element, %AHKStack_Delimiter%,, All
    If Not Stack
      Stack := Element
    Else
      Stack := Element AHKStack_Delimiter Stack
    Return Stack
  }

AHKStack_Pop(ByRef Stack)
  {
    Global AHKStack_Delimiter
    EnvSet, ERRORLEVEL, 0
    Position := InStr(Stack, AHKStack_Delimiter)
    If Position
      {
        Element := SubStr(Stack, 1, Position-1)
        Stack := SubStr(Stack, Position+1)
        Return Element
      }
    If Stack
      {
        Element := Stack
        Stack := ""
        Return Element
      }
    StringGetPos, Position, Position, SearchText ;Sets ERRORLEVEL To 1
  }

AHKStack_Poop(ByRef Stack) ; Tweaked by [VxE]
  {
    Global AHKStack_Delimiter
    EnvSet, ERRORLEVEL, 0
    Position := InStr(Stack, AHKStack_Delimiter, 0, 0)
    If Position
      {
        Element := SubStr(Stack, Position+1)
        Stack := SubStr(Stack, 1, Position-1)
        Return Element
      }
    If Stack
      {
        Element := Stack
        Stack := ""
        Return Element
      }
    StringGetPos, Position, Position, SearchText ;Sets ERRORLEVEL To 1
  }

AHKStack_Peek(ByRef Stack, Index="")
  {
    Global AHKStack_Delimiter
    EnvSet, ERRORLEVEL, 0
    If Not Stack
      {
        StringGetPos, Var, Var, SearchText ;Sets ERRORLEVEL To 1
        Return
      }
    StringSplit, StackArray, Stack, %AHKStack_Delimiter%
    If Not Index
      Return StackArray1
    Index := StackArray0 - Index - 1
    Return StackArray%Index%
  }

AHKStack_Clear(ByRef Stack)
  {
    Stack := ""
    Return Stack
  }

AHKStack_Copy(ByRef Stack)
  {
    Return Stack
  }


Last edited by no1readsthese on March 29th, 2008, 5:49 am, edited 5 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 29th, 2008, 2:22 am 
Offline

Joined: February 24th, 2007, 6:02 pm
Posts: 175
Location: Budapest, Hungary
Nice, but what is the -9999?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 29th, 2008, 2:35 am 
Offline

Joined: February 8th, 2008, 9:17 pm
Posts: 31
Location: VA
-9999 is the stack-underflow error message
i would have liked something like -1 but if someone wanted to push -1 into the stack, there would have been a problem
so i chose -9999 since it would not likely be all that common

EDIT: the stack underflow error is now handled by setting the var ERRORLEVEL equal to 1 and returning an empty string
I hope that is clearer


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 29th, 2008, 4:11 am 
Offline
User avatar

Joined: October 7th, 2006, 8:45 am
Posts: 3328
Location: Simi Valley, CA
Very nice *applause*.

Sometimes, I think that AHK spoils me by not having structs to deal with. Seeing Ye Olde Tyme Stack really brings back memories.

You may want to think about adding the Poop (the counterpart of pop) function:
Code:
AHKStack_Poop(ByRef Stack) ; Tweaked by [VxE]
  {
    Global AHKStack_Delimiter
    Global ERRORLEVEL := 0
    Position := InStr(Stack, AHKStack_Delimiter, 0, 0)
    If Position
      {
        Element := SubStr(Stack, Position+1)
        Stack := SubStr(Stack, 1, Position-1)
        Return Element
      }
    If Stack
      {
        Element := Stack
        Stack := ""
        Return Element
      }
    ERRORLEVEL := 1
  }

Although the line Global ERRORLEVEL := 0 gives me an error :( ( I think it needs to be set by EnvSet, or something)[/code]

_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 29th, 2008, 5:32 am 
Offline

Joined: February 8th, 2008, 9:17 pm
Posts: 31
Location: VA
[VxE] wrote:
You may want to think about adding the Poop (the counterpart of pop) function


I've never heard of 'poop' with stacks but oh well :D
Added it anyways. Thanks

[VxE] wrote:
Although the line Global ERRORLEVEL := 0 gives me an error :( ( I think it needs to be set by EnvSet, or something)[/code]


Sorry about that. I didn't think of checking it since it would have worked for any other var.
I fixed it by adding lines that are guaranteed to indirectly change ERRORLEVEL to the desired values


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 29th, 2008, 1:53 pm 
why not use machine code for this?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 29th, 2008, 4:09 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
These stacks are close to lists, which can be handled by the three years old List manipulation functions, too. Nice to have an alternative.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 3rd, 2009, 5:33 pm 
Offline

Joined: December 19th, 2006, 2:17 pm
Posts: 164
1. I also read these (and I use them in a soon to be released script)

2. BUGGY in Peek :

I think this
Code:
Index := StackArray0 - Index - 1

should be replaced by this :
Code:
Index := StackArray0 - Index + 1


:?:

EDIT : or maybe index should be left alone ? Cause the way it is index = 1 would give me the first element that was inserted. Is this what you want ???

_________________
XP SP3 Pro x32 / 7 x64 Pro - AHK 1.0.48.05


Last edited by Mr_and_Mrs_D on January 29th, 2010, 4:11 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
PostPosted: May 27th, 2009, 10:23 pm 
Offline

Joined: August 3rd, 2007, 8:01 am
Posts: 555
Location: Houston, TX
With this implementation you don't have to worry about the delimiter showing up in the objects you want to stack.

Code:
msgbox % stack("push", 4)
msgbox % stack("push", 5)
msgbox % stack("peek")
msgbox % stack("pop")
msgbox % stack("peek")
msgbox % stack("empty")
msgbox % stack("pop")
msgbox % stack("empty")
return


stack(command, value = 0)
{
  static
if !pointer
pointer = 10000
  if (command = "push")
  {
  _p%pointer% := value
  pointer -= 1
  return value
  }
  if (command = "pop")
  {
    pointer += 1
    return _p%pointer%
  }
  if (command = "peek")
{
next := pointer + 1   
return _p%next%
}
  if (command = "empty")
  {
   if (pointer == 10000)
    return "empty"
else
return 0
  }
}
 


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: MSNbot Media and 12 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group