How can I decompose geometry figure building in a lisp-like languages? - functional-programming

How can I decompose this process in a lisp-like languages?
Start with some geometrical figure.
We multiply it and get several copies.
Then we set this copies on a border of other figure with, e.q. equal distance between copies.
Then we set rotation of each object on the border with
dependence from its position on the border.
What ways exist to decompose in functions this process as a whole: making copies of an object, arranging its copies on a border of other object, setting rotation of its copies?
Last step is specially interesting and also ways how to compose it with previous ones.

Your question is quite broad, let's have a simple example for 2D shapes.
The code below is defined to that we can write this:
(isomorphism (alexandria:compose (scale 10)
(lift #'round)
(rotate 90))
(triangle (point 0 0)
(point 1 0)
(point 0 1)))
=> (TRIANGLE (POINT 0 0) (POINT 0 10) (POINT -10 0))
This compute a simple transform function known as an isomorphism (which preserves shape), which is first a rotation, then a rounding of the computed points, then a scale operation. The result is a list describing the resulting shape. Copying a shape is simply the isomorphism with function #'identity (but it is a bit useless if you go with a pure functional way).
NB: the rounding is here e.g. to fall back to zero when cos/sin give very small floats ; the use of floats breaks shape preservation and so does rounding, but here when they are combined the resulting shape is an actual isomorphism. This bit of correctness/accuracy might or might not be important depending of the purpose of your needs. You could also describe what transformations are applied and only "rasterize" them for display.
The transform functions works over a list of coordinates, and return list of coordinates:
(defun translate (dx &optional (dy dx))
(lambda (xy) (mapcar #'+ xy (list dx dy))))
(defun scale (sx &optional (sy sx))
(lambda (xy) (mapcar #'* xy (list sx sy))))
(defun rotate (degrees)
(let* ((radians (* degrees pi 1/180))
(cos (cos radians))
(sin (sin radians)))
(lambda (xy)
(destructuring-bind (x y) xy
(list (- (* x cos) (* y sin))
(+ (* y cos) (* x sin)))))))
(defun lift (fn)
(lambda (things)
(mapcar fn things)))
The isomorphism function is defined as follows, and recursively destructures shapes into a type-tag (which doubles as a constructor) and components, and in case of points, apply the transform function:
(defun isomorphism (transform shape)
(flet ((isomorphism (s) (isomorphism transform s)))
(with-shape (constructor components) shape
(apply constructor
(if (eq constructor 'point)
(funcall transform components)
(mapcar #'isomorphism components))))))
I defined shape and with-shape as follows, to have a little bit of abstraction over how they are represented:
(defun shape (constructor components)
(list* constructor components))
(defmacro with-shape ((constructor components) shape &body body)
`(destructuring-bind (,constructor &rest ,components) ,shape
,#body))
And I can define shapes with simple functions, that may or may not perform some checking and normalization:
(defun point (&rest coords)
(shape 'point coords))
(defun triangle (a b c)
(shape 'triangle (list a b c)))
(defun rectangle (x0 y0 x1 y1)
(shape 'rectangle
(list (min x0 x1)
(min y0 y1)
(max x0 x1)
(max y0 y1))))
Notice how the constructor always is the same symbol as the function's name. This could be enforced with a macro, where you only need return the list of components:
(defconstructor point (x y)
(list x y))
You can also build derived constructors from the one above:
(defun rectangle-xywh (x y width height)
(rectangle x y (+ x width) (+ y height)))
Here above shapes are defined in terms of points, but you can imagine having shapes being assembled from smaller shapes:
(defun group (&rest shapes)
(shape 'group shapes))
This is a bit of a toy example, but that might be useful as a starting point.
Then, if you want to take a shape and make different copies rotated by increments of 90°, you could do:
(loop
for angle from 0 below 360 by 90
collect
(isomorphism (compose (lift #'round)
(rotate angle)
(scale 2)
(translate 10 0))
(group (triangle (point 0 0)
(point 1 0)
(point 0 1)))))

Related

Drawing a Sierpinski Triangle in Racket

I am trying to do a nested pyramid in Drracket and I have hit a wall. I was hoping to get some help. I need nested pyramid to output (nested-pyramid (circle 10) 1) or (nested-pyramid (circle 10) 3) and have the pyramid change sizes.
(define (nested-pyramid p)
(define pyramid p)
(define p 1)
(if (= p 1))
pyramid p
(else (- p 1))
nested-pyramid p)
The code I have for pyramid p is:
(define (pyramid p)
(define two-p (hc-append p p))
(vc-append p two-p ))
To create a nested pyramid from a shape p with depth n, assuming n is an integer greater than or equal to 1:
if n is 1, create a pyramid from shape p;
otherwise n must be more than 1, so create a nested pyramid from p with depth n - 1.
You create a pyramid from p with (pyramid p). However pyramid can be made quite a lot simpler than your definition: if you have something that says
(define ...
(define x ...)
... use x exactly once ...)
It is very often better to just use the form that created x rather than inventing a variable you use exactly once. So
(define (pyramid p)
(define two-p (hc-append p p))
(vc-append p two-p))
can instead be
(define (pyramid p)
(vc-append p (hc-append p p)))
Thinking about the difference between these two versions of pyramid might help write nested-pyramid. If you are using something lots of times then creating a name for it can be both clearer and perhaps more efficient:
(define (rocket p)
(define three (hc-append p p p))
(vc-append p
(hc-append p p)
three
three
three
three
three))

2D to 1D transformation without dimensions

Suppose I want to track the state of cells in a grid. Let's assume that the grid has dimensions m x n. I can simply create a vector of length m*n and track cell state using the vector. In this case, each point in the grid (which is 2D) would map to an element in the vector (1D).
One method I've used before is something like this:
defun 2d->1d (x, y, m, n):
return m*y + x;
defun 1d->2d (i, m, n):
return [i%m, i/m];
My problem is this:
Is there a way to have a 2D->1D mapping as above when grid dimensions are not known or when grid is infinite?
Yes, there are mappings from 2D to 1D for natural numbers, known as Pairing functions.
For example, the Cantor pairing function:
defun 2d->1d (x, y):
return (1 / 2) * (x + y) * (x + y + 1) + y;
For the reverse function see the link above, it is a little more complex.

Scatter plot in racket with individual colors

I am exploring the plotting utilities in racket, and I have to say, so far I am incredibly impressed. However, I ran into a small difficulty.
I was trying to make a scatter plot, where each point has its own color (for visualizing classification algorithms). However, I am not sure how to make each point have its own color. Is it possible?
Here is what I have tried so far:
(define (random-choice l)
(list-ref l (random (length l))))
(define (scatter data)
(let ([x-max (apply max (map first data))]
[x-min (apply min (map first data))]
[y-max (apply max (map second data))]
[y-min (apply min (map second data))]
[colors (build-list 20
; here I am trying to create a list of desired colors
; ,but an error tells me that only single elements are accepted
(λ _ (random-choice (list "red" "blue")))])
(parameterize ([plot-new-window? #t]
[point-sym 'dot]
[point-size 20])
(plot (points data
#:color colors)
#:x-max x-max
#:x-min x-min
#:y-max y-max
#:y-min y-min))))
A rough equivalent in R would be:
c <- data.frame(x=rnorm(10),y=rnorm(10))
colors <- sample(c("red","blue"),10,replace=TRUE)
plot(c$y,c$x,col=colors)
By the way, I would welcome any (and all) comments on my racket code, such as simplifying the boundary specification for the plot.
The plot function accepts a list of renderers (more generally, a tree of renderers), and each individual renderer can be supplied with its own color.
Additionally, since Plot 5.2, the plot function will automatically scale the bounds of the plot to fit the data, if possible. Obviously, this doesn't work with things like (function sin), which is unbounded, but for points data, the automatic scaling is sufficient if custom bounds are not needed.
With #Alexis King's suggestions, I ended up with this for a simple case of two groups. Writing down for posterity.
(define-struct datum [point label])
(define (color-scatter data)
(let-values
([(group-a group-b) (partition (λ (x) (= 1 (datum-label x))) data)])
(plot (list
(points (map datum-point group-a) #:color "red")
(points (map datum-point group-b) #:color "blue")))))

Basic geometry in Clojure [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
I'm looking for a Clojure library to do some basic geometry, such as:
Calculating the slope of a line given its starting and ending coordinates
Given a line with a known slope, and an x value, calculating the y value (and calculating x given y)
I can write these quite easily, given the mathematical definitions of the equations, but it seems a shame to do so if there is a decent library out there that does this already.
Note that I don't need to plot things graphically and so on, so a library that introduces a lot of graphical dependencies is not really welcome.
I think in a case like this, seeing as the functions are so small, it is simpler just to write the functions than to introduce a dependency.
(defprotocol Line
(gradient [this] "The gradient of a line")
(intercept [this] "The intercept of a line on the y axis")
(f [this] "The line's function f(x) - takes x, returns y")
(f-inv [this] "The inverse function f-inv(x) - takes y, return x"))
(defn line
"Make a Line from a gradient and an intercept"
[gradient intercept]
(reify Line
(gradient [_] gradient)
(intercept [_] intercept)
(f [_] (fn [x] (+ (* gradient x) intercept)))
(f-inv [_] (fn [y] (/ (- y intercept) gradient)))))
(defn points->line
"Make a Line given two (different) points on the line"
[[x1 y1] [x2 y2]]
(let [gradient (/ (- y2 y1)
(- x2 x1))
intercept (- y1 (* gradient x1))]
(line gradient intercept)))
Example:
(def l (points->line [1 1] [4 2]))
(gradient l) ;=> 1/3
(intercept l) ;=> 2/3
((f l) 4) ;=> 2
((f-inv l) 2) ;=> 4

Z3 prime numbers

I am trying to learn z3, and this is the first program I write.
In this exercise, I am trying to determine if x is prime. If x is prime, return SAT, otherwise, return UNSAT alongside with two of its factors.
Here is what I have so far
http://rise4fun.com/Z3/STlX
My problem is I don't think the code is doing anything right now. It returns SAT for whatever I do. i.e if I assert that 7 is prime, it returns SAT, if I assert 7 is not prime, it returns SAT.
I am not sure how recursion works in z3, but I've seen some examples, and I tried to mimic how they did the recursion.
If you guys are able to take a look and instruct me where I went wrong, I would be really appreciative.
The following formula does not achieve what your comment specifies:
; recursively call divides on y++
;; as long as y < x
;; Change later to y < sqrt(x)
(declare-fun hasFactors (Int Int) Bool)
(assert
(and (and (not (divides x y))
(not (hasFactors x (+ y 1)))) (< y x))
)
The first problem is that x, y are free. They are declared as constants before.
Your comment says you want to recursively call divides, incrementing y until it reaches x.
You can use quantified formulas to specify a relation that satisfies this property.
You would have to write something along the lines of:
(assert (forall ((x Int) (y Int)) (iff (hasFactors x y) (and (< y x) (or (divides y x) (hasFactors x (+ y 1))))))
You would also have to specify which formulas you want to check before calling check-sat.
Finding prime numbers using an SMT solver is of course not going to be practical, but will illustrate some of the behavior you get when Z3 instantiates quantifiers, which depending
on problem domain and encoding can be either quick or very expensive.
I'm so used to thinking recursively, after tampering for a few hours, I found another way to implement it. For anyone who's interested, here is my implementation.
http://rise4fun.com/Z3/1miFN
Thanks for the partial solution! A complete solution for isPrime is:
http://rise4fun.com/Z3/jBr0
(define-fun isPrime ((x Int)) Bool
(and
(> x 1)
(not (exists ((z Int) (y Int))
(and (< y x) (< z x) (> y 1) (> z 1) (= x (* y z)))))))
Took me more than I care to admit to get it right.

Resources