fork download
  1. import java.util.*;
  2. import java.util.stream.*;
  3. import java.lang.*;
  4. import java.io.*;
  5. import static java.lang.Math.*;
  6.  
  7. class Util {
  8. public static IllegalArgumentException BadArgf(String fmt, Object... args) {
  9. return new IllegalArgumentException(String.format(fmt, args));
  10. };
  11.  
  12. public static String trace(Exception e) {
  13. e.printStackTrace(new PrintWriter(sw));
  14. return sw.toString();
  15. }
  16.  
  17. public static int rangecheck(int x, int min, int max, String what) {
  18. if (x < min || x > max) throw BadArgf("Bad %s: %d, should be [%d; %d].", what, x, min, max);
  19. return x;
  20. }
  21. }
  22.  
  23. class Bitfield2D {
  24. int[] data;
  25. int w, h;
  26. static final int BASE = Integer.SIZE;
  27. static final int SANE_BITS_LIMIT = 1_000_000_000;
  28. static final int SANE_DIMENSION_LIMIT = 100_000_000;
  29.  
  30. public Bitfield2D(int w, int h) { init(null, w, h); }
  31. Bitfield2D(int[] data, int w, int h) { init(data, w, h); }
  32.  
  33. private void init(int[] data, int w, int h) {
  34. validateSize(w, h);
  35. assert data == null || data.length >= (w*h + (BASE - 1)) / BASE;
  36. this.data = data != null ? data : new int[(w*h + (BASE - 1)) / BASE];
  37. this.w = w;
  38. this.h = h;
  39. }
  40.  
  41. static void validateSize(int w, int h) {
  42. if (w < 0 || h < 0 || w > SANE_DIMENSION_LIMIT || h > SANE_DIMENSION_LIMIT
  43. || w > 0 && h > SANE_BITS_LIMIT / w)
  44. throw Util.BadArgf("Bad bitfield size: %d×%d.", w, h);
  45. }
  46.  
  47. public boolean validCoord(int x, int y) {
  48. return x >= 0 && y >= 0 && x < w && y < h;
  49. }
  50.  
  51. public void validateCoord(int x, int y) {
  52. if (!validCoord(x, y))
  53. throw Util.BadArgf("Bad coord of bitfield %d×%d: (%d, %d).", this.w, this.h, x, y);
  54. }
  55.  
  56. void validateRect(int x, int y, int w, int h) {
  57. if (x < 0 || y < 0 || w < 0 || h < 0 || x + w > this.w || y + h > this.h)
  58. throw Util.BadArgf("Bad rect of bitfield %d×%d: (%d, %d) ~ (%d, %d).",
  59. this.w, this.h, x, y, x+w, y+h);
  60. }
  61.  
  62. boolean rawget(int index) { return (data[index / BASE] & (1 << (index % BASE))) != 0; }
  63. void rawset(int index) { data[index / BASE] |= 1 << (index % BASE); }
  64. void rawunset(int index) { data[index / BASE] &= ~(1 << (index % BASE)); }
  65. void rawset(int index, boolean value) { if (value) rawset(index); else rawunset(index); }
  66.  
  67. public boolean get(int x, int y) { validateCoord(x, y); return rawget(y*w+x); }
  68. public void set(int x, int y) { validateCoord(x, y); rawset(y*w+x); }
  69. public void unset(int x, int y) { validateCoord(x, y); rawunset(y*w+x); }
  70. public void set(int x, int y, boolean value) { validateCoord(x, y); rawset(y*w+x, value); }
  71. public int width() { return w; }
  72. public int height() { return h; }
  73.  
  74. // For functions like or() that apply one bitfield to another,
  75. // reduces potentially out-of-borders input to its valid part.
  76. static class CoordWarden {
  77. int srcX, srcY, w, h, destX, destY;
  78. CoordWarden(Bitfield2D dest, Bitfield2D src, int aSrcX, int aSrcY, int aW, int aH, int aDestX, int aDestY) {
  79. src.validateRect(aSrcX, aSrcY, aW, aH);
  80. srcX = aSrcX; srcY = aSrcY; w = aW; h = aH; destX = aDestX; destY = aDestY;
  81. if (destX < 0) { srcX -= destX; w += destX; destX = 0; }
  82. if (destX + w > dest.w) { w = dest.w - destX; }
  83. if (destY < 0) { srcY -= destY; h += destY; destY = 0; }
  84. if (destY + h > dest.h) { h = dest.h - destY; }
  85. }
  86. }
  87.  
  88. public void or(Bitfield2D b, int destX, int destY) {
  89. or(b, 0, 0, b.w, b.h, destX, destY);
  90. }
  91.  
  92. public void or(Bitfield2D b, int bx, int by, int w, int h, int destX, int destY) {
  93. var ward = new CoordWarden(this, b, bx, by, w, h, destX, destY);
  94. int thisOfs = ward.destY*this.w + ward.destX, bOfs = ward.srcY*b.w + ward.srcX;
  95. for (by = 0; by < ward.h; by++, thisOfs += this.w - ward.w, bOfs += b.w - ward.w) {
  96. for (bx = 0; bx < ward.w; bx++, thisOfs++, bOfs++)
  97. if (b.rawget(bOfs)) this.rawset(thisOfs);
  98. }
  99. }
  100.  
  101. public void andNot(Bitfield2D b, int destX, int destY) {
  102. andNot(b, 0, 0, b.w, b.h, destX, destY);
  103. }
  104.  
  105. public void andNot(Bitfield2D b, int bx, int by, int w, int h, int destX, int destY) {
  106. var ward = new CoordWarden(this, b, bx, by, w, h, destX, destY);
  107. int thisOfs = ward.destY*this.w + ward.destX, bOfs = ward.srcY*b.w + ward.srcX;
  108. for (by = 0; by < ward.h; by++, thisOfs += this.w - ward.w, bOfs += b.w - ward.w) {
  109. for (bx = 0; bx < ward.w; bx++, thisOfs++, bOfs++)
  110. if (b.rawget(bOfs)) this.rawunset(thisOfs);
  111. }
  112. }
  113.  
  114. public Bitfield2D copyFrom(Bitfield2D b, int destX, int destY) {
  115. return copyFrom(b, 0, 0, b.w, b.h, destX, destY);
  116. }
  117.  
  118. public Bitfield2D copyFrom(Bitfield2D b, int bx, int by, int w, int h, int destX, int destY) {
  119. var ward = new CoordWarden(this, b, bx, by, w, h, destX, destY);
  120. int thisOfs = ward.destY*this.w + ward.destX, bOfs = ward.srcY*b.w + ward.srcX;
  121. for (by = 0; by < ward.h; by++, thisOfs += this.w, bOfs += b.w) {
  122. copyBits(b.data, bOfs, this.data, thisOfs, ward.w);
  123. }
  124. return this;
  125. }
  126.  
  127. static int readBitsSmall(int[] src, int srcPos, int count) {
  128. assert count > 0 && count < BASE;
  129. // 0 1 2 3 4 5 6
  130. // src = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
  131. // ^srcPos=5
  132. // ^srcPos+count=11
  133. int bits = src[srcPos / BASE] >>> (srcPos % BASE); // FGH
  134. if (count > BASE - srcPos % BASE)
  135. bits |= src[srcPos / BASE + 1] << (BASE - srcPos % BASE); // FGH | 000IJKLMNOP = FGHIJKLMNOP
  136. return bits & ((1 << count) - 1); // FGHIJK
  137. }
  138.  
  139. static void writeBits1(int bits, int[] dst, int dstPos, int count) {
  140. assert count > 0 && count < BASE - dstPos % BASE && bits < 1 << count;
  141. // bits = qwer
  142. // 0 1 2 3 4 5 6
  143. // src = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
  144. // ^dstPos=3
  145. // ^dstPos+count=7
  146. dst[dstPos / BASE] = dst[dstPos / BASE] // ABCDEFGH
  147. & ~(((1 << count) - 1) << (dstPos % BASE)) // ABC0000H
  148. | (bits << (dstPos % BASE)); // ABCqwerH
  149. }
  150.  
  151. static void copyBits(int[] src, int srcPos, int[] dst, int dstPos, int count) {
  152. // Imagine BASE=8 (as if byte[] instead of int[]), srcPos = 3, dstPos = 2, count=25.
  153. //
  154. // 0 1 2 3 4 5 6
  155. // src = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
  156. // ^srcPos=3 ^srcPos+count=28
  157. // dst = ...............................................
  158. // 0 ^dstPos=2 2 3 4 5
  159. //
  160. // First we align dstPos to the multiple of BASE by reading
  161. // first BASE - dstPos%BASE bits with readBitsSmall() and writing them
  162. // into the first cell of dst[] with writeBits1.
  163. //
  164. // We'll get:
  165. // 0 1 2 3 4 5 6
  166. // src = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
  167. // ^srcPos=9 ^srcPos+count=28
  168. // dst = ..DEFGHI.......................................
  169. // 0 1 2 3 4 5
  170. // ^dstPos=8
  171. if (dstPos % BASE != 0) {
  172. int n = min(count, BASE - dstPos % BASE);
  173. if (n > 0) writeBits1(readBitsSmall(src, srcPos, n), dst, dstPos, n);
  174. srcPos += n;
  175. dstPos += n;
  176. count -= n;
  177. }
  178.  
  179. // Now we fill whole cells while possible.
  180. // We'll get:
  181. // src = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
  182. // ^srcPos=25
  183. // ^srcPos+count=28
  184. // dst = ..DEFGHIJKLMNOPQRSTUVWXY.......................
  185. // 0 1 2 3 4 5
  186. // ^dstPos=24
  187. if (srcPos % BASE == 0) {
  188. // Aligned case. This is not even an optimization, because 'int' shifts are restricted to 0..31.
  189. System.arraycopy(src, srcPos / BASE, dst, dstPos / BASE, count / BASE);
  190. } else {
  191. // Unaligned case.
  192. // src: ...ABCDE FGH.....
  193. // ^srcPos
  194. // dst: ........
  195. for (int iSrc = srcPos / BASE, iDst = dstPos / BASE, iDstEd = iDst + count / BASE; iDst < iDstEd; iDst++, iSrc++)
  196. dst[iDst] =
  197. (src[iSrc] >>> (srcPos % BASE)) // ABCDE
  198. | (src[iSrc + 1] << (BASE - srcPos % BASE)); // ABCDE | 00000FGH = ABCDEFGH
  199. }
  200. srcPos += count - count % BASE;
  201. dstPos += count - count % BASE;
  202. count %= BASE;
  203.  
  204. // Append the tail.
  205. if (count > 0)
  206. writeBits1(readBitsSmall(src, srcPos, count), dst, dstPos, count);
  207. }
  208.  
  209. @Override
  210. public String toString() {
  211. return toString("##", "..");
  212. }
  213.  
  214. public String toString(String one, String zero) {
  215. var sb = new StringBuilder();
  216. for (int ofs = 0, y = 0; y < h; y++) {
  217. if (y > 0) sb.append("\n");
  218. for (int x = 0; x < w; x++, ofs++)
  219. sb.append(rawget(ofs) ? one : zero);
  220. }
  221. return sb.toString();
  222. }
  223.  
  224. static Bitfield2D parse(String src) { return parse(src, "##"); }
  225.  
  226. static Bitfield2D parse(String src, String one) {
  227. if (one.isEmpty()) throw Util.BadArgf("'one' can't be empty.");
  228. if (one.indexOf('\n') >= 0) throw Util.BadArgf("Bad 'one': \"%s\". Shouldn't contain EOL.", one);
  229. // Prepass for size.
  230. int w = 0, h = 0;
  231. for (int pos = 0; pos < src.length(); ) {
  232. int eolp = src.indexOf("\n", pos);
  233. if (eolp < 0) eolp = src.length();
  234. if ((eolp - pos) % one.length() != 0)
  235. throw Util.BadArgf("Line %d:\n%s\ncontains %d character%s, which is not multiple of len(%s) = %d.",
  236. h, src.substring(pos, eolp), eolp - pos, eolp - pos != 1 ? "s" : "", one, one.length());
  237. w = max(w, (eolp - pos) / one.length());
  238. h++;
  239. pos = eolp + "\n".length();
  240. }
  241. var r = new Bitfield2D(w, h);
  242.  
  243. for (int y = 0, x = 0, ofs = 0, pos = 0; pos < src.length(); )
  244. if (src.charAt(pos) == '\n') {
  245. ofs += r.w - x;
  246. x = 0; y++;
  247. pos += "\n".length();
  248. } else {
  249. if (src.startsWith(one, pos)) r.rawset(ofs);
  250. pos += one.length();
  251. x++; ofs++;
  252. }
  253. return r;
  254. }
  255. }
  256.  
  257. class Ideone
  258. {
  259. // Auto-growing bitfield for procedural generation when resulting size is impractical to predict.
  260. static class ProcBitfield2D {
  261. Bitfield2D b = new Bitfield2D(0, 0);
  262. int ax, ay, bx, by, boundAx, boundAy, boundBx, boundBy;
  263.  
  264. void set(int x, int y) {
  265. if (boundAx == boundBx) {
  266. ax = x; ay = y; bx = x; by = y;
  267. boundAx = x; boundAy = y; boundBx = x; boundBy = y;
  268. }
  269. if (x < ax || y < ay || x >= bx || y >= by)
  270. grow(
  271. x < ax ? growStgy(ax - x, bx - ax) : 0,
  272. y < ay ? growStgy(ay - y, by - ay) : 0,
  273. x >= bx ? growStgy(x - bx + 1, bx - ax) : 0,
  274. y >= by ? growStgy(y - by + 1, by - ay) : 0);
  275. if (x < boundAx) boundAx = x;
  276. if (x >= boundBx) boundBx = x + 1;
  277. if (y < boundAy) boundAy = y;
  278. if (y >= boundBy) boundBy = y + 1;
  279. b.set(x-ax, y-ay);
  280. }
  281.  
  282. void unset(int x, int y) {
  283. if (x >= boundAx && x < boundBx && x >= boundAy && x < boundBy)
  284. b.unset(x-ax, y-ay);
  285. }
  286.  
  287. void set(int x, int y, boolean value) { if (value) set(x, y); else unset(x, y); }
  288.  
  289. static int growStgy(int atLeast, int present) {
  290. return max(max(8, present / 2), atLeast);
  291. }
  292.  
  293. void grow(int Lx, int Ly, int Rx, int Ry) {
  294. this.b = new Bitfield2D((bx - ax) + Lx + Rx, (by - ay) + Ly + Ry).copyFrom(
  295. this.b, boundAx - ax, boundAy - ay, boundBx - boundAx, boundBy - boundAy, (boundAx - ax) + Lx, (boundAy - ay) + Ly);
  296. ax -= Lx; ay -= Ly; bx += Rx; by += Ry;
  297. }
  298.  
  299. Bitfield2D bake() {
  300. return new Bitfield2D(boundBx - boundAx, boundBy - boundAy).copyFrom(
  301. this.b, boundAx - ax, boundAy - ay, boundBx - boundAx, boundBy - boundAy, 0, 0);
  302. }
  303. }
  304.  
  305. static Bitfield2D makeSpruce(int size) {
  306. Util.rangecheck(size, 1, 20, "size");
  307. var r = new ProcBitfield2D();
  308. int nSegs = 3+size/4, trunkWidth = 1+size/3*2;
  309. int y = 0;
  310. for (int iSeg = 0; iSeg < nSegs; iSeg++) {
  311. int maxSegWidth = trunkWidth + 2 * (size + iSeg * size / 2);
  312. int segWidth = iSeg == 0 ? 1 : trunkWidth + (size + iSeg)/3*2;
  313. for (; segWidth < maxSegWidth; segWidth += 2) {
  314. for (int x = -segWidth/2; x < (segWidth+1)/2; x++)
  315. r.set(x, y);
  316. y += 1;
  317. }
  318. }
  319. for (int yTrunk = 0; yTrunk < size; yTrunk++) {
  320. for (int x = -trunkWidth/2; x < (trunkWidth + 1)/2; x++)
  321. r.set(x, y);
  322. y++;
  323. }
  324. return r.bake();
  325. }
  326.  
  327. public static void main (String[] args) throws java.lang.Exception
  328. {
  329. try {
  330. var r = new Bitfield2D(50, 40);
  331. var moon = Bitfield2D.parse(
  332. "....######..........\n" +
  333. "..####..............\n" +
  334. "####................\n" +
  335. "####................\n" +
  336. "####................\n" +
  337. "####..............##\n" +
  338. "######..........####\n" +
  339. "..################..\n" +
  340. "....############", "##");
  341. r.or(moon, 11, 4);
  342. r.or(makeSpruce(4), -1, 15);
  343. r.or(makeSpruce(3), 29, 17);
  344. r.or(makeSpruce(2), 18, 18);
  345. r.or(makeSpruce(5), 32, 16);
  346. var rand = new Random(7);
  347. for (int iSnowflake = 0; iSnowflake < 25; iSnowflake++) {
  348. int x = rand.nextInt(r.width()),
  349. y = min(r.height() - 1, (int) (r.height() * pow(rand.nextFloat(), 2.0)));
  350. r.set(x, y, !r.get(x, y));
  351. }
  352. System.out.printf("%s\n\n", r);
  353. } catch (Exception e) {
  354. System.out.println(Util.trace(e));
  355. }
  356. }
  357. }
Success #stdin #stdout 0.12s 34300KB
stdin
Standard input is empty
stdout
..............##....................................##................##............##..............
....................................................................................................
................##..................................................................................
..............................................##....................................................
..........................######....................................................................
........................####........................................................................
......................####..........................................................................
......................####..........................................................................
......................####..........................................................................
......................####..............##..................##......................................
......................######..........####..........................................................
........................################............................................................
##........................############..............................................................
..............................................................................##....................
....................................................##............##................................
..................##..........................##..........##........................................
................######..................................................##..............##..........
..............##########..............................................##..............######........
............##########..##................##........................######..........########........
..........##################........##..######....................##########......########..####....
..............##########................######..................######..######..##################..
............##############............##########..................##########..######################
..........##################........##..######..................##..##########....##############....
........######################........##########..............####################################..
......##########################....##############................##########..######################
............##############................##....................####################################
..........##################..............##..................######################################
........######################..............................####################################....
......##########################....##....................########################################..
....##############################..................................######....######################
..##################################................................######..########################
............##############..........................................################################
..........##################............................................############################
........######################........................................##############################
......##################..######....................................################################
....##############################................................................##############....
####################################............................................##################..
######################################............##..........................######################
########################################....................................########################
................######....................................................##########################