Search files for target text in C#

[search files]

The .NET tools available in the System.IO namespace and normal string methods make it easy to search files for target text. When you click the Search button, the following code displays the lines in a file that contain a particular string.

// Search for lines containing the target text.
private void btnSearch_Click(object sender, EventArgs e)
{
    lstResults.Items.Clear();
    lblResults.Text = "";
    Refresh();

    string target = txtTarget.Text;
    string[] lines = File.ReadAllLines(txtFile.Text);
    foreach (string line in lines)
        if (line.Contains(target))
            lstResults.Items.Add(line);

    lblResults.Text = lstResults.Items.Count.ToString() + " matches";
}

This code gets the target text. It then uses File.ReadAllLines to read the file into an array holding the file’s lines.

The code then loops through the lines and uses each line’s Contains method to see if the line contains the target text. If the line does contain the text, then the program adds it to the ListBox named lstResults.

The code finishes by displaying the number of lines saved into the ListBox.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in files | Tagged , , , , , , , | Leave a comment

Write Console window output to multiple places in C#

[example]

This example captures output sent to the Console window and displays it in multiple controls plus the Console window. It is based on an excellent reply by user Servy on Stack Overflow.

The following class is a TextWriter that represents a list if places where it should write text destined to the Console window.

// Represent a list of TextWriter objects.
public class ListTextWriter : TextWriter
{
    private List<TextWriter> Writers = new List<TextWriter>();

    // Add a new textWriter to the list.
    public void Add(TextWriter writer)
    {
        Writers.Add(writer);
    }

    public override void Write(char value)
    {
        foreach (var writer in Writers)
            writer.Write(value);
    }

    public override void Write(string value)
    {
        foreach (var writer in Writers)
            writer.Write(value);
    }

    public override void Flush()
    {
        foreach (var writer in Writers)
            writer.Flush();
    }

    public override void Close()
    {
        foreach (var writer in Writers)
            writer.Close();
    }

    public override Encoding Encoding
    {
        get { return Encoding.Unicode; }
    }
}

It’s Add method adds a TextWriter object to this object’s Writers list. The overridden Write, Flush, and Close methods simply loop through the control’s writers and calls the corresponding methods for each.

The main program uses this class in the following code.

// Install a new output TextWriter and the
// Console window's default output writer.
private void Form1_Load(object sender, EventArgs e)
{            
    ListTextWriter list_writer = new ListTextWriter();
    list_writer.Add(new TextBoxWriter(txtConsole));
    list_writer.Add(new TextBoxWriter(lblConsole));
    list_writer.Add(Console.Out);

    Console.SetOut(list_writer);
}

This code makes a new ListTextWriter. It then adds two TextBoxWriter controls (from the previous post) attached to a TextBox and a Label. It also adds the Console window’s default output TextWriter. Finally, the code calls the Console object’s SetOut method to make it use the new ListTextWriter.

Now when the program sends text to the Console window, the ListTextWriter sends the text to the TextBox, Label, and normal Console window output writer.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in Uncategorized | Tagged , , , , , , , , | Leave a comment

Redirect Console window output to a TextBox in C#

[example]

This example captures output sent to the Console window and displays it in a TextBox control. It is based on an excellent reply by user Servy on Stack Overflow.

The Console object has a SetOut method that lets you change the TextWriter object to which it sends output. To redirect the output, you create a TextWriter subclass and then make the Console object send output to it.

The following code shows the TextBoxWriter class.

public class TextBoxWriter : TextWriter
{
    // The control where we will write text.
    private Control MyControl;
    public TextBoxWriter(Control control)
    {
        MyControl = control;
    }

    public override void Write(char value)
    {
        MyControl.Text += value;
    }

    public override void Write(string value)
    {
        MyControl.Text += value;
    }

    public override Encoding Encoding
    {
        get { return Encoding.Unicode; }
    }
}

This method overrides the TextWriter base class’s Write method and Encoding property. The Write(char value) method and the property are marked as abstract, so you must override them in any derived class. Overriding Write(string value) makes output more efficient.

