How to Replace elements in a nested list in Scheme - scheme

I am trying to have a list like this...
'((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6))
and replace all occurrences of a certain number.
For example when running
(replace 4 "x" '((0 1 2) (3 4 5) (6 7 8) (0 3 6) (1 4 7) (2 5 8) (0 4 8) (2 4 6)))
The Desired output is
'((0 1 2) (3 x 5) (6 7 8) (0 3 6) (1 x 7) (2 5 8) (0 x 8) (2 x 6)))
What I have tried so far is
(define (replace var player list)
(if (null? list)
'()
(if (list? (car list))
(replace var player (cdr list))
(if (equal? var (car list))
(cons player (replace var player (cdr list)))
(cons (car list) (replace var player (cdr list)))
))))
Which when I run to replace all 1's with an x the output is '(0 "x" 2)

You are on the right track, you are only missing actually applying the function on (car lst) whenever the first element is a list itself, ie:
...
(if (list? (car list))
(cons (replace var player (car list)) ;; missing this
(replace var player (cdr list)))
(if ...
Also, avoid using built-in procedures as variable names (eg. list), and when using conditionals, instead of nesting multiple if statements, use cond or its relatives that better translate to the conventional if ... else if ... else ... idea.

Related

How would I write a Scheme procedure that takes in a tree (represented as a list) and return that list with its elements reversed essentially?

I am having trouble writing a Scheme procedure that takes a tree (represented as a list) and returns a list whose elements are all the leaves of the tree arranged in right to left order.
For example, if I were to call: ( leaves '(((1 2) (3 4)) ((1 2) (3 4))) ) I would get: '(4 3 2 1 4 3 2 1)
I have the following so far, and the output is technically correct, but there is an issue with the parenthesis:
(define (leaves givenList)
(if (null? givenList) givenList
(if (list? (car givenList))
(append (leaves (cdr givenList)) (cons (leaves (car givenList)) '()))
(append (leaves (cdr givenList)) (list (car givenList))))))
The output when I call: ( leaves '(((1 2) (3 4)) ((1 2) (3 4))) ) is: (((4 3) (2 1)) ((4 3) (2 1)))
I need to get rid of the parenthesis on the inside and just get: '(4 3 2 1 4 3 2 1)
Any help or insight is greatly appreciated. Thanks!

just started learning Scheme

I don't know why this does not work. I get an error saying "Error: 1 is not a function[(anon)]"
(define (mem lst ele)
(cond ;if the list is empty return false
((null? lst) #f)
;if the first element is equal to the given element return true
;otherwise call the function with rest of the list
(else (if (= ele (car lst))
#t
(mem (cdr lst) ele)))))
(mem ’(1) ’(1 4 -2))
It works for me; how are you calling mem? I am guessing that you did something like: (mem (1 2 3 4) 1). Procedure calls always evaluate their arguments in Scheme, so in the procedure call (mem (1 2 3 4) 1) the expression (1 2 3 4) is evaluated; but lists are evaluated as if the first member is a procedure, so 1 is treated as a function; it is not, and this raises an exception.
You could quote the list: (mem (quote (1 2 3 4)) 1), or you can use the shorthand (mem '(1 2 3 4) 1). quote is a special form that does not evaluate its argument; instead it just returns whatever datum it is given. You can try this out at the REPL:
> (+ 1 2)
3
> (quote (+ 1 2))
(+ 1 2)
> '(+ 1 2)
(+ 1 2)
Here the naked expression (+ 1 2) evaluates to 3, but the quoted expressions just return the expressions given to quote. That is, (quote (+ 1 2)) evaluates to the expression (+ 1 2), not to the result of evaluating the expression (+ 1 2). In the case of (1 2 3 4):
> (quote (1 2 3 4))
(1 2 3 4)
> '(1 2 3 4)
(1 2 3 4)
> (1 2 3 4)
Exception: attempt to apply non-procedure 1
Type (debug) to enter the debugger.
The procedure call (mem '(1 2 3 4) 1) would evaluate the expression '(1 2 3 4) before passing that value to mem. Since the expression '(1 2 3 4) evaluates to a list, that list is the value which is passed to mem. This differs from the erroneous call (mem (1 2 3 4) 1), which attempts to evaluate the expression (1 2 3 4) by calling the (nonexistent) procedure 1 with the arguments 2, 3, and 4.
You could also use list to create the input: (mem (list 1 2 3 4) 1). list is also a procedure, and so it evaluates its arguments. Here the call to mem would evaluate the expression (list 1 2 3 4), and since list is a procedure the call to list would evaluate the arguments 1, 2, 3, and 4. Numbers are self-evaluating in Scheme, so the call to list would return a list (1 2 3 4); this list is the value passed to mem, which has now evaluated its argument (list 1 2 3 4).
Some Comments on the Posted Code
The cond form can take multiple conditional clauses, and there is no reason to use if here. Instead, you can do:
(define (mem lst ele)
(cond
((null? lst) #f)
((= ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
The = predicate only works for numbers; to handle more general inputs you might choose equal?:
(define (mem lst ele)
(cond
((null? lst) #f)
((equal? ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
Now you can work with, e.g., lists of symbols, or lists of lists:
> (mem '(a b c d) 'c)
#t
> (mem '(a b c d) 'e)
#f
> (mem '(1 (2 3) 4) '(2 3))
#t
> (mem '(1 (2 (3 4)) 5) '(2 (3 4)))
#t
> (mem '(1 (2 3) 4) 3) ;; does not descend into nested lists
#f
Note that changing the equality predicate to equal? will allow lists to be searched for at the top level of the input list, but no deeper. The list (2 (3 4)) can be found in the list (1 (2 (3 4)) 5) because it is at the top level of the list, i.e., (2 (3 4)) is an element of the list (1 (2 (3 4)) 5). But, (3 4) is not an element of the top level list, so the current mem procedure can't find it here. Another definition for mem would be needed to search within nested lists.
It seems from your example that you are looking for the list '(1 4 -2) in the list '(1), which should evaluate to #f. However your implementation expects all elements to be numbers since you compare with = which is a number only comparison procedure. If you want to compare any type you should use equal? which compares two objects of any type and supports comparing structures.
You were using an acute-accent instead of a single-quote for your literals.
#lang racket
(define (mem ele lst) ;; easier to read with one element -then- list
;; ..plus that's how you wrote your call to it,
;; so this arg-order makes more sense here.
(cond ;; cond doesn't need "else"
((null? lst) #f)
((if (= ele (car lst)) #t
(mem ele (cdr lst)))) ;; element, then list now
)
)
(mem 1 '(1 4 -2))
;; don't know why element needed to be wrapped in a '(1) literal list container
;; also literals require single-quote ' character, not the ’ acute-accent
https://docs.racket-lang.org/racket-cheat/index.html

contract violation expected: number?-Scheme

I am new to racket and scheme and I am attempting to map the combination of a list to the plus funtion which take each combination of the list and add them together like follows:
;The returned combinations
((1 3) (2 3) (1 4) (2 4) (3 4) (1 5) (2 5) (3 5) (4 5) (1 6) (2 6) (3 6) (4 6) (5 6) (1 2) (2 2) (3 2) (4 2) (5 2) (6 2))
; expected results
((2) (5) (5).....)
Unfortunately I am receiving the contract violation expected error from the following code:
;list of numbers
(define l(list 1 2 3 4 5 6 2))
(define (plus l)
(+(car l)(cdr l)))
(map (plus(combinations l 2)))
There are a couple of additional issues with your code, besides the error pointed out by #DanD. This should fix them:
(define lst (list 1 2 3 4 5 6 2))
(define (plus lst)
(list (+ (car lst) (cadr lst))))
(map plus (combinations lst 2))
It's not a good idea to call a variable l, at first sight I thought it was a 1. Better call it lst (not list, please - that's a built-in procedure)
In the expected output, weren't you supposed to produce a list of lists? add a call to list to plus
You're not passing plus in the way that map expects it
Do notice the proper way to indent and format your code, it'll help you in finding bugs
You want (cadr l). Not (cdr l) in your plus function:
(define (plus l)
(+ (car l) (cadr l)))
Where x is (cons 1 (cons 2 '())):
(car x) => 1
(cdr x) => (cons 2 '())
(cadr x) == (car (cdr x)) => 2

How to code Power Set in Lisp R5RS [duplicate]

This question already has answers here:
How to do a powerset in DrRacket?
(5 answers)
Closed 7 years ago.
I'm new to functional programming and I have no idea how to code this in Lisp. For example, for a given power set such as (1 2 3), how do I code it in a way to make it: (WITHOUT using Lambda functions)
( () (1) (2) (3) (1 2 3) )
So far, I have:
(define (powerSet lis)
(if (null? lis) '(()))
)
(define (APPENDS lis1 lis2)
(cond
((null? lis1) lis2)
(else (cons (car lis1)
(APPENDS (cdr lis1) lis2)))
)
)
Which just returns the empty set, or nothing.
EDIT:
Thank you so much Chris! That made so much sense. The second variation (without the append-map function) works well. However, if you input (powerset'(1 2 3 4)), it gives you:
(()
(1)
(2)
(1 2)
(3)
(1 3)
(2 3)
(1 2 3)
(4)
(1 4)
(2 4)
(1 2 4)
(3 4)
(1 3 4)
(2 3 4)
(1 2 3 4))
Is there anyway for me to make it look like:
(()
(1)
(2)
(3)
(4)
(1 2)
(1 3)
(1 4)
(2 3)
(2 4)
(3 4)
(1 2 3)
(1 2 4)
(1 3 4)
(2 3 4)
(1 2 3 4))
Thanks so much!
All user-defined functions are lambda (or case-lambda) expressions, including the powerset function you're defining. There is no way to avoid it. However, you can hide the lambda identifier by using internal definitions (it's still a lambda behind the scenes!†).
With this in mind, here's an implementation (requires Racket or SRFI 1):
(define (powerset lst)
(define (make-pair x)
(list x (cons (car lst) x)))
(if (null? lst)
'(())
(append-map make-pair (powerset (cdr lst)))))
If you're trying to avoid append-map or higher-order functions in general, you could jump through a few hoops to do the same thing:
(define (powerset lst)
(define (inner next)
(if (null? next)
'()
(cons (car next)
(cons (cons (car lst) (car next))
(inner (cdr next))))))
(if (null? lst)
'(())
(inner (powerset (cdr lst)))))
† An expression like
(define (foo bar)
baz)
is actually expanded into the following equivalent expression:
(define foo
(lambda (bar)
baz))

How to make two lists, one with even numbers and one with odd numbers, in scheme?

I have a problem.
For example:
We have one unsorted list:
(1 4 5 3 6 7)
Can you help me make 2 lists?
One odd numbered, increasing list:
(1 3 5 7)
and the other even numbered, decreasing list:
(6 4)
Don't use sort!
(define (split filter lst)
(let loop ((a '()) (b '()) (lst lst))
(if (null? lst)
(values a b)
(let ((cur (car lst)))
(if (filter cur)
(loop (cons cur a) b (cdr lst))
(loop a (cons cur b) (cdr lst)))))))
(split odd? '(1 2 3 4 5 6 7 8 9 10))
; ==> (9 7 5 3 1), (10 8 6 4 2)
Now, to make one that separates odds from evens and in a specific order would be simple.

Resources