2

I am trying to implement two functions : subterm and replace.

  1. subterm takes two lists as arguments and prints the element in the first list that is reached after exhausting the second list.

For example, calling

(subterm '(1 2 (3 4 5) (6 (7 (8) 9 10))) '(4 2 2 1))

should return

8

I have come up with the following function which prints the nth element in the list :

(define (subterm list n)                   
  (cond 
    ((null? list) '())             
    ((= n 1) (car list))              
    (else (subterm (cdr list) (- n 1)))))
  1. replace takes 3 lists and returns the result of replacing the reached value with the rest of the list unchanged.

for example calling :

 (replace '(1 2 (3 4 5) (6 (7 (8) 9 10))) '(11 12) '(4 2 2 1))

should return :

'(1 2 (3 4 5) (6 (7 ((11 12)) 9 10)))

Again, I came up with this code which replaces the nth element in the first list with the second list, leaving the rest of the first list unchanged :

#lang racket
(define (replace list elem n)
  (cond
    ((empty? list) empty)
    ((eq? n 1) (cons elem (cdr list)))
    (#t (cons (car list) (replace (cdr list) elem (- n 1))))))

How do I modify these functions to take in two lists?

Edit 1: Some examples:

> (subterm '(1 2 3 4 5) '(3))
3

> (subterm '(1 2 3 4 5) '(2))
2

> (subterm '(1 2 (3 4 5) 6 7) '(3 2))
4

Consider this example:

> (subterm '(1 2 (3 4 5) (6 (7 (8) 9 10))) '(4 2 2 1))
8

In the above example, subterm takes 2 lists. Then it reads the second list. The second list basically tells subterm to return the 1st element (8) of the 2nd element ((8)) of the 2nd element (7 (8) 9 10) of the 4th element (6 (7 (8) 9 10) of the first list (1 2 (3 4 5) (6 (7 (8) 9 10))).

> (subterm '1 '())
1

> (subterm '(1 2 (3 4 5) (6 (7 (8) 9 10))) '())
'(1 2 (3 4 5) (6 (7 (8) 9 10)))

> (replace '(1 2 3 4 5) '(6 7 8) '(3))
'(1 2 (6 7 8) 4 5)

> (replace '(1 2 3 4 5) '(6 7 8) '(2))
'(1 (6 7 8) 3 4 5)

Consider this example:

> (replace '(1 2 (3 4 5) 6 7) '(8 9) '(3 2))
'(1 2 (3 (8 9) 5) 6 7)

replace takes in three lists: first list is the list in which elements have to be replaced. The second list contains the new elements which have to be put into the first list. The third list contains the positions where the elements have to be replaced. So, it basically replaced the 2nd element (4) of the 3rd element (3 4 5) of the first list (1 2 (3 4 5) 6 7).

> (replace '(1 2 (3 4 5) (6 (7 (8) 9 10))) '(11 12) '(4 2 2 1))
'(1 2 (3 4 5) (6 (7 ((11 12)) 9 10)))

> (replace '(1 2 (3 4 5) (6 (7 (8) 9 10))) 1000 '(4 2 2 1))
'(1 2 (3 4 5) (6 (7 (1000) 9 10)))

> (replace '(1 2 (3 4 5) (6 (7 (8) 9 10))) 'x '())
'x

> (replace '1 '(2 3 4) '())
'(2 3 4)
  • What are you refering to when you say _these functions_ ? And is it possible to make `replace`'s arity equal to 2? It seems to me that you're missing something to explain. – David Merinos Apr 07 '15 at 02:31
  • @DavidMerinos: These functions meaning subterm and replace. I added a few examples for clarity. Thanks! – no10downingstreet Apr 07 '15 at 03:04
  • Ok. I get what the functions do, but what exactly is your problem? Do you want `replace` to take in **only** two lists? – David Merinos Apr 07 '15 at 03:19
  • @DavidMerinos: No, I want replace and subterm to work as in the examples. I have written similar functions but they can only take one list and one number as arguments. – no10downingstreet Apr 07 '15 at 03:25
  • @DavidMerinos: In both functions, the second list is used to go downward in a tree-like fashion through the first list. At each level in the first list, one numeric atom from the second list is consumed. This atom will indicate the left-to-right ordinal position to continue from. subterm should return the value (atom or list) that is reached when the second list has been exhausted. replace should return the result of replacing the reached value, and the rest of the first list should remain unchanged. – no10downingstreet Apr 07 '15 at 03:54

3 Answers3

1

First of all, you're using the name subterm for two different functions. Let's call the version you provided a code example for list-ref, and make the (car list) case happen when n = 0 instead of 1:

(define (list-ref list n)                   
  (cond 
    ((null? list) '())             
    ((= n 0) (car list))              
    (else (list-ref (cdr list) (- n 1)))))

As it turns out, list-ref is already in the racket library, so you shouldn't really have to implement it in the first place. So using that, your subterm is trivial:

(define (subterm main-list path)
   (match path
     ('() #f)
     ((list n) (list-ref main-list (sub1 n)))
     ((cons n rest) (subterm (list-ref main-list (sub1 n)) rest))))
Throw Away Account
  • 2,593
  • 18
  • 21
0

I tried to code the replace procedure. With my knowledge I can say this is a hard one. However I managed to make it work at least with the example you gave. You could read it, try to understand it and then try to modify it to work with any other list. I believe you'll need an extra function to make it work properly.

#lang racket
(require racket/trace)
(define (replace list elem n)
  (cond
    ((empty? list) empty)
    ((eq? n 1) (cons elem (cdr list)))
    (#t (cons (car list) (replace (cdr list) elem (- n 1))))))

(define replace-with-lists
  (λ (items replacement path res aux)
     (letrec ([splits (list-split-at items (car path) '())])
    (cond 
      ((empty? (cdr path)) 
;       (append
;        (car (list-ref res 0))
;       (list (append
;        (car (list-ref res 1))
;        (list (append (car aux) 
;               (replace (list-ref aux 1) replacement (car path))
;               (list-ref aux 2)))))))
       (let ([result (replace splits replacement 2)])
      (replace aux
               (append (car result)
              (list (cadr result))
              (caddr result)
              )
               2)))

      (else
       (replace-with-lists
             (list-ref splits 1)
             replacement
             (cdr path)
             (foldr cons (list (list 
                          (list-ref splits 0)
                          (list-ref splits 2)))
                    res)
             splits
             )))
    ))
    )

(define list-split-at
  (λ (lst place res)
    (cond
      ((empty? lst) res)
      ((= 1 place) (foldl cons
                          (list (cdr lst))
                          (foldr cons (list res) (list (car lst)))
                          ))
      (else
       (list-split-at (cdr lst) (- place 1) (foldr cons (list (car lst)) res))
       )
      )))
(trace replace-with-lists)
David Merinos
  • 1,195
  • 1
  • 14
  • 36
0

Ok, I am in your programming languages class, and I am aware that this assignment is due tomorrow, so I don't want to help too much, or give you the answer. I will do my best to give you some hints in case you are still struggling. The following hints are for the replace function.

First, you need a base case. We are given this with the following

(replace '(1 2 (3 4 5) (6 (7 (8) 9 10))) 'x '()) 'x

(replace '1 '(2 3 4) '()) '(2 3 4)

To do this, we just need a conditional statement that checks for an empty list. It is clear that if the last argument is an empty list, we need to "return" the second to last argument. (in your code this would be "elem" and "n")

Now comes the difficult part. It is really quite simply once you realize how many built in functions scheme/racket has. Here are the only ones I used, but they made solving the problem much much easier.

(append) (list) (take) (drop) (list-ref) //this one is more of a convenience than anything.

After the turn in date has passed, I will post my solution. Hope this helped.

EDIT: As this assignment was due a few minutes, I will post my solution as I don't think that would be considered cheating.

lang racket

(define (subterm term1 lat)
  (cond
    [(eqv? lat '()) term1]
    [(eqv? (car lat)1) (subterm (car term1) (cdr lat))]
    [else (subterm (cdr term1) (cons(-(car lat)1)(cdr lat)))])
  )

(define (replace term1 term2 lat)
  (cond
    [(eqv? lat '()) term2]
    [else (append(take term1 (-(car lat)1)) (list(replace (list-ref term1 (-(car lat)1)) term2 (cdr lat))) (drop term1 (car lat)))]))

Those are both functions.

user2587878
  • 121
  • 3
  • 15