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 

Range() - Range of numbers and chars, borrowed from Python

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



Joined: 11 Mar 2008
Posts: 291

PostPosted: Wed Jul 23, 2008 11:57 am    Post subject: Range() - Range of numbers and chars, borrowed from Python Reply with quote

it's equivalent to Python's built-in function Range() except :

1) Python starts from 0 but it starts from 1 so Range(10) results differently
Python : 0.1,2,3,4,5,6,7,8,9
AutoHotkey : 1,2,3,4,5,6,7,8,9,10

2) Python does not support char but it does
Python : Range("a", "z") doesn't works
AutoHotkey : Range("a", "z") results a,b,c,d,e.....v,w,x,y,z



as you can see below, Titan greatly optimized this function to have less lines but faster with additional features.
so i would like to recommend to use Titan's 2nd version.
my very first version will be kept just as a reference to give better readability.
Much appreciated to Titan and [VxE], Ian as well.

the output is Matchlist friendly (comma seperated, you can change the delimiter in Titan's version)
so you can apply it like IF Var in % Range(10)
be aware that it supports integers only which is same in Python

Code:
MsgBox % Range(1,10)        ;1,2,3,4,5,6,7,8,9,10
MsgBox % Range(10)          ;1,2,3,4,5,6,7,8,9,10 (same as above)
MsgBox % Range(5,10)        ;5,6,7,8,9,10
MsgBox % Range(1,10,2)      ;1,3,5,7,9 (step by 2)
MsgBox % Range("a", "j")    ;a,b,c,d,e,f,g,h,i,j (alphabets)
MsgBox % Range("a", "m", 2) ;a,c,e,g,i,k,m (step on alphabets as well)
MsgBox % Range("A", "J")    ;A,B,C,D,E,F,G,H,I,J (upper cases)

;added features in Titan's version
MsgBox % Range(-10,10)      ;supports negative numbers as well
MsgBox % Range("J")         ;A,B,C,D,E,F,G,H,I,J (same as "A","J")
MsgBox % Range(1,10,1,"`n") ;Using custom delimiter



Code:
;Prototype   
Range(Start, Stop="", Step=1){
    if RegExMatch(Start,"i)[a-z]") && RegExMatch(Stop,"i)[a-z]")
        Start := asc(Start) , Stop := asc(Stop) , alpha := 1
    if !alpha {
        if !Stop {
            Stop := Start
            Loop, %Stop%
                Output .= A_Index ","
        } else {
            Loop, %Stop%
                Output .= (!Mod(A_Index-1, Step) && A_Index >= Start) ? A_Index "," :
        }
    } else {
        Loop, %Stop%
            Output .= (!Mod(A_Index-1, Step) && A_Index >= Start) ? chr(A_Index) "," :
    }
    StringTrimRight, Output, Output, 1
    Return Output   
}

_________________
Easy WinAPI - Dive into Windows API World
Benchmark your AutoHotkey skills at PlayAHK.com


Last edited by heresy on Thu Jul 24, 2008 12:53 am; edited 3 times in total
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5068
Location: imaginationland

PostPosted: Wed Jul 23, 2008 3:19 pm    Post subject: Reply with quote

You asked on IRC so here's an optimized version:

Code:
range(x, y, c = 1, d = ",") {
   If (!a := x | 0)
      x := Asc(x), y := Asc(y)
   Loop, % (y - x) // c + 1
      r .= d . (a ? x : Chr(x)), x += c
   Return, SubStr(r, 1 + StrLen(d))
}


Haven't coded ahk in a while so my skillz are rusty. This won't work if you don't pass a stop value but that can easily be changed. It'll be interesting to see if Skan can write something shorter Razz

Edit: here's a version that does range(10); range("j") etc.
Edit 2: typo fix

Code:
range(x, y = "", c = 1, d = ",") {
   If (!a := x | 1)
      x := Asc(x), y := Asc(y)
   Loop, % (y == (a ? "" : 0) ? (y := x) - x := x > 96 ? 97 : x > 64 ? 65 : 1 : y - x) // c + 1
      r .= d . (a ? x : Chr(x)), x += c
   Return, SubStr(r, 1 + StrLen(d))
}

_________________

RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")


Last edited by Titan on Thu Jul 24, 2008 1:03 am; edited 2 times in total
Back to top
View user's profile Send private message Visit poster's website
[VxE]



Joined: 07 Oct 2006
Posts: 1128

PostPosted: Wed Jul 23, 2008 8:54 pm    Post subject: Reply with quote

Code:
range(x, y=0, c=1, d=",", i=0)
{
   If (x*0="")
      x := Asc(x), y := Asc(y), i := 1
   r := x + (u := c * Round((y-x+0.1)/Abs(y-x+0.1)))
   return % ((x=y || (x-2*u>=y)!=(r>=y))) ? (i ? Chr(x) : x) : ((i ? Chr(x) : x) d range(r, y, c, d, i))
}

msgbox % range("g","3", 3)
I think I've got it. I've tested chars and numbers where X>Y and Y>X. Tested C>1 a little bit. Not gonna bother with testing D. i is used internally... it could just be a static but that might be confusing.
_________________
My Home Thread
More Common Answers: 1. It's in the FAQ 2. Ternary ( ? : ) guide 3. Post code with [code][/code] tags
Back to top
View user's profile Send private message
Ian



Joined: 15 Jul 2007
Posts: 1157
Location: Enterprise, Alabama

PostPosted: Wed Jul 23, 2008 10:47 pm    Post subject: Reply with quote

mod on Titan's code.

Code:
MsgBox % range("-32") "`n" range("-32~2") "`n" range("A~J")
range(x, c = 1, d = ",") {
   StringSplit, x, x, ~
   a := x1+1,x1 := (a ? x1 : Asc(x1)),z := !x2 ? (x1>=97 ? 97 : x1>=65 ? 65 : 1) : (a ? x2 : Asc(x2))
   Loop, % Abs(z-x1)//c+1
      r .= d . (a ? (!x2 ? z : x1) : Chr((!x2 ? z : x1))),z += c,x1 += !x2 ? -c : c
   Return, SubStr(r, 1 + StrLen(d))
}


Support for one term rather than two, and negative numbers. Custom separator (~) to show two characters.

Edit:

Bugfix: LETTER~LETTER was outputting backwards.

I made another version using RegExMatch, but it does not yet support integers.

Code:
range(x, y="") {
   RegExReplace("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,"
   , (!y ? x >= a ? "a" : "A" : x) . "(.*)" . (!y ? x : y), SubPat)
   Return (!y ? x >= a ? "a" : "A" : x) . SubPat1 . (!y ? x : y)
}

_________________
ScriptPad/~dieom/dieom/izwian2k7/Trikster/God

Back to top
View user's profile Send private message
jballi



Joined: 01 Oct 2005
Posts: 348
Location: Texas, USA

PostPosted: Sat Jul 26, 2008 9:41 pm    Post subject: Reply with quote

Excellent function idea. I always figured I would get around to writing something like this but now I don't have to! Thanks to everyone who contributed. Smile
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4016
Location: Pittsburgh

PostPosted: Sun Jul 27, 2008 7:22 pm    Post subject: Reply with quote

Having one function for characters and integers can work in AHK, but it is counterintuitive in typed languages, like C. I would use two different functions instead.

It is hard to tell, what is the “right” behavior when start > end (with step > 0). In many cases you want the empty list, what Titan’s function returns, but sometimes you want to list the elements backwards: range(4,1) --> 4,3,2,1.

What would you do with step = 0? It could be an error, so return the empty list, maybe except when start=stop, in which case range can be {start}.

Here is a single line function for (not necessarily integer, signed) numbers, which returns the empty string if start > end and step > 0, or start < end and step < 0, or step = 0:
Code:
NRange(a,b,d=1,s=",") { ; {a, a+d, ..., ~b}, numbers separated by s
   Return (a-b)*d > 0 or !d ? "" : ("" = c:=NRange(a+d,b,d,s)) ? a : a . s . c
}
You can make it even shorter, but less clear. A similar oneliner can be written for characters by replacing number x with Chr(x), and character y with Asc(y), appropriately:
Code:
CRange(a,b,d=1,s=",") { ; {a, Chr(Asc(a)+d), ..., ~b}, chars separated by s
   Return (Asc(a)-Asc(b))*d > 0 or !floor(d) ? "" : ("" = c:=CRange(Chr(Asc(a)+d),b,d,s)) ? a : a . s . c
}
Back to top
View user's profile Send private message
heresy



Joined: 11 Mar 2008
Posts: 291

PostPosted: Mon Jul 28, 2008 9:53 am    Post subject: Reply with quote

Thank Laszlo for introducing another way. seems [VxE] and You're pretty familiar with recursive function. i really need a lesson on Recursive functions. Sad i might post FRange() later for floats when i completely got your recursive functions. Thanks!
_________________
Easy WinAPI - Dive into Windows API World
Benchmark your AutoHotkey skills at PlayAHK.com
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4016
Location: Pittsburgh

PostPosted: Mon Jul 28, 2008 4:14 pm    Post subject: Reply with quote

NRange works for any numbers, including floats.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   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