Reputation: 1
As part of my assignment i have been given the task to:
Write a function that takes two lists as input, a list L1 containing characters and a list L2
containing numbers. For each of the number n contained in L2, the function will display the first
n character of the list L1. For example:
L1 '("h" "e" "l" "l" "o" "w" "o" "r" "l" "d")
L2 '(2 3 1 5 10)
Output:
h e
h e l
h
h e l l o
h e l l o w o r l d.
i know the function takes two arguments but i don't know how to apply the second the list which is like a selector,it reads each number in the second list and extracts the character in that position in the first list.
( define two-sequences
( lambda ( l1 l2 )
(for/list ([ i l1 ] [ j l2 ])
which function should i use to do this.
Upvotes: 0
Views: 440
Reputation: 820
Write a function that takes two lists as input, a list L1 containing characters and a list L2 containing numbers. For each of the number n contained in L2, the function will display the first n character of the list L1.
The required function can be written compactly using for/list
, but when learning Scheme/Racket it can be
helpful to build it with basic Scheme functions, without needing to know all the for/xxxx
variations and options.
The problem can be split into two parts: (1) produce the characters to display (2) display them as shown in the question.
This answer will show the development of (1) using a systematic design method
which can be applied to many problems like this.
require
for testing:#lang racket
(require test-engine/racket-tests)
(define L1 '("h" "e" "l" "l" "o" "w" "o" "r" "l" "d"))
(define L2 '(2 3 1 5 10))
(test)
#lang racket
(require test-engine/racket-tests)
(define L1 '("h" "e" "l" "l" "o" "w" "o" "r" "l" "d"))
(define L2 '(2 3 1 5 10))
; *stub* ;; *signature*
(define (take-multiple los lon) ;; ListOfString ListOfNatural -> (ListOf ListOfString)
;; produce, for each n in lon, first n elements of los ; *purpose statement*
'() ) ; *stub body* (valid result)
;
(check-expect (take-multiple L1 '()) '() ) ; *minimal example*
(test)
(the function is named take-multiple
because it "take"s initial elements from los multiple
times, according to the numbers in lon)
take-multiple
processes a list, so try the commonest template for that kind of argument, "natural recursion":
(define (fn lox) ;; ListOfX -> Y ; *template*: (for fn with list argument)
;; produce a Y from lox using natural recursion ;
(cond ;
[(empty? lox) ... ] ; (... = "base case value" ;; Y )
[else (.... ; (.... = "inventory fn(s)" ;; X Y -> Y )
(first lox) (fn (rest lox))) ])) ;
; *inventory fns*:
(take lox n) ;; ListOfX Natural -> ListOfX ; (included because "...first n elements of los")
(cons x lox) ;; X ListOfX -> ListOfX ; (included because required result is ListOf...)
(define (take-multiple los lon) ;; ListOfString ListOfNatural -> (ListOf ListOfString)
;; produce, for each n in lon, first n elements of los
(cond
[(empty? lon) '() ] ; '() deduced from above check-expect
[else (....
(first lon) (take-multiple los (rest lon))) ]))
This won't run, because we don't know what to replace ....
with: to work this out
(check-expect (take-multiple L1 '(2)) '( ("h" "e") ) )
So we require (.... 2 (take-multiple L1 '()))
=> '( ("h" "e") ) )
We can see that (take-multiple L1 '())
is '()
, and ("h" "e")
is (take L1 2)
so (.... (first lon)
is (cons (take los (first lon))
:
(define (take-multiple los lon) ;; ListOfString ListOfNatural -> (ListOf ListOfString)
;; produce, for each n in lon, first n elements of los
(cond
[(empty? lon) '() ]
[else (cons (take los (first lon)) (take-multiple los (rest lon))) ]))
(check-expect (take-multiple L1 '(2 3)) '( ("h" "e") ("h" "e" "l") ) )
The first function is now complete (run (take-multiple L1 L2)
to check).
To produce the required display format, use this function:
(define (display-elements lolox) ;; (ListOf (ListOfX)) ->
;; display elements of lolox with newlines between first level lists
(for-each (lambda (lox)
(for-each (lambda (x)
(display x) (display " "))
lox)
(newline))
lolox))
So (display-elements (take-multiple L1 L2))
displays:
h e
h e l
h
h e l l o
h e l l o w o r l d
>
Upvotes: 0
Reputation: 10010
In Common Lisp or emacs lisp this function you want is called elt
which gives the nth element of a list. - In Racket, you have to define it yourself:
(define (elt l n)
(cond ((empty? l) '())
((zero? n) (car l))
(else (elt (cdr l) (- n 1)))))
(elt '(a b c d e f) 3) ;;=> 'd
In every-day racket, however, one wouldn't use lists - which one has to traverse like this - but vectors - whose access via an index is direct and thus much more faster.
(vector-ref #("a" "b" "c" "d" "e" "f") 3) ;;=> "d"
#(...)
is equal to (vector ...)
and creates a vector out of the sequence.
Upvotes: 0
Reputation: 9282
You need to print the first n elements of a list. Here's how you do that:
To print the first n
elements of a list, lst
:
n
is zero print a newline;n
is 1 print the first element of lst
and a newline;n
is more than 1 print the first element of the lst
, a space, and then print n - 1
elements of the rest of lst
(hint: you can use a function you are currently writing to do this);n
is anything else then this is an error.Write this as a proceducre: call it print-n
for instance. Then the procedure which answers the question is:
(define (print-ns l ns)
(for ([n (in-list ns)])
(print-n l n)))
And
> (print-ns '("h" "e" "l" "l" "o" "w" "o" "r" "l" "d") '(2 3 1 5 10))
h e
h e l
h
h e l l o
h e l l o w o r l d
Upvotes: 0