Jump to content

Recommended Posts

Posted

I am converting text into a custom base system, and when it's converted back I am using a custom _dec() function, the problem is, when I do _dec() I get the numbers, and I don;t know how to change them into text, I have tried chr, and chrw, with no luck, how do I turn dec back into regular text?

this is the process

text -> dec -> (custom base104) -> dec ??-> text

Posted (edited)
Posted (edited)

Func _Base($iDecNumber, $sChar)
Local $aBase = StringSplit($sChar, ",")
Local $iBase = $aBase[0]

Local $iLen = Int(Log($iDecNumber) / Log($iBase)) + 1

Dim $iUnit[$iLen + 1]
Local $iReturn
Local $iTemp = $iDecNumber

If $aBase[0] <> $iBase Then
SetError(1)
Return -1
EndIf

If $iDecNumber = 0 Then Return $aBase[1]

For $i = 1 To $iLen
For $i2 = 1 To $i - 1
$iTemp = $iTemp / $iBase
Next
$iUnit[$i] = $aBase[Mod($iTemp, $iBase) + 1]
$iTemp = $iDecNumber
Next

For $i = 1 To $iLen
$iReturn = $iUnit[$i] & $iReturn
Next

Return $iReturn
EndFunc ;==>_Base

Func _Dec($iNumber, $sChar)
Local $iReturn
Local $aBase = StringSplit($sChar, ",")
Local $iBase = $aBase[0]
Local $aTemp = StringRegExp($iNumber, "[a-zA-Z0-9:+¦/]{" & StringLen($aBase[1]) & "}", 3)
For $i = 0 To UBound($aTemp) - 1
$iReturn += ($iBase ^ $i) * (_ArraySearch($aBase, $aTemp[UBound($aTemp) - 1 - $i], 0, 0, 1) - 1)
Next

Return $iReturn
EndFunc ;==>_Dec

and you'll probably want to see this.

Global $base104 = "H¦,He,Li,Be,B¦,C¦,N¦,O¦,F¦,Ne,Na,Mg,Al,Si,P¦,S¦,Cl,Ar,K¦,Ca,Sc,Ti,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr,Rb,Sr,Y¦,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I¦,Xe,Cs,Ba,La,Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu,Hf,Ta,W¦,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn,Fr,Ra,Ac,Th,Pa,U¦,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Bh,Rg,Fl"

Off the top of my head I don't see a way to interface your code and mine, but I also havn't slept much, so I will look at it again in a few hours, in the mean time, any help is appreciated.

Edited by nullschritt
Posted (edited)

Basically what you have here is code to convert from decimal to another numeric base and back, although I haven't tested it. You appear to be using base 104 which I don't really understand (oh I get it, you are using elements). Where does text come into this? Did you convert some text to a number and then change the base, or what?

Edit

After messing around a bit, I discover that these functions are perhaps not best suited for your purpose. AutoIt is limited to 15 digit accuracy with numbers and these functions seem to adhere to that rule (in base 10). Therefore the type of message you could convert from text would be limited to very few characters - unless you convert each letter separately and concatenate. The code gets more complicated..A typical ascii character requires 3 decimal digits.

On a side note, you can easily convert long strings to hex and back.

Edited by czardas
Posted (edited)

Basically what you have here is code to convert from decimal to another numeric base and back, although I haven't tested it. You appear to be using base 104 which I don't really understand (oh I get it, you are using elements). Where does text come into this? Did you convert some text to a number and then change the base, or what?

Edit

After messing around a bit, I discover that these functions are perhaps not best suited for your purpose. AutoIt is limited to 15 digit accuracy with numbers and these functions seem to adhere to that rule (in base 10). Therefore the type of message you could convert from text would be limited to very few characters - unless you convert each letter separately and concatenate. The code gets more complicated..A typical ascii character requires 3 decimal digits.

On a side note, you can easily convert long strings to hex and back.

This what I am doing to convert.

$text = StringSplit($text, '')
$number = ''
for $i=1 to $text[0]
$number &= _Base(AscW($text[$i]), $base104)
Next

I'm not understanding.... perhaps? Should I not be able to turn the _dec back into the unicode number? then use chrw() on it to turn it back to the original character?

And it's part of a proof of concept project, so thank you for telling me I can convert to hex and back, but I already know this.

Am I maybe not understanding why it is so difficult to undo it ? :/

This what I had got so far trying for the reverse

$string = StringSplit($string, "")
$text = ""
for $i=1 to $string[0] step 2
$text &= _dec($string[$i]&$string[$i+1], $base104)
Next
Edited by nullschritt
Posted (edited)

Global $base104 = "H¦,He,Li,Be,B¦,C¦,N¦,O¦,F¦,Ne,Na,Mg,Al,Si,P¦,S¦,Cl,Ar,K¦,Ca,Sc,Ti,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr,Rb,Sr,Y¦,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I¦,Xe,Cs,Ba,La,Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu,Hf,Ta,W¦,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn,Fr,Ra,Ac,Th,Pa,U¦,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Bh,Rg,Fl"



