TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: MP on March 20, 2009, 05:49:19 PM
-
Convert a string to a list of binary strings, each binary string representing the value of the character's ASCII code, padded to 8 bit width.
e.g. (StringToBinary "ABC") => ("01000001" "01000010" "01000011")
Easy stuff, use the language of your choice. :)
-
Here's my LISP code:
(defun _ByteToBin ( byte / power result )
;; convert an ascii code to a binary equivalent.
;;
;; e.g. (_ByteToBin 42) returns "00101010"
(repeat (setq power 8)
(setq result
(cons
(if
(zerop
(logand byte
(expt 2
(setq power
(1- power)
)
)
)
)
0
1
)
result
)
)
)
(apply 'strcat (mapcar 'itoa (reverse result)))
)
(defun _StrToBin ( str )
(mapcar '_ByteToBin (vl-string->list str))
)
But holy <!> look at my Python equiv:
def strToBin(s):
def foo(i): return (('0'*8)+bin(i)[2:])[-8:]
return list(map(foo,map(ord,s)))
:-o :-D
-
Hi,
(defun StringToBinary (str)
(mapcar
'(lambda (x / n s)
(setq n 0
s (itoa (rem x 2))
)
(repeat 7
(setq n (1+ n))
(if (/= 0 (logand x (expt 2 n)))
(setq s (strcat "1" s))
(setq s (strcat "0" s))
)
)
)
(vl-string->list str)
)
)
-
Well done Gile! :)
-
Here is my cheesy entry.
(defun StringToBinary ( str )
(mapcar
'(lambda ( x / cnt str tempX)
(setq cnt 128)
(setq str "")
(while (not (zerop cnt))
(setq tempX (rem x cnt))
(setq str
(strcat
str
(if (equal tempX x)
"0"
"1"
)
)
)
(setq x tempX)
(setq cnt (/ cnt 2))
)
str
)
(vl-string->list str)
)
)
-
Well done Tim. :)
-
(defun vk_Dec2Bin (Dec)
(if (< (setq Dec (fix Dec)) 2)
(itoa Dec)
(strcat (vk_Dec2Bin (/ Dec 2)) (itoa (rem Dec 2)))
)
)
(mapcar 'vk_Dec2Bin (vl-string->list "ABC"))
not padded to a byte length :(
-
Nerds :-P .... and it's awesome :)
-
Nice work VovKa but ... it doesn't satisfy the requirement to pad all binary strings to an 8 bit width.
i.e. "A" should be "01000001", not "1000001". (http://www.theswamp.org/screens/mp/cop3.gif)
-
thanks MP, i was too exited to read till the end :)
(defun vk_Dec2Bin (Dec Len)
(if (< Len 2)
(itoa (rem Dec 2))
(strcat (vk_Dec2Bin (/ Dec 2) (1- Len)) (itoa (rem Dec 2)))
)
)
(mapcar '(lambda (a) (vk_Dec2Bin a 8)) (vl-string->list "ABC"))
-
Outstanding, well played. :)
-
Very nice Vovka !
Dirty C#
static string[] StringToBinary(string str)
{
Encoding ascii = Encoding.ASCII;
Byte[] bytes = ascii.GetBytes(str);
string[]result = new string[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
{
string bin = "";
for (int expt = 7; expt >= 0; expt--)
{
bin += (bytes[i] & (int)Math.Pow(2, expt)) == 0 ? "0" : "1";
}
result[i] = bin;
}
return result;
}
-
Nice Gile, including the use of the ternary operator. :)
-
I'm loving Ruby more every day
"ABC".each_byte {|x| puts x.to_s(2).rjust(8,"0")}
Returns
01000001
01000010
01000011
-
That's pretty cool, tho you didn't pen it as a function.
Python equivalent:
list(map(lambda a: (('0'*8)+bin(ord(a))[2:])[-8:],"ABC"))
=> ['01000001', '01000010', '01000011']
:P
I'm sure someone like Tim could do it more elegantly | concisely.
-
But in Ruby you don't need a function, unless you just want one
def s_to_bin(s1)
s1.each_byte {|x| puts x.to_s(2).rjust(8,"0")}
end
a1="ABC"
a1.each_byte {|x| puts x.to_s(2).rjust(8,"0")}
puts "***"
s_to_bin(a1)
puts "****"
"ABC".each_byte {|x| puts x.to_s(2).rjust(8,"0")}
All return the same thing
01000001
01000010
01000011
***
01000001
01000010
01000011
****
01000001
01000010
01000011
**Edit. Doh, Function. So you can use the return value, right? I remember functions from somewhere. Stand by one.
-
As demonstrated, Python didn't require a function def, but again to illuminate:
s = "ABC"
list(map(lambda a: (('0'*8)+bin(ord(a))[2:])[-8:],s))
=> ['01000001', '01000010', '01000011']
Having said that, I generally prefer functions, as they improve read-ability of the code.
Glad you're digging Ruby. I studied it for quite awhile but I'm preferring Python.
PS: You didn't return a list.
:P
-
Yea, I had a momentary brain freeze
def s_to_bin(s1)
retVal = Array.new
s1.each_byte {|x| retVal.push( x.to_s(2).rjust(8,"0"))}
retVal
end
a1="ABC"
x = s_to_bin(a1)
puts x.inspect
Will return
["01000001", "01000010", "01000011"]
-
Good job.
PS: not so succinct now. :P
Sorry, had to. :)
-
Give me a minute, I'm still learning :-D
-
You and me both. (http://www.theswamp.org/screens/mp/thumbsup.gif)
-
Well, the only way that I see to make it anymore succint is to shorten the variable names or use a smaller font, but I'm not sure that really helps matters :lmao:
But the fact that I can't see anyway should in no way be taken to mean that there isn't a way to do it.
Michael, why Python over Ruby? (if I may ask without hijacking your thread). I don't have enough time into Ruby yet to actually make any judgement. It is just a bit of cotton candy for the brain right now.
-
I prefer Python over Ruby for the simple matter that it aligns with my thought processes better than Ruby and I can concentrate my efforts more on solving the problem rather than the semantics of the language. Ruby had some appeal because of the Rails MVC framework, but the syntax, as concise and as expressive as it may be annoys me to be honest.
-
I prefer Python over Ruby for the simple matter that it aligns with my thought processes better than Ruby and I can concentrate my efforts more on solving the problem rather than the semantics of the language. Ruby had some appeal because of the Rails MVC framework, but the syntax, as concise and as expressive as it may be annoys me to be honest.
A book on Rails in the local library is where I first was introduced to Ruby. I don't have any need for Rails (wish that I did) but I sort of latched onto Ruby as my current time-waster-of-choice.
I do need to give Python another look. There seems to be plenty of interest in the Swamp now so maybe I can pick up a bit.
-
While I slept, you have already finished Challenge? :-o
(defun eea-dec-bin8 (a)
(apply 'strcat (mapcar '(lambda (b) (itoa (rem (lsh a (- b)) 2))) '(7 6 5 4 3 2 1 0)))
)
(mapcar 'eea-dec-bin8 (vl-string->list "ABC"))
-
nice move, Evgeniy! :)
-
Nice Evgeniy,
You give me some inspiration to try a quite shorter C# code
static string[] StringToBinary(string str)
{
Byte[] bytes = Encoding.ASCII.GetBytes(str);
string[] result = new string[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
{
string bin = "";
for (int e = 7; e >= 0; e--)
bin += ((bytes[i] >> e) % 2).ToString();
result[i] = bin;
}
return result;
}
-
> gile, VovKa
Thanks! :-)
-
While I slept, you have already finished Challenge? :-o
Very nicely done sir!
You give me some inspiration to try a quite shorter C# code
Nice translation Gile! However, you're returning a string, in C# you should return a string array. :)
Translating Gile's line by line to Python but returning a list:
def stringToBinary(s):
bytes=list(map(ord,s)); result=[]
for i in range(0,len(bytes)):
bin=""
for e in range(7,-1,-1):
bin+=str((bytes[i] >> e) % 2)
result+=[bin]
return result
Wonder how it performs compared to:
def stringToBinary(s):
return list(map(lambda a: (('0'*8)+bin(ord(a))[2:])[-8:],s))
:)
-
I do need to give Python another look. There seems to be plenty of interest in the Swamp now so maybe I can pick up a bit.
If for no other reason than peer support you may find that Python wins, at least in the CADD community where it seems to be developing more momentum. An aside, I've found there's far more books available on Python than Ruby, a big selling point for me, an admitted computer book junkie. Collyer bros anyone? lol
-
However, you're returning a string, in C# you should return a string array.
It does return a string array.
Vovka's one translation
static string[] StringToBinary(string str)
{
Byte[] bytes = Encoding.ASCII.GetBytes(str);
string[] result = new string[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
{
result[i] = DecToBin(bytes[i], 8);
}
return result;
}
static string DecToBin(int dec, int len)
{
return len < 2 ? (dec % 2).ToString() : DecToBin(dec / 2, len - 1) + (dec % 2).ToString();
}
-
OOPS. Sorry Gile, I shouldn't post before my first coffee; forgive me. (http://www.theswamp.org/screens/mp/facepalm.gif)
-
static string[] StringToBinary(string str)
{
Byte[] bytes = Encoding.ASCII.GetBytes(str);
string[] result = new string[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
{
result[i] = DecToBin(bytes[i], 8);
}
return result;
}
static string DecToBin(int dec, int len)
{
return len < 2 ? (dec % 2).ToString() : DecToBin(dec / 2, len - 1) + (dec % 2).ToString();
}
Translated to Python:
def stringToBinary(s):
bytes=list(map(ord,s)); result=[]
for i in range(0,len(bytes)):
result+=[decToBin(bytes[i])]
return result
def decToBin(dec,bits=8):
return str(dec%2) if bits < 2 else decToBin(dec//2,bits-1) + str(dec%2)
Hope you don't mind, I need the practice and this is a fun way to achieve it. :)
-
I need the practice and this is a fun way to achieve it.
So do I.
-
Another way
LISP
(defun StringToBinary (str / d2b left0)
(defun d2b (n i / m)
(if (zerop (setq m (lsh n i)))
0
(if (zerop (rem m 2))
(d2b n (1- i))
(+ (expt 10 (- i)) (d2b n (1- i)))
)
)
)
(defun left0 (s l)
(while (< (strlen s) l) (setq s (strcat "0" s)))
)
(mapcar '(lambda (x) (left0 (itoa (d2b x 0)) 8))
(vl-string->list str)
)
)
C#
static string[] StringToBinary(string str)
{
Byte[] bytes = Encoding.ASCII.GetBytes(str);
string[] result = new string[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
result[i] = String.Format("{0:00000000}", dec2bin(bytes[i], 0));
return result;
}
static int dec2bin(int n, int i)
{
int s = n >> i;
return s == 0 ? 0 : s % 2 == 0 ? dec2bin(n, i + 1) : (int)Math.Pow(10, i) + dec2bin(n, i + 1);
}
-
static string[] StringToBinary(string str)
{
Byte[] bytes = Encoding.ASCII.GetBytes(str);
string[] result = new string[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
result[i] = String.Format("{0:00000000}", dec2bin(bytes[i], 0));
return result;
}
static int dec2bin(int n, int i)
{
int s = n >> i;
return s == 0 ? 0 : s % 2 == 0 ? dec2bin(n, i + 1) : (int)Math.Pow(10, i) + dec2bin(n, i + 1);
}
Converted to Python:
def stringToBinary(s):
bytes=list(map(ord,s)); result=[]
for i in range(0,len(bytes)):
result+=[bin(bytes[i])[2:].zfill(8)]
return result
Revising one of my earlier submissions:
def stringToBinary(s):
return list(map(lambda a: bin(ord(a))[2:].zfill(8),s))
:D
-
def stringToBinary(s):
bytes=list(map(ord,s)); result=[]
for i in range(0,len(bytes)):
result+=[bin(bytes[i])[2:].zfill(8)]
return result
If one preferred the use of a pre-allocated list rather than appending the result:
def stringToBinary(s):
bytes=list(map(ord,s)); result=['']*len(bytes)
for i in range(0,len(bytes)):
result[i]=bin(bytes[i])[2:].zfill(8)
return result
Such a cool language. :)
-
Turns out I could have employed the range function more efficiently:
Original:
def stringToBinary(s):
bytes=list(map(ord,s)); result=['']*len(bytes)
for i in range([color=red]0,[/color]len(bytes)):
result[i]=bin(bytes[i])[2:].zfill(8)
return result
Improved:
def stringToBinary(s):
bytes=list(map(ord,s)); result=['']*len(bytes)
for i in range(len(bytes)):
result[i]=bin(bytes[i])[2:].zfill(8)
return result
Subtitle: If the intent is to iterate over the indexes of an indexed iterable object, there's no need to specify the lower boundary (0) because the range function will supply 0 in the absence of a specific lower bound; cool. :lightbulb:
/carry on
-
While I admire the beauty of the posted examples, I'm puzzled.
So, from a "pea brained" person's perspective...Why?
What is the intended purpose?
There is occupational incentive for me to continue to learn Lisp/VL,
so can I assume that this challenge would likely be carried to the level
of implementing the code for a purpose.
And if it is "just for the fun of it", that's okay too.
You folks amaze me.
Tony
-
Why? What is the intended purpose?
Not sure I understand Tony ... why bother writing binary functions? (was just for academic fun) or why am I trying to use/learn Python? (I've been wanting to learn it for years for general programming, especially web based stuff).
There is occupational incentive for me to continue to learn Lisp/VL, so can I assume that this challenge would likely be carried to the level
of implementing the code for a purpose.
In my own use I've only ever penned binary functions to illuminate what happens at the binary level to those just beginning to program.
And if it is "just for the fun of it", that's okay too.
And there's this. :)
You folks amaze me.Tony
The skills of our friends from around the world are impressive and I'm glad they've decided to hang their hats here and share their expertise. We all win.
:)
-
The skills of our friends from around the world are impressive and I'm glad they've decided to hang their hats here and share their expertise. We all win.
So very true (re:all winning ).
It is for that dose of commaraderie and the display of those "impressive skills" that I return when I can.
(to see, that is; I have none to disply, yet.)
I still wonder; Is Python a language that is effective for Acad?
Tony
-
OK, old thread, but here is my entry:
;;using lambda function - no apparent speed advantage to named function call
(defun string->bin_strings (str / )
(mapcar '(lambda (str / mask out)
(setq out "" mask 128)
(repeat 8
(if (zerop (logand arg mask))
(setq out (strcat out "0"))
(setq out (strcat out "1"))
)
(setq mask (/ mask 2))
)
out
)
(vl-string->list str))
)
After I got past this garbage:
;;naive iterative version - 8 bits - a real dog
(defun byte->bin_string (arg / n out power2)
(setq n 8 out "")
(repeat 8
(setq n (1- n)
power2 (expt 2 n))
(if (>= arg power2)
(progn
(setq out (strcat out "1")
arg (- arg power2))
)
(setq out (strcat out "0"))
)
)
out
)
I tried 3 ways of doing basically the same thing:
;;iterative - using logand from high bit - much faster than first one (no surprise)
(defun int->bin_string-l (arg / mask out)
(setq out "" mask 128)
(repeat 8
(if (zerop (logand arg mask))
(setq out (strcat out "0"))
(setq out (strcat out "1"))
)
(setq mask (/ mask 2))
)
out
)
;;iterative - using logand from low bit - slightly slower than above!
(defun int->bin_string-r (arg / mask out)
(setq out "" mask 1)
(repeat 8
(if (zerop (logand arg mask))
(setq out (strcat "0" out))
(setq out (strcat "1" out))
)
(setq mask (* mask 2))
)
out
)
;;iterative - using logand & lsh from low bit - slower than using multiply!
(defun int->bin_string-lsh (arg / mask out)
(setq out "" mask 1)
(repeat 8
(if (zerop (logand arg mask))
(setq out (strcat "0" out))
(setq out (strcat "1" out))
)
(setq mask (lsh mask 1))
)
out
)
Test results using BenchRRB by Robt. Bell:
Note: -> results not 100% repeatable - I am not sophisticated enough to know why
So, I suggest running the same test multiple times (like, 5 or 6)
(This could be a whole 'nother topic)
Command: (bench '(int->bin_string-l int->bin_string-r int->bin_string-lsh)
(_> '(255) 1000)
INT->BIN_STRING-L
Elapsed: 15
Average: 0.0150
INT->BIN_STRING-R
Elapsed: 16
Average: 0.0160
INT->BIN_STRING-LSH
Elapsed: 32
Average: 0.0320
Test of posted complete functions:
;;;timing using BenchRRB <- not 100% consistent - must run multiple times
Command: (bench '(_strtobin eea-str2bin stringtobinary-tw stringtobinary-gile
('(_> string->bin_strings) '("ABCD") 1000)
_STRTOBIN - MP
Elapsed: 110
Average: 0.1100
EEA-STR2BIN
Elapsed: 79
Average: 0.0790
STRINGTOBINARY-TW
Elapsed: 78
Average: 0.0780
STRINGTOBINARY-GILE - 1st Post
Elapsed: 94
Average: 0.0940
STRING->BIN_STRINGS
Elapsed: 78
Average: 0.0780
@ MP:
I think (expt) is slowing yours down
Yes, I see that part of your intention was to compare language solutions, so probably you could write faster LISP if you intended to only do that. Now, I am determined to explore some .NET - it is time.:)
@ Gile:
I didn't test your subsequent LISP post
@ TW:
Your entry is far from "cheesy"
@ Vovka:
Sorry, I kept getting a "cannot reenter LISP" error when I tried to wrap your nice recursion, so I had to omit yours.
Please accept my apology for not being able to find my error.
@ Evgeny:
Impressive. Concise & fast.
You da man.:)
Comments:
I would naively expect (lsh) to beat * or /. However, the results I got here agree with my past experience, that (lsh) is not as fast as one might expect, given its definition. I conclude it is implemented in a way not very close to the hardware.
-
Whoops:
;;using lambda function - no apparent speed advantage to named function call
(defun string->bin_strings (str / )
(mapcar '(lambda (str / mask out)
(setq out "" mask 128)
(repeat 8
(if (zerop (logand str mask))
(setq out (strcat out "0"))
(setq out (strcat out "1"))
)
(setq mask (/ mask 2))
)
out
)
(vl-string->list str))
)
Attached: Robert Bell's "Bench" program, which I used to test speed of posted functions.
Anyone is free to dissect that, or provide a better one.
-
mine
static int ads_stringtobinary(void)
{
TCHAR outbuff[33];
TCHAR formatedBuff[33];
const int padding = (sizeof(int)*8+1);
struct resbuf *pArgs =acedGetArgs () ;
struct resbuf *pHead = acutNewRb(RTSTR);
struct resbuf *pTail = pHead;
while(pArgs)
{
if(pArgs->restype == RTSTR)
{
pTail = pTail->rbnext = acutNewRb(RTLB);
for(int i = 0 ;i < _tcsclen(pArgs->resval.rstring) ; i++)
{
pTail = pTail->rbnext = acutNewRb(RTSTR);
_itot(pArgs->resval.rstring[i] , outbuff, 2);
_stprintf_s(formatedBuff,sizeof(formatedBuff),_T("%08s"),outbuff);
pTail->resval.rstring = _tcsdup(formatedBuff);
}
pTail = pTail->rbnext = acutNewRb(RTLE);
}
pArgs = pArgs->rbnext;
}
if(pHead->rbnext) { acedRetList (pHead->rbnext); };
acutRelRb(pHead);
return (RSRSLT) ;
}
-
my C# version
[LispFunction("StrToBin")]
public static ResultBuffer StrToBin(ResultBuffer args)
{
List<string> strings = new List<string>();
ResultBuffer rb = new ResultBuffer();
if (args != null)
{
foreach (TypedValue tv in args)
if (tv.TypeCode == (int)LispDataType.Text)
strings.Add((string)tv.Value);
strings.ForEach(S => new List<byte>
(Encoding.ASCII.GetBytes(S)).ForEach
(B => rb.Add(new TypedValue((int)LispDataType.Text,(Convert.ToString(B, 2).PadLeft(8,'0'))))));
}
return rb;
}