All posts by Rian

How-to: Use Mercurial with EditPlus

I use EditPlus for most of my non-Visual Studio development. I’ve recently begun extending its functionality to use it as a “lite” PHP IDE by invoking php.exe from the commandline and capturing the output. I’ve also begun using Mercurial as my version control system of choice, and wondered if it would be possible to invoke hg from within EditPlus.

Turns out you can, and it’s quite easy. I find it best to configure Mercurial with an existing set of tools. I’m doing a lot of PHP right now, so that’s where I’ve stuck it.

  1. Add Mercurial to your PATH Environment variable using the method I outlined in this post.
  2. In EditPlus, configure your user tools: Tools > Configure User Tools
  3. Add Tool > Program
    Add tool
  4. Fill out the field as displayed, making modifications to suit your preferences:
    EditPlus Mercurial preferences

Details

  • "$(FileDir)" is the EditPlus variable indicating the directory that your current source file resides in. I have it enclosed in quotes, because sometimes directories or filenames have spaces in them.
  • -v indicates that I prefer verbose output. By default, mercurial will only display output if there has been an error, but I prefer to see success messages as well.
  • -m indicates a commit message.
  • "$(Prompt)" tells EditPlus to display a dialog that I can type in. This is where I put my commit message. I have it enclosed in quotes so I don’t have to worry about spaces breaking the commit message. You may need to escape more exotic characters; I have not tested it.

Caution

This method commits the working directory that your source file is in. This may or may not make sense, depending on the directory structure of your project. If you are concerned about the integrity of your atomic commits, it might make sense to configure your arguments differently, or to commit using the commandline or TortoiseHg.

Here’s the output as I see it in my editor:
EditPlus mercurial output capture

Here is a log of the commit messages as viewed with TortoiseHg:
EditPlus TortoiseHg log file viewer

Java solution to Project Euler Problem 48

Problem 48:

The series, 1^1 + 2^2 + 3^3 + … + 10^10 = 10405071317.

Find the last ten digits of the series, 1^1 + 2^2 + 3^3 + … + 1000^1000.

Running time: 125 ms

Assessment: Again, very easy and fast using arbitrary-precision arithmetic. Like one of my other solutions, I didn’t limit the output to just the last ten digits in the series, but you could easily tack that on.

import java.math.BigInteger;
 
public class Problem048
{
	public static void main(String[] args)
	{
		long begin = System.currentTimeMillis();
		BigInteger sum = BigInteger.ZERO;
		BigInteger temp = BigInteger.ONE;
		BigInteger GrandTotal = BigInteger.ZERO;
 
		for (int i = 1; i <= 1000; i++)
		{
			sum = temp.pow(i);
			temp = temp.add(BigInteger.ONE);
			GrandTotal = GrandTotal.add(sum);
		}
 
		long end = System.currentTimeMillis();
 
		System.out.println(GrandTotal);
		System.out.println(end-begin + "ms");
	}
}

Java solution to Project Euler Problem 36

Problem 36:

The Fibonacci sequence is defined by the recurrence relation:

Fn = F(n-1) + F(n-2), where F1 = 1 and F2 = 1.

Hence the first 12 terms will be:

  • F1 = 1
  • F2 = 1
  • F3 = 2
  • F4 = 3
  • F5 = 5
  • F6 = 8
  • F7 = 13
  • F8 = 21
  • F9 = 34
  • F10 = 55
  • F11 = 89
  • F12 = 144

The 12th term, F12, is the first term to contain three digits.

What is the first term in the Fibonacci sequence to contain 1000 digits?

Running time:

  • Checking for a palindrome in Base 10 first: 500ms
  • Checking for a binary palindrome first: 650ms

Assessment: This problem isn’t super interesting. What I did find interesting was that changing the order of the isPalindrome() comparison resulted in a significant difference in execution times. This makes sense because there are more binary palindromes than Base 10 palindromes. For no particular reason, I expected the compiler to optimize that section so the difference wouldn’t be as stark.

I commented out the slower method so you can play with it if my explanation is unclear.

public class Problem036
{
	private static boolean isPalindrome(String s)
	{
		String s2 = new StringBuffer(s).reverse().toString();
		if (s.equals(s2))
			return true;
		else
			return false;
	}
 
	public static void main(String[] args)
	{
		long begin = System.currentTimeMillis();
 
		long Sum = 0; 
		for (int i = 0; i < 1000000; i++)
		{
			if ( isPalindrome(Integer.toString(i)) && isPalindrome(Integer.toBinaryString(i)) )
				Sum += i;
			/*if (isPalindrome(Integer.toBinaryString(i)) && isPalindrome(Integer.toString(i)))
				Sum += i;*/
		}
		System.out.println(Sum);
 
		long end = System.currentTimeMillis();
		System.out.println(end-begin + "ms");
	}
}

Java solution to Project Euler Problem 25

Problem 25:

The Fibonacci sequence is defined by the recurrence relation:

Fn = F(n-1) + F(n-2), where F1 = 1 and F2 = 1.

Hence the first 12 terms will be:

  • F1 = 1
  • F2 = 1
  • F3 = 2
  • F4 = 3
  • F5 = 5
  • F6 = 8
  • F7 = 13
  • F8 = 21
  • F9 = 34
  • F10 = 55
  • F11 = 89
  • F12 = 144

The 12th term, F12, is the first term to contain three digits.

What is the first term in the Fibonacci sequence to contain 1000 digits?

Running time: 36ms

Assessment: LOL.

import java.math.BigInteger;
 
public class Problem025
{
	public static void main(String[] args)
	{
		long begin = System.currentTimeMillis();
 
		BigInteger a = BigInteger.valueOf(1);
		BigInteger b = BigInteger.valueOf(2);
		BigInteger c = BigInteger.valueOf(0);
		BigInteger MAX = new BigInteger("1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
 
		int i = 3;
		for (i = 3; b.compareTo(MAX) < 0; i++)
		{
			c = a.add(b);
			a = b;
			b = c;
		}
		System.out.println("i: " + i);
 
		long end = System.currentTimeMillis();
		System.out.println(end - begin + "ms");
	}
}

Java solution to Project Euler Problem 22

Problem 22:

Using names.txt (right click and ‘Save Link/Target As…’), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 * 53 = 49714.

What is the total of all the name scores in the file?

Running time:

  • File IO: 23ms
  • 5163 names sorted: 79ms
  • Built the list of names: 154ms
  • Total runtime: 209ms

Assessment: I broke my time measurements up so I could see how fast each major piece is. I thought that file IO would be the slowest piece of the equation–I don’t have an SSD–but it isn’t. In fact, no single piece is really the bottleneck. At less than 0.3 seconds, this is, for practical purposes, instantaneous.

If I were to do this problem again–probably in C#–I would approach it the same way, but the code would look a bit cleaner, and certainly less verbose. Using higher-level data structures makes this problem pretty simple.

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
 
public class Problem022
{
	private static ArrayList<String> NameList = new ArrayList<String>();
 
	private static void buildList(String s)
	{
		long BuildListBegin = System.currentTimeMillis();
		String temp = "";
		boolean IsName = false;
		int i = 0;
		while (i < s.length())
		{
			if (s.charAt(i) == '\"')
			{	// Flip the IsName switch if a quotation mark is encountered
				IsName = !IsName;
				i++;	// Move along one character so the quote isn't included in temp
			}
			if (IsName)
			{	// If switch is on, capture characters into temp
				temp += s.charAt(i);
			}
			else
			{
				if (temp == "")
				{	// Without this, a blank line is included
					break;
				}
				else
				{
					NameList.add(temp);
					temp = "";	
				}
			}
			i++;
		}
		long SortBegin = System.currentTimeMillis();
		Collections.sort(NameList);
		long SortEnd = System.currentTimeMillis();
		long BuildListEnd = System.currentTimeMillis();
		System.out.println(NameList.size() + " items sorted in " + (SortEnd-SortBegin) + "ms");
		System.out.println("buildList() executed in " + (BuildListEnd-BuildListBegin) + "ms");
	}
 
	private static String readFile(String filename)
	{
		/*	1) Read each name beginning with " and ending with " into vector of String
		 *	2) Sort names alphabetically
		 */
		long begin = System.currentTimeMillis();
		File f = new File(filename);
		BufferedReader reader;
		String list = "";
		try
		{
			StringBuffer contents = new StringBuffer();
			String text = null;
			reader = new BufferedReader(new FileReader(f));
			while ((text = reader.readLine()) != null)
			{
				contents.append(text).append(System.getProperty("line.separator"));			
			}
			list = contents.toString();
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		System.out.println("File IO: " + (System.currentTimeMillis() - begin) + "ms");
		return list;
	}
 
	private static long calcValue()
	{
		long GrandTotal = 0;
		int i = 1;
		Iterator<String> itr = NameList.iterator();
		while(itr.hasNext())
		{
			String tmp = itr.next().toString();
			int LocalSum = 0; 
 
			for (int j = 0; j < tmp.length(); j++)
			{
				if (tmp.charAt(j) == 'A')
					LocalSum += 1;
				else if (tmp.charAt(j) == 'B')
					LocalSum += 2;
				else if (tmp.charAt(j) == 'C')
					LocalSum += 3;
				else if (tmp.charAt(j) == 'D')
					LocalSum += 4;
				else if (tmp.charAt(j) == 'E')
					LocalSum += 5;
				else if (tmp.charAt(j) == 'F')
					LocalSum += 6;
				else if (tmp.charAt(j) == 'G')
					LocalSum += 7;
				else if (tmp.charAt(j) == 'H')
					LocalSum += 8;
				else if (tmp.charAt(j) == 'I')
					LocalSum += 9;
				else if (tmp.charAt(j) == 'J')
					LocalSum += 10;
				else if (tmp.charAt(j) == 'K')
					LocalSum += 11;
				else if (tmp.charAt(j) == 'L')
					LocalSum += 12;
				else if (tmp.charAt(j) == 'M')
					LocalSum += 13;
				else if (tmp.charAt(j) == 'N')
					LocalSum += 14;
				else if (tmp.charAt(j) == 'O')
					LocalSum += 15;
				else if (tmp.charAt(j) == 'P')
					LocalSum += 16;
				else if (tmp.charAt(j) == 'Q')
					LocalSum += 17;
				else if (tmp.charAt(j) == 'R')
					LocalSum += 18;
				else if (tmp.charAt(j) == 'S')
					LocalSum += 19;
				else if (tmp.charAt(j) == 'T')
					LocalSum += 20;
				else if (tmp.charAt(j) == 'U')
					LocalSum += 21;
				else if (tmp.charAt(j) == 'V')
					LocalSum += 22;
				else if (tmp.charAt(j) == 'W')
					LocalSum += 23;
				else if (tmp.charAt(j) == 'X')
					LocalSum += 24;
				else if (tmp.charAt(j) == 'Y')
					LocalSum += 25;
				else if (tmp.charAt(j) == 'Z')
					LocalSum += 26;
			}
 
			LocalSum *= (i);
			GrandTotal += LocalSum;
			i++;
		}
 
		return GrandTotal;		
	}
 
	public static void main(String[] args)
	{
		long begin = System.currentTimeMillis();
 
		buildList(readFile("names.txt"));
		System.out.println(calcValue());
 
		long end = System.currentTimeMillis();
 
		System.out.println("Total execution time: " + (end-begin) + "ms");
	}
}

Java solution to Project Euler Problem 21

Problem 21:

Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).

If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers.

For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.

Evaluate the sum of all the amicable numbers under 10000.

Running time: 140ms

Assessment: Like some of the other problems, I had to read this a few times before I really understood it.

import java.util.ArrayList;
import java.util.Iterator;
 
public class Problem021
{
	private static int MSum;
	private static int NSum;
 
	private static int sumList(ArrayList<Integer> list)
	{
		int sum = 0;
 
		for (Iterator<Integer> iter = list.iterator(); iter.hasNext();)
		{
			sum += iter.next();
		}
 
		return sum;
	}
 
	private static ArrayList<Integer> createList(int n)
	{
		// Creates a list of integers that evenly divide into n excluding n itself
		long root = Math.round(Math.sqrt(n)) + 1;
 
		ArrayList<Integer> test = new ArrayList<Integer>();
		test.add(1);
 
		for (int i = 2; i <= root; i++)
		{
			if (n % i == 0)
			{
				test.add(i);		// Add the divisor & its complement
				test.add(n/i);
			}
		}
 
		return test;
	}
 
	private static boolean isAmicable(int n)
	{
		/*** If n's divisors form an amicable set, return true ***/
 
		// Create a list of n's proper divisors
		ArrayList<Integer> NList = new ArrayList<Integer>(createList(n));		
 
		// Sum n's proper divisors (NSum)
		NSum = sumList(NList);
 
		// Create list of NSum's proper divisors (MList)
		ArrayList<Integer> MList = new ArrayList<Integer>(createList(NSum));
 
		// Sum m's proper divisors (MSum)
		MSum = sumList(MList);
 
		if ((MSum == n) && (MSum != NSum))
			return true;	
 
		return false;
	}
 
