Page 1 of 1

sldiff -- Find closest still-lifes in Catagolue

Posted: August 8th, 2016, 8:28 pm
by calcyman
When a still-life X is difficult to synthesise, the first port of call is to look it up on Catagolue. However, if X hasn't occurred naturally, the next best option is to find a natural still-life Y which resembles X as closely as possible.

Enter sldiff, a tool for rapidly comparing still-lifes.

Firstly, you need to download the list of all natural still-lifes. In Unix, this can be accomplished by:

Code: Select all

curl https://catagolue.appspot.com/textcensus/b3s23/C1 | grep -o 'xs[0-9]*_[0-9a-z]*' > stills.txt
Now, suppose you want to find a still-life which resembles the Snark core (xs31_0g89fgkcz8llljgzx641) as closely as possible. With sldiff, this is as simple as running:

Code: Select all

cat stills.txt | ./sldiff.cpp "xs31_0g89fgkcz8llljgzx641" | sort -n | head
which will print the 10 closest matches, where distance is measured by:

d = 5 * (missing cells) + 2 * (unwanted extra cells)

The parameters 5 and 2 are located very close to the end of the source code.

Example output:

Code: Select all

29 26 2 5 xs28_oggs2uge1egozw643 xs31_0g89fgkcz8llljgzx641
39 26 7 5 xs33_mmge1egu2sggoz1y3346 xs31_0g89fgkcz8llljgzx641
42 23 1 8 xs24_0g89fgkczol553 xs31_0g89fgkcz8llljgzx641
52 21 1 10 xs22_g89fgkczd553 xs31_0g89fgkcz8llljgzx641
56 21 3 10 xs24_0okkm996z4aaq1 xs31_0g89fgkcz8llljgzx641
56 21 3 10 xs24_2egu1u0u156zy21 xs31_0g89fgkcz8llljgzx641
56 23 8 8 xs31_0caab8brz255ll2zx11 xs31_0g89fgkcz8llljgzx641
57 20 1 11 xs21_0g09fg4cz8ll91 xs31_0g89fgkcz8llljgzx641
57 20 1 11 xs21_g09fgkczd553 xs31_0g89fgkcz8llljgzx641
57 22 6 9 xs28_g88bbgz8llll8zx66 xs31_0g89fgkcz8llljgzx641
The top line means that the best match to xs31_0g89fgkcz8llljgzx641 is xs28_oggs2uge1egozw643, which has 26 matching cells, 2 extra cells, and 5 missing cells (for an overall distance of 29). The second-best match is the recently-observed xs33_mmge1egu2sggoz1y3346.

Anyway, here's the source code:

Code: Select all

//bin/cat /dev/null; outfile="$0.exe"
//bin/cat /dev/null; g++ -O3 -Wall -Wextra "$0" -o "$outfile"
//bin/cat /dev/null; "$outfile" "$@"
//bin/cat /dev/null; status=$?
//bin/cat /dev/null; rm "$outfile"
//bin/cat /dev/null; exit $status

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <stdint.h>

struct grid64 {

    uint64_t a[64];
    int height;
    int width;

};

uint64_t reverse64(uint64_t x) {

    uint64_t y = (x >> 32) | (x << 32);
    y = ((y & 0xffff0000ffff0000ull) >> 16) | ((y & 0x0000ffff0000ffffull) << 16);
    y = ((y & 0xff00ff00ff00ff00ull) >> 8) | ((y & 0x00ff00ff00ff00ffull) << 8);
    y = ((y & 0xf0f0f0f0f0f0f0f0ull) >> 4) | ((y & 0x0f0f0f0f0f0f0f0full) << 4);
    y = ((y & 0xccccccccccccccccull) >> 2) | ((y & 0x3333333333333333ull) << 2);
    y = ((y & 0xaaaaaaaaaaaaaaaaull) >> 1) | ((y & 0x5555555555555555ull) << 1);
    return y;

}

grid64 horizontal_flip(grid64 h) {

    grid64 g;
    g.width = h.width;
    g.height = h.height;
    std::memset(g.a, 0, 64 * sizeof(uint64_t));
    for (int i = 0; i < g.height; i++) {
        g.a[i] = reverse64(h.a[i]) >> (64 - g.width);
    }
    return g;

}

