Lisp links thread

Coders forum. Discuss techniques, swap code snippets, ask for help etc. relating to all forms of software development.
Post Reply
User avatar
failrate
Baaaaaa!
Baaaaaa!
Posts: 2354
Joined: Sun May 23, 2004 6:54 am 0
Location: Sandy Eggo
Contact:

Post by failrate »

ooh, haven't heard about that one. What's the performance on (amb) like? I might be curious to try that for my Void Snipers beam cannon :D (its height is clamped to the first collision it encounters).
User avatar
teamonkey
Sheepie Whore
Sheepie Whore
Posts: 12082
Joined: Thu Jun 13, 2002 1:07 am 0
XBL Gamertag: itsthetaste
PSN: teamonkey_ca
Contact:

Post by teamonkey »

The (color-europe) example takes a good few seconds on my machine, but I've not tried doing the same problems without using (amb). It's probably quite a CPU-intensive task anyway. I suspect it's slower and more memory hungry than doing the same thing by other means, because it uses call-with-current-continuation which I've heard is slow (don't know why, if it's inherently slower than using e.g. continuations in Python or Lua, or anything like that). I hope continuations aren't slow in Scheme - they're immensely useful for game scripting.

I think it's the sort of thing that might want to do with data not in real time. E.g. if you had a level editor with your game you could use it to easily do some quite complex sanity checking.

It's actually a go-back-in-time operator. When you call (amb ...) with parameters it uses call/cc to save the current program state at that instant on the end of a list. It helped me to think of the C example - it saved the current state of the call stack and all the CPU registers - although Scheme will do things differently internally. When (amb) is called without parameters the current program state is replaced by the last one that was stored, forgetting everything else that's been done in the meanwhile, effectively jumping back in time to the last point that it was called.
User avatar
failrate
Baaaaaa!
Baaaaaa!
Posts: 2354
Joined: Sun May 23, 2004 6:54 am 0
Location: Sandy Eggo
Contact:

Post by failrate »

Ah, okay, so I'll just stick with an early-out loop. That's more computation power than I need in this particular example, although I will keep it in mind if I ever need to do some pre-rendered paths or such.
User avatar
Riddik
Baaa!
Baaa!
Posts: 378
Joined: Mon Jul 09, 2007 4:07 am 0
Location: Wilmot, Tasmania
Contact:

Post by Riddik »

What about AutoLISP, which is the embedded script language in AutoCAD, which (for those that don't know) is derived from standard LISP only with the ability to use AutoCAD's direct input commands, along the lines of:

Code: Select all

(command "line" 1stpnt 2ndpnt 3rdpnt 4thpnt "c")
inside a normal (defun c: () .... ) function???

I've made some small routines that help in every day stuff like offsetting lines many times, rather than select, click, select, click. So it's automated depending on how many offset's are needed.
adam
Baaaaaa!
Baaaaaa!
Posts: 4418
Joined: Sat Jun 24, 2006 9:15 pm 0

Post by adam »

i've never used autolisp/cad, i did see a page recently about using it to draw fractal-ish patterns, which i imagine would go down well in the engineering world

"have you designed those missiles yet?"
"yes, i've been concentrating on the new infinitely recursive tailfin-thing"

something like that ;-)

what kind of stuff do you use it for?
User avatar
Riddik
Baaa!
Baaa!
Posts: 378
Joined: Mon Jul 09, 2007 4:07 am 0
Location: Wilmot, Tasmania
Contact:

Post by Riddik »

Primarily for the design of HVAC systems (High Volume Air Conditioning), where I have to work out duct sizing, air flow, and unit size to provide the amount of air flow to keep up the static pressure inside the duct. Just recently, we did one that had to maintain about 10,000 litres per second.....

With the AutoLISP side of things, I generally make small scripts to automate things a little, for eg. there's a command called "offset", which allows the user to offset lines, objects, curves, and such a predetermined distance, then the user selects the element to be offset, then the direction to offset the element, to get more than one, the user must keep select an element, then a side, repeatedly until the desired amount.

As you can imagine, some building's that use T-bar ceilings to hold ceiling tiles up, can have hundred's if not thousands of lines to represent the T-Bar ceiling. So instead of having to offset each line one at a time. I made an AutoLISP Script that asks, the offset distance, direction, and number of offsets, than lastly asks the user to select the element to offset, then performs the desired amount.

Typically, instead of a ceiling grid taking 5 10 and sometimes 30mins to do, takes seconds using this little script.

Other than, that, other things are just small snipets to calculate volumes of selected 3d objects, and converting that to how much airflow is needed at the beginning to keep static pressure at the end.

NCOT time after that lot, me thinks.....
adam
Baaaaaa!
Baaaaaa!
Posts: 4418
Joined: Sat Jun 24, 2006 9:15 pm 0

Post by adam »

yeah that sounds pretty full-on, i saw some traditional arab design that cools buildings totally passively (these big chimmney things i think), doubt it'd do 10000 litres a second though ;-)
adam
Baaaaaa!
Baaaaaa!
Posts: 4418
Joined: Sat Jun 24, 2006 9:15 pm 0

Post by adam »

http://lispm.dyndns.org/genera-concepts/genera.html

page about the lisp machine, looks like an old brochure
User avatar
teamonkey
Sheepie Whore
Sheepie Whore
Posts: 12082
Joined: Thu Jun 13, 2002 1:07 am 0
XBL Gamertag: itsthetaste
PSN: teamonkey_ca
Contact:

Post by teamonkey »

Hehe.

Code: Select all

; test-grid
(define test-grid
  '((* 3 1 * 4 8 * * 6)
    (6 * 4 9 * * * * 1)
    (* * * * * 5 3 * *)
    (2 * * 4 * * * 8 5)
    (4 * * 6 * * * 9 *)
    (* 5 * * * 9 4 * *)
    (* * 7 * * 1 5 * *)
    (* 6 9 * * * * * 7)
    (* * * * 3 * 8 2 *)))


