Project Euler: Problem 3 in Ruby

It’s been a number of years since my last math class, so I had to bust out the pen and paper. I figured that for given number n you can stop checking for factors after n / 2, but I didn’t realize till much later (and by “realize”, I mean read up on prime numbers) that you can actually stop checking for prime factors at the square root. This saves considerable time when you’re dealing with numbers in the quadrabazillions. It’s the difference between < 2 seconds and I-did-the-dishes-and-it's-still-running. On a side note, I don't consider reading up on the subject "cheating". I consider looking up algorithms and other solutions "cheating". Problem #3

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

target = 600_851_475_143

def find_highest_prime_factor n
  (Math.sqrt(n).ceil).downto 2 do |i|
    if n % i == 0 && find_highest_prime_factor(i) == 1
      return i
    end
  end
  1
end

puts find_highest_prime_factor(target)

As expected, Olathe delivers. Runs roughly 3 times as fast and is easier on the eyes…even though he loaded an external library (cheater!)

 require 'mathn'
num, factor = 317_584_931_803, 0
primes = Prime.new
while num > 1
  factor = primes.next
  num /= factor while (num % factor).zero?
end
 
puts "Largest factor is #{ factor }."

However, if you’re going to cheat…cheat big! Posted by mat:

 require 'mathn'
317584931803.prime_division.last[0]

**UPDATE**
The two not-mine solutions use a different number (317584931803. instead of 600851475143) so the solution is different, but the algorithms are correct.

Project Euler: Problem 2 in Ruby

My solution for Project Euler problem #2 came out a little fugly mainly because of the global variables, but it works. The “secret” to getting the program to run in a reasonable amount of time is to store the values of the fibonacci sequence as you compute them instead of processing the same data over again.

Problem #2

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

Find the sum of all the even-valued terms in the sequence which do not exceed four million.

My Solution

max    = 4_000_000
total  = 0
$stack = []

def fib n
  if n == 0
    return 1
  end
  if n == 1
    return 2
  end
  return $stack[n - 1] + $stack[n - 2]
end

max.times do |i|
  $stack[i] = fib i
  if $stack[i] > max
    break
  end
  if $stack[i] & 1 == 0
    total += $stack[i]
  end
end

puts total

As is quickly becoming the case, Olathe’s solution was much more elegant than mine:

x, y, sum = 1, 1, 0
while sum < 1_000_000
  sum += (x + y)
  x, y = x + 2*y, 2*x + 3*y
end
 
puts "Sum is #{ sum }."

Project Euler: Problem 1 in Ruby

I’ve been working through some of the Project Euler problems in Ruby and I thought I’d post my solutions. I refuse to “cheat”, but it’s really neat to see all the different ways other people solve the problems afterwards.

Problem #1

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

total = 0

1000.times do |i|
  if i % 3 == 0 || i % 5 == 0
    total += i
  end
end

puts total

I googled around a bit after I finished and particularly liked this solution, which seemed more ruby-ish to me:

answer = (0..999).select { |a| a%3 ==0 || a%5==0 }
puts answer.inject { |sum, n| sum+n }

And, from the forums I thought Olathe’s solution was really neat, although mathily over my head:

class Integer
  def sum_mod modulus
    n = self.div modulus
    modulus * n * (n + 1) / 2
  end
end
 
num = 999
sum = num.sum_mod(3) + num.sum_mod(5) - num.sum_mod(15)
 
puts "Sum is #{ sum }."

Ruby Line Formatting

I wrote a little utility to turn something like this

this=that,
something_else="something else entirely"

Into the much easier to read

this           = that,
something_else = "something else entirely"

I use it in conjunction with my clipboard utility so I can just copy, run, paste. I mostly use this when I’m working with ColdFusion, so it also works for those pesky cfsets.

Usage: (After copying your target text to your clipboard)

ruby clipboard_format_set.rb

Download It!

PS: I’d love to set some of my scripts up as Eclipse shortcuts so I’ve been toying with the idea of writing an Eclipse plug-in to act as a proxy. I realize you can set up and run “External Tools”, but I have yet to see a way to bind a key. I’d like the plug-in to take care of the “pasting” to save me that extra ctrl-v. Maybe this would make a good New Years Project?

2009 New Years Resolutions

I like to write this sort of thing down so I can look back later and scoff.

User Groups!
There are some really great user groups in my area and I’ve consistently missed many months of meetings. The people are great, there’s a lot of great information being swapped around and it’s FUN! No more excuses.