The two versions of the Write method simply append their parameters to the control’s Text property. As in Servy’s example, the writer’s control is a generic Control, so this will work with a TextBox, Label, or other reasonable control.

When the program starts, the following Form_Load event handler installs the new writer.

// Install a new output TextWriter for the Console window.
private void Form1_Load(object sender, EventArgs e)
{
    TextBoxWriter writer = new TextBoxWriter(txtConsole);
    Console.SetOut(writer);
}

This code creates a new TextBoxWriter associated with the form’s TextBox named txtConsole. It then passes the writer into the Console object’s SetOut method.

When you enter text in the form’s TextBox and click Write, the following code executes.

// Write to the Console window.
private void btnWrite_Click(object sender, EventArgs e)
{
    Console.WriteLine(txtOutput.Text);
    txtOutput.Clear();
}

This code simply writes your text into the Console object and then clears the input TextBox.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in console | Tagged , , , , , , , , | 1 Comment

Get a weather forecast from openweathermap.org in C#

[weather forecast]

This example displays a weather forecast from openweathermap.org. To get a forecast or other data, you build a URL describing your request and navigate to it. You then parse the returned XML or JSON data to see what openweathermap.org has to say.

The first step in using openweathermap.org is to get an API ID. You can get one for free here. You will need to sign up for a free account.

After you get an API ID, you can use it in your URLs.

This example begins with the following code.

// Enter your API key here.
// Get an API key by making a free account at:
//      http://home.openweathermap.org/users/sign_in
private const string API_KEY = "12345678901234567890123456789012";

// Query URLs. Replace @LOC@ with the location.
private const string CurrentUrl =
    "http://api.openweathermap.org/data/2.5/weather?" +
    "@QUERY@=@LOC@&mode=xml&units=imperial&APPID=" + API_KEY;
private const string ForecastUrl =
    "http://api.openweathermap.org/data/2.5/forecast?" +
    "@QUERY@=@LOC@&mode=xml&units=imperial&APPID=" + API_KEY;

This code defines your API ID. Replace the number shown here with your ID.

The two string constants hold template URLs to get current weather conditions and forecast conditions. The code will later replace the pieces @QUERY@ and @LOC@ with values for a specific query.

When the program starts, the following Load event handler executes.

// Query codes.
private string[] QueryCodes = { "q", "zip", "id", };

// Fill in query types. These should match the QueryCodes.
private void Form1_Load(object sender, EventArgs e)
{
    cboQuery.Items.Add("City");
    cboQuery.Items.Add("ZIP");
    cboQuery.Items.Add("ID");

    cboQuery.SelectedIndex = 1;
}

The QueryCodes array holds query strings to get data by city name (q), zip code, or ID.

The form’s Load event handler initializes the cboQuery ComboBox control with values corresponding to the query codes. Those values must match up with the ones in the QueryCodes array.

When you click Forecast, the following code executes.

// Get a forecast.
private void btnForecast_Click(object sender, EventArgs e)
{
    // Compose the query URL.
    string url = ForecastUrl.Replace("@LOC@", txtLocation.Text);
    url = url.Replace("@QUERY@", QueryCodes[cboQuery.SelectedIndex]);

    // Create a web client.
    using (WebClient client = new WebClient())
    {
        // Get the response string from the URL.
        try
        {
            DisplayForecast(client.DownloadString(url));
        }
        catch (WebException ex)
        {
            DisplayError(ex);
        }
        catch (Exception ex)
        {
            MessageBox.Show("Unknown error\n" + ex.Message);
        }
    }
}

This code takes the forecast URL template and replaces @LOC@ with the location that you entered. It then replaces @QUERY@ with the appropriate query code.

Next, the creates a WebClient and makes it navigate to the URL. The code then either displays the forecast or an error message. I’ll say more about those methods in a moment. First, the following shows a typical response somewhat abbreviated.

