在 Clojure (/Java) 中表示棋盘的可能方式有哪些?
http://pages.cs.wisc.edu/~psilord/blog/data/chess-pages/rep.html
我需要能够访问各个位并执行按位运算。
我想过使用 java.lang.Long 但这会导致 1x10^63 出现问题,因为标牌。我也不确定如何访问特定索引处的位?
我还查看了 BitSet,但理想情况下我需要一个固定的长度。
在 Clojure (/Java) 中表示棋盘的可能方式有哪些?
http://pages.cs.wisc.edu/~psilord/blog/data/chess-pages/rep.html
我需要能够访问各个位并执行按位运算。
我想过使用 java.lang.Long 但这会导致 1x10^63 出现问题,因为标牌。我也不确定如何访问特定索引处的位?
我还查看了 BitSet,但理想情况下我需要一个固定的长度。
没有理由不能使用直长。正如您所指出的,问题在于 java(以及因此 clojure)的 long 是有符号的,仅允许 63 位用于正数
默认情况下,Java 允许算术溢出而不会出错。默认情况下,Clojure 不允许算术溢出而没有错误(参见*unchecked-math*标志)。它增加了对算术运算和强制转换的额外检查,因此例如(byte 128)
会导致异常。由于 clojure v1.3.0 有类似的功能(unchecked-byte)
相当于 java 功能....
(unchecked-byte 128)
;=> -128 ; 2s-complement of 10000000
(unchecked-byte 2r10000001)
;=> -127 ; 2s-complement of 10000001
有大量unchecked-*
可用的操作(请参阅 clojuredocs)。
如果您使用直长并且unchecked-*
您大部分都在那里进行操作,那么您可以使用这些bit-*
操作来旋转/检查位。
最后将你的棋盘存储在一个原子中是有意义的,然后你更新它(swap! chessboard fn args)
(更新于 13 年 2 月 15 日,使用更惯用的交换!调用)
例如
(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
=> (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 以这种方式支持您需要的大多数功能。像所有 clojure 数字一样,clojure.lang.BigInt 支持二进制操作(位等)。在字节数组上,您可以使用java.util.Arrays 中的所有方法(搜索、填充、排序)。
注意 bigint fn 强制转换为 clojure.lang.BigInt,而 biginteger fn 强制转换为 java.math.BigInteger。如果你想使用java.math.BigInteger的方法,你需要通过 biginteger 强制你的 bigint 或字节数组。