	public static void main(String[] args)
	{
		long begin = System.currentTimeMillis();
 
		int sum = 0;
		for (int i = 0; i < 10000; i++)
		{
			if (isAmicable(i))
			{
				sum += NSum;
			}
		}
 
		System.out.println(sum);
 
		long end = System.currentTimeMillis();
		System.out.println(end-begin + "ms");
	}
}

Java solution to Project Euler Problem 20

Problem 20:

n! means n * (n – 1) * … * 3 * 2 * 1

For example, 10! = 10 * 9 * … * 3 * 2 * 1 = 3628800,
and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.

Find the sum of the digits in the number 100!

Running time: 2ms

Assessment: Easy and fast using arbitrary-precision arithmetic.

import java.math.BigInteger;
 
public class Problem020
{
	private static int sumDigits(String s)
	{
		int sum = 0;
 
		for (int i = 0; i < s.length(); i++)
		{
			int j = Integer.parseInt(s.substring(i,i+1));
			sum += j;
		}
 
		return sum;
	}
 
	public static void main(String[] args)
	{
		long begin = System.currentTimeMillis();
		BigInteger fact = BigInteger.valueOf(1);
 
		for (int i = 1; i <= 100; i++)
			fact = fact.multiply(BigInteger.valueOf(i));
 
		long end = System.currentTimeMillis();
 
		System.out.println(sumDigits(fact.toString()));
		System.out.println(end-begin + "ms");
	}
}

Java solution to Project Euler Problem 16

Problem 16:

2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.

What is the sum of the digits of the number 2^1000?

Running time: 5ms

Assessment: Easy and fast using arbitrary-precision arithmetic.

import java.math.BigInteger;
 
public class Problem016
{
	private static int calcDigits(String s)
	{
		int sum = 0;
 
		for (int i = 0; i < s.length(); i++)
		{
			Character c = new Character(s.charAt(i));
			String z = c.toString();
			int j = Integer.parseInt(z);
			sum += j;
		}
 
		return sum;
	}
 
	public static void main(String[] args)
	{
		long begin = System.currentTimeMillis();
 
		BigInteger n = BigInteger.valueOf(2);
		n = n.pow(1000);
		System.out.println(calcDigits(n.toString()));
 
		long end = System.currentTimeMillis();
		System.out.println(end - begin + "ms");
	}
}

Java solution to Project Euler Problem 15

Problem 15:

Starting in the top left corner of a 22 grid, there are 6 routes (without backtracking) to the bottom right corner.

How many routes are there through a 2020 grid?

Running time: 0ms

Assessment: I was totally lost on this problem, and I eventually had to search for some clue as to how to solve it. Once I learned it was an n-choose-k problem, it was a lot easier. I used the simplified binomial coefficient algorithm described in the Wikipedia article, but only after making sure I understood what was going on and why it was used.

This simplified method ensures you don’t overflow your primitives when calculating factorials, and it’s ridiculously fast. (As I recall, it’s much faster than the ideal solution posted by the project admins.)

In retrospect, it seems obvious that it’s a combinatorics problem, because you can’t go backwards or up, but that wasn’t apparent to me when I started.

public class Problem015
{
	public static long binomialCoefficient(int n, int k)
	{
		/* N-choose-k combinatorics: (n! / (k! * (n-k)!)
		 * Where:
		 * 		n is the number of moves,
		 * 		k is the number of down and right moves required (20 each) */
 
		if (k > (n-k))
			k = n - k;
 
		long c = 1;
 
		for (int i = 0; i < k; i++)
		{
			c = c * (n-i);
			c = c / (i+1);			
		}
 
		return c;
	}
 
	public static void main (String[] args)
	{
		long begin = System.currentTimeMillis();
 
		System.out.println(binomialCoefficient(40,20));
 
		long end = System.currentTimeMillis();
		System.out.println(end-begin + "ms");		
	}
}

Java solution to Project Euler Problem 14

Problem 14:

The following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)
n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?

NOTE: Once the chain starts the terms are allowed to go above one million.

Running time: 6100ms (6.1 sec)

Assessment: I had to read this problem several times before I really grokked it, and then I thought it was pretty nifty. I’m sure there’s a faster way of working out the answer than my brute force solution.

import java.util.*;
 
public class Problem014
{
	public static void main(String[] args)
	{
		long begin = System.currentTimeMillis();
 
		LinkedList<Long> list = new LinkedList<Long>();
 
		long length = 0;
		int res = 0;
 
		for(int j = 10; j < 1000000; j++)
		{
			long i = j;
 
			while (i != 1)
			{
				if (i % 2 == 0)
				{
					i /= 2;
					list.add(i);
				}
				else
				{
					i = (3 * i) + 1;
					list.add(i);
				}
			}
 
			if(list.size() > length)
			{
				length = list.size();
				res = j;
			}
			list.clear();
		}
		long end = System.currentTimeMillis();
 
		System.out.println(res+" with chain size: "+ length);
		System.out.println(end-begin + "ms");
	}
}