<weatherdata>
  <location>
    <name>Washington D.C.</name>
    <type/>
    <country>US</country>
    <timezone/>
    <location altitude="0" latitude="38.895" longitude="-77.0367" geobase="geonames" geobaseid="420008701"/>
  </location>
  <credit/>
  <meta>
    <lastupdate/>
    <calctime>0.0043</calctime>
    <nextupdate/>
  </meta>
  <sun rise="2018-07-30T10:08:00" set="2018-07-31T00:20:33"/>
  <forecast>
    <time from="2018-07-30T15:00:00" to="2018-07-30T18:00:00">
      <symbol number="500" name="light rain" var="10d"/>
      <precipitation unit="3h" value="0.11" type="rain"/>
      <windDirection deg="124.5" code="SE" name="SouthEast"/>
      <windSpeed mps="10.36" name="Fresh Breeze"/>
      <temperature unit="imperial" value="74.68" min="74.68" max="76.74"/>
      <pressure unit="hPa" value="1026.45"/>
      <humidity value="82" unit="%"/>
      <clouds value="overcast clouds" all="92" unit="%"/>
    </time>
    <time from="2018-07-30T18:00:00" to="2018-07-30T21:00:00">
      <symbol number="500" name="light rain" var="10d"/>
      <precipitation unit="3h" value="0.0075" type="rain"/>
      <windDirection deg="125.004" code="SE" name="SouthEast"/>
      <windSpeed mps="10.27" name="Fresh Breeze"/>
      <temperature unit="imperial" value="73.36" min="73.36" max="74.9"/>
      <pressure unit="hPa" value="1025.8"/>
      <humidity value="83" unit="%"/>
      <clouds value="broken clouds" all="80" unit="%"/>
    </time>
    ...
  </forecast>
</weatherdata>

The following code parses the data to get the forecast.

// Display the forecast.
private void DisplayForecast(string xml)
{
    // Load the response into an XML document.
    XmlDocument xml_doc = new XmlDocument();
    xml_doc.LoadXml(xml);

    // Get the city, country, latitude, and longitude.
    XmlNode loc_node = xml_doc.SelectSingleNode("weatherdata/location");
    txtCity.Text = loc_node.SelectSingleNode("name").InnerText;
    txtCountry.Text = loc_node.SelectSingleNode("country").InnerText;
    XmlNode geo_node = loc_node.SelectSingleNode("location");
    txtLat.Text = geo_node.Attributes["latitude"].Value;
    txtLong.Text = geo_node.Attributes["longitude"].Value;
    txtId.Text = geo_node.Attributes["geobaseid"].Value;

    lvwForecast.Items.Clear();
    char degrees = (char)176;
    
    foreach (XmlNode time_node in xml_doc.SelectNodes("//time"))
    {
        // Get the time in UTC.
        DateTime time =
            DateTime.Parse(time_node.Attributes["from"].Value,
                null, DateTimeStyles.AssumeUniversal);

        // Get the temperature.
        XmlNode temp_node = time_node.SelectSingleNode("temperature");
        string temp = temp_node.Attributes["value"].Value;

        ListViewItem item = lvwForecast.Items.Add(time.DayOfWeek.ToString());
        item.SubItems.Add(time.ToShortTimeString());
        item.SubItems.Add(temp + degrees);
    }
}

This method loads the returned XML data into an XmlDocument object. It then gets various elements in the object to find the location’s city name, country, latitude, longitude, and ID.

NOTE: City names can be hard to use. Typically, you use the city’s name and country name separated by a comma as in Springfield, US. Unfortunately, there doesn’t seem to be a good way to differentiate among different cities with the same name. A better approach is to use city ID or ZIP code.

After displaying the basic information, the program loops through the XML document’s time elements. For each of those elements, the method finds the from value. All openweathermap time values are in UTC, so the code parses the time as a universal time. Later, when the code gets the time’s value, it gets it in local time so it makes more sense.

Next, the code gets the entry’s temperature element. It then adds the weekday, time, and temperature to the lvwForecast ListView control.

If there is an error, the web response object contains additional error information. The following code shows how the program displays that information.

// Display an error message.
private void DisplayError(WebException exception)
{
    try
    {
        StreamReader reader = new StreamReader(exception.Response.GetResponseStream());
        XmlDocument response_doc = new XmlDocument();
        response_doc.LoadXml(reader.ReadToEnd());
        XmlNode message_node = response_doc.SelectSingleNode("//message");
        MessageBox.Show(message_node.InnerText);
    }
    catch (Exception ex)
    {
        MessageBox.Show("Unknown error\n" + ex.Message);
    }
}

