Print a padded binary word in Racket - racket

I want to print a padded to 32 bits word in binary in Racket. I know about printf and "~b", but I want it padded to be 32 bits long each time. How do I do this?
Example
(printf "~b" 42)
=> 101010
Want: 00000000000000000000000000101010

Here's a concise way to do it with Racket 5.3.1 and above:
Welcome to Racket v5.3.2.3.
-> (require racket/format)
-> (~r 42 #:base 2 #:min-width 32 #:pad-string "0")
"00000000000000000000000000101010"
See racket/format for more details.
In older Racket versions, you can do this:
Welcome to Racket v5.3.
-> (require srfi/13)
-> (string-pad (number->string 42 2) 32 #\0)
"00000000000000000000000000101010"

Well, I forced together a solution:
(define (print-word x)
(if (not (<= -2147483648 x 4294967295))
(error 'print-word "ERROR This number is bigger than a word ~a" x)
(let* ([positive-x (if (< x 0) (+ #x100000000 x)
x)]
[str (number->string positive-x 2)]
[padded-str (string-append
(make-string (- 32 (string-length str)) #\0)
str)])
(build-string 39
(λ(i) (cond [(= (remainder (+ 1 i) 5) 0) #\space]
[else (string-ref padded-str (- i (quotient i 5)))]))))))
This actually return the string with spaces between every 4 digits, as it was actually rather hard to read the other way.

Well here's a simple, inefficient way to do it:
(define (pad-left length padding the-str)
(if (> length (string-length the-str))
(pad-left length padding (string-append padding the-str))
the-str))
(write (pad-left 32 "0" (format "~b" 42)))

Related

Is there a string to 32 bit integer coding system in elisp?

Is there a coding system such that (encode-coding-string msg '??? t) would convert my message into a list of 32 bit integers?
The binary coding system converts well the message to 8 bit data, and I am aware that I could post-process it to convert the result into 32 bits. I'm just wondering if there is already a coding system that does this... :) #lazy
Ok, attempt number two.
I wrote a test generator snippet in python:
def make_test_2():
with open('test2.bin', 'wb') as f:
args = [1867, 1982]
for a in args:
f.write((a).to_bytes(4, byteorder='little'))
This is a pretty hacky (a couple of reverse calls etc). But, its only meant to be a quick and dirty prototype.
(defun read-int-list2 (filename)
(let ((result '())
(accumulator '())
(accum-count 0)
(accum-max 4))
(with-temp-buffer
(set-buffer-multibyte nil)
(setq buffer-file-coding-system 'binary) ;; find a way to set temporarily? not sure
(insert-file-contents-literally filename)
(while (< (point) (point-max))
(if (< accum-count accum-max)
(progn
(setq accumulator (cons (aref (buffer-substring-no-properties (point) (1+ (point))) 0) accumulator))
(setq accum-count (1+ accum-count))))
(if (>= accum-count accum-max) ;; four bytes accumulated, lets bundle
(progn
(let* ((s (reverse accumulator))
(e1 (elt s 0))
(e2 (elt s 1))
(e3 (elt s 2))
(e4 (elt s 3))
(val (logior (lsh e4 24) (lsh e3 16) (lsh e2 8) e1))) ;; assume little endian (intel, ARM)
;; (message (format "%x %x %x %x -> %d" e1 e2 e3 e4 val))
(setq result (cons val result))
(setq accum-count 0)
(setq accumulator '()))))
(forward-char)))
(reverse result)))
(read-int-list2 "test2.bin") ;; (1867 1982)
I only did the one test. So that needs improvement. In words:
accumulate 8 byte chars from the special temp buffer (special because binary/literal load)
once the bytes per integer count has been reached, merge the accumulated bytes into an integer by bit shifting (be aware some machines are big endian, I assume here little endian) the bytes into place.
dump merged into result list
reset the accumulator
go to step 1
i have no doubt there are many improvements, my lisp is rusty.

How can I convert double-float to byte array and vice versa in common lisp?

For integer (32bit or 4 bytes) I can do as follows;
(defun get-u4 (arr pos)
(let ((u4 0))
(setf (ldb (byte 8 0) u4) (aref arr pos))
(setf (ldb (byte 8 8) u4) (aref arr (+ pos 1)))
(setf (ldb (byte 8 16) u4) (aref arr (+ pos 2)))
(setf (ldb (byte 8 24) u4) (aref arr (+ pos 3)))
u4))
(defun put-u4 (arr pos int)
(setf (aref arr pos) (ldb (byte 8 0) int))
(setf (aref arr (+ pos 1)) (ldb (byte 8 8) int))
(setf (aref arr (+ pos 2)) (ldb (byte 8 16) int))
(setf (aref arr (+ pos 3)) (ldb (byte 8 24) int)))
However, I cannot figure out how can I do this for 64bit or 8byte
double-float? Little-Endianess is assumed.
=============
I found one solution (using external library);
https://www.quicklisp.org/beta/UNOFFICIAL/docs/ieee-floats/doc/index.html
using this one, I can encode/decode double-float to/from integer with proper
size.
From wikipedia we get this:
You can get the library you mentioned in the comment with quicklisp:
CL-USER> (ql:quickload 'ieee-floats)
To load "ieee-floats":
Install 1 Quicklisp release:
ieee-floats
; Fetching #<URL "http://beta.quicklisp.org/archive/ieee-floats/2015-06-08/ieee-floats-20150608-git.tgz">
; 4.92KB
==================================================
5,041 bytes in 0.01 seconds (378.68KB/sec)
; Loading "ieee-floats"
[package ieee-floats]
(IEEE-FLOATS)
CL-USER> (ieee-floats:encode-float32 23d2)
1158660096
CL-USER> (ieee-floats:decode-float32 #b010101)
2.9427268e-44
CL-USER> (ieee-floats:encode-float32 0)
; Evaluation aborted on #<TYPE-ERROR expected-type: FLOAT datum: 0>.
CL-USER> (ieee-floats:encode-float32 0.0)
0
CL-USER> (ieee-floats:encode-float32 0.1)
1036831949
you can use of course iee-floats:encode/decode-float64 of course,
You also need to know that #b010101 is a macro that represents the number in binary you can use in normal math with common lisp:
CL-USER> (+ 2 #b10)
4
so it converts the binary for you to an integer, then you can also have the utility with format
(format nil "~B" 2)
"10"
That you can use to convert integers to binary string, finally the only thing that you may take care is the 0 autocompletion before the number in binary, the ieee library removes them for the representation
CL-USER> (ieee-floats:encode-float64 1.0d0)
4607182418800017408
CL-USER> (format nil "~B" *)
"11111111110000000000000000000000000000000000000000000000000000"
CL-USER> (length *)
62
CL-USER> (ieee-floats:encode-float64 -1.0d0)
13830554455654793216
CL-USER> (format nil "~B" *)
"1011111111110000000000000000000000000000000000000000000000000000"
CL-USER> (length *)
64
CL-USER> (ieee-floats:decode-float64 #b11111111110000000000000000000000000000000000000000000000000000 )
1.0d0
CL-USER> (ieee-floats:decode-float64 #b1011111111110000000000000000000000000000000000000000000000000000 )
-1.0d0
CL-USER> (ieee-floats:decode-float64 #b0011111111110000000000000000000000000000000000000000000000000000 )
1.0d0
With this you can make all your needed transformations, good luck

Iterate list by step in Emacs Lisp

I have a list in Elisp. How do i return a list consisting of every nth element starting from the 1st? In Python i have slice notation:
>>> range(10)[::3]
[0, 3, 6, 9]
I can't find anything helpful in dash.el list API, so i wrote my solution using loop macro:
(defun step (n xs)
(loop for x in xs by (lambda (xs) (nthcdr n xs))
collect x))
ELISP> (step 3 (number-sequence 0 10))
(0 3 6 9)
By the way, (lambda (xs) (nthcdr n xs)) could be rewritten with dash.el's partial application function -partial: (-partial 'nthcdr n).
loop macro seems like overkill. How do i return elements by step in Emacs Lisp?
dash package's slice supports step from version 2.7. Therefore Python's range(10)[1:7:2] is equivalent to:
(-slice (number-sequence 0 9) 1 7 2) ; (1 3 5)
Here's a short illustration, comparing using -partial and a plain lambda in a loop:
(require 'cl-lib)
(prog1 nil
(setq bigdata (number-sequence 1 10000)))
(defun every-nth-1 (n xs)
(cl-loop for x in xs by (lambda (xs) (nthcdr n xs))
collect x))
(defun every-nth-2 (n xs)
(cl-loop for x in xs by (-partial 'nthcdr n)
collect x))
(defmacro util-timeit (expr)
(let ((t-beg (float-time))
(res (dotimes (i 1000)
(eval expr)))
(t-end (float-time)))
(/
(- t-end t-beg)
1000)))
(setq time1
(util-timeit
(length (every-nth-1 3 bigdata))))
(setq time2
(util-timeit
(every-nth-2 3 bigdata)))
(message "%s" (/ time2 time1))
Calling eval-buffer gives me a result around 4. This means that
(lambda (xs) (nthcdr n xs)) is 4 times faster than (-partial 'nthcdr n),
at least without byte compilation.
With byte-compilation, it gives an astounding 12.2-13.6 times difference in performance
in favor of a plain lambda!

Common Lisp: "no non-white-space characters in string"

For Project Euler Problem 8, I am told to parse through a 1000 digit number.
This is a brute-force Lisp solution, which basically goes through every 5 consecutive digits and multiplies them from start to finish, and returns the largest one at the end of the loop.
The code:
(defun pep8 ()
(labels ((product-of-5n (n)
(eval (append '(*)
(loop for x from n to (+ n 5)
collect (parse-integer
1000digits-str :start x :end (+ x 1)))))))
(let ((largestproduct 0))
(do ((currentdigit 0 (1+ currentdigit)))
((> currentdigit (- (length 1000digits-str) 6)) (return largestproduct))
(when (> (product-of-5n currentdigit) largestproduct)
(setf largestproduct (product-of-5n currentdigit)))))))
It compiles without any warnings, but upon running it I get:
no non-whitespace characters in string "73167176531330624919225119674426574742355349194934...".
[Condition of type SB-INT:SIMPLE-PARSE-ERROR]
I checked to see if the local function product-of-5n was working by writing it again as a global function:
(defun product-of-5n (n)
(eval (append '(*)
(loop for x from n to (+ n 5)
collect (parse-integer
1000digits-str :start x :end (+ x 1))))))
This compiled without warnings and upon running it, appears to operate perfectly. For example,
CL_USER> (product-of-5n 1) => 882
Which appears to be correct since the first five digits are 7, 3, 1, 6 and 7.
As for 1000digits-str, it was simply compiled with defvar, and with Emacs' longlines-show-hard-newlines, I don't think there are any white-space characters in the string, because that's what SBCL is complaining about, right?
I don't think there are any white-space characters in the string, because that's what SBCL is complaining about, right?
The error-message isn't complaining about the presence of white-space, but about the absence of non-white-space. But it's actually a bit misleading: what the message should say is that there's no non-white-space in the specific substring to be parsed. This is because you ran off the end of the string, so were parsing a zero-length substring.
Also, product-of-5n is not defined quite right. It's just happenstance that (product-of-5n 1) returns the product of the first five digits. Strings are indexed from 0, so (product-of-5n 1) starts with the second character; and the function iterates from n + 0 to n + 5, which is a total of six characters; so (product-of-5n 1) returns 3 × 1 × 6 × 7 × 1 × 7, which happens to be the same as 7 × 3 × 1 × 6 × 7 × 1.
EVAL is not a good idea.
Your loop upper bound is wrong.
Otherwise I tried it with the number string and it works.
It's also Euler 8, not 9.
This is my version:
(defun euler8 (string)
(loop for (a b c d e) on (map 'list #'digit-char-p string)
while e maximize (* a b c d e)))
since I don't know common lisp, I slightly modified your code to fit with elisp. As far as finding bugs go and besides what have been said ((product-of-5n 1) should return 126), the only comment I have is that in (pep8), do length-4 instead of -6 (otherwise you loose last 2 characters). Sorry that I don't know how to fix your parse-error (I used string-to-number instead), but here is the code in case you find it useful:
(defun product-of-5n (n) ;take 5 characters from a string "1000digits-str" starting with nth one and output their product
(let (ox) ;define ox as a local variable
(eval ;evaluate
(append '(*) ;concatenate the multiplication sign to the list of 5 numbers (that are added next)
(dotimes (x 5 ox) ;x goes from 0 to 4 (n is added later to make it go n to n+4), the output is stored in ox
(setq ox (cons ;create a list of 5 numbers and store it in ox
(string-to-number
(substring 1000digits-str (+ x n) (+ (+ x n) 1) ) ;get the (n+x)th character
) ;end convert char to number
ox ) ;end cons
) ;end setq
) ;end dotimes, returns ox outside of do, ox has the list of 5 numbers in it
) ;end append
) ;end eval
) ;end let
)
(defun pep8 () ;print the highest
(let ((currentdigit 0) (largestproduct 0)) ;initialize local variables
(while (< currentdigit (- (length 1000digits-str) 4) ) ;while currentdigit (cd from now on) is less than l(str)-4
;(print (cons "current digit" currentdigit)) ;uncomment to print cd
(when (> (product-of-5n currentdigit) largestproduct) ;when current product is greater than previous largestproduct (lp)
(setq largestproduct (product-of-5n currentdigit)) ;save lp
(print (cons "next good cd" currentdigit)) ;print cd
(print (cons "with corresponding lp" largestproduct)) ;print lp
) ;end when
(setq currentdigit (1+ currentdigit)) ;increment cd
) ;end while
(print (cons "best ever lp" largestproduct) ) ;print best ever lp
) ;end let
)
(setq 1000digits-str "73167176531330624919")
(product-of-5n 1)
(pep9)
which returns (when ran on the first 20 characters)
"73167176531330624919"
126
("next good cd" . 0)
("with corresponding lp" . 882)
("next good cd" . 3)
("with corresponding lp" . 1764)
("best ever lp" . 1764)
I've done this problem some time ago, and there's one thing you are missing in the description of the problem. You need to read consequent as starting at any offset into a sting, not only the offsets divisible by 5. Therefore the solution to the problem will be more like the following:
(defun pe-8 ()
(do ((input (remove #\Newline
"73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450"))
(tries 0 (1+ tries))
(result 0))
((= tries 5) result)
(setq result
(max result
(do ((max 0)
(i 0 (+ 5 i)))
((= i (length input)) max)
(setq max
(do ((j i (1+ j))
(current 1)
int-char)
((= j (+ 5 i)) (max current max))
(setq int-char (- (char-code (aref input j)) 48))
(case int-char
(0 (return max))
(1)
(t (setq current (* current int-char))))))))
input (concatenate 'string (subseq input 1) (subseq input 0 1)))))
It's a tad ugly, but it illustrates the idea.
EDIT sorry, I've confused two of your functions. So that like was incorrect.

How to calculate the sum of a digits of a number in Scheme?

I want to calculate the sum of digits of a number in Scheme. It should work like this:
>(sum-of-digits 123)
6
My idea is to transform the number 123 to string "123" and then transform it to a list '(1 2 3) and then use (apply + '(1 2 3)) to get 6.
but it's unfortunately not working like I imagined.
>(string->list(number->string 123))
'(#\1 #\2 #\3)
Apparently '(#\1 #\2 #\3) is not same as '(1 2 3)... because I'm using language racket under DrRacket, so I can not use the function like char->digit.
Can anyone help me fix this?
An alternative method would be to loop over the digits by using modulo. I'm not as used to scheme syntax, but thanks to #bearzk translating my Lisp here's a function that works for non-negative integers (and with a little work could encompass decimals and negative values):
(define (sum-of-digits x)
(if (= x 0) 0
(+ (modulo x 10)
(sum-of-digits (/ (- x (modulo x 10)) 10)))))
Something like this can do your digits thing arithmetically rather than string style:
(define (digits n)
(if (zero? n)
'()
(cons (remainder n 10) (digits2 (quotient n 10))))
Anyway, idk if its what you're doing but this question makes me think Project Euler. And if so, you're going to appreciate both of these functions in future problems.
Above is the hard part, this is the rest:
(foldr + (digits 12345) 0)
OR
(apply + (digits 1234))
EDIT - I got rid of intLength above, but in case you still want it.
(define (intLength x)
(define (intLengthP x c)
(if (zero? x)
c
(intLengthP (quotient x 10) (+ c 1))
)
)
(intLengthP x 0))
Those #\1, #\2 things are characters. I hate to RTFM you, but the Racket docs are really good here. If you highlight string->list in DrRacket and hit F1, you should get a browser window with a bunch of useful information.
So as not to keep you in the dark; I think I'd probably use the "string" function as the missing step in your solution:
(map string (list #\a #\b))
... produces
(list "a" "b")
A better idea would be to actually find the digits and sum them. 34%10 gives 4 and 3%10 gives 3. Sum is 3+4.
Here's an algorithm in F# (I'm sorry, I don't know Scheme):
let rec sumOfDigits n =
if n<10 then n
else (n%10) + sumOfDigits (n/10)
This works, it builds on your initial string->list solution, just does a conversion on the list of characters
(apply + (map (lambda (d) (- (char->integer d) (char->integer #\0)))
(string->list (number->string 123))))
The conversion function could factored out to make it a little more clear:
(define (digit->integer d)
(- (char->integer d) (char->integer #\0)))
(apply + (map digit->integer (string->list (number->string 123))))
(define (sum-of-digits num)
(if (< num 10)
num
(+ (remainder num 10) (sum-of-digits (/ (- num (remainder num 10)) 10)))))
recursive process.. terminates at n < 10 where sum-of-digits returns the input num itself.