$Z = _Base(305664, $base104)

MsgBox(0, 'Сообщение',  $Z)

MsgBox(0, 'Сообщение',  _Dec($Z, $base104))



Func _Base($iDecNumber, $sChar)

    Local $aBase = StringSplit($sChar, ",")

    Local $iBase = $aBase[0]



    Local $iLen = Int(Log($iDecNumber) / Log($iBase)) + 1



    Dim $iUnit[$iLen + 1]

    Local $iReturn

    Local $iTemp = $iDecNumber



    If $aBase[0] <> $iBase Then

        SetError(1)

        Return -1

    EndIf



    If $iDecNumber = 0 Then Return $aBase[1]



    For $i = 1 To $iLen

        For $i2 = 1 To $i - 1

            $iTemp = $iTemp / $iBase

        Next

        $iUnit[$i] = $aBase[Mod($iTemp, $iBase) + 1]

        $iTemp = $iDecNumber

    Next



    For $i = 1 To $iLen

        $iReturn = $iUnit[$i] & $iReturn

    Next



    Return $iReturn

EndFunc



Func _Dec($iNumber, $sSymbol)

    Local $i, $iPos, $iReturn, $Len, $n

    $sSymbol &= ","

    $Len = StringLen($sSymbol)/3

    If $Len < 2 Then Return SetError(1)

    $iNumber=StringTrimRight(StringRegExpReplace($iNumber, '(..)', '1,'), 1)

    $n=StringSplit($iNumber, ',')

    

    For $i = 1 To $n[0]

        $iPos = (StringInStr($sSymbol, $n[$i])+2) / 3

        If Not $iPos Then Return SetError(2)

        $iReturn += ($iPos-1)*$Len^($n[0]-$i)

    Next



    Return $iReturn

EndFunc

Edited by AZJIO
Posted (edited)

The problem is that you need to pad the numeric representation of each character with zeros, otherwise it is impossible to convert back. You are using unicode, so the largest possible numeric value would be 0xFFFF which is greater than 104^2. This implies that using base 104 requires at least three digits (six characters) to represent one unicode character. Here's how to do it:

#include <Array.au3>

Global $base104 = "H¦,He,Li,Be,B¦,C¦,N¦,O¦,F¦,Ne,Na,Mg,Al,Si,P¦,S¦,Cl,Ar,K¦,Ca,Sc,Ti,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr,Rb,Sr,Y¦,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I¦,Xe,Cs,Ba,La,Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu,Hf,Ta,W¦,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn,Fr,Ra,Ac,Th,Pa,U¦,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Bh,Rg,Fl"

$text = "Hello World"

; Convert to base 104
$text = StringSplit($text, '')
$number = ''
For $i=1 to $text[0]
    $nTemp = _Base(AscW($text[$i]), $base104)
    While StringLen($nTemp) < 6
        $nTemp = "H¦" & $nTemp
    WEnd
    $number &= $nTemp
Next
MsgBox(0, "", $number)

; Convert back to text
$aTemp = _StringEqualSplit($number, 6) ; Split to $base104 characters
If @error Then Exit

$ret = ""
For $i = 0 To UBound($aTemp) -1
    $ret &= ChrW(_Dec($aTemp[$i], $base104))
Next
MsgBox(0, "", $ret)

Func _StringEqualSplit($sString, $iNumChars)
    If (Not IsString($sString)) Or $sString = "" Then Return SetError(1, 0, 0)
    If (Not IsInt($iNumChars)) Or $iNumChars < 1 Then Return SetError(2, 0, 0)
    Return StringRegExp($sString, "(?s).{1," & $iNumChars & "}", 3)
EndFunc

Func _Base($iDecNumber, $sChar)
    Local $aBase = StringSplit($sChar, ",")
    Local $iBase = $aBase[0]

    Local $iLen = Int(Log($iDecNumber) / Log($iBase)) + 1

    Dim $iUnit[$iLen + 1]
    Local $iReturn
    Local $iTemp = $iDecNumber

    If $aBase[0] <> $iBase Then
    SetError(1)
    Return -1
    EndIf

    If $iDecNumber = 0 Then Return $aBase[1]

    For $i = 1 To $iLen
        For $i2 = 1 To $i - 1
            $iTemp = $iTemp / $iBase
        Next
        $iUnit[$i] = $aBase[Mod($iTemp, $iBase) + 1]
        $iTemp = $iDecNumber
    Next

    For $i = 1 To $iLen
        $iReturn = $iUnit[$i] & $iReturn
    Next

    Return $iReturn
EndFunc ;==>_Base