This code creates a StreamReader attached to the response stream. It reads the text from the reader and uses it to create an XML document. It then displays that object’s message element.

Unfortunately, the response seems to sometimes return XML code (as when the city doesn’t exist) and sometimes JSON code (as when the API ID is invalid). If you find a way to make it always return XML code, post a comment below. Or if you modify this method to handle both XML and JSON, which I’m too lazy to do right now, post a comment.

Download the example, get your own API ID, and give it a try!


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in internet, web, XML | Tagged , , , , , , , , , , , | Leave a comment

Draw rose curves in C#

[rose curves]

A rose curve is a curve generated by the polar coordinate equation r = cos(n / d * θ). Here n and d should be relatively prime, so the fraction n / d cannot be simplified.


When you click the Draw button, the following event handler executes.

private void btnDraw_Click(object sender, EventArgs e)
{
    float A = float.Parse(txtA.Text);
    int n = int.Parse(txtN.Text);
    int d = int.Parse(txtD.Text);

    // Make the Bitmap and associated Graphics object.
    Bitmap bm = new Bitmap(300, 300);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.Clear(Color.White);
        gr.SmoothingMode = SmoothingMode.AntiAlias;

        // Set up a transformation to map the region
        // x/y = A +/- 0.1 onto the Bitmap.
        RectangleF rect = new RectangleF(
            -A - 0.1f, -A - 0.1f, 2 * A + 0.2f, 2 * A + 0.2f);
        PointF[] pts =
        {
            new PointF(0, bm.Height),
            new PointF(bm.Width, bm.Height),
            new PointF(0, 0),
        };
        gr.Transform = new Matrix(rect, pts);

        // Draw the curve.
        DrawCurve(gr, A, n, d);

        // Draw the axes.
        DrawAxes(gr, rect.Right);

        // Display the result and size the form to fit.
        picCurve.Image = bm;
        picCurve.SizeMode = PictureBoxSizeMode.AutoSize;
        this.ClientSize = new Size(
            picCurve.Right + picCurve.Top,
            picCurve.Bottom + picCurve.Top);
    }
}

This code gets the parameters A, n, and d. The values n and d are used in the rose curve equation. The value A is simply a scale factor.

Next, the event handler creates a transformation to map the curve’s area plus a margin onto the program’s PictureBox control. It then calls the DrawCurve method to draw the curve and the DrawAxes method to draw the X and Y axes. The DrawAxes method is straightforward so I won’t show it here. Download the example to see how it works.

The following code shows the DrawCurve method.

// Draw the curve.
// n and d should be relatively prime.
private void DrawCurve(Graphics gr, float A, int n, int d)
{
    const int num_points = 1000;

    // Period is Pi * d if n and d are both odd. 2 * Pi * d otherwise.
    double period = Math.PI * d;
    if ((n % 2 == 0) || (d % 2 == 0)) period *= 2;

    double dtheta = period / num_points;
    List<PointF> points = new List<PointF>();
    double k = (double)n / d;
    for (int i = 0; i < num_points; i++)
    {
        double theta = i * dtheta;
        double r = A * Math.Cos(k * theta);
        float x = (float)(r * Math.Cos(theta));
        float y = (float)(r * Math.Sin(theta));

        points.Add(new PointF(x, y));
    }

    gr.FillPolygon(Brushes.LightBlue, points.ToArray());

    // Draw the curve.
    using (Pen pen = new Pen(Color.Red, 0))
    {
        gr.DrawLines(pen, points.ToArray());
    }
}

The method starts by calculating the curve’s period. If n and d are both odd, then the period is πd. If either n or d is even, the curve’s period is 2πd.

The method makes a list of points and then enters a loop. Inside the loop, the code increments the variable theta and uses it to calculate the next point on the curve.

After the loop ends, the program fills the curve with light blue and then outlines it in red.

Download the example program to see additional details.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, drawing, graphics, mathematics | Tagged , , , , , , , , | Leave a comment

