Racket - string->list returns strange results [duplicate] - string

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.

Related

Cosine Similarity in linear time using Lisp

The cosine similarity of two lists can be calculated in linear time using a for-loop. I'm curious as to how one would achieve this using a Lisp-like language. Below is an example of my code in Python and Hy (Hylang).
Python:
def cos_sim(A,B):
import math as _math
n,da,db,d = 0,0,0,0
for a,b in zip(A,B):
n += a*b
da += a*a
db += b*b
da = _math.sqrt(da)
db = _math.sqrt(db)
d = da*db
return n / (d + 1e-32)
Hy (Lisp):
(import math)
(defn l2norm [a]
(math.sqrt (reduce + (map (fn [s](* s s)) a))))
(defn dot [a b]
(reduce + (map * a b)))
(defn cossim [a b]
(/ (dot a b) (* (l2norm a) (l2norm b))))
"I'm curious as to how one would achieve this using a Lisp-like language." This really depends on which Lisp you are using. In Scheme you might do something similar to the posted Hy solution:
(define (cos-sim-1 u v)
(/ (dot-prod u v)
(* (norm u) (norm v))))
(define (dot-prod u v)
(fold-left + 0 (map * u v)))
(define (norm u)
(sqrt (fold-left (lambda (acc x) (+ acc (* x x)))
0
u)))
This is linear in time complexity, but it could be improved by a constant factor by passing over the input only once. Scheme provides a named let construct that can be used to bind a name to a procedure; this is convenient here as it provides a simple mechanism for building the dot product and norms:
(define (cos-sim-2 u v)
(let iter ((u u)
(v v)
(dot-product 0)
(U^2 0)
(V^2 0))
(if (null? u)
(/ dot-product (sqrt (* U^2 V^2)))
(let ((x (car u))
(y (car v)))
(iter (cdr u)
(cdr v)
(+ dot-product (* x y))
(+ U^2 (* x x))
(+ V^2 (* y y)))))))
Both of these procedures assume that the input lists have the same length; it might be useful to add some validation code that checks this. Note that fold-left is standard in R6RS Scheme, but other standards rely on SRFIs for this, and some implementations may use different names, but the fold-left functionality is commonly available (perhaps as foldl or reduce).
It is possible to solve the problem in Common Lisp using either of the basic methods shown above, though in Common Lisp you would use labels instead of named let. But it would be typical to see a Common Lisp solution using the loop macro. The Common Lisp standard does not guarantee tail call elimination (though some implementations do support that), so explicit loops are seen much more often than in Scheme. The loop macro is pretty powerful, and one way that you could solve this problem while passing over the input lists only once is this:
(defun cos-sim (u v)
(loop :for x :in u
:for y :in v
:sum (* x y) :into dot-product
:sum (* x x) :into u2
:sum (* y y) :into y2
:finally (return (/ dot-product (sqrt (* u2 y2))))))
Here are some sample interactions:
Scheme (Chez Scheme):
> (cos-sim-1 '(1 0 0) '(1 0 0))
1
> (cos-sim-1 '(1 0 0) '(-1 0 0))
-1
> (cos-sim-1 '(1 0 0) '(0 1 0))
0
> (cos-sim-1 '(1 1 0) '(0 1 0))
0.7071067811865475
> (cos-sim-2 '(1 0 0) '(1 0 0))
1
> (cos-sim-2 '(1 0 0) '(-1 0 0))
-1
> (cos-sim-2 '(1 0 0) '(0 1 0))
0
> (cos-sim-2 '(1 1 0) '(0 1 0))
0.7071067811865475
Common Lisp:
CL-USER> (cos-sim '(1 0 0) '(1 0 0))
1.0
CL-USER> (cos-sim '(1 0 0) '(-1 0 0))
-1.0
CL-USER> (cos-sim '(1 0 0) '(0 1 0))
0.0
CL-USER> (cos-sim '(1 1 0) '(0 1 0))
0.70710677
A simple option is to translate the Python version literally to Hy, like this:
(defn cos_sim [A B]
(import math :as _math)
(setv [n da db d] [0 0 0 0])
(for [[a b] (zip A B)]
(+= n (* a b))
(+= da (* a a))
(+= db (* b b)))
(setv
da (_math.sqrt da)
db (_math.sqrt db)
d (* da db))
(/ n (+ d 1e-32)))
I think your proposed solution is fairly 'lispy': build several short, easy to read functions that combine into your solution. EG:
(defun n (A B)
(sqrt (reduce #'+ (map 'list #'* A B))))
(defun da (A)
(sqrt (reduce #'+ (map 'list #'* A A))))
(defun db (B)
(sqrt (reduce #'+ (map 'list #'* B B))))
(defun cos-sim (A B)
(let ((n (n A B))
(da (da A))
(db (db B)))
(/ (* n n) (+ (* da db) 1e-32)))
But, notice that n, da, and db look very similar. We can see if we can make those a single function, or macro. In this case, a function with an optional second list parameter is easy enough. (And note that I've defined n in a slightly weird way to emphasize this, but we might prefer not to take a square root and then square it for our final calculation. This would be easy to change by checking for passing the optional parameter (included as B-p below); I chose to move the square root inside the combined function) Anyway, this gives us:
(defun d (A &optional (B A B-p))
(reduce #'+ (map 'list #'* A B)))
(defun cos-sim (A B)
(let ((n (d A B))
(da (sqrt (d A)))
(db (sqrt (d B))))
(/ n (+ (* da db) 1e-32))))
Alternately, using Loop is very Common Lisp-y, and is more directly similar to the python:
(defun cos-sim (A B)
(loop for a in A
for b in B
sum (* a b) into n
sum (* a a) into da
sum (* b b) into db
finally (return (/ n (+ (sqrt (* da db)) 1e-32)))))
Here is a fairly natural (I think) approach in Racket. Essentially this is a process of folding a pair of sequences of numbers, so that's what we do. Note that this uses no explicit assignment, and also pulls the square root up a level (sqrt(a) * sqrt(b) = sqrt(a*b) as taking roots is likely expensive (this probably does not matter in practice). It also doesn't do the weird adding of a tiny float, which I presume was an attempt to coerce a value which might not be a float to a float? If so that's the wrong way to do that, and it's also not needed in a language like Racket (and most Lisps) which strive to do arithmetic correctly where possible.
(define (cos-sim a b)
;; a and b are sequences of numbers
(let-values ([(a^2-sum b^2-sum ab-sum)
(for/fold ([a^2-running 0]
[b^2-running 0]
[ab-running 0])
([ai a] [bi b])
(values (+ (* ai ai) a^2-running)
(+ (* bi bi) b^2-running)
(+ (* ai bi) ab-running)))])
(/ ab-sum (sqrt (* a^2-sum b^2-sum)))))
You can relatively easily turn this into typed Racket:
(define (cos-sim (a : (Sequenceof Number))
(b : (Sequenceof Number)))
: Number
(let-values ([(a^2-sum b^2-sum ab-sum)
(for/fold ([a^2-running : Number 0]
[b^2-running : Number 0]
[ab-running : Number 0])
([ai a] [bi b])
(values (+ (* ai ai) a^2-running)
(+ (* bi bi) b^2-running)
(+ (* ai bi) ab-running)))])
(/ ab-sum (sqrt (* a^2-sum b^2-sum)))))
This probably is no faster, but it is fussier.
This might be faster though:
(define (cos-sim/flonum (a : (Sequenceof Flonum))
(b : (Sequenceof Flonum)))
: Flonum
(let-values ([(a^2-sum b^2-sum ab-sum)
(for/fold ([a^2-running : Flonum 0.0]
[b^2-running : Flonum 0.0]
[ab-running : Flonum 0.0])
([ai a] [bi b])
(values (+ (* ai ai) a^2-running)
(+ (* bi bi) b^2-running)
(+ (* ai bi) ab-running)))])
(/ ab-sum (assert (sqrt (* a^2-sum b^2-sum)) flonum?))))
I have not checked it is however.
Your Hy example is already linear time. None of the nested loops multiply their number of iterations based on the length of input. It could be simplified to make this easier to see
(import math)
(defn dot [a b]
(sum (map * a b)))
(defn l2norm [a]
(math.sqrt (dot a a)))
(defn cossim [a b]
(/ (dot a b) (* (l2norm a) (l2norm b))))
I think this version is clearer than the Python version, because it's closer to the math notation.
Let's also inline the l2norm to make the number of loops easier to see.
(defn cossim [a b]
(/ (dot a b)
(* (math.sqrt (dot a a))
(math.sqrt (dot b b)))))
Python's map() is lazy, so the sum() and map() together only loop once. You effectively have three loops, one for each dot, and none of them are nested. Your Python version had one loop, but it was doing more calculations each iteration. Theoretically, it doesn't matter if you calculate row-by-row or column-by-column: multiplication is commutative, either rows by columns or columns by rows are the same number of calculations.
However, in practice, Python does have significant overhead for function calls, so I would expect the Hy version using higher-order functions to be slower than the Python version that doesn't have any function calls in the loop body. This is a constant factor slowdown, so it's still linear time.
If you want fast loops for calculations in Python, put your data in a matrix and use Numpy.

How do I find the number of characters in a string using scheme programming language?

I used string-length to get the number of characters but I am having difficulties in defining a recursive function. Should I convert the string to a list and then count the elements?
There's no useful way of doing this recursively (or even tail recursively): strings in Scheme are objects which know how long they are. There would be such an approach in a language like C where strings don't know how long they are but are delimited by some special marker. So for instance if (special-marker? s i) told you whether the i'th element of s was the special marker object, then you could write a function to know how long the string was:
(define (silly-string-length s)
(let silly-string-length-loop ([i 1])
(if (special-marker? s i)
(- i 1)
(silly-string-length-loop (+ i 1)))))
But now think about how you would implement special-marker? in Scheme: in particular here's the obvious implementation:
(define (special-marker? s i)
(= i (+ (string-length s) 1)))
And you can see that silly-string-length is now just a terrible version of string-length.
Well, if you wanted to make it look even more terrible, you could, as you suggest, convert a string to a list and then compute the length of the lists. Lists are delimited by a special marker object, () so this approach is reasonable:
(define (length-of-list l)
(let length-of-list-loop ([i 0]
[lt l])
(if (null? lt)
i
(length-of-list-loop (+ i 1) (rest lt)))))
So you could write
(define (superficially-less-silly-string-length s)
(length-of-list
(turn-string-into-list s)))
But, wait, how do you write turn-string-into-list? Well, something like this perhaps:
(define (turn-string-into-list s)
(let ([l (string-length s)])
(let loop ([i 0]
[r '()])
(if (= i l)
(reverse r)
(loop (+ i 1)
(cons (string-ref s i) r))))))
And this ... uses string-length.
What is the problem with?
(string-length string)
If the question is a puzzle "count characters in a string without using string-length",
then maybe:
(define (my-string-length s)
(define (my-string-length t n)
(if (string=? s t) n
(my-string-length
(string-append t (string (string-ref s n))) (+ n 1))))
(my-string-length "" 0))
or:
(define (my-string-length s)
(define (my-string-length n)
(define (try thunk)
(call/cc (lambda (k)
(with-exception-handler (lambda (x)
(k n))
thunk))))
(try (lambda ()
(string-ref s n)
(my-string-length (+ n 1)))))
(my-string-length 0))
(but of course string-ref will be using the base string-length or equivalent)

Creating a number string from list of numbers in scheme

So I've just figured out that you can use string->number to convert string 365 into int 365. But now I have another question:
How do I take, for example, (1 2 3), and convert it to string 123 so I can apply string->number to it? Any help would be appreciated. Thanks!
If it helps: I am using drracket 6.0
I'm going to answer your original question, not your current one, which is just one possible solution approach.
There are a number of ways to solve this. One way, like you mentioned in this question, is to convert the incoming list of numbers into strings, then concatenating them:
(require srfi/13)
(define (number-concatenate nums)
(string->number (string-concatenate (map number->string nums))))
Here's another approach, that does not involve conversion to strings first:
(require srfi/1 srfi/26)
(define (number-concatenate nums)
(define (expand num)
(if (< num 10)
(list num)
(unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) num)))
(fold (lambda (num result)
(fold (lambda (digit result)
(+ digit (* result 10)))
result (expand num)))
0 nums))
If you have array of numbers you can do like this(javascript code)-
[1,2,3].join('');
o/p=>"123"

Scheme list of strings

my function in scheme looks like this
(define (func1 input)
(let kloop ((x 6))
(let ((act (string-copy (func2 input2))))
(if (eq? act "") (display "null") (display act))
(if (> x 0) (kloop (- x 1)))))))
func2 return some string which is stored in act. Now I have to create a list of all strings returned by this function. Here above, I am just displaying those strings. I tried different approaches, but nothing is working out. I tried using append and cons.
Please suggest.
Your last if is missing the else case, which is where one would expect the return value of the function to be.
You don't mention how you've tried to use append and cons, but a common pattern is to pass an accumulating parameter around in the loop:
(define (five input)
(let loop ((x 5) (outputs '()))
(if (> x 0)
(loop (- x 1) (cons input outputs))
outputs)))
> (five "yes")
'("yes" "yes" "yes" "yes" "yes")
You are calling func2 on input six times. Does it return a different value each time? If not, this works:
(define (func1 input)
(make-list 6 (func2 input)))
The question is a bit confusing, you should provide a sample of the expected output for a given input. And why the empty string is treated differently in your code? apparently the recursion should advance on the value of x, not the value of the string returned by func2. Also, why are you copying the string? seems unnecessary.
Assuming that the named let is used just for keeping track of the number of iterations, this solution seems aligned with your intent, as this will return a 6-element list of all strings returned by func2
(define (func1 input)
(let kloop ((x 6))
(if (zero? x)
'()
(cons (func2 input)
(kloop (- x 1))))))
But we can be smarter and use the named let to give a tail-recursive solution, which is more efficient:
(define (func1 input)
(let kloop ((x 6)
(acc '()))
(if (zero? x)
acc
(kloop (- x 1)
(cons (func2 input)
acc)))))

Scheme - list functions with filter

I am currently working on a homework assignment with MIT scheme, and have come across a few problems that are supposedly very short, though I'm a bit confused as to how to implement some of them.
One problem asks me to write a function that returns a list with all the integers removed. I did manage to solve that,
(define (f2a lst) (map (lambda(x) (remove number? x)) lst))
though I'm confused as to how I can rewrite it to not use remove, but rather use a filter.
*note: (f2a '(("a" 1 "b") (2 "c") (-1 "d") (-2))) returns '(("a" "b") ("c") ("d"))
The other two problems are ones to which I haven't found any solutions.
They ask me to write a function that returns a list with all positive odd and negative even integers removed. For example,
(f2b '(("a" 1 "b") (2 "c") (-1 "d") (-2)))
returns
(("a" "b") (2 "c") (-1 "d"))
I have some code down that is incorrect, but I feel shows how I have tried to approach solving this one:
(define (f2b lst)
(lambda(x)
(cond ((and (positive? x) (odd? x)) (filter x lst))
((and (negative? x) (even? x)) (filter x lst))
(else "this should never print"))))
The last problem simply asks for a function that returns a string consisting of all strings appended together in a list. (f2c '(("a" 1 "b") (2 "c") (-1 "d") (-2))) returns "abcd".
I almost managed to figure this one out, but got stuck when it kept returning strange values. This is the code I have:
(define (f2c lst)
(lambda(x)
(map (lambda (x) (filter string? x)) lst)
(list x))
(string-append (car lst) (cdr lst)))
In terms of higher-order syntax, I'm limited to map, filter, accumulate and sum. I am not asking for a direct answer, but rather some help for me to figure out what I need to do. What am I doing wrong with my code? Any assistance given with this is very much appreciated. Thank you.
The structure of the input and the desired output is identical in the first two problems; the only thing that differs is the predicate on when/when-not to remove an element. For the second case it would be:
(define (f2b lst)
(map (lambda (sublst)
(remove (lambda (x)
(and (number? x)
(or (and (positive? x) (odd? x))
(and (negative? x) (even? x)))))
sublst))
lst))
Since only the predicate differs you can generalize this as:
(define (f2x predicate)
(lambda (lst)
(map (lambda (sublst) (remove predicate sublst)) lst)))
(define f2a (f2x number?))
(define f2b (f2x (lambda (x)
(and (number? x)
(or (and (positive? x) (odd? x))
(and (negative? x) (even? x))))))
For your last problem, you can use the result of the first problem as:
(define (f2c lst)
(apply string-append (apply append (f2a list))))
Also, note that your syntax for f2b and f2a is incorrect. You are using
(define (func arg)
(lambda (x) ...))
which means that (func arg) returns a function which isn't what you want.

Resources