- I've added in some functionality to help support large bases (i.e. beyond base 36), custom single/multiple character digit strings (instead of 0-9 A-Z), and delimiter-separated numbers (as is typical for sexagesimal i.e. base 60).
- I've provided an example that shows how a DecToBase function can be used to generate string permutations. There are some other functions here:
combinations and permutations (and anagrams) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=34244
- Specifying custom digits for a BaseToDec function can require a case-sensitive lookup table, hence I use a case-sensitive Scripting.Dictionary object.
- Note: for base 16, I would typically use the following characters: 0-9 A-F (10+6=16).
- Note: for base 36, I would typically use the following characters: 0-9 A-Z (10+26=36).
- Note: for base 62, I would typically use the following characters: 0-9 A-Z a-z (10+26+26=62).
Code: Select all
;==================================================
; ;e.g.:
; ;q::
; Loop, 40 ;2 to 41
; vBase := A_Index+1
; , vOutput .= vBase "`t" JEE_BaseToDec(10, vBase) "`r`n"
; Clipboard := vOutput
; MsgBox, % vOutput
; return
; ;w::
; Loop, 40 ;2 to 41
; vBase := A_Index+1
; , vOutput .= vBase "`t" JEE_BaseToDec("F0", vBase) "`r`n"
; Clipboard := vOutput
; MsgBox, % vOutput
; return
; ;e::
; oDict := ComObjCreate("Scripting.Dictionary")
; Loop, 70
; oDict.Item(A_Index-1) := A_Index - 1
; , oDict.Item("" A_Index-1) := A_Index - 1
; , oDict.Item(Format("{:02X}", A_Index-1)) := A_Index - 1
; oNum := StrSplit("1:1:1", ":")
; MsgBox, % JEE_BaseToDec(oNum, 60, oDict)
; oNum := StrSplit("01:02:03", ":")
; MsgBox, % JEE_BaseToDec(oNum, 60, oDict)
; oNum := StrSplit("01:00:59", ":")
; MsgBox, % JEE_BaseToDec(oNum, 60, oDict)
; return
;vNum accepts a linear array, treating each item as a digit
;oDict accepts a (case-sensitive) Scripting.Dictionary object as a lookup table
;JEE_Base2Dec
JEE_BaseToDec(vNum, vBase, oDict:="")
{
local
static oDefault
vOutput := 0
if !IsObject(vNum) && !IsObject(oDict)
&& (vBase >= 2) && (vBase <= 36)
{
vPow := StrLen(vNum)
Loop, Parse, vNum
{
vPow--
vTemp := Ord(A_LoopField)
if (vTemp >= 48) && (vTemp <= 57) ;0-9
vTemp -= 48
else if (vTemp >= 97) && (vTemp <= 122) ;a-z
vTemp -= 87
else if (vTemp >= 65) && (vTemp <= 90) ;A-Z
vTemp -= 55
else
return
if (vTemp >= vBase)
return
vOutput += vTemp * (vBase**vPow)
}
return vOutput
}
if !IsObject(vNum)
vNum := StrSplit(vNum)
if !IsObject(oDefault)
{
oDefault := ComObjCreate("Scripting.Dictionary")
Loop, 10
oDefault.Item(A_Index-1) := A_Index - 1
, oDefault.Item("" A_Index-1) := A_Index - 1
Loop, 26
oDefault.Item(Chr(64+A_Index)) := A_Index + 9
, oDefault.Item(Chr(96+A_Index)) := A_Index + 9
}
if !IsObject(oDict)
oDict := oDefault
vPow := vNum.Length()
for _, vTemp in vNum
{
vPow--
if !oDict.Exists(vTemp)
return
vOutput += oDict.Item(vTemp) * (vBase**vPow)
}
return vOutput
}
;==================================================
; ;e.g.:
; ;q:: ;binary
; vBase := 2
; vOutput := ""
; Loop, 70
; {
; vNum := A_Index-1
; , vOutput .= JEE_DecToBase(vNum, vBase) "`r`n"
; }
; Clipboard := vOutput
; MsgBox, % vOutput
; return
; ;w:: ;permutations
; ;vText := "abc"
; vText := "abcde"
; ;vText := "abcdefghij"
; (oArray := StrSplit("_" vText)).RemoveAt(0) ;_,a,b,c,d,e
; vBase := oArray.Length() + 1
; vOutput := ""
; Loop, 70
; {
; vNum := A_Index-1
; , vTemp := JEE_DecToBase(vNum, vBase, oArray)
; if !InStr(vTemp, "_")
; vOutput .= vTemp "`r`n"
; }
; Clipboard := vOutput
; MsgBox, % vOutput
; return
;oArray, if used, expects a linear array with keys 0 to 'vBase-1'
JEE_DecToBase(vNum, vBase, oArray:="", vSep:="")
{
local
if (vNum = 0)
return IsObject(oArray) ? oArray.0 : 0
vTemp := 1
Loop, 1000
{
if (vTemp <= vNum)
vTemp *= vBase
else
break
}
vOutput := ""
Loop, 1000
{
vTemp := Floor(vTemp / vBase)
vDigit := Floor(vNum / vTemp)
vNum := Mod(vNum, vTemp)
if (vDigit >= vBase)
return
if IsObject(oArray)
{
if oArray.HasKey(vDigit)
vOutput .= oArray[vDigit] vSep
else
return
}
else if (vDigit <= 9) ;0-9
vOutput .= vDigit vSep
else if (vDigit <= 35) ;10-35 (A-Z)
vOutput .= Chr(55+vDigit) vSep
else if (vDigit <= 61) ;36-61 (a-z)
vOutput .= Chr(61+vDigit) vSep
else
return
if (vTemp = 1)
break
}
return StrLen(vSep) ? SubStr(vOutput, 1, -StrLen(vSep)) : vOutput
}
;==================================================