AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

AHK Stacks

 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
no1readsthese



Joined: 08 Feb 2008
Posts: 31
Location: VA

PostPosted: Fri Mar 28, 2008 11:40 pm    Post subject: AHK Stacks Reply with quote

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 Sat Mar 29, 2008 4:49 am; edited 5 times in total
Back to top
View user's profile Send private message
HuBa



Joined: 24 Feb 2007
Posts: 175
Location: Budapest, Hungary

PostPosted: Sat Mar 29, 2008 1:22 am    Post subject: Reply with quote

Nice, but what is the -9999?
Back to top
View user's profile Send private message Visit poster's website
no1readsthese



Joined: 08 Feb 2008
Posts: 31
Location: VA

PostPosted: Sat Mar 29, 2008 1:35 am    Post subject: Reply with quote

-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
Back to top
View user's profile Send private message
[VxE]



Joined: 07 Oct 2006
Posts: 3254
Location: Simi Valley, CA

PostPosted: Sat Mar 29, 2008 3:11 am    Post subject: Reply with quote

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 Sad ( 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!
Back to top
View user's profile Send private message
no1readsthese



Joined: 08 Feb 2008
Posts: 31
Location: VA

PostPosted: Sat Mar 29, 2008 4:32 am    Post subject: Reply with quote

[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 Very Happy
Added it anyways. Thanks

[VxE] wrote:
Although the line Global ERRORLEVEL := 0 gives me an error Sad ( 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
Back to top
View user's profile Send private message
widow
Guest





PostPosted: Sat Mar 29, 2008 12:53 pm    Post subject: Reply with quote

why not use machine code for this?
Back to top
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Sat Mar 29, 2008 3:09 pm    Post subject: Reply with quote

These stacks are close to lists, which can be handled by the three years old List manipulation functions, too. Nice to have an alternative.
Back to top
View user's profile Send private message
Mr_and_Mrs_D



Joined: 19 Dec 2006
Posts: 164

PostPosted: Sun May 03, 2009 4:33 pm    Post subject: Reply with quote

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


Question

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 Fri Jan 29, 2010 3:11 pm; edited 1 time in total
Back to top
View user's profile Send private message
tinku99



Joined: 03 Aug 2007
Posts: 513
Location: Houston, TX

PostPosted: Wed May 27, 2009 9:23 pm    Post subject: another stack implementation Reply with quote

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
  }
}
 
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group