'How can i write a function which extracts the nth element of a list?
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.
Solution 1:[1]
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:
- if
nis zero print a newline; - if
nis 1 print the first element oflstand a newline; - if
nis more than 1 print the first element of thelst, a space, and then printn - 1elements of the rest oflst(hint: you can use a function you are currently writing to do this); - if
nis 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
Solution 2:[2]
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.
Solution 3:[3]
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.
(1) Start (in DrRacket) with the example data and a 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)
(2) Add a stub with signature and purpose, and a minimal example
#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)
(3) Run: note that the test passes ("run early and often": make all tests pass)
(the function is named take-multiple because it "take"s initial elements from los multiple
times, according to the numbers in lon)
(4) Identify a template and inventory relevant to the requirement
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...)
(5) Edit the template by replacing the generic identifiers appropriately:
(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
(6) Add the next simplest example:
(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)):
(7) Complete the code and add another example to check:
(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
>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ignis volens |
| Solution 2 | |
| Solution 3 | mnemenaut |