Func _Dec($iNumber, $sChar)
    Local $iReturn
    Local $aBase = StringSplit($sChar, ",")
    Local $iBase = $aBase[0]
    Local $aTemp = StringRegExp($iNumber, "[a-zA-Z0-9:+¦/]{" & StringLen($aBase[1]) & "}", 3)
    For $i = 0 To UBound($aTemp) - 1
        $iReturn += ($iBase ^ $i) * (_ArraySearch($aBase, $aTemp[UBound($aTemp) - 1 - $i], 0, 0, 1) - 1)
    Next

    Return $iReturn
EndFunc ;==>_Dec

If you were to use ASCII, then you could get away with using just 2 base104 digits (4 characters) to represent each ASCII character.

Edited by czardas
Posted

The problem is that you need to pad the numeric representation of each character with zeros, otherwise it is impossible to convert back. You are using unicode, so the largest possible numeric value would be 0xFFFF which is greater than 104^2. This implies that using base 104 requires at least three digits (six characters) to represent one unicode character. Here's how to do it:

#include <Array.au3>

Global $base104 = "H¦,He,Li,Be,B¦,C¦,N¦,O¦,F¦,Ne,Na,Mg,Al,Si,P¦,S¦,Cl,Ar,K¦,Ca,Sc,Ti,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr,Rb,Sr,Y¦,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I¦,Xe,Cs,Ba,La,Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu,Hf,Ta,W¦,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn,Fr,Ra,Ac,Th,Pa,U¦,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Bh,Rg,Fl"

$text = "Hello World"

; Convert to base 104
$text = StringSplit($text, '')
$number = ''
For $i=1 to $text[0]
$nTemp = _Base(AscW($text[$i]), $base104)
While StringLen($nTemp) < 6
     $nTemp = "H¦" & $nTemp
WEnd
$number &= $nTemp
Next
MsgBox(0, "", $number)

; Convert back to text
$aTemp = _StringEqualSplit($number, 6) ; Split to $base104 characters
If @error Then Exit

$ret = ""
For $i = 0 To UBound($aTemp) -1
$ret &= ChrW(_Dec($aTemp[$i], $base104))
Next
MsgBox(0, "", $ret)

Func _StringEqualSplit($sString, $iNumChars)
If (Not IsString($sString)) Or $sString = "" Then Return SetError(1, 0, 0)
If (Not IsInt($iNumChars)) Or $iNumChars < 1 Then Return SetError(2, 0, 0)
Return StringRegExp($sString, "(?s).{1," & $iNumChars & "}", 3)
EndFunc

Func _Base($iDecNumber, $sChar)
Local $aBase = StringSplit($sChar, ",")
Local $iBase = $aBase[0]

Local $iLen = Int(Log($iDecNumber) / Log($iBase)) + 1

Dim $iUnit[$iLen + 1]
Local $iReturn
Local $iTemp = $iDecNumber

If $aBase[0] <> $iBase Then
SetError(1)
Return -1
EndIf

If $iDecNumber = 0 Then Return $aBase[1]

For $i = 1 To $iLen
     For $i2 = 1 To $i - 1
         $iTemp = $iTemp / $iBase
     Next
     $iUnit[$i] = $aBase[Mod($iTemp, $iBase) + 1]
     $iTemp = $iDecNumber
Next

For $i = 1 To $iLen
     $iReturn = $iUnit[$i] & $iReturn
Next

Return $iReturn
EndFunc ;==>_Base

Func _Dec($iNumber, $sChar)
Local $iReturn
Local $aBase = StringSplit($sChar, ",")
Local $iBase = $aBase[0]
Local $aTemp = StringRegExp($iNumber, "[a-zA-Z0-9:+¦/]{" & StringLen($aBase[1]) & "}", 3)
For $i = 0 To UBound($aTemp) - 1
     $iReturn += ($iBase ^ $i) * (_ArraySearch($aBase, $aTemp[UBound($aTemp) - 1 - $i], 0, 0, 1) - 1)
Next

Return $iReturn
EndFunc ;==>_Dec

If you were to use ASCII, then you could get away with using just 2 base104 digits (4 characters) to represent each ASCII character.

Thanks this works perfectly!
Posted

I found this kind of intriguing. One piece of advice: when you are attempting to produce a reversible, and complicated, process; it's a good idea to start with the last step in the process. Make sure that you can undo that last step before you write any more code. Working your way outwards from the middle often makes it easier to spot any potential problems with the method you are using before they occur.

Posted (edited)

I found this kind of intriguing. One piece of advice: when you are attempting to produce a reversible, and complicated, process; it's a good idea to start with the last step in the process. Make sure that you can undo that last step before you write any more code. Working your way outwards from the middle often makes it easier to spot any potential problems with the method you are using before they occur.

Yes, I knew I was close, but missing some detail. When I was pouring over it I was, sleep deprived and intoxicated, so I got frustrated and gave up for a bit lol, but now that I have seen it, I understand how simple of a thing I was missing the whole time. Edited by nullschritt

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...