Open Source Software!
This post is brought to you via the magic of WordPress, MySQL, FireFox and Ubuntu. I love and use a lot of open source software and it’s high time I start giving back. I plan on hunting down some ColdFusion projects to get into the swing of things, but eventually I’d like my own baby.

Plugins!
This goes a long with the previous bullet. I have a few ideas for FireFox and Eclipse plugins that I think would help get me in the OSS swing of things, (To use that trite and tired cliche yet again).

Unmaintained Recurring Income!
This might be a pipe dream, but I’ve been working on the web for a long time I really ought to have something out there making money, even if it’s only enough to pay for the hosting. I’ve got a few top secret ideas that I’ll share once I get into the swing of things.

JavaScript Deck of Cards Pt 2

A co-worker of mine sent me some advice on the JavaScript deck of cards I set up a while back. Everything he said was spot on. Jim, if you’re out there, you’re insight and advice is always welcome and highly respected. Thanks!

Read your blog. 🙂

In the interest of academic feedback (don’t take any of this in a negative way), I have a few comments.

It’s hard to tell from the current function names, but if the “same_suit” and “same_type” Card methods are meant to be “is_same_…” functions, they you need to change the “=” to “==”.

Card = Class.create({
	initialize: function(type,suit) {
		this.type = type;
		this.suit = suit;
	},
	same_suit: function(suit) {
		return this.suit == suit;
	},
	same_type: function(type) {
		return this.type == type;
	},
	toString: function(){
		return this.type + ' of ' + this.suit;
	}
});

JS supports the ‘+=’ operator for strings, so you could change the “message = message + …” to “message += …” in the Deck::toString method.


The first time through the Deck::toString function, the modulo check will be true, resulting in message beginning with a ‘n’ character. Wasn’t sure if that is what you wanted.

Here’s a minor optimization for the Deck::toString function. It removes the modulo operation from the loop, which is performed 52 times on a full deck, and handles the all of the leading/trailing whitespace (tabs and newlines) automatically:

toString: function() {
	var message = '';
	var i = 0, n = this.cards.length - 2;
	for(; i < n; ) {
		message += this.cards[i++] + 'tt' + this.cards[i++] + 'n';
	}
	if (i < this.cards.length) {
		message += this.cards[i++];
	}
	if (i < this.cards.length) {
		message += 'tt' + this.cards[i];
	}
	return message;
}

The following code:

var face_cards = "King,Queen,Jack"
face_cards     = face_cards.split(',');

Could be:

var face_cards = ["King","Queen","Jack"];

I don't think you need the "var i" in the Deck::add_card method.

PS: One other minor update, I got started thinking about UNO and decided to break out the French or Anglo American deck specifications out to a separate class and file.

PPS: Jim caught me using a "=" in place of a "==". These were methods that I hadn't tried yet, but knew that I would need in the future. This is exactly the sort of thing that would have been instantly caught had I written out some tests. I'm a bit late to the game on TDD, but it's something I've been toying with in Ruby and I'm starting to come around. I don't even know where to start unit testing in JavaScript, but I plan on doing a bit of homework on the matter so stay tuned!

Download the code!
JavaScript Deck of Cards V2
Current Version

Ruby Clipboard Directory List Utility

I wrote this little script to copy the filenames of a directory into the clipboard a while back and forgot to post about it. I’ve been particularly surprised about how often it’s come in handy for this or that.

 require 'clipboard'

c = Clipboard.new

list = ''

if ARGV.size == 0
	path =  "."
else
	path = ARGV[0]
end

Dir.foreach(path) {
	|file|
	if(file.length > 2)
		list << file << "n"
	end
}

c.set_data list

To use it, simply call run the script with the directory you want copied to your clipboard as an argument!

Download the code!

Target Practice Pt 2

I made a few small updates to Target Practice tonight. The biggest addition was sound although I made a few other little tweaks under the proverbial hood.

I had originally wanted to pack it up and release it as a single executable file but I was having some issues which I’ll post about once I figure out what the heck I’m doing.

Speaking of lazing, there are a few things I’d like to do differently in Target Practice. Most notably I’d like to abstract out out the media to some manager or another, and also my target manager class has grown rather bloated which I take to be a good indicator that it’s doing more than it should. I don’t care enough about this program to fix either of these issues, but hopefully I’ve learned from these mistakes!

Download it!