Given a pair I want to make a list that contains pair elements and cons of their position in the list(reverse order). Examples:
(cons "a" "b") turns into ((0 . 1) "b" "a")
(cons (cons "a" "b") (cons "x" "y")) turns into
((2 . 5) (3 . 4) "y" "x" (0 . 1) "b" "a")
(cons (cons (cons "x" "y") (cons "a" "b")) (cons (cons "x1" "y1") (cons "a1" "b1")))
turns into
((6 . 13) (9 . 12) (10 . 11) "b1" "a1" (7 . 8) "y1" "x1" (2 . 5) (3 . 4) "b" "a" (0 . 1) "y" "x")
I have no idea how to create the number pairs - don't know what order they follow.
First of all, I'm definitely assuming this is homework; it would be somewhat crazy to write this function otherwise. It looks like you're being asked to "flatten" a tree structure into a vector, where each cell contains either a string or a pair. The "counting from the end of the list" is a way of allowing you to model a vector with increasing memory locations; when you add things to the front of the list, the distance from an existing element to the end doesn't change.
With that said, let's get started. This problem is quite complicated, because it uses an accumulator. Actually, it uses two accumulators. The HtDP 2e textbook covers this in section 6:
http://www.ccs.neu.edu/home/matthias/HtDP2e/part_six.html
There is a lot of reading that comes before this, and there's a reason for that; it takes a lot of experience to be able to determine what kind of accumulator makes sense for a given problem. In this case, you need to figure out what the "in-between" information is that you need to keep track of as you're in the middle of computing this thing. So, for instance, suppose you're given the tree '(("a" . "b") . "c). Construct the answer by hand, a step at a time. Keep track of the separate steps. See if you can describe what "in-between" information you need to keep track of.
Sigh... this is the kind of problem that instructors assign without thinking about the kind of reasoning required.
Related
A number of the Common Lisp sequence functions take a proper sequence as an input and return a sequence as output. Starting with a proper sequence, how could the function not return another proper sequence? Example?
(mapcan #'rest (list (list 0 1 2) (cons :a :b)))
=> (1 2 . :b)
... but it is true that most of the time you can expect to have proper sequences as a result; functions might be underspecified for various reasons (cost to implementers, etc).
By the way, notice that NCONC is specified to return a list (at least in the HyperSpec), but the formal definition as given in the same page allows to have non-lists as a result, e.g. (nconc nil 2) is 2. This incomplete over-approximation of the type of result (in the signature, not the actual description of the function) contaminates all other results:
(mapcan #'rest (list (list) (cons 1 2)))
=> 2
See also Proposed ANSI Changes and ANSI Clarifications and Errata.
I need to remove the last two elements from a list in common list, but I can remove only one. What's the way?
(defun my-butlast (list)
(loop for l on list
while (rest l)
collect (first l)))
Simple: reverse, pop, pop, reverse ;-) 1
More efficiently, the following works too:
(let ((list '(a b c d)))
(loop
for x in list
for y in (cddr list)
collect x))
This can also be written, for some arbitrary L and N:
(mapcar #'values L (nthcdr N L))
It works because iteration over multiple lists is bounded by the shortest one. What matters here is the length of the second list (we don't care about its values), which is the length of the original list minus N, which must be a non-negative integer. Notice that NTHCDR conveniently works with sizes greater than the length of the list given in argument.
With the second example, I use the VALUES function as a generalized identity function; MAPCAR only uses the primary value of the computed values, so this works as desired.
The behavior is consistent with the actual BUTLAST2 function, which returns nil for N larger than the number of elements in the list. The actual BUTLAST function can also deal with improper (dotted) lists, but the above version cannot.
1. (alexandria:compose #'nreverse #'cddr #'reverse)
2. BUTLAST is specified as being equivalent to (ldiff list (last list n)). I completely forgot about the existence of LDIFF !
There's a function in the standard for this: butlast, or if you're willing to modify the input list, nbutlast.
butlast returns a copy of list from which the last n conses have been omitted. If n is not supplied, its value is 1. If there are fewer than n conses in list, nil is returned and, in the case of nbutlast, list is not modified.
nbutlast is like butlast, but nbutlast may modify list. It changes the cdr of the cons n+1 from the end of the list to nil.
Examples:
CL-USER> (butlast '(1 2 3 4 5) 2)
(1 2 3)
CL-USER> (nbutlast (list 6 7 8 9 10) 2)
(6 7 8)
The fact that you called your function my-butlast suggests that you might know about this function, but you didn't mention wanting to not use this function, so I assume it's still fair game. Wrapping it up is easy:
CL-USER> (defun my-butlast (list)
(butlast list 2))
MY-BUTLAST
CL-USER> (my-butlast (list 1 2 3 4))
(1 2)
Is it possible to call make-array function with a list as parameter? For example:
(make-array '((length '("a" "b")) (length '("r" "8" "5"))))
return:
#<TYPE-ERROR expected-type: NUMBER datum: (LENGTH '(...
Even if I try to cast the result of length with the following command:
(coerce (length '(1)) 'number)
it works for one dimension array but not for two dimensions.
Is it possible to call make-array function with a list as parameter?
Yes, in fact you always have to pass it a list designator, but it has to be a list (or list designator) of integers. The list '((length '("a" "b")) (length '("r" "8" "5")))) has two lists as its elements, not integers. E.g., if you do (first '((length '("a" "b")) (length '("r" "8" "5"))))), you get (length '("a" "b")), not 2. You'd need to do (make-array (list (length …) (length …)) …) instead.
It's described pretty clearly in the documentation for make-array in the HyperSpec:
Function MAKE-ARRAY
Syntax:
make-array dimensions &key element-type initial-element initial-contents adjustable fill-pointer displaced-to
displaced-index-offset
=> new-array
Arguments and Values:
dimensions—a designator for a list of valid array dimensions.
E.g., (make-array '(2 2)) returns a 2 × 2 array. Or, if you need to dynamically compute the dimensions, just list them together. E.g., (make-array (list (length '(a b c)) (length '(d e)))) returns a 3 × 2 array.
Note that the argument is designator for a list. The glossary entry says:
list designator n. a designator for a list of objects; that is, an
object that denotes a list and that is one of: a non-nil atom
(denoting a singleton list whose element is that non-nil atom) or a
proper list (denoting itself).
That means that when you do (make-array 5), the 5 is actually acting as a designator for the list (5). You can really think of make-array always accepting a list as the first argument, but that in the case of a one-element list, you can just pass the single element instead, since it's unambiguous what you'd want.
Related
These are related, but not quite duplicates, since they are about how to create a list to pass to make-array, whereas this question is about whether a list can be passed to make-array.
How to make an array with size received as arguments in a function in LISP?
How to modify this "make-matrix" function?
Simple rule 1: if you quote it, it does not get evaluated.
This is data, not code: '((length '("a" "b")) (length '("r" "8" "5"))).
Why? Because it is quoted.
Simple rule 2: if you want to compute something, then write Lisp code, not literal data.
(list 1 2) -> (1 2)
(list (length '(a b c)) (length '(1 2 3 4))) -> (3 4)
Addressing an unanswered aspect of the subject of the question: much like Common Lisp lists, multidimensional arrays also have a literal representation, which can be convenient in some situations.
Lists
(list 'a 'b 'c)
;; is equivalent to
'(a b c)
A vector (single dimensional array) is represented as #[n](foo*) -- n,optional, being the number of elements and foo being the items in the vector, e.g.
(vector 1 2 3 4)
;; is equivalent to
#4(1 2 3 4)
;; or
#(1 2 3 4)
A 'proper' multidimensional array, i.e. an array larger than one dimension, is represented as: #nA<sequence> where n is the number of dimensions and <sequence> has a structure similar to a nested list, e.g.
(make-array '(2 3) :initial-contents '((a b c) (d e f)))
;; is equivalent to the following. Note, the 'inner most' array arrays must have the same number of objects, i.e. lisp won't auto-fill them with nil or anything else.
#2A((A B C) (D E F))
But you don't need to memorize that. Like many other forms, the Lisp reader accepts as input whatever it printed as output of make-array. (Given some caveats that I won't go into, or rather will leave as an exercise for the reader!)
I am working on a problem where I want to travel through a graph. However I can see when I profilate my code that the building of the graph is the heavy part.
Every node should have a value with fixed length M. The graph should contain all combinations of base 2. Thus for example for M = 3, we have: "000" "001" "010" "011" "100" "101" "110" "111", i.e. 2^M = 8 combinations.
I then want to link the nodes together in a very specific way. Every node has two outoing edges, with value "0" and "1". For example "000" will be connected to "001" with edge 1 since if I delete the first number to the right and add the edges value at the end I will end up with "001". Similarily "111" is connedted to "110" by the edge "0".
Help needed. Note that the nodes does not necessary have to be represented with String but this was how I implemented but it seems to run too slow. The important things here is that the nodes are connected correctly.
I have solved this by storing the nodes in a HashTable and then looping through the whole set to connect the nodes to eachother.
Suggestions appreciated how to make this smarter.
UPDATE:
So you basically want to take a number and derive two numbers from it
shift it one bit to the left and unset the first bit, and let the last bit be zero
the same as above but set the last bit to be one
Now this number is connected to these 2 numbers described above.
That is my understanding.
Here is some code I wrote to compute such a graph:
import pygraphviz as pgv
# length of binary codes
for n in range(3,8):
def b(x):
return str(bin(x))[2:].zfill(n)
G=pgv.AGraph(directed=True)
for i in range(1,2**n):
for j in range(1,2**n):
I = b(i)
J = b(j)
# we make room for another bit (the zero bit)
i1 = i << 1
# we unset the first bit
i1 = i1 & ~(1<<(n+1))
# we copy the previous result
i2 = i1
# we set the last bit
i2 = i2 | 1
if i1 == j :
G.add_edge(I,J,label="0")
elif i2 == j:
G.add_edge(I,J,label="1")
G.layout(prog='dot')
G.draw("graph"+str(n)+".png")
n=3
n=4
n=5
n=6
P.S. Initially I tried using networkx, but soon realized pygraphviz was much easier to use for this.
Given that your vertexes are actually numbers, why don't you use adjacency matrix where column and row numbers represent the vertexes?
I read a lot of documentation about Clojure (and shall need to read it again) and read several Clojure questions here on SO to get a "feel" of the language. Besides a few tiny functions in elisp I've never written in any Lisp language before. I wrote my first project Euler solution in Clojure and before going further I'd like to better understand something about map and reduce.
Using a lambda, I ended up with the following (to sum all multiple of either 3 or 5 or both between 1 and 1000 inclusive):
(reduce + (map #(if (or (= 0 (mod %1 3)) (= 0 (mod %1 5))) %1 0) (range 1 1000)))
I put it on one line because I wrote it on the REPL (and it gives the correct solution).
Without the lambda, I wrote this:
(defn val [x] (if (or (= 0 (mod x 3)) (= 0 (mod x 5))) x 0))
And then I compute the solution doing this:
(reduce + (map val (range 1 1000)))
In both cases, my question concerns what the map should return, before doing the reduce. After doing the map I noticed I ended up with a list looking like this: (0 0 3 0 5 6 ...).
I tried removing the '0' at the end of the val definition but then I received a list made of (nil nil 3 nil 5 6 etc.). I don't know if the nil are an issue or not. I figured out that I was going to sum while doing a fold-left anyway so that the zero weren't really an issue.
But still: what's a sensible map to return? (0 0 3 0 5 6 ...) or (nil nil 3 nil 5 6...) or (3 5 6 ...) (how would I go about this last one?) or something else?
Should I "filter out" the zeroes / nils and if so how?
I know I'm asking a basic question but map/reduce is obviously something I'll be using a lot so any help is welcome.
It sounds like you already have an intuative undestanding of the need to seperate mapping concerns form the reducing It's perfectly natural to have data produced by map that is not used by the reduce. infact using the fact that zero is the identity value for addition make this even more elegant.
mappings job is to produce the new data (in this case 3 5 or "ignore")
reduces job is to decide what to include and to produce the final result.
what you started with is idiomatic clojure and there is no need to complicate it any more,
so this next example is just to illustrate the point of having map decide what to include:
(reduce #(if-not (zero? %1) (+ %1 %2) %2) (map val (range 10)))
in this contrived example the reduce function ignores the zeros. In typical real world code if the idea was as simple as filtering out some value then people tend to just use the filter function
(reduce + (filter #(not (zero? %)) (map val (range 10))))
you can also just start with filter and skip the map:
(reduce + (filter #(or (zero? (rem % 3)) (zero? (rem % 5))) (range 10)))
The watchword is clarity.
Use filter, not map. Then you don't have to choose a null
value that you later have to decide not to act on.
Naming the filtering/mapping function can help. Do so with let
or letfn, not defn, unless you have use for the function elsewhere.
Acting on this advice brings us to ...
(let [divides-by-3-or-5? (fn [n] (or (zero? (mod n 3)) (zero? (mod n 5))))]
(reduce + (filter divides-by-3-or-5? (range 1 1000))))
You may want to stop here for now.
This reads well, but the divides-by-3-or-5? function sticks in the throat. Change the factors and we need a completely new function. And that repeated phrase (zero? (mod n ...)) jars. So ...
We want a function, that - given a list (or other collection) of possible factors - tells us whether any of them apply to a given number. In other words, we want
a function of a collection of numbers - the possible factors - ...
that returns a function of one number - the candidate - ...
that tells us whether the candidate is divisible by any of the possible factors.
One such function is
(fn [ns] (fn [n] (some (fn [x] (zero? (mod n x))) ns)))
... which we can employ thus
(let [divides-by-any? (fn [ns] (fn [n] (some (fn [x] (zero? (mod n x))) ns)))]
(reduce + (filter (divides-by-any? [3 5]) (range 1 1000))))
Notes
This "improvement" has made the program a little slower.
divides-by-any? might prove useful enough to be promoted to a
defn.
If the operation were critical, you could consider stripping out
redundant factors. For example [2 3 6] could be reduced to [6].
If the operation were really critical, and the factors were supplied
as constants, you could consider creating the filter function with a
macro that went back to using or.
This is a bit of a shaggy-dog story, but it recounts the thoughts prompted by the problem you refer to.
In your case I would use keep instead of map. It is similar to map except that it keeps only the non-nil values.