; Displays a sudoku grid
(define (display-grid grid)
  (for-each
   (lambda (row)
     (display row)
     (newline))
   grid))


;; Solves a sudoku. Takes an incomplete grid and returns a solved one.
(define (sudoku-solver grid)
  (letrec ((debug-timer (current-seconds))
           
           ; Grab a subset of a list
           (grab-range 
            (lambda (l index num)
              (let ((short-list ()))
                (do ((i (+ index (- num 1)) (- i 1)))
                  ((< i index) short-list)
                  (set! short-list (cons (list-ref l i) short-list))))))
           
           ; Does a row consist of unique numbers?
           (list-unique?
            (lambda (row)
              (if (not (pair? row))
                  #t
                  (if (memq (car row) (cdr row))
                      #f
                      (list-unique? (cdr row))))))
                
                
           ; For each row, replace all '* with (amb 1..9)
           (solved-grid
            (map
             (lambda (row)
               (map
                (lambda (atom)
                  (if (eq? atom '*)
                      (amb 1 2 3 4 5 6 7 8 9)
                      atom))
                row))
             grid)))
    
    ; Uncomment this if you want to display the grid every 10 seconds or so to show progress
    ;(if (> (current-seconds) (+ debug-timer 10))
    ;    (begin
    ;      (display-grid solved-grid)
    ;      (newline)
    ;      (set! debug-timer (current-seconds))))
    
    
    ; Sudoku game rules
    ; .. 1-9 in each row
    (for-each
     (lambda (row)
       (if (not (list-unique? row))
           (amb)))
     solved-grid)
    
    ; .. 1-9 in each column
    ; We simply remap each column element to a single list and run list-unique on it
    (do ((i 0 (+ i 1)))
      ((>= i (length (car solved-grid))))
      (if
       (not (list-unique?
             (map
              (lambda (row)
                (list-ref row i))
              solved-grid)))
       (amb)))
    
    ; .. 1-9 in each 3x3 block
    (do ((x 0 (+ x 3)))
      ((>= x (length (car solved-grid))))
      (do ((y 0 (+ y 3)))
        ((>= y (length solved-grid)))
        (if
         (not (list-unique?
               (append
                (grab-range (list-ref solved-grid y) x 3)
                (grab-range (list-ref solved-grid (+ y 1)) x 3)
                (grab-range (list-ref solved-grid (+ y 2)) x 3))))
         (amb))))
    
    ; Output the solved grid
    solved-grid))

(sudoku-solver test-grid)
Don't ask me if it works. I'll tell you when it finishes brute-forcing all possible combinations in a few weeks. :D
User avatar
GoatFoam
Baaaaa!
Baaaaa!
Posts: 1255
Joined: Tue Dec 12, 2006 11:05 am 0
Location: Brizzle
Contact:

Post by GoatFoam »

Weeks? You'll be lucky!
adam
Baaaaaa!
Baaaaaa!
Posts: 4418
Joined: Sat Jun 24, 2006 9:15 pm 0

Post by adam »

there's some sudoku solver's here if you want to have a look at them, a couple in lisp and some in other languages (including postscript by the looks)

http://programming.reddit.com/search?q=sudoku+solver
User avatar
GoatFoam
Baaaaa!
Baaaaa!
Posts: 1255
Joined: Tue Dec 12, 2006 11:05 am 0
Location: Brizzle
Contact:

Post by GoatFoam »

teamonkey wrote:Hehe.
Don't ask me if it works. I'll tell you when it finishes brute-forcing all possible combinations in a few weeks. :D
Haven't you tested it with mini sudoku? Yuo should be able to brute force a 3x3 or 4x4 almost instantly.
User avatar
teamonkey
Sheepie Whore
Sheepie Whore
Posts: 12082
Joined: Thu Jun 13, 2002 1:07 am 0
XBL Gamertag: itsthetaste
PSN: teamonkey_ca
Contact:

Post by teamonkey »

GoatFoam wrote:Haven't you tested it with mini sudoku? Yuo should be able to brute force a 3x3 or 4x4 almost instantly.
Yeah, I tested it with a 3x3 in the REPL while I was writing it. I've never really used a REPL before even though you can have access to one in Lua and Javascript and now I'm a complete convert.

I've written faster, more intelligent sudoku solvers before, but I did it to see exactly how quickly I could write one in Scheme. About 30 minutes for this one, but I got confused by the (do) construct again. I could make it vastly more efficient by quickly scanning rows, columns and blocks for used numbers and then feeding only unused numbers into (amb).

Which reminds me: if you have a list of values that you want to pass in to a function as parameters, what's the best way of doing it?

Code: Select all

(define (myfunc a b c) ...)

(define a-list-of-params '(1 2 3))

; Want to do (myfunc 1 2 3) not (myfunc (1 2 3))
(eval (cons 'myfunc a-list-of-params))
seems rather inelegant.
adam
Baaaaaa!
Baaaaaa!
Posts: 4418
Joined: Sat Jun 24, 2006 9:15 pm 0

Post by adam »

this is a guess, but i think you could write a macro that takes the first element of a list & evaluates it as a function, and the other elements as parameters

i thought that was how it worked anyway, in that you can do (+ 1 2) not have to do (+ (1 2))

or am i missing something?
adam
Baaaaaa!
Baaaaaa!
Posts: 4418
Joined: Sat Jun 24, 2006 9:15 pm 0

Post by adam »

Hacking CL into a Lisp-1 (an intro to code-walking)
http://www.cl-user.net/asp/QF1V/sdataQk ... 3F$sSHnB==
Post Reply