How to solve pathfinding problem in Scheme? - scheme

I been studing in Scheme for weeks and I ran into a problem that I couldn't solve. I can't find a way to solved it. Here is the problem:
Figure 1 shows an example path, which has a grid layout. In the grid, black cells are simply walls, which
are basically obstacles for you. You can move among the white cells and you cannot pass the boundaries
of the grid. In each path, the starting location will be the square of [0,0]. Additionally, there is also one
white cell labeled with F. This label shows the finish square of the path. So, your aim is to find the
movements from the starting location to the finish location. To this end, you can move in 4 directions;
up, down, left, right. These 4 directions will be represented by characters U, D, L, and R, respectively.
The solution for the path shown in Figure 1 is "D D R R R R D D", which means move down 2 times, then
move right 4 times and move down 2 times. The path is not a maze! It is a simple one way road and It
has only one solution: there is always one possible next square for each move.
TASKS
In Scheme, a path will be represented in the form of a linked-list. Figure 2 shows how the path in
Figure 1 is represented in terms of a linked list in Scheme. Starting cell [0,0] has the letter S, the
finishing cell has the letter F and empty cells have the letter E. The walls have the letter - (minus)
The following function "buildPath" on the left is given for you which takes a list of lists and creates
a path (grid) using the lists. You can use this function to create different paths in order to test your
code. On the right the code shows how the path in Figure 2 is created.
Task 1: Define two functions "getHeight" and "getWidth" which takes a path as an input and returns the height and the width of the path.
(getHeight sample-path) → should return 5
(getWidth sample-path) → should return 5
Task 2: Define a function "getLetter" which takes a path, a row number and a column number. Then it returns the letter from the path on the corresponding location [row, column]
(getLetter sample-path 0 0) → should return S
(getLetter sample-path 1 0) → should return E
(getLetter sample-path 1 1) → should return -
(getLetter sample-path 4 4) → should return F
Task 3: Define a function "solvePath" which takes a path and returns the solution for the path.
(solvePath sample-path) → should return (D D R R R R D D)
My codes are:
#lang scheme
(define (buildPath rows)
(cond
((null? rows) null)
(else (cons (buildPath (cdr rows))
(car rows)))))
(define sample-path (buildPath
'(("S" "-" "-" "-" "-")
("E" "-" "-" "-" "-")
("E" "E" "E" "E" "E")
("-" "-" "-" "-" "E")
("-" "-" "-" "-" "F"))))
(define (getHeight mylist)
(define count 0)
(define (height mylist)
(cond
((null? mylist) null)
(else
(if (null? (filter filter-out (cdr mylist))) null (set! count (+ 1 count)))
(height (car mylist))
)))
(height mylist) count)
(define (getWidth mylist)
(define count 0)
(define (width mylist)
(cond
((null? mylist) null)
(else
(define list-length (length(filter filter-out (cdr mylist))))
(if (> list-length count) (set! count (+ 0 list-length)) null)
(width (car mylist))
)))
(width mylist) count)
(define (getLetter mylist rownum columnum)
(define count 0)
(define (letter mylist)
(cond
((eq? count rownum) (list-ref (cdr mylist) columnum))
(else
(set! count (+ 1 count))
(letter (car mylist))
)))
(letter mylist))
(define (filter-out x)
(if (eq? x "-") #f #t))
I solved Task 1 and Task 2 but stuck at Task 3. What logic can i use?

This answer shows one way to approach "Task 3" by starting
with simple examples (as check-expect tests) to direct
development.
First, Tasks 1 and 2, with tests as specified:
#lang scheme
(require test-engine/racket-tests)
(define (buildPath rows)
(cond
[(null? rows) null ]
[else (cons (buildPath (cdr rows))
(car rows))]))
(define sample-path (buildPath
'(("S" "-" "-" "-" "-")
("E" "-" "-" "-" "-")
("E" "E" "E" "E" "E")
("-" "-" "-" "-" "E")
("-" "-" "-" "-" "F"))))
(define (getWidth path) ;; Path -> Natural
;; produce number of columns in path
(length (cdr path)))
(define (getHeight path) ;; Path -> Natural
;; produce number of rows in path
(cond
[(null? (car path)) 1 ]
[else (+ 1 (getHeight (car path))) ]))
(check-expect (getWidth sample-path) 5)
(check-expect (getHeight sample-path) 5)
(define (getLetter path row col) ;; Path Natural Natural -> String
;; produce the string at [row,col] of path
(define (letter path count)
(cond
[(= count row) (list-ref (cdr path) col) ]
[else (letter (car path) (+ 1 count)) ]))
(letter path 0))
(check-expect (getLetter sample-path 0 0) "S")
(check-expect (getLetter sample-path 1 0) "E")
(check-expect (getLetter sample-path 1 1) "-")
(check-expect (getLetter sample-path 4 4) "F")
(test)
Welcome to DrRacket, version 8.4 [cs].
Language: scheme, with debugging.
All 6 tests passed!
>
For Task 3, start with the simplest possible grid, write tests, and construct corresponding functions:
(define minimal-path (buildPath '(("S" "F"))))
(check-expect (step minimal-path 1 (list)) '())
(check-expect (step minimal-path 0 (list)) '(R))
(define (step path col result) ;; Path Natural ListOfSymbol -> ListOfSymbol
;; produce step directions (minimal-path only)
(cond
[(string=? (getLetter path 0 col) "F") result ]
[(string=? (getLetter path 0 (+ col 1)) "F")
(step path (+ col 1) (append result '(R))) ]))
Extend step to handle the next simplest example
(run after every change to check that all tests pass -
some may need adjustment as functions develop):
(define short-path (buildPath '(("S" "E" "E" "F"))))
(check-expect (step short-path 0 0 (list)) '(R R R))
(define (step path row col result) ;; Path Natural Natural ListOfSymbol -> ListOfSymbol
;; produce step directions (short-path only)
(cond
[(string=? (getLetter path row col) "F") result ]
[(or (string=? (getLetter path 0 (+ col 1)) "E")
(string=? (getLetter path 0 (+ col 1)) "F"))
(step path row (+ col 1) (append result '(R))) ]))
And then (extending getLetter to produce an appropriate value for row/col outside the boundary of the grid):
(define corner-path (buildPath '(("S" "E" "E")
("-" "-" "F"))))
(check-expect (step corner-path 0 0 (list)) '(R R D))
(define (getLetter path row col) ;; Path Natural Natural -> String
;; produce the string at [row,col] of path, "-" if outside grid
(define (letter path count)
(cond
[(= count row) (list-ref (cdr path) col) ]
[else (letter (car path) (+ 1 count)) ]))
(if (or (negative? row) (>= row (getHeight path))
(negative? col) (>= col (getWidth path)))
"-"
(letter path 0)))
(define (step path row col result) ;; Path Natural Natural ListOfSymbol -> ListOfSymbol
;; produce path from [0,0] to "F"
(cond
[(string=? (getLetter path row col) "F") result ]
[(or (string=? (getLetter path row (+ col 1)) "F")
(string=? (getLetter path row (+ col 1)) "E"))
(step path row (+ col 1) (append result '(R))) ]
[(or (string=? (getLetter path (+ row 1) col) "F")
(string=? (getLetter path (+ row 1) col) "E"))
(step path (+ row 1) col (append result '(D))) ]))
This version works for the sample-path provided in the question:
(define (solvePath path) ;; Path -> ListOfSymbol
;; produce path from [0,0] to "F"
(step path 0 0 (list)))
(check-expect (solvePath sample-path) '(D D R R R R D D))
Welcome to DrRacket, version 8.4 [cs].
Language: scheme, with debugging.
All 11 tests passed!
>
step can now be extended for paths with "left" and "up" directions, with an example:
(define (step path row col result) ;; Path Natural Natural ListOfSymbol -> ListOfSymbol
;; produce path from [0,0] to "F"
(define (step? n-row n-col) ;; Natural Natural -> Boolean
;; is [n-row,n-col] a possible next step on path?
(or (string=? (getLetter path n-row n-col) "F")
(string=? (getLetter path n-row n-col) "E")))
(cond
[(string=? (getLetter path row col) "F") result ]
[(step? row (+ col 1))
(step path row (+ col 1) (append result '(R))) ]
[(step? (+ row 1) col)
(step path (+ row 1) col (append result '(D))) ]
[(step? row (- col 1))
(step path row (- col 1) (append result '(L))) ]
[(step? (- row 1) col)
(step path (- row 1) col (append result '(U))) ]))
(define twisty-path (buildPath
'(("S" "-" "E" "E" "E")
("E" "E" "E" "-" "E")
("-" "-" "-" "E" "E")
("-" "E" "E" "E" "-")
("-" "F" "-" "-" "-"))))
But (solvePath twisty-path) results in the step above looping (oscillating between right and left).
One way to fix this is to add arguments to step and step? to detect and avoid it:
(define (step path row col result back) ;; Path Natural Natural ListOfSymbol -> ListOfSymbol
;; produce path from [0,0] to "F"
(define (step? n-row n-col direction) ;; Natural Natural Symbol -> Boolean
;; is [n-row,n-col] a possible next step on path?
(and (not (eq? direction back))
(or (string=? (getLetter path n-row n-col) "F")
(string=? (getLetter path n-row n-col) "E"))))
(cond
[(string=? (getLetter path row col) "F") result ]
[(step? row (+ col 1) 'R)
(step path row (+ col 1) (append result '(R)) 'L) ]
[(step? (+ row 1) col 'D)
(step path (+ row 1) col (append result '(D)) 'U) ]
[(step? row (- col 1) 'L)
(step path row (- col 1) (append result '(L)) 'R) ]
[(step? (- row 1) col 'U)
(step path (- row 1) col (append result '(U)) 'D) ]))
(define (solvePath path) ;; Path -> ListOfSymbol
;; produce path from [0,0] to "F"
(step path 0 0 (list) '-))
(check-expect (solvePath twisty-path) '(D R R U R R D D L D L L D))
(test)

Related

What is a smallest set of indices that allows to fully bind any pattern of 6-tuple in one hop?

I am trying to build a 6-tuple store on top of wiredtiger. The tuples can be described as follow:
(graph, subject, predicate, object, alive, transaction)
Every tuple stored in the database is unique.
Queries are like regular SPARQL queries except that the database store 6 tuples.
Zero of more elements of a tuple can be variable. Here is an example query that allows to retrieve all changes introduces by a particular transaction P4X432:
SELECT ?graph ?subject ?predicate ?object ?alive
WHERE
{
?graph ?subject ?predicate ?object ?alive "P4X432"
}
Considering all possible patterns ends up with considering all combinations of:
(graph, subject, predicate, object, alive, transaction)
That is given by the following function:
def combinations(tab):
out = []
for i in range(1, len(tab) + 1):
out.extend(x for x in itertools.combinations(tab, i))
assert len(out) == 2**len(tab) - 1
return out
Where:
print(len(combinations(('graph', 'subject', 'predicate', 'object', 'alive', 'transaction'))))
Display:
63
That is there 63 combinations of the 6-tuples. I can complete each indices with the missing tuple item, e.g. the following combination:
('graph', 'predicate', 'transaction')
Will be associated with the following index:
('graph', 'predicate', 'transaction', 'subject', 'alive', 'object')
But I know there is a smaller subset of all permutations of the 6-tuple that has the following property:
A set of n-permutations of {1, 2, ..., n} where all combinations of {1, 2, ..., n} are prefix-permutation of at least one element of the set.
Otherwise said, all combinations have a permutation that is prefix of one element of the set.
I found using a brute force algorithm a set of size 25 (inferior to 63) that has that property:
((5 0 1 2 3 4) (4 5 0 1 2 3) (3 4 5 0 1 2) (2 3 4 5 0 1) (1 2 3 4 5 0) (0 1 2 3 4 5) (0 2 1 3 4 5) (0 3 2 1 5 4) (0 4 3 1 5 2) (0 4 2 3 1 5) (2 1 5 3 0 4) (3 2 1 5 0 4) (3 1 4 5 0 2) (3 1 5 4 2 0) (3 0 1 4 2 5) (3 5 2 0 1 4) (4 3 1 0 2 5) (4 2 1 5 3 0) (4 1 0 2 5 3) (4 5 2 1 0 3) (5 4 1 2 3 0) (5 3 0 1 4 2) (5 2 1 3 4 0) (5 1 2 4 0 3) (5 0 2 4 3 1))
Here is the r7rs scheme program I use to compute that solution:
(define-library (indices)
(export indices)
(export permutations)
(export combination)
(export combinations)
(export run)
(import (only (chezscheme) trace-define trace-lambda random trace-let))
(import (scheme base))
(import (scheme list))
(import (scheme comparator))
(import (scheme hash-table))
(import (scheme process-context))
(import (scheme write))
(begin
(define (combination k lst)
(cond
((= k 0) '(()))
((null? lst) '())
(else
(let ((head (car lst))
(tail (cdr lst)))
(append (map (lambda (y) (cons head y)) (combination (- k 1) tail))
(combination k tail))))))
(define (factorial n)
(let loop ((n n)
(out 1))
(if (= n 0)
out
(loop (- n 1) (* n out)))))
(define (%binomial-coefficient n k)
;; https://en.wikipedia.org/wiki/Binomial_coefficient#Multiplicative_formula
(let loop ((i 1)
(out 1))
(if (= i (+ k 1))
out
(loop (+ i 1) (* out (/ (- (+ n 1) i) i))))))
(define (memo proc)
(let ((m (make-hash-table (make-equal-comparator))))
(lambda args
(if (hash-table-contains? m args)
(hash-table-ref m args)
(let ((v (apply proc args)))
(hash-table-set! m args v)
v)))))
(define binomial-coefficient
(memo
(lambda (n k)
(cond
((= n k) 1)
((= k 0) 1)
(else (%binomial-coefficient n k))))))
;; k-combination ranking and unranking procedures according to
;; https://en.wikipedia.org/wiki/Combinatorial_number_system
(define (ranking lst)
(let loop ((lst (sort < lst)) ;; increasing sequence
(k 1)
(out 0))
(if (null? lst)
out
(loop (cdr lst) (+ k 1) (+ out (binomial-coefficient (car lst) k))))))
(define (%unranking k N)
(let loop ((n (- k 1)))
(if (< N (binomial-coefficient (+ n 1) k))
n
(loop (+ n 1)))))
(define (unranking k N)
(let loop ((k k)
(N N)
(out '()))
(if (= k 0)
out
(let ((m (%unranking k N)))
(loop (- k 1) (- N (binomial-coefficient m k)) (cons m out))))))
(define fresh-random
(let ((memo (make-hash-table (make-eqv-comparator))))
(lambda (n)
(when (= (hash-table-size memo) n)
(error 'oops "no more fresh number" n
))
(let loop ()
(let ((r (random n)))
(if (hash-table-contains? memo r)
(loop)
(begin (hash-table-set! memo r #t) r)))))))
(define (random-k-combination k n)
(unranking k (fresh-random (binomial-coefficient n k))))
(define (combinations lst)
(if (null? lst) '(())
(let* ((head (car lst))
(tail (cdr lst))
(s (combinations tail))
(v (map (lambda (x) (cons head x)) s)))
(append s v))))
;; (define (combinations lst)
;; (append-map (lambda (k) (combination k lst)) (iota (length lst))))
(define (permutations s)
;; http://rosettacode.org/wiki/Permutations#Scheme
(cond
((null? s) '(()))
((null? (cdr s)) (list s))
(else ;; extract each item in list in turn and permutations the rest
(let splice ((l '()) (m (car s)) (r (cdr s)))
(append
(map (lambda (x) (cons m x)) (permutations (append l r)))
(if (null? r) '()
(splice (cons m l) (car r) (cdr r))))))))
(define (shift lst index)
(append (drop lst index) (take lst index)))
(define (rotations lst)
(reverse! (map (lambda (index) (shift lst index)) (iota (length lst)))))
(define (prefix? lst other)
"Return #t if LST is prefix of OTHER"
(let prefix ((lst lst)
(other other))
(if (null? lst)
#t
(if (= (car lst) (car other))
(prefix (cdr lst) (cdr other))
#f))))
(define (indices lst)
(let ((candidates (permutations lst)))
(let loop ((out (rotations lst)) ;; all rotations are solutions
(combinations (combinations lst)))
(if (null? combinations)
(reverse! out)
(let ((permutations (permutations (car combinations))))
(if (any (lambda (s) (any (lambda (p) (prefix? p s)) permutations)) out)
;; there is an existing "solution" for the
;; permutations of COMBINATION move to the next
;; combination
(loop out (cdr combinations))
(loop (cons (find (lambda (c) (if (member c out)
#f
(any (lambda (p) (prefix? p c)) permutations)))
candidates)
out)
(cdr combinations))))))))
(define (permutation-prefix? c o)
(any (lambda (p) (prefix? p o)) (permutations c)))
(define (ok? combinations candidate)
(every (lambda (c) (any (lambda (p) (permutation-prefix? c p)) candidate)) combinations))
(define (run)
(let* ((n (string->number (cadr (command-line))))
(N (iota n))
(solution (indices N))
(min (length solution))
(rotations (rotations N))
(R (length rotations))
;; other stuff
(cx (combinations N))
(px (filter (lambda (x) (not (member x rotations))) (permutations N)))
;; other other stuff
(pn (length px))
(PN (iota pn)))
(display "(length solution) => ") (display (length solution))
(display "\n")
(display "(length rotations) => ") (display R)
(display "\n")
(let try ((x (- (length solution) 1)))
(let ((count (binomial-coefficient pn (- x R))))
(let loop ((index 0)
(cxx (map (lambda (x) (list-ref px x)) (random-k-combination (- x R) pn))))
(when (= (modulo index (expt 10 5)) 0)
(display "n=") (display n) (display " x=") (display x)
(display " ")
(display index) (display "/") (display count) (display "\n"))
(let ((candidate (append rotations cxx)))
(let ((continue? (not (ok? cx candidate))))
(if continue?
(loop (+ index 1)
(map (lambda (x) (list-ref px x)) (random-k-combination (- x R) pn)))
(begin (display "new solution n=") (display n)
(display " length=") (display x)
(display " ") (display candidate)
(display "\n")
(try (- x 1)))))))))))
))
With that list of permutations I can query any pattern.
I am wondering if there is a smaller set and whether there is definitive algorithm to compute that kind of set.
Based on this answer https://math.stackexchange.com/a/3146793/23663
The following program yields a solution that is a minimal solution according to math ™:
import itertools
import math
f = math.factorial
bc = lambda n, k: f(n) // f(k) // f(n-k) if k<n else 0
def pk(*args):
print(*args)
return args[-1]
def stringify(iterable):
return ''.join(str(x) for x in iterable)
def combinations(tab):
out = []
for i in range(1, len(tab) + 1):
out.extend(stringify(x) for x in itertools.combinations(tab, i))
assert len(out) == 2**len(tab) - 1
return out
def ok(solutions, tab):
cx = combinations(tab)
px = [stringify(x) for x in itertools.permutations(tab)]
for combination in cx:
pcx = [''.join(x) for x in itertools.permutations(combination)]
# check for existing solution
for solution in solutions:
if any(solution.startswith(p) for p in pcx):
# yeah, there is an existing solution
break
else:
print('failed with combination={}'.format(combination))
break
else:
return True
return False
def run(n):
tab = list(range(n))
cx = list(itertools.combinations(tab, n//2))
for c in cx:
L = [(i, i in c) for i in tab]
A = []
B = []
while True:
for i in range(len(L) - 1):
if (not L[i][1]) and L[i + 1][1]:
A.append(L[i + 1][0])
B.append(L[i][0])
L.remove((L[i + 1][0], True))
L.remove((L[i][0], False))
break
else:
break
l = [i for (i, _) in L]
yield A + l + B
for i in range(7):
tab = stringify(range(i))
solutions = [stringify(x) for x in run(i)]
assert ok(solutions, tab)
print("n={}, size={}, solutions={}".format(i, len(solutions), solutions))
The above program output is:
n=0, size=1, solutions=['']
n=1, size=1, solutions=['0']
n=2, size=2, solutions=['01', '10']
n=3, size=3, solutions=['012', '120', '201']
n=4, size=6, solutions=['0123', '2031', '3012', '1230', '1302', '2310']
n=5, size=10, solutions=['01234', '20341', '30142', '40123', '12340', '13402', '14203', '23410', '24013', '34021']
n=6, size=20, solutions=['012345', '301452', '401253', '501234', '203451', '240513', '250314', '340521', '350124', '450132', '123450', '142503', '152304', '134502', '135024', '145032', '234510', '235104', '245130', '345210']

not a procedure; expected a procedure that can be applied to arguments given: #<void> in scheme

I got it print sub (A 3333) (A 4444), but I can't figure out to print out both
sub (A 3333) (A 4444)
add (R 0) (R 1)
(define tree '("S" ( ("-"("A" 3333 )("A" 4444))) ("W" (("+" ("R" 0) ("R" 1))))))
(define (OperandNode on)
(display on))
(define (TwoOperandNode x)
(car x)
(if(equal? (car x) "-")
((display "sub")
(OperandNode (cadr x))
(OperandNode (caddr x)))))
(TwoOperandNode (caadr tree))
(define (WhileNode h)
(car h)
(if(equal? (car h) "+")
((display "add")
(WhileNode (cadr h))
(WhileNode (caddr h)))))
(WhileNode (caaadr tree))
You know that for the following form:
(+ 1 2)
The parts are evaluated, eg. + gets evaluated ta procedure #<procedure:+> and the numbers get evaluated to themselves. Then Scheme applies it and gets the result 3. Now look at what you have done in WhileNode:
((display "add") (WhileNode (cadr h)) (WhileNode (caddr h))) ; ==
(#<void> ...) ; throws error
So the parts get evaluated here to. However the problem is that the expression in operator position, (display "add"), returns #<void>. It doesn't know how to continue from this. In Java the same code would look like this:
System.out.println("add")(WhileNode(cadr(h)), WhileNode(caddr(h)));
In Scheme its perfectly natural to have expressions in operator position, but it must evaluate to a procedure:
(define (abs-proc x)
(if (positive? x)
values
-))
((abs-proc -5) -5) ; ==
(- -5) ; ==
; ==> 5
((abs-proc 3) 3) ; ==
(values 3) ; ==
; ==> 3

Checking parenthesis of racket function

I'm trying to make a function that takes a non-empty string representing a Racket function and an index of that string. If the index refers to a right parenthesis, then the index of the matching left parentheses is returned. Else false.
> (find-paren "(if (zero? x) (* 2 x) x)" 11)
false
> (find-paren "(if (zero? x) (* 2 x) x)" 12)
4
> (find-paren "(+ (* 2 (- 5 3)) (/ (+ 4 2) 3))" 14)
8
> (find-paren "(+ (* 2 (- 5 3)) (/ (+ 4 2) 3))" 15)
3
> (find-paren "(+ (* 2 (- 5 3)) (/ (+ 4 2) 3))" 30)
0
And I'm trying to do this the quickest way possible so no explode, substring, string->list, string-ith.` I've been stuck on this problem for almost an hour now. If the string was symetric then my function would work:
(define (find-paren expr i)
(cond [(not (equal? #\) (string-ref expr i))) false]
[else (- (string-length expr) i)]))
But it's not symmetric. I also created a function that counts how many times a character appears in a string, but I'm not sure if it would help that much:
(define (char-count c s)
(local [(define (loop i count)
(cond
[(negative? i) count]
[(char=? c (string-ref s i))
(loop (sub1 i) (add1 count))]
[else
(loop (sub1 i) count)]))]
(loop (sub1 (string-length s)) 0)))
Any help would be great in ISL+
If you are to work with actual Racket expression, you will sooner rather than later need to turn the string representation into a list of tokens using a lexer.
The program below shows how to find pairs of matching left and right parentheses.
Given that list, it is easy to find the left parenthesis that match a given right parenthesis.
If you a solution that works directly on the string representation, you need to mimick the algorithm in pair-parens-loop.
; a TOKEN consists of a lexeme (a 'left, 'right or a char)
; and the position from which the lexeme was read.
(define-struct token (lexeme pos))
; left? and right? checks whether the token was a left or right parenthesis respectively.
(define (left? t) (eq? (token-char t) 'left))
(define (right? t) (eq? (token-char t) 'right))
; lex : string -> list-of-tokens
; lex the whole string
(define (lex s)
(lex-loop s 0))
; lex-loop : string natural -> list-of-tokens
; lex-loop the part of the string that begins with position p
(define (lex-loop s p)
(cond
[(= p (string-length s)) '()]
[(char=? (string-ref s p) #\() (cons (make-token 'left p) (lex-loop s (+ p 1)))]
[(char=? (string-ref s p) #\)) (cons (make-token 'right p) (lex-loop s (+ p 1)))]
[else (lex-loop s (+ p 1))]))
; pair-parens : list-of-tokens -> list-of-list-of-tokens
; return a list of mathcing left/right tokens
(define (pair-parens ts)
(pair-parens-loop ts '() '()))
(define (pair-parens-loop ts pending found)
(cond
[(empty? ts) found]
[(left? (first ts))
(pair-parens-loop (rest ts) (cons (first ts) pending) found)]
[(right? (first ts))
(pair-parens-loop (rest ts) (rest pending) (cons (list (first pending) (first ts)) found))]
[else (error)]))
;;;
;;; EXAMPLE
;;;
> (lex "(if (zero? x) (* 2 x) x)")
(list
(make-token 'left 0)
(make-token 'left 4)
(make-token 'right 12)
(make-token 'left 14)
(make-token 'right 20)
(make-token 'right 23))
> (pair-parens (lex "(if (zero? x) (* 2 x) x)"))
(list
(list (make-token 'left 0) (make-token 'right 23))
(list (make-token 'left 14) (make-token 'right 20))
(list (make-token 'left 4) (make-token 'right 12)))

Frequency list 2 - Huffman project

Previously I had the question about adding a character to a frequency list(Add a character to a frequency list), it got solved, but i have problems again with the rest of the project. The next 2 functions are working:
Write a function which creates the frequency list( from a list of characters)
(statistiques '("a" "b" "r" "a" "c" "a" "d" "a" "b" "r" "a"))
→ (("a" 5) ("r" 2) ("b" 2) ("d" 1) ("c" 1))
My code:
(define statistiques
(lambda (l)
(if (null? l)
l
(ajoute1(car l)(statistiques (cdr l))))))
Write a function which is inserting a pair (a character and a number which indicates the occurrence of that character in a list), in a list of pairs which is sorted by the number of occurrence
(inserefreq '("b" 2) '(("d" 1) ("a" 5)))
→ (("d" 1) ("b" 2) ("a" 5))
(define inserefreq
(lambda (c l)
(cond ((null? l)
(list c))
((<= (cadr c) (cadar l))
(cons c l))
(else
(cons (car l) (inserefreq c (cdr l)))))))*
Then the problem is with the next one, which is asking to sort a frequency list by successive insertion
(triefreq '(("a" 5) ("r" 2) ("b" 2) ("d" 1) ("c" 1)))
→ (("d" 1) ("c" 1) ("r" 2) ("b" 2) ("a" 5))
My code:
(define tirefreq
(lambda (l)
(inserefreq(car l) (tirefreq (cdr l)))))
Result/error:
You're just missing the base case, when l is empty:
(define triefreq
(lambda (l)
(if (null? l)
'()
(inserefreq (car l) (triefreq (cdr l))))))

passing function output as another function argument for matrix transpose in lisp

I'm in the process of writing a matrix transpose function in lisp. My approach can be seen from the following code:
(defun matrix-T (matrix)
(cond ((null matrix) matrix)
(t (list
(do ((i 0 (+ i 1)))
((> i (length matrix)))
(format t "(mapcar #'(lambda (x)(nth ~A x)) matrix) %" i))))))
As you can see, I'm trying to get the output from the do loop to pass as an
argument for the list function. However, I only get the do loop output returned from matrix-T. Is there anyway I can rectify this?
A dead-simple straight forward way to transpose a matrix:
(defun transpose-matrix (matrix)
(let ((result
(make-array (reverse (array-dimensions matrix))
:element-type (array-element-type matrix))))
(dotimes (i (array-dimension result 0) result)
(dotimes (j (array-dimension result 1))
(setf (aref result i j) (aref matrix j i))))))
(print
(transpose-matrix
#2A((1 2 3)
(4 5 6))))
;; #2A((1 4) (2 5) (3 6))
You need to actually run the MAPCAR and collect its results in a list, not just print or return it as a string.
(defun matrix-T (matrix)
(cond ((null matrix) matrix)
(t (do ((i 0 (1+ i))
(result '())
(cols (length (car matrix))))
((>= i cols) (nreverse result))
(push (mapcar #'(lambda (x) (nth i x)) matrix) result)))))
An elegant way to transpose using mapcar*
(defun transpose-matrix (matrix)
(apply #'mapcar* #'list matrix))
(transpose-matrix '(("1" "a" "e") ("2" "b" "f") ("4" "c" "g") ("5" "d" "h")))
(("1" "2" "4" "5") ("a" "b" "c" "d") ("e" "f" "g" "h"))

Resources