2012-04-27 20 views
7

¿Cuáles son algunas de las formas posibles de representar un tablero de bits de ajedrez en Clojure (/ Java)?¿Cómo debo representar un tablero de bits de ajedrez en clojure?

http://pages.cs.wisc.edu/~psilord/blog/data/chess-pages/rep.html

que necesitan poder acceder a los bits individuales y también llevan a cabo operaciones bit a bit.

Pensé en usar java.lang.Long pero esto causa problemas con 1x10^63 debido a la señalización. Tampoco estoy seguro de cómo accedería a bits en un índice específico.

También miré BitSet, pero necesito una longitud fija idealmente.

+0

'la mejor manera' - muestre su código en http://codereview.stackexchange.com/; 'Como debería' - no constructivo. ¿Qué código tienes? ¿Cuáles son sus requisitos? ¿Dónde estás atrapado? – sehe

+0

@sehe He intentado usar java.lang.Long pero tuve problemas con parseLong() y "10000 ... x63" - 1x10^63) Además, no estoy seguro de si puedo acceder al bit en un momento específico ¿índice? Estoy pidiendo sugerencias e ideas racionalizadas, no necesariamente absolutas. – DanS

+0

Debe editar estos detalles en su pregunta. – sehe

Respuesta

7

No hay ninguna razón por la que no pueda usar una escalera. El problema, como ha notado, es que java (y por lo tanto, clojure) long está firmado, permitiendo solo 63 bits para números positivos

Java, de forma predeterminada, permite el desbordamiento aritmético sin error. Clojure, de forma predeterminada, no permite el desbordamiento aritmético sin error (consulte *unchecked-math* indicador). Agrega verificación adicional alrededor de operaciones aritméticas y conversiones, por lo que, por ejemplo, (byte 128) causará una excepción. Desde v1.3.0 clojure hay funciones como (unchecked-byte) que es equivalente a la funcionalidad java ....

(unchecked-byte 128) 
;=> -128 ; 2s-complement of 10000000 
(unchecked-byte 2r10000001) 
;=> -127 ; 2s-complement of 10000001 

Hay toda una serie de operaciones unchecked-* disponibles (see clojuredocs).

Si usa una recta y las operaciones unchecked-*, la mayoría de las veces está allí, y luego puede usar las operaciones bit-* para doblar/verificar bits.

Finalmente el almacenamiento de su tablero de ajedrez en un átomo tiene sentido, y luego actualizarlo con (swap! chessboard fn args)

(llamadas actualizados 15/02/13 con un poco más de intercambio idiomático!)

por ejemplo,

(inc Long/MAX_VALUE) ; java.lang.ArithmeticException 

(unchecked-inc Long/MAX_VALUE) ; wraps. 
-9223372036854775808 

(def chessboard (atom 0)) 
@chessboard 
;=> 0 
(bit-test @chessboard 1) 
;=> false 
(swap! chessboard bit-flip 1) 
;=> 2 
(bit-test @chessboard 1) 
;=> true 
@chessboard 
;=> 2 
(reset! chessboard 0) 
;=> 0 
(swap! chessboard bit-flip 63) 
;=> -9223372036854775808 
(bit-test @chessboard 63) 
;=> true 
+0

Gracias, muy – DanS

+0

útiles Hmmm, esto debería ser en el núcleo pero por alguna razón estoy consiguiendo: 'user => (sin marcar bytes 2r100101) java.lang.Exception: No se puede resolver símbolo: sin marcar bytes en este contexto (NO_SOURCE_FILE : 4) ' – DanS

+0

No importa, yo estaba en 1.2.1. Ahora, usando 1.4.0 y es reconocido ... – DanS

1
=> (def chessboard (byte-array 8)) 
#'user/chessboard 

=> (vec chessboard) 
[0 0 0 0 0 0 0 0] 

=> (for [row (range 8)] (aset-byte chessboard row (rand-int 8))) 
(3 0 6 6 2 3 6 7) 

=> (bigint chessboard) 
216179404987106823N 

=> (defn bigint-to-array 
[bi] 
(.toByteArray (biginteger bi))) 

=> (vec (bigint-to-array 216179404987106823N)) 
[3 0 6 6 2 3 6 7] 

Clojure es compatible con la mayoría de las funciones que necesita de esta manera. Al igual que todos los números de clojure, clojure.lang.BigInt admite operaciones binarias (bit-y etc.). En una matriz de bytes, puede usar todos los métodos desde java.util.Arrays (buscar, rellenar, ordenar).

Tenga en cuenta que bigint fn coacciona a clojure.lang.BigInt, y el biginteger fn coacciona a java.math.BigInteger. Si desea utilizar los métodos de java.math.BigInteger, necesita forzar su bigint o array de bytes a través de biginteger.

+0

Gracias, no estoy seguro de cómo se podría comparar el rendimiento en comparación con el uso prolongado. Me imagino que es más lento. – DanS

+1

Clojure bigints no admiten operaciones de bits. user => (bit-and (bigint 5) (bigint 3)) Operación de bit IllegalArgumentException no soportada para: class clojure.lang.BigInt clojure.lang.Numbers.bitOpsCast (Numbers.java:1008) – RedDeckWins

Cuestiones relacionadas