2012-04-27 36 views
7

在Clojure(/ Java)中代表棋盘的一些可能的方式是什么?我应该如何在clojure中代表象棋棋盘?

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

我需要能够访问各个位,并执行按位运算。

我想过使用java.lang.Long,但由于标牌,这导致1x10^63的问题。我也不确定我将如何访问特定索引处的位?

我也看了一下BitSet,但是我需要一个固定的长度。

+0

'最好的方式' - 在http://codereview.stackexchange.com/上显示您的代码; '我应该如何' - 不具有建设性。你有什么代码?你有什么要求?你卡在哪里? – sehe 2012-04-27 08:27:27

+0

@sehe我试过使用java.lang.Long但遇到了parseLong()和“10000 ... x63” - 1x10^63的问题)另外,我不确定是否可以访问特定位指数? 我要求合理化的建议和想法,不一定是绝对的。 – DanS 2012-04-27 09:10:58

+0

你应该在你的问题中编辑这些细节。 – sehe 2012-04-27 09:12:18

回答

7

没有理由不能使用直长。正如您所指出的那样,问题在于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-*操作(see clojuredocs)的整个筏。

如果你使用直线长和unchecked-*的操作,你大部分都在那里,然后你可以使用bit-*操作来旋转/检查位。

最后储存您的棋盘中的原子是有道理的,然后你用(swap! chessboard fn args)

(更新15/02/13略有更地道掉!呼叫)更新

例如

(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

非常感谢有帮助 – DanS 2012-04-27 14:21:54

+0

嗯,这应该是在核心,但由于某些原因,我得到: 'user =>(未检查字节2r100101) java.lang.Exception:无法解析符号:在此上下文中未检查字节(NO_SOURCE_FILE :4)' – DanS 2012-04-27 20:28:29

+0

没关系,我在1.2.1上。现在使用1.4.0,它被认可... – DanS 2012-04-27 20:43:48

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支持您需要的大多数功能。像所有clojure数字一样,clojure.lang.BigInt支持二进制操作(比特等)。在字节数组上,您可以使用java.util.Arrays(搜索,填充,排序)中的所有方法。

注意bigint fn强制clojure.lang.BigInt,biginteger fn强制java.math.BigInteger。如果你想使用java.math.BigInteger的方法,你需要通过biginteger强制你的bigint或者字节数组。

+0

谢谢,不知道这将如何比较性能方面与使用long?我想它会变慢。 – DanS 2012-04-27 14:26:49

+1

Clojure bigints不支持位操作。 user =>(bit-and(bigint 5)(bigint 3)) IllegalArgumentException位操作不支持:类clojure.lang.BigInt clojure.lang.Numbers.bitOpsCast(Numbers.java:1008) – RedDeckWins 2013-08-13 17:30:28