Find two sets where the median of one is the mean of the other and vice versa in C#

[sets]

For an upcoming book, I wanted to find sets where the mean (average) of one is the median (middle value) of the other and vice versa. I wanted to avoid trivial examples such as {1, 1, 1} and where the two sets are the same.

This example does that by making a list of all possible sets containing three values between one and a maximum that you specify. It then compares two lists of sets and compares means and medians.

The following method generates the sets.

private List<List<int>> Triples(int max)
{
    List<List<int>> results = new List<List<int>>();

    for (int i = 1; i < max; i++)
        for (int j = i + 1; j < max; j++)
            for (int k = j + 1; k < max; k++)
            {
                results.Add(new List<int>(new int[] { i, j, k }));
            }
    return results;
}

This method simply uses three loops to generate sets containing three items. Each looping variable starts one greater than the previous one. For example, j starts looping at i + 1. That prevents the sets from having duplicate values. It also means the values in a set are sorted so the median value is the second one in the set.

The following code shows how the program uses the list of sets.

private void btnGo_Click(object sender, EventArgs e)
{
    lstMatches.Items.Clear();
    lblNumMatches.Text = "";
    Cursor = Cursors.WaitCursor;
    Refresh();

    int max = int.Parse(txtMax.Text);

    List<List<int>> list1 = Triples(max);
    foreach (List<int> triple1 in list1)
    {
        int sum1 = triple1.Sum();
        if (sum1 % 3 != 0) continue;
        int mean1 = sum1 / 3;
        int median1 = triple1[1];
        if (mean1 == median1) continue;

        foreach (List<int> triple2 in list1)
        {
            if ((triple1[0] == triple2[0]) &&
                (triple1[1] == triple2[1]) &&
                (triple1[2] == triple2[2]))
                continue;

            int sum2 = triple2.Sum();
            if (sum2 % 3 != 0) continue;
            int mean2 = sum2 / 3;
            int median2 = triple2[1];
            if (mean2 == median2) continue;

            if ((mean1 == median2) && (mean2 == median1))
            {
                // Find sets where the mean of one is the
                // median of the other and vice versa.
                lstMatches.Items.Add(
                    TripleString(triple1) + '\t' +
                    TripleString(triple2));
                Console.WriteLine(
                    TripleString(triple1) + '\t' +
                    triple1.Sum() / 3 + '\t' +
                    triple1[1].ToString() + '\t' +

                    TripleString(triple2) + '\t' +
                    triple2.Sum() / 3 + '\t' +
                    triple2[1].ToString());
                Refresh();
            }
        }
    }

    lblNumMatches.Text = lstMatches.Items.Count.ToString();
    Cursor = Cursors.Default;
}

This code makes a list containing the possible sets. It then makes variable triple1 loop through the list. For each set, it calculates the set's mean and median. It then makes variable triple2 loop over the sets, again.

If the two sets are the same, the loop continues. If the sets are different, the code calculates the second set's mean and median and compares the values for the two sets. If there's a match, the program adds the two sets to the lstMatches list box. It also adds the sets, their means, and their medians to the Console window.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, combinatorics | Tagged , , , , , , , , , , | Leave a comment

Trim images in C#

[trim images]

This example shows how you can trim images to remove unnecessary whitespace around their edges.

Sometimes when I make pictures for a book, it’s hard to tell where the edges of the picture begin, so I risk either including more white space than necessary or clipping off the edges of shapes that are antialiased near the picture’s edges. This example loops over the image’s pixels to see where the non-white pixels begin.

The heart of the program is the following TrimImage method.

// Trim the image to its non-white pixels plus a margin.
private Bitmap TrimImage(Bitmap image, int margin)
{
    // Make a Bitmap32.
    Bitmap32 bm32 = new Bitmap32(image);
    bm32.LockBitmap();

    // Find the pixel bounds.
    Rectangle src_rect = ImageBounds(bm32);
    bm32.UnlockBitmap();

    // Copy the non-white area.
    int wid = src_rect.Width + 2 * margin;
    int hgt = src_rect.Height + 2 * margin;
    Bitmap bm = new Bitmap(wid, hgt);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.Clear(Color.White);
        Rectangle dest_rect = new Rectangle(
            margin, margin, src_rect.Width, src_rect.Height);
        gr.DrawImage(image, dest_rect, src_rect, GraphicsUnit.Pixel);
    }

    return bm;
}

