chrislo-sourceclassifier 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (316) hide show
  1. data/Manifest +0 -312
  2. data/Rakefile +2 -2
  3. data/sourceclassifier.gemspec +6 -6
  4. metadata +4 -316
  5. data/sources/gcc/ackermann.gcc-2.gcc +0 -93
  6. data/sources/gcc/ackermann.gcc-3.gcc +0 -20
  7. data/sources/gcc/ary.gcc +0 -40
  8. data/sources/gcc/binarytrees.gcc +0 -136
  9. data/sources/gcc/binarytrees.gcc-2.gcc +0 -140
  10. data/sources/gcc/binarytrees.gcc-3.gcc +0 -134
  11. data/sources/gcc/chameneos.gcc +0 -117
  12. data/sources/gcc/chameneos.gcc-2.gcc +0 -134
  13. data/sources/gcc/chameneos.gcc-3.gcc +0 -120
  14. data/sources/gcc/chameneosredux.gcc +0 -306
  15. data/sources/gcc/echo.gcc +0 -144
  16. data/sources/gcc/except.gcc +0 -52
  17. data/sources/gcc/fannkuch.gcc +0 -105
  18. data/sources/gcc/fannkuch.gcc-2.gcc +0 -94
  19. data/sources/gcc/fasta.gcc +0 -158
  20. data/sources/gcc/fasta.gcc-2.gcc +0 -132
  21. data/sources/gcc/fasta.gcc-3.gcc +0 -145
  22. data/sources/gcc/fasta.gcc-4.gcc +0 -141
  23. data/sources/gcc/fibo.gcc +0 -20
  24. data/sources/gcc/harmonic.gcc +0 -22
  25. data/sources/gcc/hash.gcc +0 -31
  26. data/sources/gcc/hash2.gcc +0 -38
  27. data/sources/gcc/heapsort.gcc +0 -72
  28. data/sources/gcc/hello.gcc-2.gcc +0 -12
  29. data/sources/gcc/hello.gcc-3.gcc +0 -20
  30. data/sources/gcc/knucleotide.gcc +0 -173
  31. data/sources/gcc/knucleotide.gcc-2.gcc +0 -168
  32. data/sources/gcc/lists.gcc +0 -226
  33. data/sources/gcc/magicsquares.gcc +0 -378
  34. data/sources/gcc/mandelbrot.gcc +0 -84
  35. data/sources/gcc/mandelbrot.gcc-2.gcc +0 -63
  36. data/sources/gcc/mandelbrot.gcc-3.gcc +0 -91
  37. data/sources/gcc/mandelbrot.gcc-4.gcc +0 -78
  38. data/sources/gcc/matrix.gcc +0 -66
  39. data/sources/gcc/message.gcc-2.gcc +0 -72
  40. data/sources/gcc/message.gcc-3.gcc +0 -64
  41. data/sources/gcc/methcall.gcc +0 -89
  42. data/sources/gcc/moments.gcc +0 -120
  43. data/sources/gcc/nbody.gcc +0 -142
  44. data/sources/gcc/nbody.gcc-2.gcc +0 -143
  45. data/sources/gcc/nbody.gcc-3.gcc +0 -142
  46. data/sources/gcc/nestedloop.gcc +0 -25
  47. data/sources/gcc/nsieve.gcc +0 -35
  48. data/sources/gcc/nsievebits.gcc-2.gcc +0 -37
  49. data/sources/gcc/nsievebits.gcc-3.gcc +0 -53
  50. data/sources/gcc/objinst.gcc +0 -95
  51. data/sources/gcc/partialsums.gcc +0 -86
  52. data/sources/gcc/partialsums.gcc-3.gcc +0 -81
  53. data/sources/gcc/partialsums.gcc-4.gcc +0 -68
  54. data/sources/gcc/pidigits.gcc +0 -105
  55. data/sources/gcc/primes.gcc +0 -75
  56. data/sources/gcc/prodcons.gcc +0 -86
  57. data/sources/gcc/random.gcc +0 -29
  58. data/sources/gcc/raytracer.gcc +0 -125
  59. data/sources/gcc/raytracer.gcc-2.gcc +0 -181
  60. data/sources/gcc/recursive.gcc +0 -68
  61. data/sources/gcc/recursive.gcc-2.gcc +0 -55
  62. data/sources/gcc/regexdna.gcc-2.gcc +0 -126
  63. data/sources/gcc/regexmatch.gcc +0 -136
  64. data/sources/gcc/revcomp.gcc +0 -85
  65. data/sources/gcc/revcomp.gcc-2.gcc +0 -88
  66. data/sources/gcc/revcomp.gcc-4.gcc +0 -71
  67. data/sources/gcc/reversefile.gcc +0 -103
  68. data/sources/gcc/reversefile.gcc-2.gcc +0 -56
  69. data/sources/gcc/sieve.gcc +0 -34
  70. data/sources/gcc/spectralnorm.gcc +0 -54
  71. data/sources/gcc/spellcheck.gcc +0 -72
  72. data/sources/gcc/spellcheck.gcc-2.gcc +0 -61
  73. data/sources/gcc/strcat.gcc +0 -38
  74. data/sources/gcc/sumcol.gcc-2.gcc +0 -98
  75. data/sources/gcc/sumcol.gcc-3.gcc +0 -22
  76. data/sources/gcc/sumcol.gcc-4.gcc +0 -18
  77. data/sources/gcc/sumcol.gcc-5.gcc +0 -32
  78. data/sources/gcc/takfp.gcc +0 -23
  79. data/sources/gcc/tcp-stream.gcc +0 -122
  80. data/sources/gcc/tcpecho.gcc +0 -122
  81. data/sources/gcc/tcpecho.gcc-2.gcc +0 -136
  82. data/sources/gcc/tcprequest.gcc +0 -122
  83. data/sources/gcc/threadring.gcc +0 -73
  84. data/sources/gcc/wc.gcc +0 -52
  85. data/sources/gcc/wc.gcc-2.gcc +0 -40
  86. data/sources/gcc/wc.gcc-3.gcc +0 -46
  87. data/sources/gcc/wordfreq.gcc-2.gcc +0 -85
  88. data/sources/perl/ackermann.perl +0 -28
  89. data/sources/perl/ackermann.perl-2.perl +0 -25
  90. data/sources/perl/ackermann.perl-3.perl +0 -20
  91. data/sources/perl/ackermann.perl-4.perl +0 -18
  92. data/sources/perl/ary.perl +0 -25
  93. data/sources/perl/ary.perl-2.perl +0 -23
  94. data/sources/perl/binarytrees.perl +0 -66
  95. data/sources/perl/binarytrees.perl-2.perl +0 -71
  96. data/sources/perl/chameneos.perl +0 -67
  97. data/sources/perl/echo.perl +0 -81
  98. data/sources/perl/except.perl +0 -73
  99. data/sources/perl/fannkuch.perl +0 -44
  100. data/sources/perl/fannkuch.perl-2.perl +0 -38
  101. data/sources/perl/fasta.perl +0 -112
  102. data/sources/perl/fasta.perl-2.perl +0 -135
  103. data/sources/perl/fasta.perl-4.perl +0 -122
  104. data/sources/perl/fibo.perl +0 -15
  105. data/sources/perl/fibo.perl-2.perl +0 -0
  106. data/sources/perl/fibo.perl-3.perl +0 -0
  107. data/sources/perl/harmonic.perl +0 -7
  108. data/sources/perl/hash.perl +0 -23
  109. data/sources/perl/hash.perl-2.perl +0 -17
  110. data/sources/perl/hash.perl-3.perl +0 -24
  111. data/sources/perl/hash2.perl +0 -16
  112. data/sources/perl/heapsort.perl +0 -65
  113. data/sources/perl/heapsort.perl-2.perl +0 -0
  114. data/sources/perl/hello.perl +0 -5
  115. data/sources/perl/knucleotide.perl-2.perl +0 -30
  116. data/sources/perl/lists.perl +0 -48
  117. data/sources/perl/mandelbrot.perl-2.perl +0 -32
  118. data/sources/perl/matrix.perl +0 -59
  119. data/sources/perl/matrix.perl-2.perl +0 -0
  120. data/sources/perl/matrix.perl-3.perl +0 -0
  121. data/sources/perl/message.perl +0 -27
  122. data/sources/perl/methcall.perl +0 -66
  123. data/sources/perl/moments.perl +0 -44
  124. data/sources/perl/nbody.perl +0 -108
  125. data/sources/perl/nestedloop.perl +0 -28
  126. data/sources/perl/nsieve.perl-2.perl +0 -41
  127. data/sources/perl/nsieve.perl-4.perl +0 -43
  128. data/sources/perl/nsievebits.perl +0 -37
  129. data/sources/perl/objinst.perl +0 -73
  130. data/sources/perl/partialsums.perl-3.perl +0 -31
  131. data/sources/perl/pidigits.perl +0 -52
  132. data/sources/perl/pidigits.perl-2.perl +0 -47
  133. data/sources/perl/process.perl +0 -50
  134. data/sources/perl/prodcons.perl +0 -47
  135. data/sources/perl/random.perl-4.perl +0 -17
  136. data/sources/perl/recursive.perl-2.perl +0 -57
  137. data/sources/perl/regexdna.perl +0 -48
  138. data/sources/perl/regexdna.perl-2.perl +0 -43
  139. data/sources/perl/regexdna.perl-3.perl +0 -50
  140. data/sources/perl/regexdna.perl-4.perl +0 -49
  141. data/sources/perl/regexdna.perl-5.perl +0 -42
  142. data/sources/perl/regexdna.perl-6.perl +0 -43
  143. data/sources/perl/regexmatch.perl +0 -35
  144. data/sources/perl/revcomp.perl-2.perl +0 -34
  145. data/sources/perl/reversefile.perl +0 -8
  146. data/sources/perl/reversefile.perl-2.perl +0 -0
  147. data/sources/perl/reversefile.perl-3.perl +0 -0
  148. data/sources/perl/sieve.perl +0 -23
  149. data/sources/perl/spectralnorm.perl-2.perl +0 -54
  150. data/sources/perl/spellcheck.perl +0 -24
  151. data/sources/perl/strcat.perl +0 -13
  152. data/sources/perl/strcat.perl-2.perl +0 -0
  153. data/sources/perl/sumcol.perl +0 -8
  154. data/sources/perl/takfp.perl +0 -23
  155. data/sources/perl/takfp.perl-3.perl +0 -20
  156. data/sources/perl/tcpecho.perl +0 -61
  157. data/sources/perl/tcprequest.perl +0 -61
  158. data/sources/perl/tcpstream.perl +0 -61
  159. data/sources/perl/threadring.perl +0 -55
  160. data/sources/perl/threadring.perl-2.perl +0 -43
  161. data/sources/perl/wc.perl +0 -20
  162. data/sources/perl/wc.perl-2.perl +0 -14
  163. data/sources/perl/wordfreq.perl +0 -22
  164. data/sources/perl/wordfreq.perl-3.perl +0 -0
  165. data/sources/perl/wordfreq.perl3.perl +0 -0
  166. data/sources/python/ackermann.python +0 -21
  167. data/sources/python/ary.python +0 -19
  168. data/sources/python/binarytrees.python +0 -39
  169. data/sources/python/binarytrees.python-3.python +0 -44
  170. data/sources/python/chameneos.python-6.python +0 -73
  171. data/sources/python/chameneosredux.python +0 -126
  172. data/sources/python/chameneosredux.python-2.python +0 -122
  173. data/sources/python/dispatch.python +0 -176
  174. data/sources/python/dispatch.python-2.python +0 -136
  175. data/sources/python/echo.python +0 -64
  176. data/sources/python/except.python +0 -62
  177. data/sources/python/fannkuch.python +0 -50
  178. data/sources/python/fannkuch.python-2.python +0 -54
  179. data/sources/python/fasta.python-2.python +0 -79
  180. data/sources/python/fibo.python +0 -17
  181. data/sources/python/fibo.python-2.python +0 -0
  182. data/sources/python/fibo.python-3.python +0 -0
  183. data/sources/python/harmonic.python-2.python +0 -9
  184. data/sources/python/hash.python +0 -21
  185. data/sources/python/hash.python-2.python +0 -0
  186. data/sources/python/hash2.python +0 -30
  187. data/sources/python/heapsort.python-3.python +0 -66
  188. data/sources/python/hello.python +0 -5
  189. data/sources/python/implicitode.python +0 -231
  190. data/sources/python/knucleotide.python +0 -55
  191. data/sources/python/lists.python +0 -44
  192. data/sources/python/magicsquares.python +0 -145
  193. data/sources/python/mandelbrot.python +0 -44
  194. data/sources/python/mandelbrot.python-2.python +0 -35
  195. data/sources/python/mandelbrot.python-3.python +0 -46
  196. data/sources/python/matrix.python +0 -34
  197. data/sources/python/matrix.python-2.python +0 -23
  198. data/sources/python/message.python +0 -24
  199. data/sources/python/message.python-2.python +0 -20
  200. data/sources/python/message.python-3.python +0 -19
  201. data/sources/python/meteor.python +0 -210
  202. data/sources/python/meteor.python-2.python +0 -192
  203. data/sources/python/methcall.python +0 -51
  204. data/sources/python/moments.python +0 -65
  205. data/sources/python/nbody.python +0 -123
  206. data/sources/python/nbody.python-2.python +0 -120
  207. data/sources/python/nestedloop.python +0 -24
  208. data/sources/python/nsieve.python +0 -27
  209. data/sources/python/nsieve.python-2.python +0 -23
  210. data/sources/python/nsieve.python-4.python +0 -25
  211. data/sources/python/nsievebits.python +0 -27
  212. data/sources/python/nsievebits.python-2.python +0 -43
  213. data/sources/python/objinst.python +0 -53
  214. data/sources/python/partialsums.python +0 -37
  215. data/sources/python/partialsums.python-2.python +0 -35
  216. data/sources/python/partialsums.python-3.python +0 -48
  217. data/sources/python/pidigits.python +0 -38
  218. data/sources/python/pidigits.python-3.python +0 -63
  219. data/sources/python/pidigits.python-4.python +0 -24
  220. data/sources/python/process.python +0 -51
  221. data/sources/python/process.python-2.python +0 -133
  222. data/sources/python/prodcons.python +0 -51
  223. data/sources/python/prodcons.python-2.python +0 -0
  224. data/sources/python/random.python +0 -27
  225. data/sources/python/raytracer.python +0 -203
  226. data/sources/python/recursive.python +0 -35
  227. data/sources/python/regexdna.python +0 -39
  228. data/sources/python/regexdna.python-2.python +0 -34
  229. data/sources/python/regexmatch.python +0 -36
  230. data/sources/python/revcomp.python-3.python +0 -31
  231. data/sources/python/reversefile.python +0 -13
  232. data/sources/python/reversefile.python-2.python +0 -0
  233. data/sources/python/reversefile.python-3.python +0 -0
  234. data/sources/python/sieve.python +0 -50
  235. data/sources/python/spectralnorm.python-2.python +0 -36
  236. data/sources/python/spellcheck.python +0 -17
  237. data/sources/python/strcat.python +0 -35
  238. data/sources/python/strcat.python-2.python +0 -0
  239. data/sources/python/sumcol.python-2.python +0 -0
  240. data/sources/python/sumcol.python-3.python +0 -0
  241. data/sources/python/takfp.python +0 -19
  242. data/sources/python/tcpecho.python +0 -67
  243. data/sources/python/tcprequest.python +0 -67
  244. data/sources/python/tcpstream.python +0 -67
  245. data/sources/python/threadring.python +0 -47
  246. data/sources/python/threadring.python-2.python +0 -40
  247. data/sources/python/threadring.python-3.python +0 -34
  248. data/sources/python/wc.python-2.python +0 -19
  249. data/sources/python/wordfreq.python +0 -43
  250. data/sources/python/wordfreq.python-2.python +0 -0
  251. data/sources/python/wordfreq.python-3.python +0 -28
  252. data/sources/python/wordfreq.python-4.python +0 -38
  253. data/sources/python/wordfreq.python-5.python +0 -39
  254. data/sources/ruby/ackermann.ruby +0 -17
  255. data/sources/ruby/ackermann.ruby-5.ruby +0 -153
  256. data/sources/ruby/ary.ruby +0 -22
  257. data/sources/ruby/binarytrees.ruby-2.ruby +0 -55
  258. data/sources/ruby/chameneos.ruby-2.ruby +0 -71
  259. data/sources/ruby/dispatch.ruby +0 -114
  260. data/sources/ruby/echo.ruby +0 -41
  261. data/sources/ruby/except.ruby +0 -61
  262. data/sources/ruby/except.ruby-2.ruby +0 -61
  263. data/sources/ruby/fannkuch.ruby +0 -42
  264. data/sources/ruby/fasta.ruby +0 -81
  265. data/sources/ruby/fibo.ruby +0 -15
  266. data/sources/ruby/harmonic.ruby-2.ruby +0 -15
  267. data/sources/ruby/hash.ruby +0 -19
  268. data/sources/ruby/hash2.ruby +0 -23
  269. data/sources/ruby/heapsort.ruby +0 -55
  270. data/sources/ruby/hello.ruby +0 -6
  271. data/sources/ruby/knucleotide.ruby-2.ruby +0 -44
  272. data/sources/ruby/lists.ruby +0 -46
  273. data/sources/ruby/mandelbrot.ruby-3.ruby +0 -63
  274. data/sources/ruby/matrix.ruby +0 -40
  275. data/sources/ruby/matrix.ruby-2.ruby +0 -30
  276. data/sources/ruby/message.ruby +0 -29
  277. data/sources/ruby/message.ruby-2.ruby +0 -24
  278. data/sources/ruby/meteor.ruby +0 -386
  279. data/sources/ruby/meteor.ruby-2.ruby +0 -561
  280. data/sources/ruby/methcall.ruby +0 -58
  281. data/sources/ruby/methcall.ruby-2.ruby +0 -54
  282. data/sources/ruby/moments.ruby +0 -64
  283. data/sources/ruby/nbody.ruby-2.ruby +0 -145
  284. data/sources/ruby/nestedloop.ruby +0 -22
  285. data/sources/ruby/nsieve.ruby +0 -36
  286. data/sources/ruby/nsieve.ruby-2.ruby +0 -25
  287. data/sources/ruby/nsievebits.ruby-2.ruby +0 -42
  288. data/sources/ruby/objinst.ruby +0 -58
  289. data/sources/ruby/partialsums.ruby +0 -39
  290. data/sources/ruby/pidigits.ruby +0 -92
  291. data/sources/ruby/pidigits.ruby-2.ruby +0 -109
  292. data/sources/ruby/prodcons.ruby +0 -41
  293. data/sources/ruby/random.ruby +0 -17
  294. data/sources/ruby/recursive.ruby-2.ruby +0 -53
  295. data/sources/ruby/regexdna.ruby +0 -32
  296. data/sources/ruby/regexdna.ruby-2.ruby +0 -38
  297. data/sources/ruby/regexmatch.ruby +0 -33
  298. data/sources/ruby/revcomp.ruby +0 -28
  299. data/sources/ruby/reversefile.ruby +0 -7
  300. data/sources/ruby/sieve.ruby +0 -30
  301. data/sources/ruby/spectralnorm.ruby +0 -48
  302. data/sources/ruby/spellcheck.ruby +0 -18
  303. data/sources/ruby/spellcheck.ruby-2.ruby +0 -0
  304. data/sources/ruby/strcat.ruby +0 -12
  305. data/sources/ruby/strcat.ruby-2.ruby +0 -12
  306. data/sources/ruby/sumcol.ruby +0 -12
  307. data/sources/ruby/sumcol.ruby-2.ruby +0 -5
  308. data/sources/ruby/takfp.ruby +0 -15
  309. data/sources/ruby/tcpecho.ruby +0 -45
  310. data/sources/ruby/tcprequest.ruby +0 -45
  311. data/sources/ruby/tcpstream.ruby +0 -45
  312. data/sources/ruby/threadring.ruby +0 -61
  313. data/sources/ruby/threadring.ruby-2.ruby +0 -33
  314. data/sources/ruby/wc.ruby +0 -15
  315. data/sources/ruby/wordfreq.ruby +0 -17
  316. data/sources/ruby/wordfreq.ruby2.ruby +0 -0
