#lang racket

;;Relaciones de vecindad según regla 1
(define filas-vecinas
  (lambda (fila-a filas)
    (cond
      ((= fila-a 0) 
       (values filas (add1 fila-a)))
      ((= fila-a filas) 
       (values (sub1 fila-a) 0))
      (else
       (values (sub1 fila-a) (add1 fila-a)) )
      )
    ))
(define columnas-vecinas
  (lambda (columna-a columnas)
    (cond
      ((= columna-a 0) 
       (values columnas (add1 columna-a)))
      ((= columna-a columnas) 
       (values (sub1 columna-a) 0))
      (else
       (values (sub1 columna-a) (add1 columna-a)) )
      )
    ))
(define regla-1
  (lambda (columna-a columnas)
    (let-values
        ([(pre-c post-c) (columnas-vecinas columna-a columnas)])
      (values
       (cons 0 pre-c)
       (cons 0 post-c))
      )
    ))
(define von-Neumann
  (lambda (fila-a columna-a filas columnas)
    (let-values
        ([(pre-f post-f) (filas-vecinas fila-a filas)]
         [(pre-c post-c) (columnas-vecinas columna-a columnas)]
         )
      (values
       (cons pre-f columna-a);T
       (cons fila-a post-c);R
       (cons post-f columna-a);B
       (cons fila-a pre-c);L
       )
      )
    ))
;;von-Neumann con rotacion
;; (values T R B L)
;; (values L T R B)
;; (values B L T R)
;; (values R B L T)
(define Moore
  (lambda (fila-a columna-a filas columnas)
    (let-values
        ([(pre-f post-f) (filas-vecinas fila-a filas)]
         [(pre-c post-c) (columnas-vecinas columna-a columnas)]
         )
;      (printf "~a ~a; ~a ~a~n" pre-f post-f pre-c post-c)
      (values
       (cons pre-f pre-c)
       (cons pre-f columna-a)
       (cons pre-f post-c)
       (cons fila-a post-c)
       (cons post-f post-c)
       (cons post-f columna-a )
       (cons post-f pre-c)
       (cons fila-a pre-c)
       )
      )
    ))

(define filas-2-vecinas
  (lambda (fila-a filas)
    (cond
      ((= fila-a 0) 
       (values (- filas 1) filas fila-a (+ fila-a 1) (+ fila-a 2)))
      ((= fila-a 1)
       (values filas (- fila-a 1) fila-a (+ fila-a 1) (+ fila-a 2)))
      ((= fila-a filas) 
       (values 1 0 fila-a (- filas 1) (- filas 2)))
      ((= fila-a (sub1 filas))
       (values 0 (+ fila-a 1) fila-a (- fila-a 1) (- fila-a 2)))
      (else
       (values (- fila-a 2) (- fila-a 1) fila-a (+ 1 fila-a) (+ 2 fila-a)) )
      )
    ))
(define columnas-2-vecinas
  (lambda (columna-a columnas)
    (cond
      ((= columna-a 0) 
       (values (- columnas 1) columnas columna-a (+ columna-a 1) (+ columna-a 2)))
      ((= columna-a 1)
       (values columnas (- columna-a 1) columna-a (+ columna-a 1) (+ columna-a 2)))
      ((= columna-a columnas) 
       (values (- columnas 2) (- columnas 1) columna-a 0 1))
      ((= columna-a (sub1 columnas))
       (values (- columnas 2) (- columnas 1) columna-a (+ columna-a 1) 0))
      (else
       (values (- columna-a 2) (- columna-a 1) columna-a (+ columna-a 1) (+ columna-a 2)) )
      )
    ))
(define Moore2
  (lambda (fila-a columna-a filas columnas)
    (let-values
        ([(f1 f2 f3 f4 f5) (filas-2-vecinas fila-a filas)]
         [(c1 c2 c3 c4 c5) (columnas-2-vecinas columna-a columnas)]
         )
;      (printf "~a ~a; ~a ~a~n" pre-f post-f pre-c post-c)
      (values
       (cons f1 c1)
       (cons f1 c2)
       (cons f1 c3)
       (cons f1 c4)
       (cons f1 c5)
       (cons f2 c5)
       (cons f3 c5)
       (cons f4 c5)
       (cons f5 c5)
       (cons f5 c4)
       (cons f5 c3)
       (cons f5 c2)
       (cons f5 c1)
       (cons f4 c1)
       (cons f3 c1)
       (cons f2 c1)
       )
      )
    ))

(provide regla-1 von-Neumann Moore Moore2)