This method creates a Bitmap32 object and locks it so we can work with it. For information on how that class works, see the post Use the Bitmap32 class to manipulate image pixels very quickly in C#.

The method then calls the ImageBounds method described shortly to find the bounds where the image is non-white and adds a margin if desired. The method then creates a new Bitmap to fit the desired area and makes an associated Graphics object. It clears the bitmap and uses its DrawImage method to copy the desired part of the original image onto the bitmap. The method finishes by returning the new bitmap.

The following code shows the ImageBounds method.

// Get the image's bounds.
private Rectangle ImageBounds(Bitmap32 bm32)
{
    // ymin.
    int ymin = bm32.Height - 1;
    for (int y = 0; y < bm32.Height; y++)
    {
        if (!RowIsWhite(bm32, y))
        {
            ymin = y;
            break;
        }
    }

    // ymax.
    int ymax = 0;
    for (int y = bm32.Height - 1; y >= ymin; y--)
    {
        if (!RowIsWhite(bm32, y))
        {
            ymax = y;
            break;
        }
    }

    // xmin.
    int xmin = bm32.Width - 1;
    for (int x = 0; x < bm32.Width; x++)
    {
        if (!ColumnIsWhite(bm32, x))
        {
            xmin = x;
            break;
        }
    }

    // xmax.
    int xmax = 0;
    for (int x = bm32.Width - 1; x >= xmin; x--)
    {
        if (!ColumnIsWhite(bm32, x))
        {
            xmax = x;
            break;
        }
    }

    // Build the rectangle.
    return new Rectangle(xmin, ymin,
        xmax - xmin + 1, ymax - ymin + 1);
}

This method loops through the image’s rows starting at row 0 and working its way down through the image. For each row, the method calls RowIsWhite (described next) to see if the row has any non-white pixels. When it finds a non-white row, the method saves its index in variable ymin and then breaks out of its loop.

The method performs similar steps to find the bottommost non-white row. It then uses similar calculations to find the largest and smallest non-white columns.

The following code shows the RowIsWhite method.

// Return true if this row is all white.
private bool RowIsWhite(Bitmap32 bm32, int y)
{
    byte r, g, b, a;
    for (int x = 0; x < bm32.Width; x++)
    {
        bm32.GetPixel(x, y, out r, out g, out b, out a);
        if ((r != 255) || (g != 255) || (b != 255)) return false;
    }
    return true;
}

This method loops through the pixels in the image's row with the indicated y coordinate. If any of a pixel's red, green, or blue component is less than 255, the method returns false to indicate that the row is not completely white.

You could modify that test to look for other colors. For example, you could see if the components are less than 230 to skip pixels that are close to but not exactly white. Or you could look for components that are greater than 0 to skip black pixels. (In that case, you should probably change the method's name to something less misleading.)

The ColumnIsWhite method is similar to RowIsWhite except it checks columns instead of rows.

Download the example to see additional details.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in Uncategorized | Tagged , , , , , , , , | Leave a comment

Find Mersenne primes in C#

[example]

Mersenne primes are prime numbers of the from 2n – 1 for some integer n. For example, 22 – 1 = 4 – 1 = 3 and 3 is prime, so 3 is a Mersenne prime.

This example uses a relatively straightforward approach to find Mersenne primes. When you click the Go button, the following code executes.

private void btnGo_Click(object sender, EventArgs e)
{
    lstPrimes.Items.Clear();
    Cursor = Cursors.WaitCursor;
    Refresh();

    try
    {
        checked
        {
            long power = 1;
            for (int n = 1; n < 63; n++)
            {
                // Get the next power of 2.
                power *= 2;

                // See if power - 1 is prime.
                if (IsPrime(power - 1))
                {
                    lstPrimes.Items.Add(
                        n.ToString() + ": " + (power - 1).ToString());
                    Refresh();
                }
            }
        }
    }
    catch
    {
    }

    Cursor = Cursors.Default;
}

This code loops through values of n ranging from 1 to 63 and calls the IsMersennePrime method described shortly to see if 2n – 1 is prime. The code only checks values up to n = 63 because 264 – 1 is too big to fit in a long integer.

The following code shows the IsPrimes method.

// Return true if the number is prime.
private bool IsMersennePrime(long number)
{
    // Handle 2 separately.
    if (number == 2) return true;

    // See if the number is divisible by odd values up to Sqrt(number).
    long sqrt = (long)Math.Sqrt(number);
    for (long i = 3; i < sqrt; i += 2)
        if (number % i == 0) return false;

    // If we get here, the number is prime.
    return true;
}

This method determines whether a number is prime, but it is optimized slightly for Mersenne primes. If n ≥ 1, then the value 2n must be even so the value 2n - 1 must be odd. For that reason, the code doesn't check to see if the number is divisible by 2. Instead it loops through odd numbers between 3 and the square root of the number. If the number is divisible by any of those values, then the number is not prime.

If the number is not divisible by any of the n considered by the loop, then the number is prime.

The program quickly finds the Mersenne primes up to 231 - 1. For larger values of n, the value 2n - 1 is large enough that the search slows down and finding 261 - 1 takes longer.

To find larger Mersenne primes, you can use the BigInteger structure in the System.Numerics namespace, but the numbers become so large that your search will slow considerably. You'll probably need to switch to a new method is you want to find new Mersenne primes larger than the current largest known value of 277,232,917 - 1.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, mathematics | Tagged , , , , , , , , , | Leave a comment

Display a progress bar with text in WPF and C#

[progress bar]

As is so often the case in WPF, the solution is simple after you spend a few hours figuring out what controls to use. This example uses a normal Grid control that holds a StackPanel. The following code shows the controls inside the StackPanel.

<Button Name="goButton" Width="75" Height="30"
    Content="Go" Click="goButton_Click"/>

<Border Name="progBorder"
    Margin="0,10,0,0" Width="300" Height="25"
    BorderBrush="Black" BorderThickness="1">
    <Grid Margin="0">
        <Label Name="progBgLabel" Width="0" 
            HorizontalAlignment="Left"
            Background="LightGreen" />
        <Label Name="progLabel"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Content="0%" />
    </Grid>
</Border>

The button is there to let you start the progress simulation.

After the button comes a Border. This displays the black border around the progress bar and acts as a container for the remaining controls. This is the control that you should use to change the size or position of the progress bar. For example, this program makes the progress bar 300 pixels wide, 25 pixels tall, and centered inside the StackPanel. You can modify the Border control to change those values.

The progress bar must hold two Label controls, one to display the colored background and one to display text. Because a Border control can have only one child, the XAML code places a Grid inside the Border and then places the two Label controls inside the Grid.

Initially the controls are set to show no green background and the string “0%.”

The program uses the following code behind to prepare to update the progress.

// The timer.
private DispatcherTimer Timer = null;

// Progress parameters.
private const double ProgressMinimum = 0;
private const double ProgressMaximum = 100;
private const double ProgressStep = 4;
private double ProgressValue = ProgressMinimum;

WPF doesn’t have a Timer control, so the code declares a DispatcherTimer to use instead.

The code then defines some values to use while updating the progress. The ProgressValue variable shows the current progress.

When the window loads, the following code executes.

// Create the timer.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    Timer = new DispatcherTimer();
    Timer.Tick += new EventHandler(Timer_Tick);
    Timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
}

This code creates the DispatcherTimer, assigns its Tick event handler, and sets its interval to 100 milliseconds.

When you click the Go button, the following code executes.

// Start a timer.
private void goButton_Click(object sender, RoutedEventArgs e)
{
ProgressValue = ProgressMinimum;
Timer.Start();
}

This code sets ProgressValue to the minimum and enables the timer. The following event handler executes when the timer fires.

// Simulate a task's progress.
private void Timer_Tick(object sender, EventArgs e)
{
    ProgressValue += ProgressStep;
    if (ProgressValue > ProgressMaximum)
    {
        ProgressValue = ProgressMinimum;
        Timer.Stop();
    }

    // Show the progress.
    double fraction = (ProgressValue - ProgressMinimum) /
        (ProgressMaximum - ProgressMinimum);
    progBgLabel.Width = progBorder.Width * fraction;

    progLabel.Content = ProgressValue.ToString() + "%";
}

This code adds ProgressStep to ProgressValue. Then if ProgressValue is greater than ProgressMaximum, the code resets ProgessValue to ProgressMinimum and stops the timer.

After it updates ProgressValue, the code calculates the fraction of the Border control’s width that should filled with background. It multiplies that fraction by the Border control’s width and sets the background label’s width to the result.

The code finishes by setting the progLabel control’s contents to the ProgressValue. Note that this string is displayed with no digits after the decimal as long as ProgressValue has an integer value, as it does in this example.

There are several modifications that you could make to this example. For instance, you could left justify the text label. You could also fill the background label with a color gradient or tiled picture.

If you need to do something like this often, then you might want to make a custom control to fill the background and display the numeric value more easily.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in controls, user interface, wpf, XAML | Tagged , , , , , , , , , , , , , | 1 Comment

Convert between ragged arrays and two-dimensional arrays


[example]

Ragged arrays are arrays that hold other arrays, as opposed to two-dimensional arrays. They are called “ragged arrays” because they work like two-dimensional arrays (or higher-dimensional arrays) where each row in the array can hold a different number of elements.

Converting between ragged arrays and two-dimensional arrays isn’t too hard, it just requires some bookkeeping. You can also use generic parameters to make a method to convert between ragged arrays and two-dimensional arrays holding any type of objects.

The following extension method converts from a two-dimensional array to a ragged array.

// Convert T[,] to T[][].
public static T[][] ToRagged<T>(this T[,] values)
{
    // Get the number of rows and columns.
    int num_rows = values.GetUpperBound(0) + 1;
    int num_cols = values.GetUpperBound(1) + 1;

    // Make the ragged array.
    T[][] result = new T[num_rows][];

    // Copy values into the ragged array.
    for (int r = 0; r < num_rows; r++)
    {
        result[r] = new T[num_cols];
        for (int c = 0; c < num_cols; c++)
            result[r][c] = values[r, c];
    }

    return result;
}

The method first gets the two-dimensional array’s dimensions. It then creates a one-dimensional array to hold the ragged array’s rows.

The code then loops through the two-dimensional array’s rows. For each row, the method creates a one-dimensional array to hold the row’s values and then copies the values into the row.

The following extension method converts a ragged array into a two-dimensional array.

// Convert T[][] to T[,].
public static T[,] To2DArray<T>(this T[][] values)
{
    // Get the number of rows.
    int num_rows = values.GetUpperBound(0) + 1;

    // Get the maximum number of columns in any row.
    int num_cols = 0;
    for (int r = 0; r < num_rows; r++)
        if (num_cols < values[r].Length)
            num_cols = values[r].Length;

    // Make the two-dimensional array.
    T[,] result = new T[num_rows, num_cols];

    // Copy values into the ragged array.
    for (int r = 0; r < num_rows; r++)
    {
        for (int c = 0; c < values[r].Length; c++)
            result[r, c] = values[r][c];
    }

    return result;
}

This method gets the number of rows in the ragged array. It then loops through its rows to see how long its longest row is.

The code then allocates a two-dimensional array with the correct number of rows and columns. It then loops through the ragged array’s values adding them to the two-dimensional array.

Note that any entries in the two-dimensional array that do not correspond to entries in the ragged array are left uninitialized. For example, suppose the longest row in the ragged array has 25 entries but the first row has only 10 entries. In that case, the last 15 entries in the first row of the result array will hold only 10 values and the last 15 values will be uninitialized and will holdd the default value for their data type.


Download Example   Follow me on Twitter   RSS feed   Donate




Posted in algorithms, arrays, extension methods, generic | Tagged , , , , , , , , , , , | Leave a comment