@@ -1,29 +0,0 @@
1
- # The Computer Language Shootout
2
- # http://shootout.alioth.debian.org/
3
- #
4
- # Contributed by Jesse Millikan
5
-
6
- require 'thread'
7
-
8
- N = ARGV[0].to_i
9
- next_q = last_q = SizedQueue.new(1)
10
-
11
- 500.times {
12
- q = SizedQueue.new(1)
13
- q2 = next_q
14
- Thread.new{
15
- i = N
16
- while i > 0
17
- q2.push(q.pop+1)
18
- i -= 1
19
- end
20
- }
21
- next_q = q
22
- }
23
-
24
- Thread.new{N.times{next_q.push(0)}}
25
-
26
- t = 0
27
- N.times{t+=last_q.pop}
28
- puts t
29
-
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Gonzalo Garramuno -- Dec.31 2006
4
- #
5
-
6
- def coroutine(n)
7
- if n > 1
8
- coroutine(n-1) { |x| yield x + 1 }
9
- else
10
- yield 1 while true
11
- end
12
- end
13
-
14
- iter = 0
15
- last = ARGV[0].to_i
16
- count = 0
17
-
18
- coroutine( 500 ) { |x|
19
- break if iter >= last
20
- count += x
21
- iter += 1
22
- }
23
-
24
- puts count
@@ -1,386 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # The Computer Language Shootout
4
- # http://shootout.alioth.debian.org
5
- # contributed by Kevin Barnes (Ruby novice)
6
-
7
- def blank_board
8
- 0b111111100000100000100000100000100000100000100000100000100000100000
9
- end
10
-
11
- def is_even( location)
12
- (location % 12) < 6
13
- end
14
-
15
- def create_collector_support
16
- odd_map = [0b11, 0b110, 0b1100, 0b11000, 0b10000]
17
- even_map = [0b1, 0b11, 0b110, 0b1100, 0b11000]
18
-
19
- all_odds = Array.new(0b100000)
20
- all_evens = Array.new(0b100000)
21
- bit_counts = Array.new(0b100000)
22
- new_regions = Array.new(0b100000)
23
- 0.upto(0b11111) do | i |
24
- bit_count = odd = even = 0
25
- 0.upto(4) do | bit |
26
- if (i[bit] == 1) then
27
- bit_count += 1
28
- odd |= odd_map[bit]
29
- even |= even_map[bit]
30
- end
31
- end
32
- all_odds[i] = odd
33
- all_evens[i] = even
34
- bit_counts[i] = bit_count
35
- new_regions[i] = create_regions( i)
36
- end
37
-
38
- @@converter = []
39
- 10.times { | row | @@converter.push((row % 2 == 0) ? all_evens : all_odds) }
40
- @@bit_counts = bit_counts
41
- @@regions = new_regions.collect { | set | set.collect { | value | [ value, bit_counts[value], value] } }
42
-
43
- end
44
-
45
- def prunable( board, location, slotting = false)
46
- collectors = []
47
- (location / 6).to_i.upto(9) do | row_on |
48
- regions = @@regions[(board >> (row_on * 6)) & 0b11111 ^ 0b11111]
49
- converter = @@converter[row_on]
50
- initial_collector_count = collectors.length
51
- regions.each do | region |
52
- collector_found = nil
53
- region_mask = region[0]
54
- initial_collector_count.times do | collector_num |
55
- collector = collectors[collector_num]
56
- if (collector) then
57
- collector_mask = collector[0]
58
- if (collector_mask & region_mask != 0) then
59
- if (collector_found) then
60
- collector_found[0] |= collector_mask
61
- collector_found[1] += collector[1]
62
- collector_found[2] |= collector[2]
63
- collectors[collector_num] = nil
64
- else
65
- collector_found = collector
66
- collector[1] += region[1]
67
- collector[2] |= region_mask
68
- end
69
- end
70
- end
71
- end
72
- if (collector_found == nil) then
73
- collectors.push(Array.new(region))
74
- end
75
- end
76
- collectors.length.times do | collector_num |
77
- collector = collectors[collector_num]
78
- if (collector) then
79
- if (collector[2] == 0) then
80
- return true if (collector[1] % 5 != 0)
81
- collectors[collector_num] = nil
82
- else
83
- return false if (collector[2] == 0b11111 && !slotting)
84
- collector[0] = converter[collector[2]]
85
- collector[2] = 0
86
- end
87
- end
88
- end
89
- collectors.compact!
90
- end
91
- return false if (collectors.length <= 1)
92
- collectors.any? { | collector | (collector[1] % 5) != 0 }
93
- end
94
-
95
- def as_binary( value)
96
- rtn = ""
97
- 5.times do | i |
98
- rtn += "#{value[i]}"
99
- end
100
- rtn
101
- end
102
-
103
- def create_regions( value )
104
- regions = []
105
- cur_region = 0
106
- 5.times do | bit |
107
- if (value[bit] == 1) then
108
- cur_region |= 1 << bit
109
- else
110
- if (cur_region !=0 ) then
111
- regions.push( cur_region)
112
- cur_region = 0;
113
- end
114
- end
115
- end
116
- regions.push(cur_region) if (cur_region != 0)
117
- regions
118
- end
119
-
120
- def print_board( board, padding = "", rows = 10, row_offset = 0)
121
- rows.times do | row |
122
- rtn = padding
123
- rtn = "#{rtn} " if ((row + row_offset) % 2) == 1
124
- 6.times do | col |
125
- rtn = "#{rtn}#{board[row*6+col]} "
126
- end
127
- print "#{rtn}\n"
128
- end
129
- end
130
-
131
- class Rotation
132
- attr_reader :start_masks
133
-
134
- @@rotation_even_adder = { :west => -1, :east => 1, :nw => -7, :ne => -6, :sw => 5, :se => 6 }
135
- @@rotation_odd_adder = { :west => -1, :east => 1, :nw => -6, :ne => -5, :sw => 6, :se => 7 }
136
-
137
- def initialize( directions )
138
- values, min = get_values( directions )
139
- @even_offsets, @odd_offsets = normalize_offsets( values, min)
140
-
141
- @even_mask = mask_for_offsets( @even_offsets)
142
- @odd_mask = mask_for_offsets( @odd_offsets)
143
-
144
- @start_masks = Array.new(60)
145
-
146
- 0.upto(59) do | offset |
147
- mask = is_even(offset) ? (@even_mask << offset) : (@odd_mask << offset)
148
- if (blank_board & mask == 0 && !prunable(blank_board | mask, 0, true)) then
149
- @start_masks[offset] = mask
150
- else
151
- @start_masks[offset] = false
152
- end
153
- end
154
- end
155
-
156
- def offsets( location)
157
- if is_even( location) then
158
- @even_offsets.collect { | value | value + location }
159
- else
160
- @odd_offsets.collect { | value | value + location }
161
- end
162
- end
163
-
164
- def normalize_offsets( values, min)
165
- even_min = is_even(min)
166
- other_min = even_min ? min + 6 : min + 7
167
- other_values = values.collect do | value |
168
- if is_even(value) then
169
- value + 6 - other_min
170
- else
171
- value + 7 - other_min
172
- end
173
- end
174
- values.collect! { | value | value - min }
175
-
176
- if even_min then
177
- [values, other_values]
178
- else
179
- [other_values, values]
180
- end
181
- end
182
-
183
- def mask_for_offsets( offsets )
184
- mask = 0
185
- offsets.each { | value | mask = mask + ( 1 << value ) }
186
- mask
187
- end
188
-
189
- def start_adjust( directions )
190
- south = east = 0;
191
- directions.each do | direction |
192
- east += 1 if ( direction == :sw || direction == :nw || direction == :west )
193
- south += 1 if ( direction == :nw || direction == :ne )
194
- end
195
- [south, east]
196
- end
197
-
198
- def get_values ( directions )
199
- south, east = start_adjust(directions)
200
- min = start = south * 6 + east
201
- values = [ start ]
202
- directions.each do | direction |
203
- if (start % 12 >= 6) then
204
- start += @@rotation_odd_adder[direction]
205
- else
206
- start += @@rotation_even_adder[direction]
207
- end
208
- min = start if (start < min)
209
- values += [ start ]
210
- end
211
-
212
- if (values.length != 5)
213
- values.uniq!
214
- end
215
-
216
- [ values, min ]
217
- end
218
- end
219
-
220
- class Piece
221
- attr_reader :rotations, :type, :masks
222
- attr_accessor :placed
223
-
224
- @@flip_converter = { :west => :west, :east => :east, :nw => :sw, :ne => :se, :sw => :nw, :se => :ne }
225
- @@rotate_converter = { :west => :nw, :east => :se, :nw => :ne, :ne => :east, :sw => :west, :se => :sw }
226
-
227
- def initialize( directions, type )
228
- @type = type
229
- @rotations = Array.new();
230
- @map = {}
231
- generate_rotations( directions )
232
- directions.collect! { | value | @@flip_converter[value] }
233
- generate_rotations( directions )
234
-
235
- @masks = Array.new();
236
- 0.upto(59) do | i |
237
- @masks[i] = @rotations.collect do | rotation |
238
- mask = rotation.start_masks[i]
239
- @map[mask] = [ i, rotation ] if (mask)
240
- mask || nil
241
- end
242
- @masks[i].compact!
243
- end
244
- end
245
-
246
- def generate_rotations( directions )
247
- 6.times do
248
- rotations.push( Rotation.new(directions))
249
- directions.collect! { | value | @@rotate_converter[value] }
250
- end
251
- end
252
-
253
- def fill_array( board_array)
254
- location, rotation = @map[@placed]
255
- rotation.offsets(location).each do | offset |
256
- row, col = offset.divmod(6)
257
- board_array[ row*5 + col ] = @type.to_s
258
- end
259
- end
260
- end
261
-
262
- class Processor
263
- attr :pieces, :board
264
-
265
- def initialize()
266
- create_collector_support
267
- @pieces = [
268
- Piece.new( [ :east, :east, :east, :se ], 0),
269
- Piece.new( [ :ne, :east, :ne, :nw ], 1),
270
- Piece.new( [ :nw, :ne, :east, :east ], 2),
271
- Piece.new( [ :east, :east, :sw, :se ], 3),
272
- Piece.new( [ :ne, :nw, :se, :east, :se ], 4),
273
- Piece.new( [ :east, :ne, :se, :ne ], 5),
274
- Piece.new( [ :east, :sw, :sw, :se ], 6),
275
- Piece.new( [ :ne, :se, :east, :ne ], 7),
276
- Piece.new( [ :se, :se, :east, :se ], 8),
277
- Piece.new( [ :se, :se, :se, :west ], 9) ];
278
-
279
- @all_pieces = Array.new( @pieces)
280
-
281
- @min_board = "99999999999999999999999999999999999999999999999999"
282
- @max_board = "00000000000000000000000000000000000000000000000000"
283
- @stop_count = ARGV[0].to_i || 2089
284
- @all_boards = {}
285
- @boards_found = 0
286
- end
287
-
288
- def find_all
289
- find_top( 0)
290
- find_top( 1)
291
- print_results
292
- end
293
-
294
- def print_results
295
- print "#{@boards_found} solutions found\n\n"
296
- print_full_board( @min_board)
297
- print "\n"
298
- print_full_board( @max_board)
299
- print "\n"
300
- end
301
-
302
- def find_top( rotation_skip)
303
- board = blank_board
304
- @pieces.length.times do
305
- piece = @pieces.shift
306
- piece.masks[0].each do | mask |
307
- if ((rotation_skip += 1) % 2 == 0) then
308
- piece.placed = mask
309
- find( 1, 1, board | mask)
310
- end
311
- end
312
- @pieces.push(piece)
313
- end
314
- end
315
-
316
- def find( start_location, placed, board)
317
- while board[start_location] == 1
318
- start_location += 1
319
- end
320
-
321
- return if (start_location < 28 && prunable( board, start_location))
322
-
323
- @pieces.length.times do
324
- piece = @pieces.shift
325
- piece.masks[start_location].each do | mask |
326
- if (mask & board == 0) then
327
- piece.placed = mask
328
- if (placed == 9) then
329
- add_board
330
- else
331
- find( start_location + 1, placed + 1, board | mask)
332
- end
333
- end
334
- end
335
- @pieces.push(piece)
336
- end
337
- end
338
-
339
- def print_full_board( board_string)
340
- 10.times do | row |
341
- print " " if (row % 2 == 1)
342
- 5.times do | col |
343
- print "#{board_string[row*5 + col,1]} "
344
- end
345
- print "\n"
346
- end
347
- end
348
-
349
- def add_board
350
- board_array = Array.new(50)
351
- @all_pieces.each do | piece |
352
- piece.fill_array( board_array )
353
- end
354
- start_board = board_string = board_array.join("")
355
- save( board_string)
356
- board_string = flip( board_string)
357
- save( board_string)
358
- end
359
-
360
- def flip( board_string)
361
- new_string = ""
362
- 50.times do | i |
363
- row, col = i.divmod(5)
364
- new_string += board_string[((9 - row) * 5) + (4 - col), 1]
365
- end
366
- new_string
367
- end
368
-
369
- def save( board_string)
370
- if (@all_boards[board_string] == nil) then
371
- @min_board = board_string if (board_string < @min_board)
372
- @max_board = board_string if (board_string > @max_board)
373
- @all_boards.store(board_string,true)
374
- @boards_found += 1
375
-
376
- if (@boards_found == @stop_count) then
377
- print_results
378
- exit(0)
379
- end
380
- end
381
- end
382
-
383
- end
384
-
385
- proc = Processor.new.find_all
386
-
@@ -1,561 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # The Computer Language Shootout
4
- # http://shootout.alioth.debian.org
5
- # contributed by Kevin Barnes (Ruby novice)
6
-
7
- # PROGRAM: the main body is at the bottom.
8
- # 1) read about the problem here: http://www-128.ibm.com/developerworks/java/library/j-javaopt/
9
- # 2) see how I represent a board as a bitmask by reading the blank_board comments
10
- # 3) read as your mental paths take you
11
-
12
- # class to represent all information about a particular rotation of a particular piece
13
- class Rotation
14
- # an array (by location) containing a bit mask for how the piece maps at the given location.
15
- # if the rotation is illegal at that location the mask will contain false
16
- attr_reader :start_masks
17
-
18
- # maps a direction to a relative location. these differ depending on whether it is an even or
19
- # odd row being mapped from
20
- @@rotation_even_adder = { :west => -1, :east => 1, :nw => -7, :ne => -6, :sw => 5, :se => 6 }
21
- @@rotation_odd_adder = { :west => -1, :east => 1, :nw => -6, :ne => -5, :sw => 6, :se => 7 }
22
-
23
- def initialize( directions )
24
- @even_offsets, @odd_offsets = normalize_offsets( get_values( directions ))
25
-
26
- @even_mask = mask_for_offsets( @even_offsets)
27
- @odd_mask = mask_for_offsets( @odd_offsets)
28
-
29
- @start_masks = Array.new(60)
30
-
31
- # create the rotational masks by placing the base mask at the location and seeing if
32
- # 1) it overlaps the boundries and 2) it produces a prunable board. if either of these
33
- # is true the piece cannot be placed
34
- 0.upto(59) do | offset |
35
- mask = is_even(offset) ? (@even_mask << offset) : (@odd_mask << offset)
36
- if (blank_board & mask == 0 && !prunable(blank_board | mask, 0, true)) then
37
- imask = compute_required( mask, offset)
38
- @start_masks[offset] = [ mask, imask, imask | mask ]
39
- else
40
- @start_masks[offset] = false
41
- end
42
- end
43
- end
44
-
45
- def compute_required( mask, offset )
46
- board = blank_board
47
- 0.upto(offset) { | i | board |= 1 << i }
48
- board |= mask
49
- return 0 if (!prunable(board | mask, offset))
50
- board = flood_fill(board,58)
51
- count = 0
52
- imask = 0
53
- 0.upto(59) do | i |
54
- if (board[i] == 0) then
55
- imask |= (1 << i)
56
- count += 1
57
- end
58
- end
59
- (count > 0 && count < 5) ? imask : 0
60
- end
61
-
62
- def flood_fill( board, location)
63
- return board if (board[location] == 1)
64
- board |= 1 << location
65
- row, col = location.divmod(6)
66
- board = flood_fill( board, location - 1) if (col > 0)
67
- board = flood_fill( board, location + 1) if (col < 4)
68
- if (row % 2 == 0) then
69
- board = flood_fill( board, location - 7) if (col > 0 && row > 0)
70
- board = flood_fill( board, location - 6) if (row > 0)
71
- board = flood_fill( board, location + 6) if (row < 9)
72
- board = flood_fill( board, location + 5) if (col > 0 && row < 9)
73
- else
74
- board = flood_fill( board, location - 5) if (col < 4 && row > 0)
75
- board = flood_fill( board, location - 6) if (row > 0)
76
- board = flood_fill( board, location + 6) if (row < 9)
77
- board = flood_fill( board, location + 7) if (col < 4 && row < 9)
78
- end
79
- board
80
- end
81
-
82
- # given a location, produces a list of relative locations covered by the piece at this rotation
83
- def offsets( location)
84
- if is_even( location) then
85
- @even_offsets.collect { | value | value + location }
86
- else
87
- @odd_offsets.collect { | value | value + location }
88
- end
89
- end
90
-
91
- # returns a set of offsets relative to the top-left most piece of the rotation (by even or odd rows)
92
- # this is hard to explain. imagine we have this partial board:
93
- # 0 0 0 0 0 x [positions 0-5]
94
- # 0 0 1 1 0 x [positions 6-11]
95
- # 0 0 1 0 0 x [positions 12-17]
96
- # 0 1 0 0 0 x [positions 18-23]
97
- # 0 1 0 0 0 x [positions 24-29]
98
- # 0 0 0 0 0 x [positions 30-35]
99
- # ...
100
- # The top-left of the piece is at position 8, the
101
- # board would be passed as a set of positions (values array) containing [8,9,14,19,25] not necessarily in that
102
- # sorted order. Since that array starts on an odd row, the offsets for an odd row are: [0,1,6,11,17] obtained
103
- # by subtracting 8 from everything. Now imagine the piece shifted up and to the right so it's on an even row:
104
- # 0 0 0 1 1 x [positions 0-5]
105
- # 0 0 1 0 0 x [positions 6-11]
106
- # 0 0 1 0 0 x [positions 12-17]
107
- # 0 1 0 0 0 x [positions 18-23]
108
- # 0 0 0 0 0 x [positions 24-29]
109
- # 0 0 0 0 0 x [positions 30-35]
110
- # ...
111
- # Now the positions are [3,4,8,14,19] which after subtracting the lowest value (3) gives [0,1,5,11,16] thus, the
112
- # offsets for this particular piece are (in even, odd order) [0,1,5,11,16],[0,1,6,11,17] which is what
113
- # this function would return
114
- def normalize_offsets( values)
115
- min = values.min
116
- even_min = is_even(min)
117
- other_min = even_min ? min + 6 : min + 7
118
- other_values = values.collect do | value |
119
- if is_even(value) then
120
- value + 6 - other_min
121
- else
122
- value + 7 - other_min
123
- end
124
- end
125
- values.collect! { | value | value - min }
126
-
127
- if even_min then
128
- [values, other_values]
129
- else
130
- [other_values, values]
131
- end
132
- end
133
-
134
- # produce a bitmask representation of an array of offset locations
135
- def mask_for_offsets( offsets )
136
- mask = 0
137
- offsets.each { | value | mask = mask + ( 1 << value ) }
138
- mask
139
- end
140
-
141
- # finds a "safe" position that a position as described by a list of directions can be placed
142
- # without falling off any edge of the board. the values returned a location to place the first piece
143
- # at so it will fit after making the described moves
144
- def start_adjust( directions )
145
- south = east = 0;
146
- directions.each do | direction |
147
- east += 1 if ( direction == :sw || direction == :nw || direction == :west )
148
- south += 1 if ( direction == :nw || direction == :ne )
149
- end
150
- south * 6 + east
151
- end
152
-
153
- # given a set of directions places the piece (as defined by a set of directions) on the board at
154
- # a location that will not take it off the edge
155
- def get_values ( directions )
156
- start = start_adjust(directions)
157
- values = [ start ]
158
- directions.each do | direction |
159
- if (start % 12 >= 6) then
160
- start += @@rotation_odd_adder[direction]
161
- else
162
- start += @@rotation_even_adder[direction]
163
- end
164
- values += [ start ]
165
- end
166
-
167
- # some moves take you back to an existing location, we'll strip duplicates
168
- values.uniq
169
- end
170
- end
171
-
172
- # describes a piece and caches information about its rotations to as to be efficient for iteration
173
- # ATTRIBUTES:
174
- # rotations -- all the rotations of the piece
175
- # type -- a numeic "name" of the piece
176
- # masks -- an array by location of all legal rotational masks (a n inner array) for that location
177
- # placed -- the mask that this piece was last placed at (not a location, but the actual mask used)
178
- class Piece
179
- attr_reader :rotations, :type, :masks
180
- attr_accessor :placed
181
-
182
- # transform hashes that change one direction into another when you either flip or rotate a set of directions
183
- @@flip_converter = { :west => :west, :east => :east, :nw => :sw, :ne => :se, :sw => :nw, :se => :ne }
184
- @@rotate_converter = { :west => :nw, :east => :se, :nw => :ne, :ne => :east, :sw => :west, :se => :sw }
185
-
186
- def initialize( directions, type )
187
- @type = type
188
- @rotations = Array.new();
189
- @map = {}
190
-
191
- generate_rotations( directions )
192
- directions.collect! { | value | @@flip_converter[value] }
193
- generate_rotations( directions )
194
-
195
- # creates the masks AND a map that returns [location, rotation] for any given mask
196
- # this is used when a board is found and we want to draw it, otherwise the map is unused
197
- @masks = Array.new();
198
- 0.upto(59) do | i |
199
- even = true
200
- @masks[i] = @rotations.collect do | rotation |
201
- mask = rotation.start_masks[i]
202
- @map[mask[0]] = [ i, rotation ] if (mask)
203
- mask || nil
204
- end
205
- @masks[i].compact!
206
- end
207
- end
208
-
209
- # rotates a set of directions through all six angles and adds a Rotation to the list for each one
210
- def generate_rotations( directions )
211
- 6.times do
212
- rotations.push( Rotation.new(directions))
213
- directions.collect! { | value | @@rotate_converter[value] }
214
- end
215
- end
216
-
217
- # given a board string, adds this piece to the board at whatever location/rotation
218
- # important: the outbound board string is 5 wide, the normal location notation is six wide (padded)
219
- def fill_string( board_string)
220
- location, rotation = @map[@placed]
221
- rotation.offsets(location).each do | offset |
222
- row, col = offset.divmod(6)
223
- board_string[ row*5 + col, 1 ] = @type.to_s
224
- end
225
- end
226
- end
227
-
228
- # a blank bit board having this form:
229
- #
230
- # 0 0 0 0 0 1
231
- # 0 0 0 0 0 1
232
- # 0 0 0 0 0 1
233
- # 0 0 0 0 0 1
234
- # 0 0 0 0 0 1
235
- # 0 0 0 0 0 1
236
- # 0 0 0 0 0 1
237
- # 0 0 0 0 0 1
238
- # 0 0 0 0 0 1
239
- # 0 0 0 0 0 1
240
- # 1 1 1 1 1 1
241
- #
242
- # where left lest significant bit is the top left and the most significant is the lower right
243
- # the actual board only consists of the 0 places, the 1 places are blockers to keep things from running
244
- # off the edges or bottom
245
- def blank_board
246
- 0b111111100000100000100000100000100000100000100000100000100000100000
247
- end
248
-
249
- def full_board
250
- 0b111111111111111111111111111111111111111111111111111111111111111111
251
- end
252
-
253
- # determines if a location (bit position) is in an even row
254
- def is_even( location)
255
- (location % 12) < 6
256
- end
257
-
258
- # support function that create three utility maps:
259
- # @@converter -- for each row an array that maps a five bit row (via array mapping)
260
- # to the a a five bit representation of the bits below it
261
- # @@bit_count -- maps a five bit row (via array mapping) to the number of 1s in the row
262
- # @@new_regions -- maps a five bit row (via array mapping) to an array of "region" arrays
263
- # a region array has three values the first is a mask of bits in the region,
264
- # the second is the count of those bits and the third is identical to the first
265
- # examples:
266
- # 0b10010 => [ 0b01100, 2, 0b01100 ], [ 0b00001, 1, 0b00001]
267
- # 0b01010 => [ 0b10000, 1, 0b10000 ], [ 0b00100, 1, 0b00100 ], [ 0b00001, 1, 0b00001]
268
- # 0b10001 => [ 0b01110, 3, 0b01110 ]
269
- def create_collector_support
270
- odd_map = [0b11, 0b110, 0b1100, 0b11000, 0b10000]
271
- even_map = [0b1, 0b11, 0b110, 0b1100, 0b11000]
272
-
273
- all_odds = Array.new(0b100000)
274
- all_evens = Array.new(0b100000)
275
- bit_counts = Array.new(0b100000)
276
- new_regions = Array.new(0b100000)
277
- 0.upto(0b11111) do | i |
278
- bit_count = odd = even = 0
279
- 0.upto(4) do | bit |
280
- if (i[bit] == 1) then
281
- bit_count += 1
282
- odd |= odd_map[bit]
283
- even |= even_map[bit]
284
- end
285
- end
286
- all_odds[i] = odd
287
- all_evens[i] = even
288
- bit_counts[i] = bit_count
289
- new_regions[i] = create_regions( i)
290
- end
291
-
292
- @@converter = []
293
- 10.times { | row | @@converter.push((row % 2 == 0) ? all_evens : all_odds) }
294
- @@bit_counts = bit_counts
295
- @@regions = new_regions.collect { | set | set.collect { | value | [ value, bit_counts[value], value] } }
296
- end
297
-
298
- # determines if a board is punable, meaning that there is no possibility that it
299
- # can be filled up with pieces. A board is prunable if there is a grouping of unfilled spaces
300
- # that are not a multiple of five. The following board is an example of a prunable board:
301
- # 0 0 1 0 0
302
- # 0 1 0 0 0
303
- # 1 1 0 0 0
304
- # 0 1 0 0 0
305
- # 0 0 0 0 0
306
- # ...
307
- #
308
- # This board is prunable because the top left corner is only 3 bits in area, no piece will ever fit it
309
- # parameters:
310
- # board -- an initial bit board (6 bit padded rows, see blank_board for format)
311
- # location -- starting location, everything above and to the left is already full
312
- # slotting -- set to true only when testing initial pieces, when filling normally
313
- # additional assumptions are possible
314
- #
315
- # Algorithm:
316
- # The algorithm starts at the top row (as determined by location) and iterates a row at a time
317
- # maintainng counts of active open areas (kept in the collector array) each collector contains
318
- # three values at the start of an iteration:
319
- # 0: mask of bits that would be adjacent to the collector in this row
320
- # 1: the number of bits collected so far
321
- # 2: a scratch space starting as zero, but used during the computation to represent
322
- # the empty bits in the new row that are adjacent (position 0)
323
- # The exact procedure is described in-code
324
- def prunable( board, location, slotting = false)
325
- collectors = []
326
- # loop accross the rows
327
- (location / 6).to_i.upto(9) do | row_on |
328
- # obtain a set of regions representing the bits of the curent row.
329
- regions = @@regions[(board >> (row_on * 6)) & 0b11111]
330
- converter = @@converter[row_on]
331
-
332
- # track the number of collectors at the start of the cycle so that
333
- # we don't compute against newly created collectors, only existing collectors
334
- initial_collector_count = collectors.length
335
-
336
- # loop against the regions. For each region of the row
337
- # we will see if it connects to one or more existing collectors.
338
- # if it connects to 1 collector, the bits from the region are added to the
339
- # bits of the collector and the mask is placed in collector[2]
340
- # If the region overlaps more than one collector then all the collectors
341
- # it overlaps with are merged into the first one (the others are set to nil in the array)
342
- # if NO collectors are found then the region is copied as a new collector
343
- regions.each do | region |
344
- collector_found = nil
345
- region_mask = region[2]
346
- initial_collector_count.times do | collector_num |
347
- collector = collectors[collector_num]
348
- if (collector) then
349
- collector_mask = collector[0]
350
- if (collector_mask & region_mask != 0) then
351
- if (collector_found) then
352
- collector_found[0] |= collector_mask
353
- collector_found[1] += collector[1]
354
- collector_found[2] |= collector[2]
355
- collectors[collector_num] = nil
356
- else
357
- collector_found = collector
358
- collector[1] += region[1]
359
- collector[2] |= region_mask
360
- end
361
- end
362
- end
363
- end
364
- if (collector_found == nil) then
365
- collectors.push(Array.new(region))
366
- end
367
- end
368
-
369
- # check the existing collectors, if any collector overlapped no bits in the region its [2] value will
370
- # be zero. The size of any such reaason is tested if it is not a muliple of five true is returned since
371
- # the board is prunable. if it is a multiple of five it is removed.
372
- # Collector that are still active have a new adjacent value [0] set based n the matched bits
373
- # and have [2] cleared out for the next cycle.
374
- collectors.length.times do | collector_num |
375
- collector = collectors[collector_num]
376
- if (collector) then
377
- if (collector[2] == 0) then
378
- return true if (collector[1] % 5 != 0)
379
- collectors[collector_num] = nil
380
- else
381
- # if a collector matches all bits in the row then we can return unprunable early for the
382
- # follwing reasons:
383
- # 1) there can be no more unavailable bits bince we fill from the top left downward
384
- # 2) all previous regions have been closed or joined so only this region can fail
385
- # 3) this region must be good since there can never be only 1 region that is nuot
386
- # a multiple of five
387
- # this rule only applies when filling normally, so we ignore the rule if we are "slotting"
388
- # in pieces to see what configurations work for them (the only other time this algorithm is used).
389
- return false if (collector[2] == 0b11111 && !slotting)
390
- collector[0] = converter[collector[2]]
391
- collector[2] = 0
392
- end
393
- end
394
- end
395
-
396
- # get rid of all the empty converters for the next round
397
- collectors.compact!
398
- end
399
- return false if (collectors.length <= 1) # 1 collector or less and the region is fine
400
- collectors.any? { | collector | (collector[1] % 5) != 0 } # more than 1 and we test them all for bad size
401
- end
402
-
403
- # creates a region given a row mask. see prunable for what a "region" is
404
- def create_regions( value )
405
- regions = []
406
- cur_region = 0
407
- 5.times do | bit |
408
- if (value[bit] == 0) then
409
- cur_region |= 1 << bit
410
- else
411
- if (cur_region != 0 ) then
412
- regions.push( cur_region)
413
- cur_region = 0;
414
- end
415
- end
416
- end
417
- regions.push(cur_region) if (cur_region != 0)
418
- regions
419
- end
420
-
421
- # find up to the counted number of solutions (or all solutions) and prints the final result
422
- def find_all
423
- find_top( 1)
424
- find_top( 0)
425
- print_results
426
- end
427
-
428
- # show the board
429
- def print_results
430
- print "#{@boards_found} solutions found\n\n"
431
- print_full_board( @min_board)
432
- print "\n"
433
- print_full_board( @max_board)
434
- print "\n"
435
- end
436
-
437
- # finds solutions. This special version of the main function is only used for the top level
438
- # the reason for it is basically to force a particular ordering on how the rotations are tested for
439
- # the first piece. It is called twice, first looking for placements of the odd rotations and then
440
- # looking for placements of the even locations.
441
- #
442
- # WHY?
443
- # Since any found solution has an inverse we want to maximize finding solutions that are not already found
444
- # as an inverse. The inverse will ALWAYS be 3 one of the piece configurations that is exactly 3 rotations away
445
- # (an odd number). Checking even vs odd then produces a higher probability of finding more pieces earlier
446
- # in the cycle. We still need to keep checking all the permutations, but our probability of finding one will
447
- # diminsh over time. Since we are TOLD how many to search for this lets us exit before checking all pieces
448
- # this bennifit is very great when seeking small numbers of solutions and is 0 when looking for more than the
449
- # maximum number
450
- def find_top( rotation_skip)
451
- board = blank_board
452
- (@pieces.length-1).times do
453
- piece = @pieces.shift
454
- piece.masks[0].each do | mask, imask, cmask |
455
- if ((rotation_skip += 1) % 2 == 0) then
456
- piece.placed = mask
457
- find( 1, 1, board | mask)
458
- end
459
- end
460
- @pieces.push(piece)
461
- end
462
- piece = @pieces.shift
463
- @pieces.push(piece)
464
- end
465
-
466
- # the normail find routine, iterates through the available pieces, checks all rotations at the current location
467
- # and adds any boards found. depth is acheived via recursion. the overall approach is described
468
- # here: http://www-128.ibm.com/developerworks/java/library/j-javaopt/
469
- # parameters:
470
- # start_location -- where to start looking for place for the next piece at
471
- # placed -- number of pieces placed
472
- # board -- current state of the board
473
- #
474
- # see in-code comments
475
- def find( start_location, placed, board)
476
- # find the next location to place a piece by looking for an empty bit
477
- while board[start_location] == 1
478
- start_location += 1
479
- end
480
-
481
- @pieces.length.times do
482
- piece = @pieces.shift
483
- piece.masks[start_location].each do | mask, imask, cmask |
484
- if ( board & cmask == imask) then
485
- piece.placed = mask
486
- if (placed == 9) then
487
- add_board
488
- else
489
- find( start_location + 1, placed + 1, board | mask)
490
- end
491
- end
492
- end
493
- @pieces.push(piece)
494
- end
495
- end
496
-
497
- # print the board
498
- def print_full_board( board_string)
499
- 10.times do | row |
500
- print " " if (row % 2 == 1)
501
- 5.times do | col |
502
- print "#{board_string[row*5 + col,1]} "
503
- end
504
- print "\n"
505
- end
506
- end
507
-
508
- # when a board is found we "draw it" into a string and then flip that string, adding both to
509
- # the list (hash) of solutions if they are unique.
510
- def add_board
511
- board_string = "99999999999999999999999999999999999999999999999999"
512
- @all_pieces.each { | piece | piece.fill_string( board_string ) }
513
- save( board_string)
514
- save( board_string.reverse)
515
- end
516
-
517
- # adds a board string to the list (if new) and updates the current best/worst board
518
- def save( board_string)
519
- if (@all_boards[board_string] == nil) then
520
- @min_board = board_string if (board_string < @min_board)
521
- @max_board = board_string if (board_string > @max_board)
522
- @all_boards.store(board_string,true)
523
- @boards_found += 1
524
-
525
- # the exit motif is a time saver. Ideally the function should return, but those tests
526
- # take noticable time (performance).
527
- if (@boards_found == @stop_count) then
528
- print_results
529
- exit(0)
530
- end
531
- end
532
- end
533
-
534
-
535
- ##
536
- ## MAIN BODY :)
537
- ##
538
- create_collector_support
539
- @pieces = [
540
- Piece.new( [ :nw, :ne, :east, :east ], 2),
541
- Piece.new( [ :ne, :se, :east, :ne ], 7),
542
- Piece.new( [ :ne, :east, :ne, :nw ], 1),
543
- Piece.new( [ :east, :sw, :sw, :se ], 6),
544
- Piece.new( [ :east, :ne, :se, :ne ], 5),
545
- Piece.new( [ :east, :east, :east, :se ], 0),
546
- Piece.new( [ :ne, :nw, :se, :east, :se ], 4),
547
- Piece.new( [ :se, :se, :se, :west ], 9),
548
- Piece.new( [ :se, :se, :east, :se ], 8),
549
- Piece.new( [ :east, :east, :sw, :se ], 3)
550
- ];
551
-
552
- @all_pieces = Array.new( @pieces)
553
-
554
- @min_board = "99999999999999999999999999999999999999999999999999"
555
- @max_board = "00000000000000000000000000000000000000000000000000"
556
- @stop_count = ARGV[0].to_i || 2089
557
- @all_boards = {}
558
- @boards_found = 0
559
-
560
- find_all ######## DO IT!!!
561
-