Check occurrence of keyword with value in sublist - lisp

I have a data structure, consisting of property lists within lists, which are themselves inside a list. Essentially a 2d matrix of plists. It's of the form:
(((:VALUE 0 :GROUP 0) (:VALUE 0 :GROUP 0))
((:VALUE 0 :GROUP 0) (:VALUE 0 :GROUP 0))
((:VALUE 0 :GROUP 0) (:VALUE 0 :GROUP 0)))
Each :value and :group will contain an arbitrary integer value. I need to find if any of the :group keywords are 0. I've been trying to achieve this with the member function, but it only ever returns nil.
My code, assuming the data structure is called data, is:
(member '(:group 0) data :test 'equal))
How would I use the member function to check the occurrence of :group 0 in a sublist of a sublist? (if indeed that's possible, or should I just use a couple of loops to iterate through?)

Try getf as
the :key
for find/find-if
and/or remove/remove-if-not:
Level 1 nesting
Prepare the data
(defparameter *data-1*
(loop repeat 10 collect (list :value (random 10) :group (random 10))))
*data-1*
((:VALUE 7 :GROUP 4) (:VALUE 9 :GROUP 6) (:VALUE 2 :GROUP 7) (:VALUE 8 :GROUP 2)
(:VALUE 5 :GROUP 6) (:VALUE 4 :GROUP 7) (:VALUE 3 :GROUP 5) (:VALUE 8 :GROUP 7)
(:VALUE 0 :GROUP 3) (:VALUE 5 :GROUP 5))
A: Find the 1st occurrence of group 7:
(find 7 *data-1* :key (lambda (pl) (getf pl :group)))
==> (:VALUE 2 :GROUP 7)
B: Find all occurrences of group 7:
(remove 7 *data-1* :key (lambda (pl) (getf pl :group)) :test-not #'eql)
==> ((:VALUE 2 :GROUP 7) (:VALUE 4 :GROUP 7) (:VALUE 8 :GROUP 7))
Level 2 nesting
Prepare the data:
(defparameter *data-2*
(loop repeat 10 collect
(loop repeat (random 4) collect
(list :value (random 10) :group (random 10)))))
*data-2*
(((:VALUE 9 :GROUP 9) (:VALUE 8 :GROUP 2) (:VALUE 6 :GROUP 7)) NIL
((:VALUE 9 :GROUP 5)) ((:VALUE 9 :GROUP 1)) NIL
((:VALUE 2 :GROUP 7) (:VALUE 6 :GROUP 5) (:VALUE 2 :GROUP 1))
((:VALUE 1 :GROUP 4) (:VALUE 5 :GROUP 5))
((:VALUE 9 :GROUP 7) (:VALUE 9 :GROUP 8) (:VALUE 7 :GROUP 4))
((:VALUE 4 :GROUP 7)) NIL)
C: Find the 1st occurrence of group 7:
(find-if (lambda (l)
(find 7 l :key (lambda (pl) (getf pl :group))))
*data-2*)
==> ((:VALUE 9 :GROUP 9) (:VALUE 8 :GROUP 2) (:VALUE 6 :GROUP 7))
D: Find all occurrences of group 7:
(remove-if-not (lambda (l)
(find 7 l :key (lambda (pl) (getf pl :group))))
*data-2*)
==>
(((:VALUE 9 :GROUP 9) (:VALUE 8 :GROUP 2) (:VALUE 6 :GROUP 7))
((:VALUE 2 :GROUP 7) (:VALUE 6 :GROUP 5) (:VALUE 2 :GROUP 1))
((:VALUE 9 :GROUP 7) (:VALUE 9 :GROUP 8) (:VALUE 7 :GROUP 4))
((:VALUE 4 :GROUP 7)))
Define functions:
Depending on your needs, you might want to define functions
(defun get-group (plist)
(getf plist :group))
(defun find-group (list-of-plists group)
(find group list-of-plists :key #'get-group))
(defun make-group-finder (group)
(lambda (list-of-plists) (find-group list-of-plists group)))
Now you can use them for the tasks above:
A: (find-group *data-1* 7)
B: (remove 7 *data-1* :key #'get-group :test-not #'eql)
C: (find-if (make-group-finder 7) *data-2*)
D: (remove-if-not (make-group-finder 7) *data-2*)
PS remove-if-not is the Lisp idiom for "filter".

Related

Creating a function using DrRacket that takes two lists and outputs it as a fraction

Write a function that takes two lists of numbers, numerators and denominators, and returns a list of fractions produced by dividing numerators by denominators. If one list is shorter than the other, assume that the corresponding numbers are all 1s. Don't worry about zeros in the denominators (it's ok if your function breaks when dividing by zero).
Input: (list 1 2 3) (list 1 3 5)
Output: (list 1/1 2/3 3/5)
You can solve it by recursion:
(define (r-map func l1 l2 (default-l1 1) (default-l2 1) (acc '()))
(cond ((and (null? l1) (null? l2)) (reverse acc))
((null? l1) (r-map func '() (cdr l2) default-l1 default-l2 (cons (func default-l1 (car l2)) acc)))
((null? l2) (r-map func (cdr l1) '() default-l1 default-l2 (cons (func (car l1) default-l2) acc)))
(else (r-map func (cdr l1) (cdr l2) default-l1 default-l2 (cons (func (car l1) (car l2)) acc)))))
The nice thing with this function is that you can change the default value for each list independently from each other.
Test it:
(define a '(1 2 3))
(define b '(4 5 6))
(define c '(10 20))
(define d '(40 50 60 70))
;; run all combinations of the four:
(let ((lists (list a b c d)))
(for*/list [(x lists)
(y lists)]
(list `(r-map ,x ,y ,default-l1 ,default-l2) '=> (r-map / x y))))
It returns:
Welcome to DrRacket, version 6.11 [3m].
Language: racket, with debugging; memory limit: 128 MB.
'(((r-map (1 2 3) (1 2 3) 1 1) => (1 1 1))
((r-map (1 2 3) (4 5 6) 1 1) => (1/4 2/5 1/2))
((r-map (1 2 3) (10 20) 1 1) => (1/10 1/10 3))
((r-map (1 2 3) (40 50 60 70) 1 1) => (1/40 1/25 1/20 1/70))
((r-map (4 5 6) (1 2 3) 1 1) => (4 2 1/2 2))
((r-map (4 5 6) (4 5 6) 1 1) => (1 1 1))
((r-map (4 5 6) (10 20) 1 1) => (2/5 1/4 6))
((r-map (4 5 6) (40 50 60 70) 1 1) => (1/10 1/10 1/10 1/70))
((r-map (10 20) (1 2 3) 1 1) => (10 10 1/3))
((r-map (10 20) (4 5 6) 1 1) => (2 1/2 4 1/6))
((r-map (10 20) (10 20) 1 1) => (1 1))
((r-map (10 20) (40 50 60 70) 1 1) => (1/4 2/5 1/60 1/70))
((r-map (40 50 60 70) (1 2 3) 1 1) => (40 25 20 70))
((r-map (40 50 60 70) (4 5 6) 1 1) => (10 10 10 70))
((r-map (40 50 60 70) (10 20) 1 1) => (4 2 1/2 60 70))
((r-map (40 50 60 70) (40 50 60 70) 1 1) => (1 1 1 1)))
Let's do this a bit more straightforwardly.
There are two simple cases:
Both lists are empty; the result is '()
Neither list is empty; cons the fraction of the cars onto the result of recursing.
Short-circuiting out the tricky cases:
(define (fractions ns ds)
(cond [(and (null? ns) (null? ds)) '()]
[(null? ns) 'only-denominators]
[(null? ds) 'only-numerators]
[else (cons (/ (car ns) (car ds)) (fractions (cdr ns) (cdr ds)))]))
Test:
> (fractions '() '())
'()
> (fractions '(1 2) '(4 5))
'(1/4 2/5)
> (fractions '(1 2 3) '(4 5))
'(1/4 2/5 . only-numerators)
> (fractions '(1 2) '(4 5 6))
'(1/4 2/5 . only-denominators)
If there are only numerators, the results are the same as those numerators, since x/1 is the same as x:
...
[(null? ds) ns]
...
And if there are only denominators, you divide 1 with each element.
This is easy with map:
...
[(null? ns) (map (lambda (d) (/ 1 d)) ds)]
...
In full:
(define (fractions ns ds)
(cond [(and (null? ns) (null? ds)) '()]
[(null? ns) (map (lambda (d) (/ 1 d)) ds)]
[(null? ds) ns]
[else (cons (/ (car ns) (car ds)) (fractions (cdr ns) (cdr ds)))]))
Test:
> (fractions '() '(4 5 6))
'(1/4 1/5 1/6)
> (fractions '(1 2 3) '())
'(1 2 3)
> (fractions '(1 2 3) '(4 5))
'(1/4 2/5 3)
> (fractions '(1 2) '(4 5 6))
'(1/4 2/5 1/6)

Can this type of problem be easily expressed in logic programming paradigm?

For simplicity, this is a toy version of the actual problem: given a set of integers, find the longest sequence of consecutive numbers from that set.
I looked at CLIPS and other expert systems, and they seem ill-suited to express this kind of problem. Specifically, I don't see a list like data structure, which seems to be necessary to implement a solution. I'm looking for an example of implementation using logic programming.
One way:
CLIPS (6.4 2/9/21)
CLIPS>
(deffacts start
(set 1 9 2 10 4 3 11 13 5 14))
CLIPS>
(defrule combine-1
?f <- (set $?b ?n $?e)
=>
(retract ?f)
(assert (combine ?n))
(assert (set ?b ?e)))
CLIPS>
(defrule combine-2
?f1 <- (combine $?b ?j1)
?f2 <- (combine ?j2&=(+ ?j1 1) $?e)
=>
(retract ?f1 ?f2)
(assert (combine ?b ?j1 ?j2 ?e)))
CLIPS>
(defrule longest
(declare (salience -10))
(combine $?c)
(not (combine $?o&:(> (length$ ?o) (length$ ?c))))
=>
(println "Longest is " ?c))
CLIPS> (reset)
CLIPS> (run)
Longest is (1 2 3 4 5)
CLIPS> (facts)
f-21 (set)
f-22 (combine 13 14)
f-26 (combine 1 2 3 4 5)
f-28 (combine 9 10 11)
For a total of 4 facts.
CLIPS>
Another way:
CLIPS> (clear)
CLIPS>
(deffacts start
(set 1 9 2 10 4 3 11 13 5 14))
CLIPS>
(defrule sort
?f <- (set $?s)
(test (neq ?s (sort > ?s)))
=>
(retract ?f)
(assert (set (sort > ?s))))
CLIPS>
(deffunction consecutive ($?s)
(loop-for-count (?i (- (length$ ?s) 1))
(if (<> (+ (nth$ ?i ?s) 1) (nth$ (+ ?i 1) ?s))
then (return FALSE)))
(return TRUE))
CLIPS>
(defrule longest
(set $? $?s&:(consecutive $?s) $?)
(not (set $? $?s2&~$?s&:(consecutive $?s2)&:(> (length$ ?s2) (length$ ?s)) $?))
=>
(println "Longest is " ?s))
CLIPS> (reset)
CLIPS> (run)
Longest is (1 2 3 4 5)
CLIPS> (facts)
f-2 (set 1 2 3 4 5 9 10 11 13 14)
For a total of 1 fact.
CLIPS>

Algorithms for moving the cursor to a date on a 12 month rotating calendar in Emacs

GOAL:  The goal of this thread is to create two (2) mathematical formulas to replace the long-hand solution by #lawlist in the function lawlist-calendar-cursor-to-visible-date (below).
                                                            STORY PROBLEM
There now exists a 12-month calendar in Emacs that scrolls forwards and backwards one month (or more) at a time. The function lawlist-calendar-cursor-to-visible-date is used to mark dates with overlays for designated events (e.g., birthdays, holidays, appointments, etc.); or, to simply move the cursor to a particular date. #lawlist has devised a solution by long-hand, which does not entirely use mathematical equations to calculate the cursor position for each of the 365 days that are displayed. It may be possible to create two (2) concise algorithms to replace the long-hand solution.
A working draft of the 12-month scrolling calendar (without the long-hand solution) may be found here:
     https://stackoverflow.com/a/21409154/2112489
LEGEND:
displayed-month (numbers 1 through 12) is the month that appears in the upper left-hand corner of the buffer, and this changes as the 12-month calendar is scrolled forwards or backwards.
The target month (numbers 1 through 12) is the month that we need to locate with assistance from the two mathematical formulas -- its location varies depending upon the date being marked (e.g., birthday, holiday, appointment), and depending upon the displayed-month in the upper left-hand corner of the buffer. The target month can be in any one of 12 possible positions. There are three (3) possible x axis coordinates (i.e., 6, 31, or 56). There are four (4) possible y axis coordinates (i.e., 0, 9, 18 or 27). [Citation to x / y coordinates: http://www.mathsisfun.com/data/cartesian-coordinates.html ]
A row is defined as 3 months horizontally.
A column is defined as 4 months vertically.
The first forumula must equal 0, 9, 18 or 27 depending upon whether the point is on row 1, 2, 3 or 4 -- i.e., from top to bottom.
The second forumula must equal 6, 31, or 56 depending upon whether the point is on column 1, 2 or 3 -- i.e., from left to right.
EXAMPLE:
If displayed-month is January (i.e., 1) and the target month is August (i.e., 8), then row equals 18 and column equals 31.
If displayed-month is February (i.e., 2) and the target month is August (i.e., 8), then row equals 18 and column equals 6.
If displayed-month is March (i.e., 3) and the target month is August (i.e., 8), then row equals 9 and column equals 56.
If displayed-month is April (i.e., 4) and target month is August (i.e., 8), then row equals 9 and column equals 31.
If displayed-month is May (i.e., 5) and the target month is August (i.e., 8), then row equals 9 and column equals 6.
The 12-month calendar looks like the following as the layout scrolls forward one month at a time:
;; 1 2 3
;; 4 5 6
;; 7 8 9
;; 10 11 12
;; 2 3 4
;; 5 6 7
;; 8 9 10
;; 11 12 1
;; 3 4 5
;; 6 7 8
;; 9 10 11
;; 12 1 2
;; 4 5 6
;; 7 8 9
;; 10 11 12
;; 1 2 3
;; 5 6 7
;; 8 9 10
;; 11 12 1
;; 2 3 4
;; 6 7 8
;; 9 10 11
;; 12 1 2
;; 3 4 5
;; 7 8 9
;; 10 11 12
;; 1 2 3
;; 4 5 6
;; 8 9 10
;; 11 12 1
;; 2 3 4
;; 5 6 7
;; 9 10 11
;; 12 1 2
;; 3 4 5
;; 6 7 8
;; 10 11 12
;; 1 2 3
;; 4 5 6
;; 7 8 9
;; 11 12 1
;; 2 3 4
;; 5 6 7
;; 8 9 10
;; 12 1 2
;; 3 4 5
;; 6 7 8
;; 9 10 11
The long-hand solution by #lawlist is as follows:
(defun lawlist-calendar-cursor-to-visible-date (date)
"Move the cursor to DATE that is on the screen."
(let* (
(month (calendar-extract-month date))
(day (calendar-extract-day date))
(year (calendar-extract-year date))
(first-of-month-weekday (calendar-day-of-week (list month 1 year))))
(goto-line
(+ 3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(cond
;; 1 2 3
;; 4 5 6
;; 7 8 9
;; 10 11 12
((and
(eq displayed-month 1)
(memq month `(1 2 3)))
0)
((and
(eq displayed-month 1)
(memq month `(4 5 6)))
9)
((and
(eq displayed-month 1)
(memq month `(7 8 9)))
18)
((and
(eq displayed-month 1)
(memq month `(10 11 12)))
27)
;; 2 3 4
;; 5 6 7
;; 8 9 10
;; 11 12 1
((and
(eq displayed-month 2)
(memq month `(2 3 4)))
0)
((and
(eq displayed-month 2)
(memq month `(5 6 7)))
9)
((and
(eq displayed-month 2)
(memq month `(8 9 10)))
18)
((and
(eq displayed-month 2)
(memq month `(11 12 1)))
27)
;; 3 4 5
;; 6 7 8
;; 9 10 11
;; 12 1 2
((and
(eq displayed-month 3)
(memq month `(3 4 5)))
0)
((and
(eq displayed-month 3)
(memq month `(6 7 8)))
9)
((and
(eq displayed-month 3)
(memq month `(9 10 11)))
18)
((and
(eq displayed-month 3)
(memq month `(12 1 2)))
27)
;; 4 5 6
;; 7 8 9
;; 10 11 12
;; 1 2 3
((and
(eq displayed-month 4)
(memq month `(4 5 6)))
0)
((and
(eq displayed-month 4)
(memq month `(7 8 9)))
9)
((and
(eq displayed-month 4)
(memq month `(10 11 12)))
18)
((and
(eq displayed-month 4)
(memq month `(1 2 3)))
27)
;; 5 6 7
;; 8 9 10
;; 11 12 1
;; 2 3 4
((and
(eq displayed-month 5)
(memq month `(5 6 7)))
0)
((and
(eq displayed-month 5)
(memq month `(8 9 10)))
9)
((and
(eq displayed-month 5)
(memq month `(11 12 1)))
18)
((and
(eq displayed-month 5)
(memq month `(2 3 4)))
27)
;; 6 7 8
;; 9 10 11
;; 12 1 2
;; 3 4 5
((and
(eq displayed-month 6)
(memq month `(6 7 8)))
0)
((and
(eq displayed-month 6)
(memq month `(9 10 11)))
9)
((and
(eq displayed-month 6)
(memq month `(12 1 2)))
18)
((and
(eq displayed-month 6)
(memq month `(3 4 5)))
27)
;; 7 8 9
;; 10 11 12
;; 1 2 3
;; 4 5 6
((and
(eq displayed-month 7)
(memq month `(7 8 9)))
0)
((and
(eq displayed-month 7)
(memq month `(10 11 12)))
9)
((and
(eq displayed-month 7)
(memq month `(1 2 3)))
18)
((and
(eq displayed-month 7)
(memq month `(4 5 6)))
27)
;; 8 9 10
;; 11 12 1
;; 2 3 4
;; 5 6 7
((and
(eq displayed-month 8)
(memq month `(8 9 10)))
0)
((and
(eq displayed-month 8)
(memq month `(11 12 1)))
9)
((and
(eq displayed-month 8)
(memq month `(2 3 4)))
18)
((and
(eq displayed-month 8)
(memq month `(5 6 7)))
27)
;; 9 10 11
;; 12 1 2
;; 3 4 5
;; 6 7 8
((and
(eq displayed-month 9)
(memq month `(9 10 11)))
0)
((and
(eq displayed-month 9)
(memq month `(12 1 2)))
9)
((and
(eq displayed-month 9)
(memq month `(3 4 5)))
18)
((and
(eq displayed-month 9)
(memq month `(6 7 8)))
27)
;; 10 11 12
;; 1 2 3
;; 4 5 6
;; 7 8 9
((and
(eq displayed-month 10)
(memq month `(10 11 12)))
0)
((and
(eq displayed-month 10)
(memq month `(1 2 3)))
9)
((and
(eq displayed-month 10)
(memq month `(4 5 6)))
18)
((and
(eq displayed-month 10)
(memq month `(7 8 9)))
27)
;; 11 12 1
;; 2 3 4
;; 5 6 7
;; 8 9 10
((and
(eq displayed-month 11)
(memq month `(11 12 1)))
0)
((and
(eq displayed-month 11)
(memq month `(2 3 4)))
9)
((and
(eq displayed-month 11)
(memq month `(5 6 7)))
18)
((and
(eq displayed-month 11)
(memq month `(8 9 10)))
27)
;; 12 1 2
;; 3 4 5
;; 6 7 8
;; 9 10 11
((and
(eq displayed-month 12)
(memq month `(12 1 2)))
0)
((and
(eq displayed-month 12)
(memq month `(3 4 5)))
9)
((and
(eq displayed-month 12)
(memq month `(6 7 8)))
18)
((and
(eq displayed-month 12)
(memq month `(9 10 11)))
27) )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(/ (+ day -1
(mod
(- (calendar-day-of-week (list month 1 year)) calendar-week-start-day)
7))
7)))
(move-to-column
(+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(cond
;; 1 2 3
;; 4 5 6
;; 7 8 9
;; 10 11 12
((and
(eq displayed-month 1)
(memq month `(1 4 7 10)))
6)
((and
(eq displayed-month 1)
(memq month `(2 5 8 11)))
31)
((and
(eq displayed-month 1)
(memq month `(3 6 9 12)))
56)
;; 2 3 4
;; 5 6 7
;; 8 9 10
;; 11 12 1
((and
(eq displayed-month 2)
(memq month `(2 5 8 11)))
6)
((and
(eq displayed-month 2)
(memq month `(3 6 9 12)))
31)
((and
(eq displayed-month 2)
(memq month `(4 7 10 1)))
56)
;; 3 4 5
;; 6 7 8
;; 9 10 11
;; 12 1 2
((and
(eq displayed-month 3)
(memq month `(3 6 9 12)))
6)
((and
(eq displayed-month 3)
(memq month `(4 7 10 1)))
31)
((and
(eq displayed-month 3)
(memq month `(5 8 11 2)))
56)
;; 4 5 6
;; 7 8 9
;; 10 11 12
;; 1 2 3
((and
(eq displayed-month 4)
(memq month `(4 7 10 1)))
6)
((and
(eq displayed-month 4)
(memq month `(5 8 11 2)))
31)
((and
(eq displayed-month 4)
(memq month `(6 9 12 3)))
56)
;; 5 6 7
;; 8 9 10
;; 11 12 1
;; 2 3 4
((and
(eq displayed-month 5)
(memq month `(5 8 11 2)))
6)
((and
(eq displayed-month 5)
(memq month `(6 9 12 3)))
31)
((and
(eq displayed-month 5)
(memq month `(7 10 1 4)))
56)
;; 6 7 8
;; 9 10 11
;; 12 1 2
;; 3 4 5
((and
(eq displayed-month 6)
(memq month `(6 9 12 3)))
6)
((and
(eq displayed-month 6)
(memq month `(7 10 1 4)))
31)
((and
(eq displayed-month 6)
(memq month `(8 11 2 5)))
56)
;; 7 8 9
;; 10 11 12
;; 1 2 3
;; 4 5 6
((and
(eq displayed-month 7)
(memq month `(7 10 1 4)))
6)
((and
(eq displayed-month 7)
(memq month `(8 11 2 5)))
31)
((and
(eq displayed-month 7)
(memq month `(9 12 3 6)))
56)
;; 8 9 10
;; 11 12 1
;; 2 3 4
;; 5 6 7
((and
(eq displayed-month 8)
(memq month `(8 11 2 5)))
6)
((and
(eq displayed-month 8)
(memq month `(9 12 3 6)))
31)
((and
(eq displayed-month 8)
(memq month `(10 1 4 7)))
56)
;; 9 10 11
;; 12 1 2
;; 3 4 5
;; 6 7 8
((and
(eq displayed-month 9)
(memq month `(9 12 3 6)))
6)
((and
(eq displayed-month 9)
(memq month `(10 1 4 7)))
31)
((and
(eq displayed-month 9)
(memq month `(11 2 5 8)))
56)
;; 10 11 12
;; 1 2 3
;; 4 5 6
;; 7 8 9
((and
(eq displayed-month 10)
(memq month `(10 1 4 7)))
6)
((and
(eq displayed-month 10)
(memq month `(11 2 5 8)))
31)
((and
(eq displayed-month 10)
(memq month `(12 3 6 9)))
56)
;; 11 12 1
;; 2 3 4
;; 5 6 7
;; 8 9 10
((and
(eq displayed-month 11)
(memq month `(11 2 5 8)))
6)
((and
(eq displayed-month 11)
(memq month `(12 3 6 9)))
31)
((and
(eq displayed-month 11)
(memq month `(1 4 7 10)))
56)
;; 12 1 2
;; 3 4 5
;; 6 7 8
;; 9 10 11
((and
(eq displayed-month 12)
(memq month `(12 3 6 9)))
6)
((and
(eq displayed-month 12)
(memq month `(1 4 7 10)))
31)
((and
(eq displayed-month 12)
(memq month `(2 5 8 11)))
56) )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(* 3 (mod
(- (calendar-day-of-week date) calendar-week-start-day)
7))))))
I must be missing something because it looks like the formulas are as simple as (pseudocode):
first = 9 * ( rows - 1 )
second = 6 + 25 * ( cols - 1 )
based on your edit, you can calculate the rows and cols to move with:
if target > display
difference = target - display
else
difference = 12 + target - display
rows = difference / 3
cols = difference % 3
rowmove = 9 * rows
colmove = 6 + 25 * cols
And then use the formula above.
My attempt at elisp:
(let difference (if (>= target-month display-month)
(- target-month display-month)
(- (+ target-month 12) display-month)))
(let rows (/ difference 3))
(let cols (% difference 3))
(let rowmove (* 9 rows))
(let colmove (+ 6 (* 25 cols)))

How to print a list as matrix in Common Lisp

I am working in Common Lisp, trying to make Windows game minesweeper.
I have a list (1 1 1 2 2 2 3 3 3) and want to print that like matrix
(1 1 1
2 2 2
3 3 3)
How to do that?
Edit
I am at the beginning of
(format t "Input width:")
(setf width (read))
(format t "Input height:")
(setf height (read))
(format t "How many mines:")
(setf brMina (read))
(defun matrica (i j)
(cond ((= 0 i) '())
(t (append (vrsta j) (matrica (1- i) j) ))))
(setf minefield (matrica width height))
(defun stampaj ()
(format t "~%~a" minefield ))
Another example, using the pretty-printer for fun:
(defun print-list-as-matrix
(list elements-per-row
&optional (cell-width (1+ (truncate (log (apply #'max list) 10)))))
(let ((*print-right-margin* (* elements-per-row (1+ cell-width)))
(*print-miser-width* nil)
(*print-pretty* t)
(format-string (format nil "~~<~~#{~~~ad~~^ ~~}~~#:>~%" cell-width)))
(format t format-string list)))
Works like this:
CL-USER> (print-list-as-matrix (loop for i from 1 to 9 collect i) 3)
1 2 3
4 5 6
7 8 9
NIL
CL-USER> (print-list-as-matrix (loop for i from 1 to 25 collect i) 5)
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
NIL
CL-USER> (print-list-as-matrix (loop for i from 1 to 16 collect i) 2)
1 2
3 4
5 6
7 8
9 10
11 12
13 14
15 16
Like this:
(defun print-list-as-grid (list rows cols)
(assert (= (length list) (* rows cols))
(loop for row from 0 below rows do
(loop for col from 0 below cols do
(princ (car list))
(princ #\space)
(setf list (cdr list)))
(princ #\newline)))
* (print-list-as-grid '(a b c d e f g h i) 3 3)
A B C
D E F
G H I
NIL

defining a starting point for dolist

Is it possible to tell dolist to start at (or even better after) a certain element in the given list? As I may not want to evaluate all the elements before.
If there is no way to do so, is there any other macro which might do the job?
Considering this example:
(defvar *liste* #(1 2 3 4 5 6))
(dolist (x *liste* :start-after: '4)
(FORMAT t "~a~%" x))
resulting in:
5
6
Which Lisp dialect are we talking about?
Assuming Common Lisp.
#(1 2 3 4 5 6) is not a list. It is a vector.
CL-USER > (let ((v #(1 2 3 4 5 6)))
(loop for i from 4 below (length v)
do (print (aref v i))))
5
6
NIL
With a list:
CL-USER 1 > (mapc #'print (nthcdr 4 '(1 2 3 4 5 6)))
5
6
(5 6)
What's wrong with NTHCDR?
http://www.lispworks.com/documentation/HyperSpec/Body/f_nthcdr.htm#nthcdr