Skip to content

Instantly share code, notes, and snippets.

@louisswarren
Last active April 26, 2021 03:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save louisswarren/aac24e1b3106f8c13b8cf3247393624f to your computer and use it in GitHub Desktop.
Save louisswarren/aac24e1b3106f8c13b8cf3247393624f to your computer and use it in GitHub Desktop.
Menger sponge sides
.PHONY: default
default: menger8.png
%.png: %.pbm
convert $^ $@
menger%.pbm: menger
./$^ $* > $@
menger%.svg: menger.py
python3 $^ $* > $@
menger: menger.c
.PHONY: clean
clean:
rm -f menger *.png *.svg
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long three_power(long n)
{
long i;
long x = 1;
for (i = 0; i < n; ++i)
x *= 3;
return x;
}
int
main(int argc, char *argv[])
{
int n = 4;
long i, j, k, x, y;
long dim;
if (argc > 1 && !(n = atoi(argv[1]))) {
fprintf(stderr, "Usage: menger <level>\n");
return 1;
}
dim = three_power(n);
if (dim > ((size_t) -1) / dim) {
fprintf(stderr, "Dimension too large.\n");
return 1;
}
printf("P1\n%ld %ld\n", dim, dim);
/* VLA trick */
char (*board)[dim] = malloc(dim * dim);
memset(board, '1', dim * dim);
memset(&board[dim/3][dim/3], '0', dim / 3);
for (i = 0; i < dim/3; ++i) {
for (j = 0; j < dim/3; ++j) {
for (k = 0; k < n; ++k) {
x = three_power(k);
if ((x <= i % (3 * x) && i % (3 * x) < 2 * x)
&& (x <= j % (3 * x) && j % (3 * x) < 2 * x)) {
board[i][j] = '0';
break;
}
}
}
}
for (i = 0; i < dim/3; ++i) {
fwrite(board[i], dim/3, 1, stdout);
fwrite(board[i], dim/3, 1, stdout);
fwrite(board[i], dim/3, 1, stdout);
}
for (i = 0; i < dim/3; ++i) {
fwrite(board[i], dim/3, 1, stdout);
fwrite(board[dim/3] + dim/3, dim/3, 1, stdout);
fwrite(board[i], dim/3, 1, stdout);
}
for (i = 0; i < dim/3; ++i) {
fwrite(board[i], dim/3, 1, stdout);
fwrite(board[i], dim/3, 1, stdout);
fwrite(board[i], dim/3, 1, stdout);
}
}
import math
import sys
from svg import *
def log(*a, **k):
print(*a, **k, file=sys.stderr)
def svg_square_centred(p, size, *args, **kwargs):
return svg_rect((p[0] - size/2, p[1] - size/2), size, size, *args, **kwargs)
# Basic header
svg_header()
svg_open(width=1200, height=1200, x_bias=-150, y_bias=-150, xw=300, yh=300)
svg_square_centred((0,0), 300)
def menger(n, p=(0,0), k=1):
unit = 300/3**k
svg_square_centred(p, unit, fill='white')
if k < n:
menger(n, (p[0] - unit, p[1] - unit), k + 1)
menger(n, (p[0] , p[1] - unit), k + 1)
menger(n, (p[0] + unit, p[1] - unit), k + 1)
menger(n, (p[0] - unit, p[1] ), k + 1)
menger(n, (p[0] + unit, p[1] ), k + 1)
menger(n, (p[0] - unit, p[1] + unit), k + 1)
menger(n, (p[0] , p[1] + unit), k + 1)
menger(n, (p[0] + unit, p[1] + unit), k + 1)
if len(sys.argv) >= 2:
menger(int(sys.argv[1]))
else:
menger(4)
# Footer
svg_close()
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
def xml(tag, _xml_tag_is_a_singleton=True, **options):
s = f'<{tag}'
kw_attrib = lambda x: x.replace('_', '-')
if options:
s += ' '
s += ' '.join(f'{kw_attrib(k)}="{str(v)}"' for k, v in options.items())
if _xml_tag_is_a_singleton:
s += ' />'
else:
s += '>'
print(s)
def xml_open(*args, **kwargs):
xml(*args, **kwargs, _xml_tag_is_a_singleton=False)
def xml_close(tag):
print(f'</{tag}>')
def svg_header():
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
def svg_open(width, height, x_bias, y_bias, xw, yh):
vb = f'{x_bias} {y_bias} {xw} {yh}'
ns = 'http://www.w3.org/2000/svg'
xml_open('svg', width=width, height=height, viewBox=vb, xmlns=ns)
def svg_close():
xml_close('svg')
def svg_poly(*points, **opts):
point_str = ' '.join(f'{x},{y}' for x, y in points)
xml('polyline', points=point_str, **opts)
def svg_circle(point, radius, **opts):
xml('circle', cx=point[0], cy=point[1], r=radius, **opts)
def svg_line(p1, p2, **opts):
xml('line', x1=p1[0], y1=p1[1], x2=p2[0], y2=p2[1], **opts)
def svg_rect(p, width, height, x_radius=0, y_radius=0, **opts):
xml('rect', x=p[0], y=p[1], width=width, height=height,
rx=x_radius, ry=y_radius, **opts)
@louisswarren
Copy link
Author

To freeze your computer, try make menger8.png

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment