sudo make me a sandwich
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.
- Add Mercurial to your PATH Environment variable using the method I outlined in this post.
- In EditPlus, configure your user tools: Tools > Configure User Tools
- Add Tool > Program

- Fill out the field as displayed, making modifications to suit your 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.-vindicates 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.-mindicates 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:

Here is a log of the commit messages as viewed with TortoiseHg:
Java solution to Project Euler 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
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
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
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
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
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
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
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"); } }

