I need a subroutine for my program written in scheme that takes an integer, say 34109, and puts it into a list with elements 3, 4, 1, 0, 9. The integer can be any length. Does anyone have a trick for this? I've thought about using modulo for every place, but I don't think it should be that complicated.
The simplest way I can think of, is by using arithmetic operations and a named let for implementing a tail-recursion:
(define (number->list num)
(let loop ((num num)
(acc '()))
(if (< num 10)
(cons num acc)
(loop (quotient num 10)
(cons (remainder num 10) acc)))))
Alternatively, you can solve this problem using string operations:
(define char-zero (char->integer #\0))
(define (char->digit c)
(- (char->integer c) char-zero))
(define (number->list num)
(map char->digit
(string->list (number->string num))))
This can be compressed into a single function, but I believe it's easier to understand if we split the problem in subparts as above.
(define (number->list num)
(map (lambda (c) (- (char->integer c) (char->integer #\0)))
(string->list
(number->string num))))
Anyway, the results are as expected:
(number->list 34109)
> '(3 4 1 0 9)
Something like this:
(define (num2list-helper num lst)
(cond ((< num 10) (cons num lst))
(else (num2list-helper (floor (/ num 10)) (cons (modulo num 10) lst)))))
(define (num2list num)
(num2list-helper num '()))
(num2list 1432)
As itsbruce commented you can hide helper function inside main one:
(define (num2list num)
(define (num2list-helper num lst)
(cond ((< num 10) (cons num lst))
(else (num2list-helper (floor (/ num 10)) (cons (modulo num 10) lst)))))
(num2list-helper num '()))
(num2list 1432)
to be continued...
I'm not a fan of manual looping, so here's a solution based on unfold (load SRFI 1 and SRFI 26 first):
(define (digits n)
(unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) n))
This returns an empty list for 0, though. If you want it to return (0) instead, we add a special case:
(define (digits n)
(case n
((0) '(0))
(else (unfold-right zero? (cut modulo <> 10) (cut quotient <> 10) n))))
Of course, you can generalise this for other bases. Here, I implement this using optional arguments, so if you don't specify the base, it defaults to 10:
(define (digits n (base 10))
(case n
((0) '(0))
(else (unfold-right zero? (cut modulo <> base) (cut quotient <> base) n))))
Different Scheme implementations use different syntaxes for optional arguments; the above uses Racket-style (and/or SRFI 89-style) syntax.
Related
Working on this program that's supposed to take a vector of integers as input and return the one with the longest integer. Example (vector 20 738 5942 125) and would return 4 as its the longest one. I'm pretty sure I have most of this done the only issue I have is in the conditional as I have to call an outside function (count-integers), this is what I have so far:
(require while)
(define (empty-VINT? low high) (> low high))
(define (count-integers n)
(cond [(< n 10) 1]
(else(+ 1 (count-integers [/ n 10])))))
(define (count-digits V)
(local [
(define x (void))
(define accum (void))
(define largest 0)]
(begin
(set! x (vector-length V))
(set! accum 0)
(while (< accum (vector-length V))
(cond [(empty-VINT? x accum) accum]
[(> (count-integers (vector-ref V accum) largest)
(add1 x) accum(vector-ref V accum))]
[else add1 accum])))))
Right now when its run, I get this message: cond: expected a clause with a question and an answer, but found a clause with only one part. Any suggestions would be great, thanks
First of all, it's not clear what do you want to return. 4 isn't the longest integer (that's 5942), 4 is a maximal digit count among integers in given vector.
Secondly, your code isn't idiomatic and without your comment, it's very hard to say what's going on. Programming in functional languages requies functional way of thinking. Forget about while, set!, void, local and nested define and instead spend some time learning about apply, map, filter and foldl.
I would solve this problem like this:
(define (digits number)
(string-length (number->string number)))
(define (max-digit-count vec)
(apply max (map digits (vector->list vec))))
(max-digit-count (vector 20 738 5942 125))
=> 4
From comments:
Design and implement a function to find the number of digits in the longest integer in a (vectorof integer) ...
use ... while loops
So a plan (design) might be:
count-digits: integer -> natural
max-digit-count: (vectorof integer) -> natural
..something while something max count-digits something ???
Implementing count-digits seems straightforward (but
integers can be negative, and in Racket (integer? 123.000) is true).
#lang racket
(define (count-digits int) ;; Integer -> Natural
;; produce count of digits in int
(string-length (number->string (abs (exact-truncate int)))))
As #Gwang-Jin Kim mentions, while could be defined:
(define-syntax-rule (while condition body ...)
;; From: https://stackoverflow.com/questions/10968212/while-loop-macro-in-drracket
(let loop ()
(when condition
body ...
(loop))))
and then one could use it:
(define (max-digit-count vec) ;; VectorOfInteger -> Natural
;; produce maximum of digit counts of vec elements
(define vx 0)
(define acc 0)
(while (< vx (vector-length vec))
(set! acc (max accum (count-digits (vector-ref vec vx))))
(set! vx (add1 vx)))
acc)
(max-digit-count (vector 20 -738.00 5942 125)) ;=> 4
One of the problems with while is that it can't produce a value (where would it come
from if the condition is false on entry?)
If one "enhanced" while a bit:
(define-syntax-rule (while< x-id limit a-id a-init update)
;; "while loop" incrementing x-id from 0 to limit-1, updating a-id
(let loop ([x-id 0] [a-id a-init])
(if (< x-id limit)
(loop (add1 x-id) update)
a-id)))
max-digit-count could be neater:
(define (max-digit-count vec) ;; VectorOfInteger -> Natural
;; produce maximum of digit counts of vec elements
(while< vx (vector-length vec)
acc 0 (max acc (count-digits (vector-ref vec vx)))))
#MartinPuda's answer is quite good.
I would have defined:
(define (digits n (acc 0))
(if (< n 1)
acc
(digits (/ n 10) (+ acc 1))))
(define (max-digits lst)
(digits (car (sort lst >))))
To apply it:
(max-digits (vector->list (vector 20 738 5942 125)))
Why you should not use while
Using while would force you to mutate variable values. It is much more "natural" for lisp languages to follow the functional style (recursive functions instead of while loops or other loops) rather than the imperative style with mutation of variables.
That is why while is not in the lisp languages.
But if you want to use it:
(define-syntax-rule (while condition body ...)
;; From: https://stackoverflow.com/questions/10968212/while-loop-macro-in-drracket
(let loop ()
(when condition
body ...
(loop))))
(define (digits n (acc 0))
(cond ((< n 1) acc)
(else (digits (/ n 10) (+ acc 1)))))
(define (max-digits lst)
(let ((max-digit 0))
(while (not (null? lst))
(let ((digit (digits (car lst))))
(when (< max-digit digit)
(set! max-digit digit))
(set! lst (cdr lst))))
max-digit))
Then you can try:
> (max-digits (vector->list v))
4
> (max-digits '(1111 123456 2345 34))
6
Prefer let over define
Why? Because if you use let, you can control the scope of the to-be-mutated variable very precisely. You can define in your definition, from where on your variable canNOT have any effect on your code (since its scope ended at some point). While with define you don't have this fine-grained control. (Or this control is implicit not explicite like with let). You could delete/unbind the variable explicitely but that is rarely done in real life.
Therefore, in Lisp, for variable declarations use whenever possible let, especially whenever you deal with mutated variables.
All imperative = declarations should be in Lisp languages let expressions!
You can use function arguments instead of let-definitions, because they are anyway implemented using lets
Just you save syntactically some lines - and the fewer lines you occupy the cleaner the code.
#lang racket
(define (digits n)
(string-length (number->string n)))
(define (max-digit a b)
(if (< (digits a) (digits b)) b a))
(define (max-digits lst (res ""))
(while (not (null? lst))
(set! res (max-digit res (car lst)))
(set! lst (cdr lst)))
(digits res))
****What I tried****
(define(help num)
(if(= num 1)
num
(cons(num (help( - num 1))))))
;i called this defination in the bottom one
(define (list-expand L)
(cond
[(empty? L)'()]
[(=(car L)1)(cons(car L)(list-expand (cdr L)))]
[(>(car L)1) (cons(help(car L)(list-expand(cdr L))))]))
In the help procedure, the base case is incorrect - if the output is a list then you must return a list. And in the recursive step, num is not a procedure, so it must not be surrounded by brackets:
(define (help num)
(if (<= num 0)
'()
(cons num (help (- num 1)))))
And in list-expand, both recursive steps are incorrect. You just need to test whether the list is empty or not, calling help with the correct number of parameters; use append to combine the results, because we're concatenating sublists together:
(define (list-expand L)
(if (empty? L)
'()
(append (help (car L)) (list-expand (cdr L)))))
That should work as expected, but please spend some time studying Scheme's syntax, you still have trouble with the basics, for instance, when and where to use brackets...
(list-expand '(3 2))
=> '(3 2 1 2 1)
Just for fun - a non-recursive solution in Racket:
(append-map (lambda (n) (stream->list (in-range n 0 -1))) '(3 2))
;; or:
(append-map (lambda (n) (for/list ((x (in-range n 0 -1))) x)) '(3 2))
Returning:
'(3 2 1 2 1)
If i have a scheme code that generates the following result: (i'm using cons)
'((1 . 0) . 0)
How can i take this, and just simply display 100 as if it were just one integer number and not a list presented with those dots and parenthesis?
Thanks!
EDIT:
my full code:
(define (func X)
(if ( <= X 3 )
X
(cons (modulo X 4) (func(floor(/ X 4)) ))
))
If I understand correctly, you're trying to convert a number from base 10 to base 4, and then display it as a number, but there are several problems with your implementation.
You're building a list as output - but that's not what you want, you want a number. Also, you're traversing the input in the wrong order, and that's not the correct way to find the quotient between two numbers. Perhaps this will help:
(define (func X)
(let loop ((n X) (acc 0) (mult 1))
(if (< n 4)
(+ (* mult n) acc)
(loop (quotient n 4)
(+ (* mult (modulo n 4)) acc)
(* mult 10)))))
Alternatively, you could output a string to stress the fact that the output is not in base 10:
(define (func X)
(let loop ((n X) (acc ""))
(if (< n 4)
(string-append (number->string n) acc)
(loop (quotient n 4)
(string-append (number->string (modulo n 4)) acc)))))
It'll work as expected:
(func 16)
=> 100
Oscar Lopez's answer is excellent. I can't help adding that this problem doesn't need the "loop" construct:
;; translate a string to a base-4 string.
(define (func n)
(cond [(< n 4) (number->string n)]
[else (string-append (func (quotient n 4))
(number->string (modulo n 4)))]))
I'm trying to create a function that takes in user input, x, and displays all of the numbers from 1 up to x. Not quite sure where to go from here:
(define (iota x)
(if (>= x 1)
(display
;; Takes a number n
;; and returns a list with 1..n
;; in order.
(define (make-list n)
(let loop ((n n) (accumulator '()))
(if (zero? n)
accumulator
(loop (- n 1) (cons n accumulator)))))
;; prints data and adds
;; a newline
(define (println x)
(display x)
(newline))
;; prints 1..n by applying println
;; for-each element over the list 1..n
(define (iota n)
(for-each println (make-list n)))
Basically you want to use recursion. So think of it was counting up. As you count up either you've added enough numbers and you are done building your list or you need to add the current number to your list and go on to the next number.
Look at the following code:
(define (range-2 next-num max-num cur-list)
;;if we've added enough numbers return
(if (> next-num max-num)
cur-list
;; otherwise add the current number to the list and go onto the next one
(range-2
(+ 1 next-num)
max-num
(append cur-list (list next-num))
)))
But to get the function you wanted you need to start off with the constants you specified (ie 1), so lets create a convenience function for calling range with the starter values you need to set up the recursion, sometimes called priming the recursion:
(define (range X)
(range-2 1 X `() ))
You could do it without the second function using lambda, but this is pretty common style from what I've seen.
Once you've constructed a list of the numbers you need you just display it using
(display (range 10))
If you're using Racket you're in luck, you can use iterations and comprehensions, for instance in-range:
(define (iota x)
(for ([i (in-range 1 (add1 x))])
(printf "~a " i)))
Or for a more standard solution using explicit recursion - this should work in most interpreters:
(define (iota x)
(cond ((positive? x)
(iota (- x 1))
(display x)
(display " "))))
Either way, it works as expected:
(iota 10)
=> 1 2 3 4 5 6 7 8 9 10
(define iota2
(lambda (y)
(let loop ((n 1))
(if (<= n y)
(cons n (loop (+ n 1)))
'()))))
(define (iota x)
(if (>= x 1)
(begin
(iota (- x 1))
(display x)
(newline))))
I have 2 numbers let's say number1=5 and number2=3 and I want to create a list in this form
((1(1 2 3)) (2(1 2 3)) (3(1 2 3)) (4(1 2 3)) (5(1 2 3)))
So the number1 indicates the number of the elements in the list and number2 indicates the total elements that will be as the second part of every element..
I have smth like this untill now
(define mylist '())
(define (pushlist item item2)
(do ((j 1 (+ j 1))) ((> j item2))
(set! mylist(list mylist (list item j)))))
(define (createlist number number2)
(do ((j 1 (+ j 1))) ((> j number))
(pushlist j number2)
))
(createlist 5 3)
Unfortunately it doesn't work.. It doesn't give the result I want.. It gives me this (((((((((((((((() (1 1)) (1 2)) (1 3)) (2 1)) (2 2)) (2 3)) (3 1)) (3 2)) (3 3)) (4 1)) (4 2)) (4 3)) (5 1)) (5 2)) (5 3))
There are many ways to solve this problem - for example, using explicit recursion, or using higher-order procedures. Your approach is not recommended, in Scheme you should try to avoid thinking about loops and mutation operations. Although it is possible to write such a solution, it won't be idiomatic. I'll try to explain how to write a more idiomatic solution, using explicit recursion first:
; create a list from i to n
(define (makelist i n)
(if (> i n)
'()
(cons i (makelist (add1 i) n))))
; create a list from i to m, together with
; a list returned by makelist from 1 to n
(define (makenumlist i m n)
(if (> i m)
'()
(cons (list i (makelist 1 n))
(makenumlist (add1 i) m n))))
; call previous functions
(define (createlist number1 number2)
(makenumlist 1 number1 number2))
Now, an even more idiomatic solution would be to use higher-order procedures. This will work in Racket:
; create a list from i to n
(define (makelist n)
(build-list n add1))
; create a list from i to m, together with
; a list returned by makelist from 1 to n
(define (makenumlist m n)
(build-list m
(lambda (i)
(list (add1 i) (makelist n)))))
; call previous functions
(define (createlist number1 number2)
(makenumlist number1 number2))
See how we can avoid explicit looping? that's the Scheme way of thinking, the way you're expected to solve problems - embrace it!
I don't think that your pushlist procedure is doing what you you expect it to.
(define (pushlist item item2)
(do ((j 1 (+ j 1)))
((> j item2))
(set! mylist (list mylist (list item j)))))
If you have a list (x y z) and you want to push a new value v into it, you'd do
(set! lst (cons v lst))
because (cons v (x y z)) == (v x y z). By doing
(set! mylist (list mylist (list item j)))
you're making mylist always have exactly two elements, where the first is a deeper and deeper nested list. Óscar López's answer gives a more idiomatic approach to this problem. Here's a similar idiomatic approach:
(define (range n)
; returns a list (1 ... n)
(let rng ((n n) (l '()))
(if (zero? n)
l
(rng (- n 1) (cons n l)))))
If the sublists (1 ... n) can all be the same list (i.e., the actual list object is the same), then you can create it just once:
(define (createlist m n)
(let ((sublist (range n)))
(map (lambda (main)
(list main sublist))
(range m))))
Otherwise, if they need to be distinct, you can generate one for each of 1 ... m:
(define (createlist m n)
(map (lambda (main)
(list main (range n)))
(range m)))