আসুন অলস হতে হবে এবং এই প্রশ্ন থেকে আমার উত্তর অভিযোজিত !
অ্যালগরিদম উপরের বাম কোণ থেকে শুরু করে একটি "সাপের পাথ" গণনা করে যা পুরো আয়তক্ষেত্রটি পূর্ণ করে। সাপটি কেবল উপরে, নীচে, বাম দিকে, ডানদিকে যেতে পারে।
সাপের পথ অনুসরণ করা হয় এবং প্রথম রঙ, তারপর দ্বিতীয় রঙ ইত্যাদি দিয়ে পূর্ণ হয় ... রঙের শতাংশ বিবেচনায় নেওয়া
এই অ্যালগরিদম প্রচুর সরল রেখা উত্পাদন করে; এটির উন্নতি করতে, আমি তাদের সনাক্ত করি এবং তাদের "তরঙ্গ" দিয়ে প্রতিস্থাপন করি যা একই পরিমাণ পিক্সেল রাখে।
প্যারামিটার: 380 260 233 420 1300 3511 4772 5089 9507 22107 25117 26744
প্যারামিটার: 380 260 8 5 6 7 8 4 5 6 7 9 4 6 9 5 8 8 7 5
ক্যামলোটের অন্ধকার বয়স (213 307 1 1 1)
কোড:
package map;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
public class GenMap2 {
private enum State { NO, YES, SHIFT };
public final static int TOP = 1, BOTTOM = 2, LEFT = 4, RIGHT = 8;
enum Action { ADD_LINE_TOP, ADD_LINE_LEFT, DOUBLE_SIZE, CREATE};
public static void main(String[] args) throws IOException {
int w = Integer.parseInt(args[0]), h = Integer.parseInt(args[1]);
List<Integer> areas = new ArrayList<Integer>();
int total = 0;
for (int i = 2; i < args.length; i++) {
int area = Integer.parseInt(args[i]);
areas.add(area);
total += area;
}
Collections.sort(areas);
Collections.reverse(areas);
int [][] tab = build(w, h);
BufferedImage dest = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
int [] black = {0, 0, 0};
for (int j = 0; j < dest.getHeight(); j++) {
for (int i = 0; i < dest.getWidth(); i++) {
dest.getRaster().setPixel(i, j, black);
}
}
int x = 0, y = -1;
int go = BOTTOM, previous = BOTTOM;
List<Color> colors = new ArrayList<Color>();
Random rand = new Random(0); // prog must be deterministic
while (colors.size() < areas.size()) {
Color c = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
boolean ok = true;
for (Color existing : colors) {
if (existing.equals(c)) {
ok = false;
break;
}
}
if (ok) {
colors.add(c);
}
}
int [][] map = new int[w][h];
int cpt = 0;
while (true) {
if (go == BOTTOM) y++;
if (go == TOP) y--;
if (go == LEFT) x--;
if (go == RIGHT) x++;
int tmp = (int)(((long)cpt) * total / (w * h));
int i = 0;
for (i = 0; i < areas.size(); i++) {
int area = areas.get(i);
if (tmp < area) {
break;
}
tmp -= area;
}
map[x][y] = i;
previous = go;
go = -1;
if ((tab[x][y] & TOP) != 0 && previous != BOTTOM) go = TOP;
if ((tab[x][y] & BOTTOM) != 0 && previous != TOP) go = BOTTOM;
if ((tab[x][y] & LEFT) != 0 && previous != RIGHT) go = LEFT;
if ((tab[x][y] & RIGHT) != 0 && previous != LEFT) go = RIGHT;
if (go == -1) break;
cpt++;
}
String [] src0 = srcPattern(16);
String [] repl0 = destPattern(16);
while (findPattern(map, src0, Arrays.asList(repl0, flip(repl0)))){}
while (findPattern(map, rotate(src0), Arrays.asList(rotate(repl0), rotate(flip(repl0))))){}
String [] src1 = srcPattern(8);
String [] repl1 = destPattern(8);
while (findPattern(map, src1, Arrays.asList(repl1, flip(repl1)))){}
while (findPattern(map, rotate(src1), Arrays.asList(rotate(repl1), rotate(flip(repl1))))){}
String [] src2 = srcPattern(4);
String [] repl2 = destPattern(4);
while (findPattern(map, src2, Arrays.asList(repl2, flip(repl2)))){}
while (findPattern(map, rotate(src2), Arrays.asList(rotate(repl2), rotate(flip(repl2))))){}
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
Color c = colors.get(map[x][y]);
dest.getRaster().setPixel(x, y, new int[] {c.getRed(), c.getGreen(), c.getBlue()});
}
}
ImageIO.write(dest, "png", new FileOutputStream("map.png"));
}
private static Random randPat = new Random(0);
private static String [] srcPattern(int size) {
String [] ret = new String[size*2];
for (int i = 0; i < size*2; i++) {
ret[i] = "";
for (int j = 0; j < size*4; j++) {
ret[i] += i < size ? "1" : "2";
}
}
return ret;
}
private static String [] destPattern(int size) {
String [] ret = new String[size*2];
for (int i = 0; i < size*2; i++) {
ret[i] = "";
for (int j = 0; j < size*2; j++) {
//int target = (int)((1 + Math.sin(j * Math.PI * .5/ size) * .4) * size);
int target = (int)((1 + (Math.cos(j * Math.PI/ size) - 1) * .2) * size);
ret[i] += (i < target) ? '1' : '2';
}
}
for (int i = 0; i < size*2; i++) {
for (int j = 0; j < size*2; j++) {
ret[i] += ret[size*2 - 1 - i].charAt(size*2 - 1 - j) == '1' ? '2' : '1';
}
}
return ret;
}
private static String [] flip(String [] pat) {
String [] ret = new String[pat.length];
for (int i = 0; i < ret.length; i++) {
ret[i] = new StringBuilder(pat[i]).reverse().toString();
}
return ret;
}
private static String [] rotate(String [] pat) {
String [] ret = new String[pat[0].length()];
for (int i = 0; i < ret.length; i++) {
ret[i] = "";
for (int j = 0; j < pat.length; j++) {
ret[i] += pat[j].charAt(i);
}
}
return ret;
}
private static boolean findPattern(int [][] map, String [] src, List<String []> dest) {
for (int y = 0; y < map[0].length - src.length; y++) {
for (int x = 0; x < map.length - src[0].length(); x++) {
int c1 = -1, c2 = -1;
boolean wrong = false;
for (int y1 = 0; y1 < src.length; y1++) {
for (int x1 = 0; x1 < src[0].length(); x1++) {
if (src[y1].charAt(x1) == '1') {
if (c1 == -1) {
c1 = map[x+x1][y+y1];
} else {
if (c1 != map[x+x1][y+y1]) {
wrong = true;
}
}
}
if (src[y1].charAt(x1) == '2') {
if (c2 == -1) {
c2 = map[x+x1][y+y1];
} else {
if (c2 != map[x+x1][y+y1]) {
wrong = true;
}
}
}
if (c1 != -1 && c1 == c2) wrong = true;
if (wrong) break;
}
if (wrong) break;
}
if (!wrong) {
System.out.println("Found match at " + x + " " + y);
String [] repl = dest.get(randPat.nextInt(dest.size()));
for (int y1 = 0; y1 < src.length; y1++) {
for (int x1 = 0; x1 < src[0].length(); x1++) {
map[x+x1][y+y1] = repl[y1].charAt(x1) == '1' ? c1 : c2;
}
}
return true;
}
}
}
return false;
}
public static int [][] build(int width, int height) {
List<Action> actions = new ArrayList<Action>();
while (height>1 && width>1) {
if (height % 2 == 1) {
height--;
actions.add(Action.ADD_LINE_TOP);
}
if (width % 2 == 1) {
width--;
actions.add(Action.ADD_LINE_LEFT);
}
if (height%2 == 0 && width%2 == 0) {
actions.add(Action.DOUBLE_SIZE);
height /= 2;
width /= 2;
}
}
actions.add(Action.CREATE);
Collections.reverse(actions);
int [][] tab = null;
for (Action action : actions) {
if (action == Action.CREATE) {
tab = new int[width][height];
if (height >= width) {
for (int i = 0; i < height-1; i++) {
tab[0][i] = TOP|BOTTOM;
}
tab[0][height-1] = TOP;
} else {
tab[0][0] = TOP|RIGHT;
for (int i = 1; i < width-1; i++) {
tab[i][0] = RIGHT|LEFT;
}
tab[width-1][0] = LEFT;
}
}
if (action == Action.DOUBLE_SIZE) {
tab = doubleTab(tab);
}
if (action == Action.ADD_LINE_TOP) {
int [][] tab2 = new int[tab.length][tab[0].length+1];
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
tab2[i][j+1] = tab[i][j];
}
}
tab2[0][0] = BOTTOM|RIGHT;
for (int i = 1; i < tab.length-1; i++) {
tab2[i][0] = RIGHT|LEFT;
}
tab2[tab.length-1][0] = TOP|LEFT;
mirror(tab2);
tab = tab2;
}
if (action == Action.ADD_LINE_LEFT) {
int [][] tab2 = new int[tab.length+1][tab[0].length];
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
tab2[i+1][j] = tab[i][j];
}
}
tab2[0][0] = BOTTOM|RIGHT;
tab2[1][0] |= LEFT;
tab2[1][0] -= TOP;
for (int i = 1; i < tab[0].length-1; i++) {
tab2[0][i] = TOP|BOTTOM;
}
tab2[0][tab[0].length-1] = TOP|BOTTOM;
flip(tab2);
tab = tab2;
}
}
return tab;
}
private static void mirror(int [][] tab) {
for (int i = 0; i < tab.length/2; i++) {
for (int j = 0; j < tab[0].length; j++) {
int tmp = tab[tab.length - 1 - i][j];
tab[tab.length - 1 - i][j] = tab[i][j];
tab[i][j] = tmp;
}
}
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
if ((tab[i][j] & LEFT)!=0 && (tab[i][j] & RIGHT)==0) {
tab[i][j] -= LEFT; tab[i][j] |= RIGHT;
} else if ((tab[i][j] & RIGHT)!=0 && (tab[i][j] & LEFT)==0) {
tab[i][j] -= RIGHT; tab[i][j] |= LEFT;
}
}
}
}
private static void flip(int [][] tab) {
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length/2; j++) {
int tmp = tab[i][tab[0].length - 1 - j];
tab[i][tab[0].length - 1 - j] = tab[i][j];
tab[i][j] = tmp;
}
}
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
if ((tab[i][j] & TOP)!=0 && (tab[i][j] & BOTTOM)==0) {
tab[i][j] -= TOP; tab[i][j] |= BOTTOM;
} else if ((tab[i][j] & BOTTOM)!=0 && (tab[i][j] & TOP)==0) {
tab[i][j] -= BOTTOM; tab[i][j] |= TOP;
}
}
}
}
public static int [][] doubleTab(int [][] tab) {
boolean [][] shiftTop = new boolean[tab.length][],
shiftLeft = new boolean[tab.length][],
shiftBottom = new boolean[tab.length][],
shiftRight = new boolean[tab.length][];
for (int i = 0; i < tab.length; i++) {
shiftTop[i] = new boolean[tab[i].length];
shiftLeft[i] = new boolean[tab[i].length];
shiftBottom[i] = new boolean[tab[i].length];
shiftRight[i] = new boolean[tab[i].length];
}
int x = 0, y = -1;
for (int i = 0; i < tab.length; i++) {
if ((tab[i][0] & TOP) != 0) {
x = i;
}
}
int go = BOTTOM, previous = BOTTOM;
boolean init = false;
while (true) {
if (go == BOTTOM) y++;
if (go == TOP) y--;
if (go == LEFT) x--;
if (go == RIGHT) x++;
previous = go;
go = -1;
if ((tab[x][y] & TOP) != 0 && previous != BOTTOM) go = TOP;
if ((tab[x][y] & BOTTOM) != 0 && previous != TOP) go = BOTTOM;
if ((tab[x][y] & LEFT) != 0 && previous != RIGHT) go = LEFT;
if ((tab[x][y] & RIGHT) != 0 && previous != LEFT) go = RIGHT;
if (previous == BOTTOM) {
shiftTop[x][y] = y==0 ? init : shiftBottom[x][y-1];
}
if (previous == TOP) {
shiftBottom[x][y] = shiftTop[x][y+1];
}
if (previous == RIGHT) {
shiftLeft[x][y] = shiftRight[x-1][y];
}
if (previous == LEFT) {
shiftRight[x][y] = shiftLeft[x+1][y];
}
if (go == -1) break;
if (previous == BOTTOM && go == LEFT) {
shiftLeft[x][y] = !shiftTop[x][y];
}
if (previous == BOTTOM && go == RIGHT) {
shiftRight[x][y] = shiftTop[x][y];
}
if (previous == BOTTOM && go == BOTTOM) {
shiftBottom[x][y] = shiftTop[x][y];
}
if (previous == TOP && go == LEFT) {
shiftLeft[x][y] = shiftBottom[x][y];
}
if (previous == TOP && go == RIGHT) {
shiftRight[x][y] = !shiftBottom[x][y];
}
if (previous == TOP && go == TOP) {
shiftTop[x][y] = shiftBottom[x][y];
}
if (previous == RIGHT && go == TOP) {
shiftTop[x][y] = !shiftLeft[x][y];
}
if (previous == RIGHT && go == BOTTOM) {
shiftBottom[x][y] = shiftLeft[x][y];
}
if (previous == RIGHT && go == RIGHT) {
shiftRight[x][y] = shiftLeft[x][y];
}
if (previous == LEFT && go == TOP) {
shiftTop[x][y] = shiftRight[x][y];
}
if (previous == LEFT && go == BOTTOM) {
shiftBottom[x][y] = !shiftRight[x][y];
}
if (previous == LEFT && go == LEFT) {
shiftLeft[x][y] = shiftRight[x][y];
}
}
int [][] tab2 = new int[tab.length * 2][];
for (int i = 0; i < tab2.length; i++) {
tab2[i] = new int[tab[0].length * 2];
}
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
State left = State.NO, right = State.NO, top = State.NO, bottom = State.NO;
if ((tab[i][j] & LEFT) != 0) {
left = shiftLeft[i][j] ? State.SHIFT : State.YES;
}
if ((tab[i][j] & TOP) != 0) {
top = shiftTop[i][j] ? State.SHIFT : State.YES;
}
if ((tab[i][j] & RIGHT) != 0) {
right = shiftRight[i][j] ? State.SHIFT : State.YES;
}
if ((tab[i][j] & BOTTOM) != 0) {
bottom = shiftBottom[i][j] ? State.SHIFT : State.YES;
}
int [] comp = compute(left, top, right, bottom);
tab2[i*2][j*2] = comp[0];
tab2[i*2+1][j*2] = comp[1];
tab2[i*2][j*2+1] = comp[2];
tab2[i*2+1][j*2+1] = comp[3];
}
}
return tab2;
}
private static int [] compute(State left, State top, State right, State bottom) {
// |
// --+
//
if (left == State.YES && top == State.SHIFT) {
return new int[] {LEFT|BOTTOM, TOP|BOTTOM, TOP|RIGHT, TOP|LEFT};// "v^>^";
}
if (left == State.SHIFT && top == State.YES) {
return new int[] {TOP|RIGHT, LEFT|BOTTOM, LEFT|RIGHT, LEFT|TOP}; //"^<>^";
}
//
// --+
// |
if (left == State.YES && bottom == State.YES) {
return new int[] {LEFT|RIGHT, LEFT|BOTTOM, RIGHT|BOTTOM, LEFT|TOP}; //">vv<";
}
if (left == State.SHIFT && bottom == State.SHIFT) {
return new int[] {RIGHT|BOTTOM, LEFT|BOTTOM, LEFT|TOP, TOP|BOTTOM}; //">v^v";
}
// |
// +--
//
if (right == State.SHIFT && top == State.SHIFT) {
return new int [] {RIGHT|BOTTOM,LEFT|TOP,TOP|RIGHT, LEFT|RIGHT}; //" v<>>";
}
if (right == State.YES && top == State.YES) {
return new int [] {TOP|BOTTOM,RIGHT|BOTTOM,TOP|RIGHT,TOP|LEFT}; //"v>>^";
}
//
// +--
// |
if (right == State.YES && bottom == State.SHIFT) {
return new int [] {RIGHT|BOTTOM, LEFT|RIGHT, TOP|RIGHT, LEFT|BOTTOM}; //"v<>v";
}
if (right == State.SHIFT && bottom == State.YES) {
return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, TOP|BOTTOM, RIGHT|TOP}; //"v<v^";
}
//
// --+--
//
if (right == State.YES && left == State.YES) {
return new int [] {LEFT|BOTTOM, RIGHT|BOTTOM, TOP|RIGHT, LEFT|TOP};
}
if (right == State.SHIFT && left == State.SHIFT) {
return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, LEFT|TOP, RIGHT|TOP};
}
// |
// +
// |
if (top == State.YES && bottom == State.YES) {
return new int [] {TOP|RIGHT, LEFT|BOTTOM, BOTTOM|RIGHT, LEFT|TOP};
}
if (top == State.SHIFT && bottom == State.SHIFT) {
return new int [] {RIGHT|BOTTOM, LEFT|TOP, RIGHT|TOP, LEFT|BOTTOM};
}
//
// +--
//
if (right == State.YES && bottom == State.NO && left == State.NO && top == State.NO) {
return new int [] {BOTTOM, RIGHT|BOTTOM, TOP|RIGHT, LEFT|TOP};
}
if (right == State.SHIFT && bottom == State.NO && left == State.NO && top == State.NO) {
return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, TOP, RIGHT|TOP};
}
// |
// +
//
if (top == State.YES && bottom == State.NO && left == State.NO && right == State.NO) {
return new int [] {TOP|RIGHT, LEFT|BOTTOM, RIGHT, LEFT|TOP};
}
if (top == State.SHIFT && bottom == State.NO && left == State.NO && right == State.NO) {
return new int [] {BOTTOM|RIGHT, LEFT|TOP, TOP|RIGHT, LEFT};
}
//
// +
// |
if (bottom == State.YES && top == State.NO && left == State.NO && right == State.NO) {
return new int [] {RIGHT, LEFT|BOTTOM, BOTTOM|RIGHT, LEFT|TOP};
}
if (bottom == State.SHIFT && top == State.NO && left == State.NO && right == State.NO) {
return new int [] {BOTTOM|RIGHT, LEFT, TOP|RIGHT, LEFT|BOTTOM};
}
//
// --+
//
if (left == State.YES && bottom == State.NO && right == State.NO && top == State.NO) {
return new int [] {LEFT|BOTTOM, BOTTOM, TOP|RIGHT, LEFT|TOP};
}
if (left == State.SHIFT && bottom == State.NO && right == State.NO && top == State.NO) {
return new int [] {BOTTOM|RIGHT, LEFT|BOTTOM, LEFT|TOP, TOP};
}
return null;
}
}