
Question:
I challenged myself to create a program to experiment with Prime Numbers, I already have an idea how to do it, but not the coding skills..
My plan is this: First ill create a program in C# that makes straight lines that follow some rules:
<strong>rule 1:</strong> all lines have the same length.
<strong>rule 2:</strong> all lines are either horizontal or vertical (no diagonals).
<strong>rule 3:</strong> Every new line begins where the previous line has ended (that way all the lines are joined).
Now for the tricky part:
I would like to make a counter that goes up by 1 each time a new line is created (starting value is 1 I presume), and whenever it reaches a prime number, the lines change 'direction' and start 'going' to the left of the original direction.
<strong>The first 10 lines will look something like this:</strong>
|
__ |
| | |
|__ __|
Notice how it changed direction at the 2nd, 3rd, 5th and 7th line.
(starting from the inside ending at the outside)
This will create a long twisting line and it will be pretty cool to see what pattern it makes.
Thanks for helping!
Answer1:This was a fun project to play with. Thanks for my morning entertainment!
I used SLaks code in <a href="https://stackoverflow.com/questions/1510124/program-to-find-prime-numbers/1510186#1510186" rel="nofollow">this SO thread</a> to get a list of Primes less than a specified number.
Here is some sample output:
<a href="https://i.stack.imgur.com/6WRgR.jpg" rel="nofollow"><img alt="Example Output #1" class="b-lazy" data-src="https://i.stack.imgur.com/6WRgR.jpg" data-original="https://i.stack.imgur.com/6WRgR.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a> <a href="https://i.stack.imgur.com/wjDy6.jpg" rel="nofollow"><img alt="Example Output #2" class="b-lazy" data-src="https://i.stack.imgur.com/wjDy6.jpg" data-original="https://i.stack.imgur.com/wjDy6.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a> <a href="https://i.stack.imgur.com/iEeeq.jpg" rel="nofollow"><img alt="Example Output #3" class="b-lazy" data-src="https://i.stack.imgur.com/iEeeq.jpg" data-original="https://i.stack.imgur.com/iEeeq.jpg" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>
After generating the Primes, I walk the list and store the lines in a <a href="https://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.graphicspath(v=vs.110).aspx" rel="nofollow">GraphicsPath</a>. Using the Graphics.GetBounds()
method then allows us to appropriately scale and transform the Graphics in the Paint() event of our Panel so that the entire drawing can be seen:
public partial class Form1 : Form
{
private const int segmentLength = 10;
private GraphicsPath gpPrimes = null;
public Form1()
{
InitializeComponent();
nudLessThanMax.Minimum = 15;
nudLessThanMax.Maximum = 500000;
nudLessThanMax.Value = nudLessThanMax.Minimum;
pnlPrimes.Paint += PnlPrimes_Paint;
pnlPrimes.SizeChanged += PnlPrimes_SizeChanged;
}
private void PnlPrimes_SizeChanged(object sender, EventArgs e)
{
pnlPrimes.Invalidate();
}
private void PnlPrimes_Paint(object sender, PaintEventArgs e)
{
if (gpPrimes != null)
{
RectangleF rectF = gpPrimes.GetBounds();
float max = Math.Max(rectF.Width + (2 * segmentLength), rectF.Height + (2 * segmentLength));
e.Graphics.TranslateTransform(pnlPrimes.Width / 2, pnlPrimes.Height / 2);
e.Graphics.ScaleTransform((float)pnlPrimes.Width / max, (float)pnlPrimes.Height / max);
e.Graphics.TranslateTransform(-(rectF.Left + rectF.Width / 2), -(rectF.Top + rectF.Height / 2));
e.Graphics.DrawPath(Pens.Black, gpPrimes);
}
}
private void btnGraphPrimes_Click(object sender, EventArgs e)
{
btnGraphPrimes.Enabled = false;
backgroundWorker1.RunWorkerAsync((int)this.nudLessThanMax.Value);
}
private List<int> PrimesLessThan(int num) // SLaks: https://stackoverflow.com/a/1510186/2330053
{
return Enumerable.Range(0, (int)Math.Floor(2.52 * Math.Sqrt(num) / Math.Log(num))).Aggregate(
Enumerable.Range(2, num - 1).ToList(),
(result, index) =>
{
var bp = result[index]; var sqr = bp * bp;
result.RemoveAll(i => i >= sqr && i % bp == 0);
return result;
}
);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int diff;
int num = (int)e.Argument;
Point pt = new Point(0, 0);
Point pt2 = pt;
GraphicsPath gp = new GraphicsPath();
List<int> primes = PrimesLessThan(num);
for(int i = 1; i < primes.Count; i++)
{
diff = primes[i] - primes[i - 1];
switch(i % 4)
{
case 1: // up
pt2 = new Point(pt.X, pt.Y - (segmentLength * diff));
break;
case 2: // left
pt2 = new Point(pt.X - (segmentLength * diff), pt.Y);
break;
case 3: // down
pt2 = new Point(pt.X, pt.Y + (segmentLength * diff));
break;
case 0: // right
pt2 = new Point(pt.X + (segmentLength * diff), pt.Y);
break;
}
gp.AddLine(pt, pt2);
pt = pt2;
}
gpPrimes = gp;
e.Result = primes;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lbPrimes.DataSource = (List<int>)e.Result;
pnlPrimes.Invalidate();
btnGraphPrimes.Enabled = true;
}
}
Answer2:Once again I wish I had enough points to make this just a comment, but I wanted to make sure you knew ahead of time this will not result in a sprial all the way out. There are pairs of primes only 2 apart (n, n+2 both prime) which will make your snake do a 180 and cross over itself.
If you are OK with that, then look into the System.Drawing namespace, especially at the Graphics.Drawline method. Or have a look at a little code that will help give you the right idea. Just put a pictureBox in a Windows Form and this code will put a line on it. From there you can work on your pen colors, scale, finding your primes, etc.
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawLine(new Pen(Color.Red), 300, 100, 100, 100);
}
pictureBox1.Image = bmp;