Learning vectors - scheme

I'm learning how vectors work.
I have two vectors, one contains names and the other one contains "phone numbers". I wrote a function which is displaying all names and all phone number next to each other:
(define v4 (vector 'Tom 'Michael 'John 'Julia))
(define v5 (vector 2343 1343 2112 372637))
(define db (λ (n)
(cond
((equal? (vector-length v4) n ) "stop" )
(equal? 0 (display (vector-ref v4 n))
(display " ")
(display (vector-ref v5 n ))
(displayln " ")
(set! n (+ n 1))
(db n)
))))
(db 0)
Result is:
Tom 2343
Michael 1343
John 2112
Julia 372637
"stop"
Is this the right way to do it? Is there a better way to do it?

Here's a simpler way in Racket, using iterations and comprehensions and format strings. Arguably, this is more idiomatic and easier to understand:
(define (db v1 v2)
(for ([name (in-vector v1)]
[phone (in-vector v2)])
(printf "~a ~a~n" name phone))
"stop")
Even if we were to write an implementation using only explicit recursion and standard procedures, it's better to avoid using set! to increment the index, pass parameters instead - including the vectors that are going to be iterated, there's no need to refer to global definitions:
(define (db v1 v2)
(let loop ((idx 0))
(cond ((>= idx (vector-length v1)) "stop")
(else
(display (vector-ref v1 idx))
(display " ")
(display (vector-ref v2 idx))
(newline)
(loop (+ idx 1))))))
Either way and assuming that both vectors have the same length, it works as expected:
(define v1 (vector 'Tom 'Michael 'John 'Julia))
(define v2 (vector 2343 1343 2112 372637))
(db v1 v2)
Tom 2343
Michael 1343
John 2112
Julia 372637
"stop"

Related

How to change this function, "car" got problems

I want to write a function, which converts from a "normal" notation like this: "1+4*2-8" to this pre-notation: "+1-*428".
I hope you get the point here.
Important: It must be in Strings.
What I get so far:
(define (converter lst )
(let ((operand1 (car lst))
(operator (car (cdr lst)))
(operand2 (caddr lst)))
(list operator
(converter operand1)
(converter operand2)))
)
(infixLst->prefixLst '(1 + 2 * 3))
I got two problems here.
1) It's for Lists, I need it work for Strings like "1+3" and not '(1+3)
2) It doesn't work so far (even not for Lists), because it give me some errors regarding the "car", e.g: car: expects a pair, given 1
Soo starting with the List -> String change: (I know that (list is unappropriate here. As well as the other list-methods but I didnt got a better idea so far.
(define (infix->prefix str)
(let ((operand1 (car str))
(operator (cadr str))
(operand2 (caddr str)))
(list operator
(infix->prefix operand1)
(infix->prefix operand2)))
)
(infix->prefix "1 + 2")
The normal notation 1+4*2-8 is called infix notation.
If you simply need to use that notation, Racket has a ready module: (require infix), here's a link to its documentation.
If you want to practice writing your own infix parser, the shunting-yard algorithm can do that. It uses a stack to keep track of the operators in the math expression.
If you want to parse math from a string, you need to first split the string into a list of tokens (numbers and operators). Start with a math->tokens procedure that simply returns a list of the tokens without caring about their meaning. There are many ways to write it. Here is one:
(define (math->tokens s)
(let collect-tokens ((i 0) (tokens '()))
(if (= i (string-length s))
(reverse tokens)
(let ((char (string-ref s i)))
(if (not (char-numeric? char))
(let ((operator (string->symbol (string char))))
(collect-tokens (+ i 1) (cons operator tokens)))
(let collect-number ((j (+ i 1)))
(if (and (< j (string-length s))
(char-numeric? (string-ref s j)))
(collect-number (+ j 1))
(let ((number (string->number (substring s i j))))
(collect-tokens j (cons number tokens))))))))))
For example, (math->tokens "+1-*428") returns the list of tokens (+ 1 - * 428). Now you can apply the shunting-yard algorithm to that list.

Idiomatic way to decode hex-formatted strings in Racket Scheme or other schemes

My input data is a hex-formatted string without restriction on the length. I need to process the bytes individually. As an example, for "AABBCCDDEEFF" I want to process AA, then BB, CC, DD, EE, FF.
Using Common Lisp, we can use LOOP:
(loop for (a b) on list do [processing])
In Racket Scheme, I wrote this solution:
(define (split-string str)
(let ((bit #t)
(char-1 null)
(char-2 null)
(result '()))
(for ((char str))
(if bit
(begin
(set! bit #f)
(set! char-1 char))
(begin
(set! bit #t)
(set! char-2 char)
(set! result (cons (~a char-1 char-2) result)))))
;; return
(reverse result)))
(split-string "AABBCCDDEEFF")
;; '("AA" "BB" "CC" "DD" "EE" "FF")
I feel like this is not idiomatic Racket or Scheme code. I wrote a second solution:
(define (split-string2 str)
(bytes->list (integer->integer-bytes (string->number str 16) 8 false)))
(split-string2 "AABBCCDDEEFF")
;; '(255 238 221 204 187 170 0 0)
What is the idiomatic way to perform this kind of operations in Racket Scheme and more generally in Lisp?
There are a bunch of ways of doing this in Racket (as opposed to Scheme more generally): the notions you want are sequences, streams and generators.
First of all a function to compute hex digits from characters (this may exist in Racket, but I was too lazy to find it, and this works):
(define (char->hex-digit c)
;; Turn a character into a hex digit
(cond [(char<=? #\0 c #\9)
(- (char->integer c) (char->integer #\0))]
[(char<=? #\A c #\F)
(+ 10 (- (char->integer c) (char->integer #\A)))]
[(char<=? #\a c #\f)
(+ 10 (- (char->integer c) (char->integer #\a)))]
[else
(error 'char->hex-digit "~A is not a hex character" c)]))
Now here is a simple-minded approach to turning a hex string into a list of bytes which works by creating two sequences from the string, one of which picks out the high and the other the low digit in each pair:
(define (hex-string->byte-list hs)
(for/list ([h (in-string hs 0 #f 2)]
[l (in-string hs 1 #f 2)])
(+ (* (char->hex-digit h) 16) (char->hex-digit l))))
Obviously depending on which variant of for you use you can construct different results.
Examples:
> (hex-string->byte-list "F00D")
'(240 13)
> (hex-string->byte-list "0102030405060708090a0b0C0D0F")
'(1 2 3 4 5 6 7 8 9 10 11 12 13 15)
> (hex-string->byte-list "01xa")
; char->hex-digit: x is not a hex character [,bt for context]
Another approach is to use in-slice:
(define (hex-string->byte-list hs)
(for/list ([hl (in-slice 2 (in-string hs))])
(+ (* (char->hex-digit (first hl)) 16) (char->hex-digit (second hl)))))
And there are lots of other ways of doing this, including creating your own sequence or stream types, so you could write (for/list ([b (in-hex-stream-bytes ...)]) b).
Note that the Common Lisp version would not work since the input is a string; in order to use the same approach you should first convert the string to a list of characters; secondly, you would need to add a by directive to advance over the list by cddr, i.e. skipping the already read b.
That would finally look like:
(loop
for (a b) on (coerce "AABBCCDDEEFF" 'list) by #'cddr
collect (parse-integer (coerce (vector a b) 'string)
:radix 16))
=> (170 187 204 221 238 255)
But, this is a bit wasteful, parse-integer admits :start and :end arguments, so you do not need to allocate any intermediate list or string (apart for the last collect; you could skip it too and just process the value directly):
(loop
with string = "AABBCCDDEEFF"
with size = (length string)
initially (assert (evenp size))
for start from 0 by 2
for end from 2 by 2 upto size
collect (parse-integer string :start start :end end :radix 16))
=> (170 187 204 221 238 255)
One of the idiomatic ways would be to use recursion (preserving the same functionality as your split-string) as follows:
(define (split-string-recur str)
(cond [(or (string=? str "") (string=? "" (substring str 1))) '()]
[else (cons (substring str 0 2) (split-string-recur (substring str 2)))]))
and a tail-recursive version:
(define (split-string-trecur str)
(define (split-string-recur str acc)
(cond [(or (string=? str "") (string=? "" (substring str 1))) acc]
[else (split-string-recur (substring str 2) (append acc (list (substring str 0 2))))]))
(split-string-recur str '()))
The for/list approach with in-slice on in-string sequence (mentioned here) is also an idiomatic approach.
Note that we can also use a small interface on strings like the following to make it more readable:
(module string-util typed/racket
(provide (all-defined-out))
(: empty-string? : (-> String Boolean))
(define (empty-string? s)
(string=? "" s))
(: string-first : (-> String String))
(define (string-first s)
(substring s 0 1))
(: string-last : (-> String String))
(define (string-last s)
(substring s (- (string-length s) 1) (string-length s)))
(: string-rest : (-> String String))
(define (string-rest s)
(substring s 1 (string-length s))))
(require 'string-util)
(define (split-string-recur str)
(cond [(or (empty-string? str) (empty-string? (string-rest str))) '()]
[else (cons (string-append (string-first str) (string-first (string-rest str)))
(split-string-recur (string-rest (string-rest str))))]))
CL-USER 2 > (defun split-string (string)
(loop for i from 0 below (length string) by 2
collect (subseq string i (+ i 2))))
SPLIT-STRING
CL-USER 3 > (split-string "AABBCCDDEEFF")
("AA" "BB" "CC" "DD" "EE" "FF")
CL-USER 4 > (mapcar (lambda (s) (parse-integer s :radix 16)) *)
(170 187 204 221 238 255)

How to use multiple statements inside cond?

For example I have the following code, I define a variable v1 then check the value of v1. If v1 == 1, I want to (print-list q2) and read another input and store to v2, something like this: (define v2 (read)).
(define v1 (read))
(cond
[(null? v1) (printf "No input..\n")]
[(= v1 1) (print-list q2)]
How do I achieve my solution above?
You can write more than one expression after a cond's condition:
(define v1 (read))
(cond
[(null? v1) (printf "No input..\n")]
[(= v1 1)
(define v2 (read))
(print-list q2)]
[else (error "Unexpected value")])
Of course, the above will only work if print-list and q2 were previously defined, but it illustrates the general idea of what you want to do. Just remember that although all expressions after the condition will be executed sequentially, only the value of the last expression will be returned, which in this example is (print-list q2).
One can also use recursion to read repeatedly:
(define (f)
(let loop ((v (read)))
(cond [(= 0 v) "End."]
[(= 1 v) (println '(a b c))]
; [.. other options ..]
[else
(println '(1 2 3))
(loop (read))])))
Testing:
(f)
1
'(a b c)
0
"End."
>

Tonumber function (tonumber ‘(one two three) --> 123

After the solution of how to spell a number in racket? (spellNum) ,now I am trying to write a function which is opposite of this function. i.e
(tonumber ‘(one two three) --> 123
so far I have written this working code
(define (symbol->digit n)
(case n
('zero 0)
('one 1)
('two 2)
('three 3)
('four 4)
('five 5)
('six 6)
('seven 7)
('eight 8)
('nine 9)
(else (error "unknown symbol:" n))))
(define (numlist n)
(map symbol->digit n))
(numlist '(one two three))
From numlist, I got '(1 2 3). But to there is some problem in the function below in which I want to convert list to number
(define (list->number l)
(set! multiplier (* 10 (lenght l)))
(for/list [(c l)]
(* multiplier c))
(set! multiplier (/ multiplier 10)))
(list->number '(1 2 3))
any help will be appreciated. I can't find documentation of all kind of loops online. at
http://docs.racket-lang.org/ts-reference/special-forms.html?q=loop#%28part._.Loops%29
I want to become familiar with Racket so I want to avoid builtin conversion functions. In list->number,I am trying to take digits one by one from list and then i want to multiply them with 10,100,1000 so on depending on the length of list. so that it can return a number. For example '(1 2 3) = 1*100+2*10+3*1
Here's the exact opposite of my previous solution, once again using tail recursion for the list->number procedure:
(define (symbol->digit n)
(case n
('zero 0)
('one 1)
('two 2)
('three 3)
('four 4)
('five 5)
('six 6)
('seven 7)
('eight 8)
('nine 9)
(else (error "unknown symbol:" n))))
(define (list->number lst)
(let loop ((acc 0) (lst lst))
(if (null? lst)
acc
(loop (+ (car lst) (* 10 acc)) (cdr lst)))))
(define (toNumber lst)
(list->number (map symbol->digit lst)))
It works as expected:
(toNumber '(four six seven))
=> 467
Just for fun, in Racket we can write a function like list->number using iteration and comprehensions. Even so, notice that we don't use set! anywhere, mutating state is the norm in a language like Python but in Scheme in general and Racket in particular we try to avoid modifying variables inside a loop - there are more elegant ways to express a solution:
(define (list->number lst)
(for/fold ([acc 0]) ([e lst])
(+ e (* 10 acc))))
(define (symbol->digit n)
(case n
('zero "0")
('one "1")
('two "2")
('three "3")
('four "4")
('five "5")
('six "6")
('seven "7")
('eight "8")
('nine "9")
(else (error "unknown symbol:" n))))
(define (symbols->number symb)
(string->number (string-join (map symbol->digit symb) "")))
(symbols->number '(one two three))
Lots of ways to skin a cat. Here is version that uses fold-left. Like Óscar's solution it uses math rather than chars and strings.
#!r6rs
(import (rnrs))
;; converts list with worded digits into
;; what number they represent.
;; (words->number '(one two zero)) ==> 120
(define (words->number lst)
(fold-left (lambda (acc x)
(+ x (* acc 10)))
0
(map symbol->digit lst)))
For a #!racket version just rename fold-left to foldl and switch the order of x and acc.

Scheme function: calculating distance of 2 "vectors" of any size

My vectors are defined as:
(x1, x2, …, xn) and (y1, y2, …yn)
I'm trying to calculate them like so:
sqrt((x1-y1)*(x1-y1) + (x2-y2)*(x2-y2) + … + (xn-yn)*(xn-yn))
I'm having trouble with vectors of more than 2 elements. I've been trying to use a for-each loop but I can't get the recursion to work right.
Also, I can get everything but the sqrt of the final number. I tried to define the final number as a variable, then take the sqrt of that variable, but my interpreter said something about "define not allowed in expression . . .".
My working code so far:
(define vectordistance
(lambda (v1 v2)
(if
(null? v1) 0
(+
(*
(- (car v1) (car v2))
(- (car v1) (car v2))
)
(vectordistance (cdr v1) (cdr v2))
)
)
))
First, you're using lists - a vector is a different beast in Scheme. The key point for the solution is that you have to iterate over the lists, and somehow accumulate the answer until there are no more elements left. Also, a helper function will be useful here, because first we have to accumulate the addition and take the square root only at the end. Assuming that both lists have the same length:
; this is the same as yours, but better formatted
(define (helper v1 v2)
(if (null? v1)
0
(+ (* (- (car v1) (car v2))
(- (car v1) (car v2)))
(helper (cdr v1) (cdr v2)))))
; call the above as a helper and take the square root of the result
(define (vectordistance v1 v2)
(sqrt (helper v1 v2)))
As a bonus (suggested by Chris) you can write the helper in a more idiomatic way by using a fold procedure. Check your interpreter's documentation, it might be called foldl or fold-left or simply fold, but this is how you'd use it - the idea is to avoid using explicit recursion and favoring the use of higher-order procedures:
(define (square x)
(* x x))
(define (helper v1 v2)
(foldl (lambda (e1 e2 r)
(+ (square (- e1 e2)) r))
0
v1 v2))

Resources