Is there a way to get the mouse's X and Y coordinates in MIT Scheme? - x11

I've been experimenting with X Graphics in MIT Scheme, and I was wondering whether there is a way to get the cursor position on the screen/in relation to the X window from within the language, to change the graphics based on the mouse location.

I figured out a way myself, but it's pretty nasty since I had to use additional packages:
(define (get-position)
(define a (open-output-string))
(run-shell-command "xdotool getmouselocation" 'output a)
(define output (get-output-string a))
(close-port a)
((lambda (x) (list (string->number (cadar x)) (string->number (cadadr x))))
(map (string-splitter 'delimiter #\:) ((string-splitter) ((string-trimmer) output)))))
(define resolution (let ((a (open-output-string)))
(run-shell-command "xdpyinfo | grep dimensions | awk '{print $2;}'" 'output a)
(define output (get-output-string a))
(close-port a)
(map string->number ((string-splitter 'delimiter #\x)
((string-trimmer) output)))))
Then, to get the relative position of the cursor on the screen, you just do
(map (lambda (x y) (inexact (/ x y))) (get-position) resolution)
(You do have install xdpyinfo and xdotool beforehand though, so keep that in mind)

Related

Racket: Trying to subtract numbers, getting list

I'm currently learning Racket/Scheme for a course (I'm not sure what's the difference, actually, and I'm not sure if the course covered that). I'm trying a basic example, implementing the Newton method to find a square root of a number; however, I ran into a problem with finding the distance between two numbers.
It seems that for whatever reason, when I'm trying to apply the subtraction operator between two numbers, it returns a list instead.
#lang racket
(define distance
(lambda (x y) (
(print (real? x))
(print (real? y))
(abs (- x y))
)
)
)
(define abs
(lambda x (
(print (list? x))
(if (< x 0) (- x) x)
)
)
)
(distance 2 5)
As you can see, I've added printing of the types of variables to make sure the problem is what I think it is, and the output of all those prints is #t. So:
In calling distance, x and y are both real.
In calling abs, x is a list.
So, the conclusion is that (- x y) returns a list, but why?
I double-checked with the documentation and it seems I'm using the subtraction operator correctly; I've typed (- 2 5) and then (real? (- 2 5)) into the same REPL I'm using to debug my program (Dr. Racket, to be specific), and I'm getting the expected results (-3 and #t, respectively).
Is there any wizard here that can tell me what kind of sorcery is this?
Thanks in advance!
How about this...
(define distance
(lambda (x y)
(print (real? x))
(print (real? y))
(abs (- x y))))
(define abs
(lambda (x) ;; instead of (lambda x ...), we are using (lambda (x) ...) form which is more strict in binding with formals
(print (list? x))
(if (< x 0) (- x) x)))
Read further about various lambda forms and their binding with formals.

implement member? on simply scheme

I'm following SICP and Computer Science 61A using Dr. racket and simply-scheme as my editor, there is a function member? that check if the first argument is an element of the second that is not implemented in simply-scheme so I'm trying to implement my own, I have this recursive procedure:
(define vocals '(a e i o u))
(define (member? x (y vocals))
(cond ((equal? x (first y)) #t)
((member? x (bf y)))
))
It works for vocals but i don't know how to add a stop case for when x is not a vocal

How to calculate the degree of a polynomial in scheme?

I need to create a scheme code that allows me to calculate the degree of a polynomial and show it, is there a special function in scheme that allows me to treat them?
pd: What is the way to raise these types of problems?
There is no such function just like there are no functions for guns in games in the standard libraries. There isn't even one data structure for a polynomial.
As with all user defined extensions you have the power to model your data as you wish and you make an interface to work with that data. This is how you extend the language to support the data you want to play with.
;; this is not part of the interface
(define tag-point (list 'point))
;; these are the interface
(define (point x y)
(list tag-point x y))
(define point-x cadr)
(define point-y caddr)
(define (point? p)
(and (pair? p)
(eq? (car p) tag-point)))
;; implemented distance that uses the interface
(define (distance p1 p2)
;; (assert (and (point? p1) (point? p2)))
(sqrt (+ (square (- (point-x p1) (point-x p2)))
(square (- (point-y p1) (point-y p2))))))
(distance (point 3 0 ) (point 0 4)) ; ==> 5
Now you can change your data structure as long as the interface stays intact:
;; implement points using complex numbers
(define (point x y) (make-rectangular x y))
(define (point-x p) (real-part p))
(define (point-y p) (imag-part p))
(define (point? p) (complex? p))
One could just do (define point make-rectangular) but then the interface documentation would be vague.
In the SICP videos I remember they did a polynomial type. It's in part 4B. It explains pretty much the same as I do here and they actually implement polynomials as a type you can do arithmetic on. Thus it might not be what you are looking for, but their data structure can give you an idea.

scheme, sicp, solution 3.19, procedure with infinite loop works in case it is provided as argument

could someone help me with clarification to one of the possible solution to exercise 3.19. the procedure mystery is infinite loop in case list cycle is given as argument. nevertheless when we use procedure eq? to check if list contains the cycle, it works and provides true value.
(define (last-pair x)
(if (null? (cdr x))
x
(last-pair (cdr x))
)
)
(define (make-cycle x)
(set-cdr! (last-pair x) x)
)
(define (mystery x)
(define (loop x y)
(if (null? x)
y
(let ((temp (cdr x)))
(set-cdr! x y)
(loop temp x)
)
)
)
(loop x '())
)
(define t (list 1 2 3))
(define w (make-cycle t))
(eq? (mystery t) t)
it looks like magic. I would appreciate for any help.
mystery reverses an array "in-place" by repeatedly snipping off the cdr of each entry and replacing that with the cdr of the previous x.
If this list has no loop, then it will end up reversed by the time you get back to the original '(). If there is a loop, you'll have the original array's pointer.
This is definitely a tricky to understand issue. If you make a box-and-pointer diagram it will definitely help and you'll only need to draw 3 diagrams.
Automatically Generating Diagrams of Lists
In the process of doing SICP myself, I found myself wanting a way to visualize list mutation (and to skip the numerous "draw a list diagram of..." exercises). I wrote a small function for doing so and I thought you might find it helpful if I shared it.
These diagrams are an example of this function being run on x each time loop (within the mystery function) is ran.
The following code is what I used for generating these diagrams. I wrote this code as a Scheme novice, but it's very simple to use: the function (list->graphviz) accepts a parameter lst which is the list you'd like a diagram of, as well as an optional argument graph-name which gives the graph a special name.
(define* (list->graphviz lst #:optional graph-name)
"""Convert a list into a set of Graphviz instructions
`lst' is the list you'd like a diagram of
`graph-name` is an optional parameter indicating the name you'd like to give the graph."""
(define number 0)
(define result "")
(define ordinals '())
(define (result-append! str)
(set! result (string-append result str)))
(define* (nodename n #:optional cell)
(format #f "cons~a~a" n (if cell (string-append ":" cell) "")))
(define* (build-connector from to #:optional from-cell)
(format #f "\t~a -> ~a;~%" (nodename from from-cell) (nodename to)))
(define (build-shape elt)
(define (build-label cell)
(cond ((null? cell) "/");; "∅") ; null character
((pair? cell) "*");; "•") ; bullet dot character
(else (format #f "~a" cell))))
(set! number (+ number 1))
(format #f "\t~a [shape=record,label=\"<car> ~a | <cdr> ~a\"];~%"
(nodename number)
(build-label (car elt))
(build-label (cdr elt))))
(define* (search xs #:optional from-id from-cell)
(let ((existing (assq xs ordinals)))
(cond
;; if we're not dealing with a pair, don't bother making a shape
((not (pair? xs)) (result-append! "\tnothing [shape=polygon, label=\"not a pair\"]\n"))
((pair? existing)
(result-append! (build-connector from-id (cdr existing) from-cell)))
(else
(begin
(result-append! (build-shape xs))
(set! ordinals (assq-set! ordinals xs number))
(let ((parent-id number))
;; make a X->Y connector
(if (number? from-id)
(result-append! (build-connector from-id parent-id from-cell)))
;; recurse
(if (pair? (car xs)) (search (car xs) parent-id "car"))
(if (pair? (cdr xs)) (search (cdr xs) parent-id "cdr"))))))))
(search lst)
(string-append "digraph " graph-name " {\n" result "}\n"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;; Here is where `mystery' begins ;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define t '(1 2 3))
(set-cdr! (cddr t) t)
(define (mystery x)
(define (loop x y graph-num)
(display (list->graphviz x (format #f "graph~a" graph-num)))
(if (null? x)
y
(let ((temp (cdr x)))
(set-cdr! x y)
(loop temp x (+ 1 graph-num)))))
(loop x '() 0))
(mystery t)
The code above code generates Graphviz graph description statements, which must then be processed by dot (Graphviz) to be rendered to a graphical format.
For example, you can run the code above and pipe it into dot:
$ scheme generate_box_ptr.scm | dot -o ptrs.ps -Tps
This command generates a postscript file which has the advantage of separating each list into it's own page if you've run list->graphviz more than once. dot can also output PNGs, PDFs and many other file formats as the manpage describes.

Implement a faster algorithm

I have been stuck on this question for days. Apparently I need to write a better algorithm to win the algorithm below. The below code is implemented from the famous Aima file. Is there any expert here who could guide me on how to win the algorithm?
(defun find-closest (list)
(x (car (array-dimensions list)))
(y (cadr (array-dimensions list)))
(let ((elems (aref list x y)))
(dolist (e elems)
(when (eq (type-of e) type)
(return-from find-closest (list x y)))) nil))
I tried implementing a DFS but failed and I do not quite know why. Below is my code.
(defun find-closest (list)
(let ((open (list list))
(closed (list))
(steps 0)
(expanded 0)
(stored 0))
(loop while open do
(let ((x (pop open)))
(when (finished? x)
(return (format nil "Found ~a in ~a steps.
Expanded ~a nodes, stored a maximum of ~a nodes." x steps expanded stored)))
(incf steps)
(pushnew x closed :test #'equal)
(let ((successors (successors x)))
(incf expanded (length successors))
(setq successors
(delete-if (lambda (a)
(or (find a open :test #'equal)
(find a closed :test #'equal)))
successors))
(setq open (append open successors))
(setq stored (max stored (length open))))))))
Looking at the code, the function find-some-in-grid returns the first found thing of type. This will, essentially, give you O(n * m) time for an n * m world (imagine a world, where you have one dirt on each line, alternating between "left-most" and "right-most".
Since you can pull out a list of all dirt locations, you can build a shortest traversal, or at least a shorter-than-dump traversal, by instead of picking whatever dirt you happen to find first you pick the closest (for some distance metric, from the code it looks like you have Manhattan distances (that is, you can only move along the X xor the Y axis, not both at the same time). That should give you a robot that is at least as good as the dumb-traversal robot and frequently better, even if it's not optimal.
With the provision that I do NOT have the book and base implementation purely on what's in your question, something like this might work:
(defun find-closest-in-grid (radar type pos-x pos-y)
(labels ((distance (x y)
(+ (abs (- x pos-x))
(abs (- y pos-y)))))
(destructuring-bind (width height)
(array-dimensions radar)
(let ((best nil)
((best-distance (+ width height))))
(loop for x from 0 below width
do (loop for y from 0 below height
do (loop for element in (aref radar x y)
do (when (eql (type-of element) type)
(when (<= (distance x y) best-distance)
(setf best (list x y))
(setf best-distance (distance x y))))))))
best)))

Resources