Big Fat Lazy Spiral

Discussion of challenges you have already solved
Post Reply
User avatar
Hippo
Posts: 339
Joined: Sat Feb 01, 2014 12:05 am
Location: Praha 5

Big Fat Lazy Spiral

Post by Hippo »

I failed to get the transformation perfect, fortunately it was readable.
eulerscheZahl
Posts: 58
Joined: Thu Nov 29, 2012 7:45 pm
Location: Germany

Post by eulerscheZahl »

That's all of the discussion about this one?

I didn't even try to detect the circles. Instead I detected regions and counted the pixels used (43.5 per circle is a good value). If the number of pixels in the group is somewhere between, I simply tried both - but that only happened in the previous spiral.

Here is my C# code, runs within a few seconds:

Code: Select all

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Linq;
using System.Drawing;

namespace lazySpiral
{
	class MainClass
	{
		static bool FillRegion(Bitmap bmp, int x, int y, List<List<bool>> bits, bool white, out int xtmp, out int ytmp) {
			xtmp = 0; ytmp = 0;
			HashSet<Point> current = new HashSet<Point> { new Point(x,y) };
			int hits = 0;
			int[,] offset = new int[,] { {-1,0}, {1,0}, {0,-1}, {0,1} };
			while (current.Count > 0) {
				Point tmp = current.First ();
				current.Remove (tmp);
				hits++;
				bmp.SetPixel (tmp.X, tmp.Y, Color.Black);
				for (int dir = 0; dir < 4; dir++) {
					Color cl = bmp.GetPixel (tmp.X + offset [dir, 0], tmp.Y + offset [dir, 1]);
					Point neighbor = new Point (tmp.X + offset [dir, 0], tmp.Y + offset [dir, 1]);
					if (cl.B < 100)
						continue;
					if (white) {
						if (cl.B == cl.G) { //is white
							current.Add (neighbor);
						} else if (cl.B > cl.G) { //is purple
							if (Enumerable.Range (0, 4).Any (p => 
							                                 bmp.GetPixel (neighbor.X + offset [p, 0], neighbor.Y + offset [p, 1]).B > 
							                                 bmp.GetPixel (neighbor.X + offset [p, 0], neighbor.Y + offset [p, 1]).G && 
							                                 bmp.GetPixel (neighbor.X + offset [p, 0], neighbor.Y + offset [p, 1]).B >= 100)) {
								xtmp = tmp.X + offset [dir, 0];
								ytmp = tmp.Y + offset [dir, 1];
							}
						}
					} else {
						if (cl.B > cl.G) { //is purple
							current.Add (neighbor);
						} else if (cl.B == cl.G) { //is white
							if (Enumerable.Range (0, 4).Any (p => 
							                                 bmp.GetPixel (neighbor.X + offset [p, 0], neighbor.Y + offset [p, 1]).B == 
							                                 bmp.GetPixel (neighbor.X + offset [p, 0], neighbor.Y + offset [p, 1]).G &&
							    							 bmp.GetPixel (neighbor.X + offset [p, 0], neighbor.Y + offset [p, 1]).B >= 100)) {
								xtmp = tmp.X + offset [dir, 0];
								ytmp = tmp.Y + offset [dir, 1];
							}
						}
					}
				}
			}
			float pixelPerDot = 43.5f;
			foreach (List<bool> l in bits) {
				for (int i = 0; i < Math.Round(hits/pixelPerDot); i++) {
					l.Add (white);
				}
			}
			Console.WriteLine (x + "/" + y + ": " + hits);
			//error correction
			float remainder = hits % pixelPerDot;
			if (remainder > pixelPerDot / 2)
				remainder = pixelPerDot - remainder;
			if (remainder > 15) {
				Console.WriteLine (x + "/" + y + ": " + hits + "   remainder: " + remainder);
				for (int i = bits.Count - 1; i >= 0; i--) {
					bits.Add (new List<bool> (bits [i]));
					if (hits % pixelPerDot < pixelPerDot / 2) {
						bits [i].Add (white);
					} else {
						bits [i].RemoveAt (bits [i].Count - 1);
					}
				}
			}
			return hits != 1;
		}

		static void Main(string[] args)
		{
			Bitmap bmp = new Bitmap ("/home/eulerschezahl/Downloads/spiral3.png"); //image is edited for previous spiral
			int x = 2050;
			int y = 2050;
			int xtmp, ytmp;
			List<List<bool>> bits = new List<List<bool>> { new List<bool>() };
			bool white = true;
			int c = 0;
			do {
				FillRegion (bmp, x, y, bits, white, out xtmp, out ytmp);
				white = !white;
				x = xtmp;
				y = ytmp;
				//bmp.Save ("/home/eulerschezahl/Downloads/spiral2_post" + (c++).ToString("D4") + ".png");
			} while(x != 0 || y != 0);
			bmp.Save ("/home/eulerschezahl/Downloads/spiral3_post.png");
			foreach (List<bool> l in bits) {
				if (l.Count % 8 != 0)
					continue;
				List<byte> bytes = new List<byte> ();
				for (int i = 0; i < l.Count; i+=8) {
					byte b = 0;
					for (int j = 0; j < 8; j++) {
						b *= 2;
						if (l [i + j])
							b++;
					}				
					bytes.Add (b);
				}
				File.WriteAllBytes ("/home/eulerschezahl/Downloads/solution" + (c++) + ".png", bytes.ToArray ());
			}
		}
	}
}
Post Reply