grid64 vertical_flip(grid64 h) {

    grid64 g;
    g.width = h.width;
    g.height = h.height;
    std::memset(g.a, 0, 64 * sizeof(uint64_t));
    for (int i = 0; i < g.height; i++) {
        g.a[i] = h.a[(g.height - 1) - i];
    }
    return g;

}

grid64 apgcode_to_grid(std::string apgcode, bool transpose) {

    grid64 g;
    std::memset(g.a, 0, 64 * sizeof(uint64_t));
    int l = apgcode.length();
    bool underscore = false;

    g.width = 0;
    g.height = 0;

    int x = 0;
    int y = 0;
    bool iny = false;

    for (int i = 0; i < l; i++) {

        char c = apgcode[i];
        if (underscore) {
            int d = -1;
            if ((c >= 97) && (c < 123)) {
                d = c - 87;
            } else if ((c >= 48) && (c < 58)) {
                d = c - 48;
            } else if ((c >= 65) && (c < 91)) {
                d = c - 55;
            }
            if (d >= 0) {
                if (iny) {
                    iny = false;
                    x += d;
                } else {
                    if (d < 32) {
                        for (int j = 0; j < 5; j++) {
                            if (d & (1 << j)) {
                                if (transpose) {
                                    g.a[x] |= (1ull << (y + j));
                                    g.width = ((y + j) > g.width) ? (y + j) : g.width;
                                    g.height = (x > g.height) ? x : g.height;
                                } else {
                                    g.a[y + j] |= (1ull << x);
                                    g.width = (x > g.width) ? x : g.width;
                                    g.height = ((y + j) > g.height) ? (y + j) : g.height;
                                }
                            }
                        }
                        x += 1;
                    } else {
                        if (d == 35) {
                            x = 0;
                            y += 5;
                        } else {
                            x += 2;
                            if (d >= 33) {
                                x += 1;
                                if (d >= 34) {
                                    x += 1;
                                    iny = true;
                                }
                            }
                        }
                    }
                }
            }

        } else {
            underscore = (c == '_');
        }

    }

    g.width += 1;
    g.height += 1;

    return g;

}

int popcount2d(uint64_t* a, int ah) {

    int c = 0;
    for (int i = 0; i < ah; i++) {
        c += __builtin_popcountll(a[i]);
    }
    return c;

}

int popcount2d(grid64 g) {

    return popcount2d(g.a, g.height);

}

int vconvolve(uint64_t* a, int ah, uint64_t* b, int bh, int shift) {

    int counts[ah + bh - 1];
    std::memset(counts, 0, (ah + bh - 1) * sizeof(int));

    for (int i = 0; i < ah; i++) {
        for (int j = 0; j < bh; j++) {
            counts[i + j] += __builtin_popcountll(a[i] & (b[j] << shift));
        }
    }

    int c = 0;
    for (int i = 0; i < ah + bh - 1; i++) {
        c = (c < counts[i]) ? counts[i] : c;
    }

    return c;

}

int convolve2d(uint64_t* a, int ah, int aw, uint64_t* b, int bh, int bw) {

    int d = 0;
    for (int i = 0; i < aw - 1; i++) {
        int c = vconvolve(a, ah, b, bh, i);
        d = (d < c) ? c : d;
    }
    for (int i = 0; i < bw - 1; i++) {
        int c = vconvolve(b, bh, a, ah, i);
        d = (d < c) ? c : d;
    }
    return d;

}

int convolve2d(grid64 g, grid64 h) {

    return convolve2d(g.a, g.height, g.width, h.a, h.height, h.width);

}

void display_grid(grid64 g) {

    for (int y = 0; y < g.height; y++) {
        for (int x = 0; x < g.width; x++) {
            if (g.a[y] & (1ull << x)) {
                std::cout << '*';
            } else {
                std::cout << '.';
            }
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;

}

int main(int argc, char *argv[]) {

    std::vector<grid64> grids;
    std::vector<std::string> names;

    /*
    grid64 ma = apgcode_to_grid("xs15_354cgc453", false);
    std::cout << ma.width << " by " << ma.height << " (pop : ";
    std::cout << popcount2d(ma.a, ma.height) << ")" << std::endl;
    */

    for (int i = 1; i < argc; i++) {

        std::string argument(argv[i]);
        // std::cout << argument << std::endl;
        grids.push_back(apgcode_to_grid(argument, false));
        grids.push_back(apgcode_to_grid(argument, true));
        names.push_back(argument);
        names.push_back(argument);

    }

    int l = grids.size();
    for (int i = 0; i < l; i++) {
        grids.push_back(vertical_flip(grids[i]));
        names.push_back(names[i]);
    }
    l += l;
    for (int i = 0; i < l; i++) {
        grids.push_back(horizontal_flip(grids[i]));
        names.push_back(names[i]);
    }
    l += l;
    /*
    for (int i = 0; i < l; i++) {
        std::cout << names[i] << std::endl;
        display_grid(grids[i]);
    }
    */

    std::string line;
    while (std::getline(std::cin, line)) {

        int ersection = -1;
        std::string name = "";
        grid64 g = apgcode_to_grid(line, false);
        int p = popcount2d(g);
        int q = -1;

        for (int i = 0; i < l; i++) {
            int e = convolve2d(g, grids[i]);
            if (e > ersection) {
                ersection = e;
                name = names[i];
                q = popcount2d(grids[i]);
            }
        }

        std::cout << 2 * (p - ersection) + 5 * (q - ersection) << " ";
        std::cout << ersection << " ";
        std::cout << p - ersection << " ";
        std::cout << q - ersection << " ";
        std::cout << line << " " << name << std::endl;

    }

    return 0;

}

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 8th, 2016, 8:35 pm
by calcyman
The closest match to the still-life inside the syringe is a 20-cell eater2 variant:

https://catagolue.appspot.com/object/xs ... z121/b3s23

It's a proper subset of the syringe catalyst (i.e. 0 extra cells). Here's the sldiff input and output:

Code: Select all

$ cat stills.txt | ./sldiff.cpp "xs41_8e1eo0kcwo4oz33034al913kp" | sort -n | head
105 20 0 21 xs20_0gbbgraa4z121 xs41_8e1eo0kcwo4oz33034al913kp
107 20 1 21 xs21_0gbbgraa4z321 xs41_8e1eo0kcwo4oz33034al913kp
110 21 5 20 xs26_25a4o0okkozx3ege2 xs41_8e1eo0kcwo4oz33034al913kp
111 20 3 21 xs23_25ac0ccz3117871 xs41_8e1eo0kcwo4oz33034al913kp
111 20 3 21 xs23_8e1u08kcz330346 xs41_8e1eo0kcwo4oz33034al913kp
112 19 1 22 xs20_0gbairaa4z121 xs41_8e1eo0kcwo4oz33034al913kp
112 19 1 22 xs20_0gbb8raa4z121 xs41_8e1eo0kcwo4oz33034al913kp
113 20 4 21 xs24_c88c2dicz178711 xs41_8e1eo0kcwo4oz33034al913kp
114 19 2 22 xs21_0gbairaa4z321 xs41_8e1eo0kcwo4oz33034al913kp
114 19 2 22 xs21_0gbb8raa4z321 xs41_8e1eo0kcwo4oz33034al913kp

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 8th, 2016, 8:53 pm
by drc
What's the closest to the still life in eater 3

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 8th, 2016, 9:37 pm
by calcyman
drc wrote:What's the closest to the still life in eater 3
Apparently this one:

https://catagolue.appspot.com/object/xs ... 0796/b3s23

Image

Here's the input and output:

Code: Select all

cat stills.txt | ./sldiff.cpp "xs24_xo81v04a4z3iai21zw1" | sort -n | head
39 19 7 5 xs26_69b88gzx32gv0796 xs24_xo81v04a4z3iai21zw1
39 19 7 5 xs26_69b88gzx3i0v04aczy011 xs24_xo81v04a4z3iai21zw1
40 18 5 6 xs23_69b88gzx320fgka4 xs24_xo81v04a4z3iai21zw1
40 18 5 6 xs23_wgilmzml46221z11 xs24_xo81v04a4z3iai21zw1
42 18 6 6 xs24_rb8oz01qaai3zx11 xs24_xo81v04a4z3iai21zw1
42 18 6 6 xs24_wgilmzml46243z11 xs24_xo81v04a4z3iai21zw1
42 18 6 6 xs24_wgjlmzml46221z11 xs24_xo81v04a4z3iai21zw1
43 17 4 7 xs21_wgiliczml46z11 xs24_xo81v04a4z3iai21zw1
44 18 7 6 xs25_gilmggz1w66078kk8 xs24_xo81v04a4z3iai21zw1
44 18 7 6 xs25_x696zca9d553z33 xs24_xo81v04a4z3iai21zw1
I'm using biggiemac's pattern-to-apgcode converter to obtain the parameter:

http://conwaylife.com/forums/viewtopic. ... ode#p27202

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 9th, 2016, 2:50 pm
by simsim314
@calcyman looks like your function will prefer smaller objects that fit inside the input, and not larger that fit less well, but have more "working material".

This is really neat small app, I think we have at least two directions from here:

1. Analyze the soups, and look for "synthesis friendly" examples. One of the things that is actually pretty tricky is to have good estimation of "synthesis friendliness" which could benefit a lot from small db of examples or something of the sort.

2. Search that tries to complete/modify the resulting SL step by step to reach the destination SL.

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 9th, 2016, 4:36 pm
by calcyman
simsim314 wrote:@calcyman looks like your function will prefer smaller objects that fit inside the input, and not larger that fit less well, but have more "working material".
Well, there's a 5-point penalty for missing a cell and only a 2-point penalty for having an extra cell. Increasing the value of 5 (or decreasing the value of 2) will make it favour larger objects with 'more working material'.

I guess I could make the '2' and '5' changeable via command-line options.
This is really neat small app, I think we have at least two directions from here:
Thanks! I wanted it to be fast, simple, and compatible with the use of Unix pipelines (which is why it reads from stdin and writes to stdout).
1. Analyze the soups, and look for "synthesis friendly" examples. One of the things that is actually pretty tricky is to have good estimation of "synthesis friendliness" which could benefit a lot from small db of examples or something of the sort.
Morally, we favour reactions which produce the object at a lower temperature.

I guess we could make this rigorous by having a real-valued function (a 'temperature map') superposed on the Life universe, and have the temperature of a square change according to the following rules:
  • The temperature at a point increases whenever the cell changes state (from alive to dead or vice-versa);
  • Temperature follows a simple diffusion rule (say, becomes closer to the average of its four neighbours, Laplacian-style);
  • The temperature slowly decays over time.
Then we can look at the total temperature of a still-life at the first moment it appears. (As a refinement, it is probably better to compare the state at time t with that at t-2 rather than t-1, so that blinkers don't radiate excessive amounts of heat.)
2. Search that tries to complete/modify the resulting SL step by step to reach the destination SL.
Ooh, that sounds difficult.

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 9th, 2016, 4:54 pm
by simsim314
Here are my modification to the script:

It accepts rle and path to C1.txt and reports the SLs in visually appealing format (together with the score and apgcode). The input rle doesn't have to be SL, it could be any valid rle that fits in 64x64 grid.

Code: Select all

//bin/cat /dev/null; outfile="$0.exe"
//bin/cat /dev/null; g++ -O3 -Wall -Wextra "$0" -o "$outfile"
//bin/cat /dev/null; "$outfile" "$@"
//bin/cat /dev/null; status=$?
//bin/cat /dev/null; rm "$outfile"
//bin/cat /dev/null; exit $status

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <stdint.h>
#include <fstream>
#include <algorithm>

#ifdef _MSC_VER
	#include <intrin.h>
	#define __builtin_popcountll __popcnt64
#endif

using namespace std; 


struct grid64 {

	uint64_t a[64];
	int height;
	int width;

};

void init(grid64& g)
{
	std::memset(g.a, 0, 64 * sizeof(uint64_t));
	g.width = 0;
	g.height = 0;
}

void set_cell(grid64& g, const int& x, const int& y)
{
	g.a[y] |= (1ull << x);
	g.width = (x + 1 > g.width) ? x + 1: g.width;
	g.height = (y + 1 > g.height) ? y + 1 : g.height;
}

bool get_cell(const grid64& g, const int& x, const int& y)
{
	return (g.a[y] & (1ull << x)) != 0;
}

uint64_t reverse64(uint64_t x) {

	uint64_t y = (x >> 32) | (x << 32);
	y = ((y & 0xffff0000ffff0000ull) >> 16) | ((y & 0x0000ffff0000ffffull) << 16);
	y = ((y & 0xff00ff00ff00ff00ull) >> 8) | ((y & 0x00ff00ff00ff00ffull) << 8);
	y = ((y & 0xf0f0f0f0f0f0f0f0ull) >> 4) | ((y & 0x0f0f0f0f0f0f0f0full) << 4);
	y = ((y & 0xccccccccccccccccull) >> 2) | ((y & 0x3333333333333333ull) << 2);
	y = ((y & 0xaaaaaaaaaaaaaaaaull) >> 1) | ((y & 0x5555555555555555ull) << 1);
	return y;

}

grid64 horizontal_flip(const grid64& h) {

	grid64 g;
	g.width = h.width;
	g.height = h.height;
	std::memset(g.a, 0, 64 * sizeof(uint64_t));
	for (int i = 0; i < g.height; i++) {
		g.a[i] = reverse64(h.a[i]) >> (64 - g.width);
	}
	return g;

}

grid64 vertical_flip(const grid64& h) {

	grid64 g;
	g.width = h.width;
	g.height = h.height;
	std::memset(g.a, 0, 64 * sizeof(uint64_t));
	for (int i = 0; i < g.height; i++) {
		g.a[i] = h.a[(g.height - 1) - i];
	}
	return g;
}


grid64 transpose(const grid64& h) {

	grid64 g;
	init(g);

	for (int y = 0; y < h.height; y++) {
		for (int x = 0; x < h.width; x++) {

			if (get_cell(h, x, y))
				set_cell(g, y, x);
		}
	}
	return g;
}

grid64 parse(const char* rle)
{
	grid64 g;
	init(g);

	char ch;
	int cnt, i, j;
	int x, y;
	x = 0;
	y = 0;
	cnt = 0;

	i = 0;

	while ((ch = rle[i]) != '\0')
	{

		if (ch >= '0' && ch <= '9')
		{
			cnt *= 10;
			cnt += (ch - '0');
		}
		else if (ch == 'o')
		{

			if (cnt == 0)
				cnt = 1;

			for (j = 0; j < cnt; j++)
			{
				set_cell(g, x, y);
				x++;
			}

			cnt = 0;
		}
		else if (ch == 'b')
		{
			if (cnt == 0)
				cnt = 1;

			x += cnt;
			cnt = 0;

		}
		else if (ch == '$')
		{
			if (cnt == 0)
				cnt = 1;

			if (cnt == 129)
				return g;

			y += cnt;
			x = 0;
			cnt = 0;
		}
		else if (ch == '!')
		{
			break;
		}
		else
		{
			return g;
		}

		i++;
	}

	return g;
}

grid64 apgcode_to_grid(std::string apgcode, bool transpose) {

	grid64 g;
	init(g);

	int l = apgcode.length();
	bool underscore = false;

	int x = 0;
	int y = 0;
	bool iny = false;

	for (int i = 0; i < l; i++) {

		char c = apgcode[i];
		if (underscore) {
			int d = -1;
			if ((c >= 97) && (c < 123)) {
				d = c - 87;
			}
			else if ((c >= 48) && (c < 58)) {
				d = c - 48;
			}
			else if ((c >= 65) && (c < 91)) {
				d = c - 55;
			}
			if (d >= 0) {
				if (iny) {
					iny = false;
					x += d;
				}
				else {
					if (d < 32) {
						for (int j = 0; j < 5; j++) {
							if (d & (1 << j)) {
								if (transpose) {
									g.a[x] |= (1ull << (y + j));
									g.width = ((y + j) > g.width) ? (y + j) : g.width;
									g.height = (x > g.height) ? x : g.height;
								}
								else {
									g.a[y + j] |= (1ull << x);
									g.width = (x > g.width) ? x : g.width;
									g.height = ((y + j) > g.height) ? (y + j) : g.height;
								}
							}
						}
						x += 1;
					}
					else {
						if (d == 35) {
							x = 0;
							y += 5;
						}
						else {
							x += 2;
							if (d >= 33) {
								x += 1;
								if (d >= 34) {
									x += 1;
									iny = true;
								}
							}
						}
					}
				}
			}

		}
		else {
			underscore = (c == '_');
		}

	}

	g.width += 1;
	g.height += 1;

	return g;

}

int popcount2d(uint64_t* a, int ah) {

	int c = 0;
	for (int i = 0; i < ah; i++) {
		c += __builtin_popcountll(a[i]);
	}
	return c;

}

int popcount2d(grid64 g) {

	return popcount2d(g.a, g.height);

}

int vconvolve(uint64_t* a, const int ah, uint64_t* b, const int bh, int shift) {

	vector<int> counts(ah + bh - 1, 0);
	
	for (int i = 0; i < ah; i++) {
		for (int j = 0; j < bh; j++) {
			counts[i + j] += __builtin_popcountll(a[i] & (b[j] << shift));
		}
	}

	int c = 0;
	for (int i = 0; i < ah + bh - 1; i++) {
		c = (c < counts[i]) ? counts[i] : c;
	}

	return c;

}

int convolve2d(uint64_t* a, int ah, int aw, uint64_t* b, int bh, int bw) {

	int d = 0;
	for (int i = 0; i < aw - 1; i++) {
		int c = vconvolve(a, ah, b, bh, i);
		d = (d < c) ? c : d;
	}
	for (int i = 0; i < bw - 1; i++) {
		int c = vconvolve(b, bh, a, ah, i);
		d = (d < c) ? c : d;
	}
	return d;

}

int convolve2d(grid64 g, grid64 h) {

	return convolve2d(g.a, g.height, g.width, h.a, h.height, h.width);

}

void display_grid(grid64 g) {

	for (int y = 0; y < g.height; y++) {
		for (int x = 0; x < g.width; x++) {
			if (g.a[y] & (1ull << x)) {
				std::cout << 'O';
			}
			else {
				std::cout << '.';
			}
		}
		std::cout << std::endl;
	}
	std::cout << std::endl;

}

int main(int argc, char *argv[]) {

	std::vector<grid64> grids;
	
	/*
	grid64 ma = apgcode_to_grid("xs15_354cgc453", false);
	std::cout << ma.width << " by " << ma.height << " (pop : ";
	std::cout << popcount2d(ma.a, ma.height) << ")" << std::endl;
	*/

	
	std::string query(argv[1]);
	/*grids.push_back(apgcode_to_grid(query, false));
	grids.push_back(apgcode_to_grid(query, true));
	names.push_back(query);
	names.push_back(query);
	display_grid(grids[0]);
	*/

	grids.push_back(parse(query.c_str()));
	display_grid(grids[0]);
	
	grids.push_back(transpose(grids[0]));
	
	std::string fname(argv[2]);

	std::string line;
	std::vector<std::string> vecSL;

	std::ifstream infile(fname);
	while (std::getline(infile, line))
	{
		if (line[1] == 'x' && line[2] == 's')
		{
			int j = 1;

			std::string sl;
			while (line[j] != '"' && j < line.size())
				sl.push_back(line[j++]);

			vecSL.push_back(sl);
		}
	}

	int l = grids.size();
	for (int i = 0; i < l; i++) {
		grids.push_back(vertical_flip(grids[i]));
		
	}
	l += l;
	for (int i = 0; i < l; i++) {
		grids.push_back(horizontal_flip(grids[i]));
		
	}
	l += l;
	
	/*
	for (int i = 0; i < l; i++) {
		display_grid(grids[i]);
	}
	*/

	vector<pair<int, int>> scored_grids(vecSL.size());

	for (int idx = 0; idx < vecSL.size(); idx++)
	{
		int ersection = -1;
		grid64 bestg; 

		grid64 g = apgcode_to_grid(vecSL[idx], false);
		//display_grid(g);
		int p = popcount2d(g);
		int q = -1;

		for (int i = 0; i < l; i++) {
			int e = convolve2d(g, grids[i]);
			if (e > ersection) {
				ersection = e;
				
				q = popcount2d(grids[i]);
				
			}
		}

		scored_grids[idx].first = 1 * (p - ersection) + 5 * (q - ersection);
		scored_grids[idx].second = idx;

		/*std::cout << 2 * (p - ersection) + 5 * (q - ersection) << " ";
		std::cout << ersection << " ";
		std::cout << p - ersection << " ";
		std::cout << q - ersection << " ";
		std::cout << line << " " << name << std::endl;*/
	}

	sort(scored_grids.begin(), scored_grids.end());

	for (int i = 0; i < 10; i++)
	{
		cout << "\n\n"; 
		cout << scored_grids[i].first << " , " << vecSL[scored_grids[i].second] << endl;
		cout << "\n\n";
		grid64 g = apgcode_to_grid(vecSL[scored_grids[i].second], false);
		display_grid(g);
	}

	return 0;
}
usage:

slddiff.exe <rle> <path/to/c1.txt>

C1 can be downloaded here.

It uses 1,5 weights (instead of calcyman's 5,2)- I find those to be more corresponding to the intuition of closeness.

It also works with MSVC.

EDIT SL that could be Dart base:

xs27_cit1u0u1ticzy11

Code: Select all

 
..OO...OO..
.O..O.O..O.
O.O.O.O.O.O
O.O.O.O.O.O
.OO.O.O.OO.
.....O.....
The dart base:

Code: Select all

...O.
..O.O
.OO..
....O
O...O
O....
.OOOO
.....
.OOOO
O....
O...O
....O
.OO..
..O.O
...O.

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 9th, 2016, 5:17 pm
by simsim314
calcyman wrote:I wanted it to be fast, simple, and compatible with the use of Unix pipelines (which is why it reads from stdin and writes to stdout).
Woops... my modifications didn't went in this direction. I just wanted it to work independent of OS, and be more visual.
calcyman wrote:Morally, we favour reactions which produce the object at a lower temperature.
This is certainly a good "first derivative" approximation. But this approach has a problem - pi for example is very synthesis friendly, and yet generates a lot of heat. I think we would like to estimate temperature more accurately by probability/popularity of some constellations vs the others. We could even have some small database of common objects.

----

There is another point to this search. We currently rate all the cells with same weight - but there are obvious "internal" cells, and external ones. The internal "core" is something very hard to modify, on the other hand the external stuff is much more flexible. I think we should rate the cells by their relation to the "core" i.e. relative to the distance to the "outside". The more difficult for some cell to get "outside" the more important it's for it to be part of the SL.

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 10th, 2016, 10:50 pm
by BlinkerSpawn
simsim314 wrote:I think we should rate the cells by their relation to the "core" i.e. relative to the distance to the "outside". The more difficult for some cell to get "outside" the more important it's for it to be part of the SL.
Do you think simply calculating the moments of each cell would suffice?

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 10th, 2016, 11:51 pm
by Scorbie
BlinkerSpawn wrote:
simsim314 wrote:I think we should rate the cells by their relation to the "core" i.e. relative to the distance to the "outside". The more difficult for some cell to get "outside" the more important it's for it to be part of the SL.
Do you think simply calculating the moments of each cell would suffice?
Rather than giving them a somewhat arbitrary meaning like moment, I think it suffices to score them as is. Cells inside are much much harder to modify and I doubt there is a way to modify them with the current components. Perhaps we should give them high enough penalty, possibly increasing as the cell is farther from the boundary.

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 11th, 2016, 10:15 pm
by BlinkerSpawn
Scorbie wrote:
BlinkerSpawn wrote:
simsim314 wrote:I think we should rate the cells by their relation to the "core" i.e. relative to the distance to the "outside". The more difficult for some cell to get "outside" the more important it's for it to be part of the SL.
Do you think simply calculating the moments of each cell would suffice?
Rather than giving them a somewhat arbitrary meaning like moment, I think it suffices to score them as is. Cells inside are much much harder to modify and I doubt there is a way to modify them with the current components. Perhaps we should give them high enough penalty, possibly increasing as the cell is farther from the boundary.
I feel my comment was misinterpreted. To weight the cells by difficulty as simsim mentioned, would it be possible to treat each cell as a unit weight and calculate its net moment relative to the SL's center of gravity?
(In which case, cells w/ higher moments would have lower weights in the resultant score and vice versa)

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 11th, 2016, 10:19 pm
by Scorbie
BlinkerSpawn wrote:I feel my comment was misinterpreted. To weight the cells by difficulty as simsim mentioned, would it be possible to treat each cell as a unit weight and calculate its net moment relative to the SL's center of gravity?
(In which case, cells w/ higher moments would have lower weights in the resultant score and vice versa)
I think I should have said clearer. As construction modifies things from the outside, I think "the distance from the boundary" is a more important factor than "the distance from cog"... Just my personal opinion.

Re: sldiff -- Find closest still-lifes in Catagolue

Posted: August 13th, 2016, 8:11 am
by Scorbie
calcyman wrote:
simsim314 wrote:2. Search that tries to complete/modify the resulting SL step by step to reach the destination SL.
Ooh, that sounds difficult.
Something similar is used to prune out "trivial" syntheses by Mike Niemec:
http://codercontest.com/mniemiec/lifemeth.htm
I guess we only need to work it out backwards. (Yeah, I know, that's the hard part.) At least it does seem easier than "difficult".